115
117
def scale_value(cls, value, range):
116
118
scaled = cls.int_scale_value(value, range)
117
119
clipped = cls.clip_value(scaled)
118
Data.check_clip(scaled, clipped)
122
def check_clip(scaled, clipped):
123
120
if clipped != scaled:
124
121
warnings.warn('One or more of of your data points has been '
125
122
'clipped because it is out of range.')
128
126
class SimpleData(Data):
291
288
LINEAR_STRIPES = 'ls'
293
290
def __init__(self, width, height, title=None, legend=None, colours=None,
294
auto_scale=True, x_range=None, y_range=None,
295
colours_within_series=None):
291
auto_scale=True, x_range=None, y_range=None):
296
292
if type(self) == Chart:
297
293
raise AbstractClassException('This is an abstract class')
298
294
assert(isinstance(width, int))
347
341
url_bits.append('chtt=%s' % self.title)
349
343
url_bits.append('chdl=%s' % '|'.join(self.legend))
350
if self.legend_position:
351
url_bits.append('chdlp=%s' % (self.legend_position))
353
url_bits.append('chco=%s' % ','.join(self.colours))
354
if self.colours_within_series:
355
url_bits.append('chco=%s' % '|'.join(self.colours_within_series))
345
url_bits.append('chco=%s' % ','.join(self.colours))
356
346
ret = self.fill_to_url()
358
348
url_bits.append(ret)
359
349
ret = self.axis_to_url()
363
url_bits.append(self.markers_to_url())
353
url_bits.append(self.markers_to_url())
364
354
if self.line_styles:
366
356
for index in xrange(max(self.line_styles) + 1):
384
374
raise BadContentTypeException('Server responded with a ' \
385
375
'content-type of %s' % opener.headers['content-type'])
387
open(file_name, 'wb').write(opener.read())
377
open(file_name, 'wb').write(urllib.urlopen(self.get_url()).read())
389
379
# Simple settings
390
380
# -------------------------------------------------------------------------
405
395
self.legend = None
407
def set_legend_position(self, legend_position):
409
self.legend_position = urllib.quote(legend_position)
411
self.legend_position = None
414
398
# -------------------------------------------------------------------------
423
407
_check_colour(col)
424
408
self.colours = colours
426
def set_colours_within_series(self, colours):
427
# colours needs to be a list, tuple or None
428
assert(isinstance(colours, list) or isinstance(colours, tuple) or
430
# make sure the colours are in the right format
434
self.colours_within_series = colours
436
410
# Background/Chart colours
437
411
# -------------------------------------------------------------------------
499
473
return ExtendedData
501
def _filter_none(self, data):
502
return [r for r in data if r is not None]
504
475
def data_x_range(self):
505
476
"""Return a 2-tuple giving the minimum and maximum x-axis
509
lower = min([min(self._filter_none(s))
510
for type, s in self.annotated_data()
480
lower = min([min(s) for type, s in self.annotated_data()
512
upper = max([max(self._filter_none(s))
513
for type, s in self.annotated_data()
482
upper = max([max(s) for type, s in self.annotated_data()
515
484
return (lower, upper)
516
485
except ValueError:
524
lower = min([min(self._filter_none(s))
525
for type, s in self.annotated_data()
493
lower = min([min(s) for type, s in self.annotated_data()
527
upper = max([max(self._filter_none(s)) + 1
528
for type, s in self.annotated_data()
495
upper = max([max(s) + 1 for type, s in self.annotated_data()
530
497
return (lower, upper)
531
498
except ValueError:
551
518
if x_range is None:
552
519
x_range = self.data_x_range()
553
520
if x_range and x_range[0] > 0:
554
x_range = (x_range[0], x_range[1])
521
x_range = (0, x_range[1])
555
522
self.scaled_x_range = x_range
557
524
# Determine the y-axis range for scaling.
558
525
if y_range is None:
559
526
y_range = self.data_y_range()
560
527
if y_range and y_range[0] > 0:
561
y_range = (y_range[0], y_range[1])
528
y_range = (0, y_range[1])
562
529
self.scaled_y_range = y_range
569
536
scale_range = y_range
570
537
elif type == 'marker-size':
571
538
scale_range = (0, max(dataset))
575
scaled_dataset.append(None)
577
scaled_dataset.append(
578
data_class.scale_value(v, scale_range))
579
scaled_data.append(scaled_dataset)
539
scaled_data.append([data_class.scale_value(v, scale_range)
580
541
return scaled_data
582
543
def add_data(self, data):
665
626
# Markers, Ranges and Fill area (chm)
666
627
# -------------------------------------------------------------------------
668
def markers_to_url(self):
629
def markers_to_url(self):
669
630
return 'chm=%s' % '|'.join([','.join(a) for a in self.markers])
671
632
def add_marker(self, index, point, marker_type, colour, size, priority=0):
673
634
str(size), str(priority)))
675
636
def add_horizontal_range(self, colour, start, stop):
676
self.markers.append(('r', colour, '0', str(start), str(stop)))
678
def add_data_line(self, colour, data_set, size, priority=0):
679
self.markers.append(('D', colour, str(data_set), '0', str(size), str(priority)))
681
def add_marker_text(self, string, colour, data_set, data_point, size, priority=0):
682
self.markers.append((str(string), colour, str(data_set), str(data_point), str(size), str(priority)))
637
self.markers.append(('r', colour, '1', str(start), str(stop)))
684
639
def add_vertical_range(self, colour, start, stop):
685
self.markers.append(('R', colour, '0', str(start), str(stop)))
640
self.markers.append(('R', colour, '1', str(start), str(stop)))
687
642
def add_fill_range(self, colour, index_start, index_end):
688
643
self.markers.append(('b', colour, str(index_start), str(index_end), \
966
class QRChart(Chart):
968
def __init__(self, *args, **kwargs):
969
Chart.__init__(self, *args, **kwargs)
974
def type_to_url(self):
977
def data_to_url(self, data_class=None):
979
raise NoDataGivenException()
980
return 'chl=%s' % urllib.quote(self.data[0])
982
def get_url_bits(self, data_class=None):
983
url_bits = Chart.get_url_bits(self, data_class=data_class)
985
url_bits.append('choe=%s' % self.encoding)
987
url_bits.append('chld=%s|%s' % (self.ec_level, self.margin))
990
def set_encoding(self, encoding):
991
self.encoding = encoding
993
def set_ec(self, level, margin):
994
self.ec_level = level
998
921
class ChartGrammar(object):
1000
923
def __init__(self):