116
117
def scale_value(cls, value, range):
117
118
scaled = cls.int_scale_value(value, range)
118
119
clipped = cls.clip_value(scaled)
119
Data.check_clip(scaled, clipped)
123
def check_clip(scaled, clipped):
124
120
if clipped != scaled:
125
121
warnings.warn('One or more of of your data points has been '
126
122
'clipped because it is out of range.')
129
126
class SimpleData(Data):
292
288
LINEAR_STRIPES = 'ls'
294
290
def __init__(self, width, height, title=None, legend=None, colours=None,
295
auto_scale=True, x_range=None, y_range=None,
296
colours_within_series=None):
291
auto_scale=True, x_range=None, y_range=None):
297
292
if type(self) == Chart:
298
293
raise AbstractClassException('This is an abstract class')
299
294
assert(isinstance(width, int))
347
339
# optional arguments
349
341
url_bits.append('chtt=%s' % self.title)
350
if self.title_colour and self.title_font_size:
351
url_bits.append('chts=%s,%s' % (self.title_colour, \
352
self.title_font_size))
354
url_bits.append('chdl=%s' % '%7c'.join(self.legend))
355
if self.legend_position:
356
url_bits.append('chdlp=%s' % (self.legend_position))
343
url_bits.append('chdl=%s' % '|'.join(self.legend))
358
url_bits.append('chco=%s' % ','.join(self.colours))
359
if self.colours_within_series:
360
url_bits.append('chco=%s' % '%7c'.join(self.colours_within_series))
345
url_bits.append('chco=%s' % ','.join(self.colours))
361
346
ret = self.fill_to_url()
363
348
url_bits.append(ret)
364
349
ret = self.axis_to_url()
368
url_bits.append(self.markers_to_url())
353
url_bits.append(self.markers_to_url())
369
354
if self.line_styles:
371
356
for index in xrange(max(self.line_styles) + 1):
434
407
_check_colour(col)
435
408
self.colours = colours
437
def set_colours_within_series(self, colours):
438
# colours needs to be a list, tuple or None
439
assert(isinstance(colours, list) or isinstance(colours, tuple) or
441
# make sure the colours are in the right format
445
self.colours_within_series = colours
447
410
# Background/Chart colours
448
411
# -------------------------------------------------------------------------
510
473
return ExtendedData
512
def _filter_none(self, data):
513
return [r for r in data if r is not None]
515
475
def data_x_range(self):
516
476
"""Return a 2-tuple giving the minimum and maximum x-axis
520
lower = min([min(self._filter_none(s))
521
for type, s in self.annotated_data()
480
lower = min([min(s) for type, s in self.annotated_data()
523
upper = max([max(self._filter_none(s))
524
for type, s in self.annotated_data()
482
upper = max([max(s) for type, s in self.annotated_data()
526
484
return (lower, upper)
527
485
except ValueError:
562
518
if x_range is None:
563
519
x_range = self.data_x_range()
564
520
if x_range and x_range[0] > 0:
565
x_range = (x_range[0], x_range[1])
521
x_range = (0, x_range[1])
566
522
self.scaled_x_range = x_range
568
524
# Determine the y-axis range for scaling.
569
525
if y_range is None:
570
526
y_range = self.data_y_range()
571
527
if y_range and y_range[0] > 0:
572
y_range = (y_range[0], y_range[1])
528
y_range = (0, y_range[1])
573
529
self.scaled_y_range = y_range
665
615
url_bits.append('chxt=%s' % ','.join(available_axis))
667
url_bits.append('chxl=%s' % '%7c'.join(label_axis))
617
url_bits.append('chxl=%s' % '|'.join(label_axis))
669
url_bits.append('chxr=%s' % '%7c'.join(range_axis))
619
url_bits.append('chxr=%s' % '|'.join(range_axis))
671
url_bits.append('chxp=%s' % '%7c'.join(positions))
621
url_bits.append('chxp=%s' % '|'.join(positions))
673
url_bits.append('chxs=%s' % '%7c'.join(styles))
623
url_bits.append('chxs=%s' % '|'.join(styles))
674
624
return '&'.join(url_bits)
676
626
# Markers, Ranges and Fill area (chm)
677
627
# -------------------------------------------------------------------------
679
def markers_to_url(self):
680
return 'chm=%s' % '%7c'.join([','.join(a) for a in self.markers])
629
def markers_to_url(self):
630
return 'chm=%s' % '|'.join([','.join(a) for a in self.markers])
682
632
def add_marker(self, index, point, marker_type, colour, size, priority=0):
683
633
self.markers.append((marker_type, colour, str(index), str(point), \
684
634
str(size), str(priority)))
686
636
def add_horizontal_range(self, colour, start, stop):
687
self.markers.append(('r', colour, '0', str(start), str(stop)))
689
def add_data_line(self, colour, data_set, size, priority=0):
690
self.markers.append(('D', colour, str(data_set), '0', str(size), \
693
def add_marker_text(self, string, colour, data_set, data_point, size, \
695
self.markers.append((str(string), colour, str(data_set), \
696
str(data_point), str(size), str(priority)))
637
self.markers.append(('r', colour, '1', str(start), str(stop)))
698
639
def add_vertical_range(self, colour, start, stop):
699
self.markers.append(('R', colour, '0', str(start), str(stop)))
640
self.markers.append(('R', colour, '1', str(start), str(stop)))
701
642
def add_fill_range(self, colour, index_start, index_end):
702
643
self.markers.append(('b', colour, str(index_start), str(index_end), \
985
class QRChart(Chart):
987
def __init__(self, *args, **kwargs):
988
Chart.__init__(self, *args, **kwargs)
993
def type_to_url(self):
996
def data_to_url(self, data_class=None):
998
raise NoDataGivenException()
999
return 'chl=%s' % urllib.quote(self.data[0])
1001
def get_url_bits(self, data_class=None):
1002
url_bits = Chart.get_url_bits(self, data_class=data_class)
1004
url_bits.append('choe=%s' % self.encoding)
1006
url_bits.append('chld=%s%%7c%s' % (self.ec_level, self.margin))
1009
def set_encoding(self, encoding):
1010
self.encoding = encoding
1012
def set_ec(self, level, margin):
1013
self.ec_level = level
1014
self.margin = margin
1017
921
class ChartGrammar(object):
1019
923
def __init__(self):