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