~alf-rodrigo/cairoplot/trunk

« back to all changes in this revision

Viewing changes to trunk/CairoPlot.py

  • Committer: Rodrigo Moreira Araújo
  • Date: 2009-01-28 01:46:56 UTC
  • Revision ID: alf.rodrigo@gmail.com-20090128014656-y92gxtm29h3nojz4
* CairoPlot.py: Bug fixes;
                        Code refactoring for the Plot and DotLinePlot classes;
                        Added ScatterPlot class;
                        Changed the code Josselin added to draw the y axis
                        title. Moved the code to render_axis and changed
                        the way the titles are drawn to make the x and y titles
                more similar;
* tests.py: Added tests for ScatterPlot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
    else:
42
42
        return HORZ
43
43
 
 
44
#Class definition
 
45
 
44
46
class Plot(object):
45
47
    def __init__(self, 
46
48
                 surface=None,
56
58
        self.width = width
57
59
        self.height = height
58
60
        self.context = cairo.Context(self.surface)
59
 
        self.load_series(data, h_labels, v_labels, series_colors)
60
 
 
 
61
        
61
62
        self.labels={}
62
63
        self.labels[HORZ] = h_labels
63
64
        self.labels[VERT] = v_labels
 
65
        
 
66
        self.load_series(data, h_labels, v_labels, series_colors)
 
67
 
64
68
 
65
69
        self.font_size = 10
66
70
        
194
198
                 v_labels = None,
195
199
                 h_bounds = None,
196
200
                 v_bounds = None,
 
201
                 h_title  = None,
197
202
                 v_title  = None,
198
203
                 series_colors = None):
199
204
        
202
207
        self.bounds[VERT] = v_bounds
203
208
        self.bounds[NORM] = None
204
209
        
 
210
        self.titles = {}
 
211
        self.titles[HORZ] = h_title
 
212
        self.titles[VERT] = v_title
 
213
        
205
214
        Plot.__init__(self, surface, data, width, height, background, border, h_labels, v_labels, series_colors)
206
215
        self.axis = axis
207
216
        self.dots = dots
208
217
        self.grid = grid
209
218
        self.series_legend = series_legend
210
 
        self.v_title = v_title
211
219
 
212
220
        self.max_value = {}
213
221
        
225
233
    def load_series(self, data, h_labels = None, v_labels = None, series_colors=None):
226
234
        Plot.load_series(self, data, h_labels, v_labels, series_colors)
227
235
        self.calc_boundaries()
 
236
        self.calc_labels()
228
237
    
229
238
    def calc_boundaries(self):
230
239
        if not self.bounds[HORZ]:
238
247
                if min(series) < min_data_value:
239
248
                    min_data_value = min(series)
240
249
            self.bounds[VERT] = (min_data_value, max_data_value)
 
250
    
 
251
    def calc_labels(self):
 
252
        if not self.labels[HORZ]:
 
253
            self.labels[HORZ] = [str(i) for i in range(self.bounds[HORZ][0], self.bounds[HORZ][1])]
 
254
        if not self.labels[VERT]:
 
255
            amplitude = self.bounds[VERT][1] - self.bounds[VERT][0]
 
256
            if amplitude % 10: #if vertical labels need floating points
 
257
                self.labels[VERT] = ["%.2lf" % (float(self.bounds[VERT][0] + (amplitude * i / 10.0))) for i in range(11) ]
 
258
            else:
 
259
                self.labels[VERT] = [str(int(self.bounds[VERT][0] + (amplitude * i / 10.0))) for i in range(11) ]
241
260
 
242
261
    def calc_extents(self, direction):
243
262
        self.context.set_font_size(self.font_size * 0.8)
244
 
        self.max_value[direction] = 0
245
 
        if self.labels[direction]:
246
 
            self.max_value[direction] = max(self.context.text_extents(item)[2] for item in self.labels[direction])
247
 
            self.borders[other_direction(direction)] = self.max_value[direction] + self.border + 20
248
 
        else:
249
 
            self.max_value[direction] = self.context.text_extents(str(self.bounds[direction][1]))[2]
250
 
            self.borders[other_direction(direction)] = self.max_value[direction] + self.border + 20
 
263
        self.max_value[direction] = max(self.context.text_extents(item)[2] for item in self.labels[direction])
 
264
        self.borders[other_direction(direction)] = self.max_value[direction] + self.border + 20
 
265
        #if self.titles[direction] :
 
266
        #    self.borders[other_direction(direction)] += self.context.text_extents(self.titles[direction])[3] #subtract axis title height
251
267
 
252
268
    def calc_all_extents(self):
253
269
        self.calc_extents(HORZ)
256
272
        self.plot_height = self.height - 2 * self.borders[VERT]
257
273
        self.plot_top = self.height - self.borders[VERT]
258
274
        series_amplitude = self.bounds[VERT][1] - self.bounds[VERT][0]
259
 
        self.vertical_step = float (self.plot_height) / series_amplitude
 
275
        if series_amplitude:
 
276
            self.vertical_step = float (self.plot_height) / series_amplitude
 
277
        else:
 
278
            self.vertical_step = 0.00
260
279
 
261
280
        self.plot_width = self.width - 2* self.borders[HORZ]
262
281
        largest_series_length = max(len(x) for x in self.data)
263
 
        self.horizontal_step = float (self.plot_width) / largest_series_length
264
 
 
265
 
    def render_axis(self):
266
 
        cr = self.context
267
 
        h_border = self.borders[HORZ]
268
 
        v_border = self.borders[VERT]
269
 
        cr.set_source_rgb(*self.line_color)
270
 
 
271
 
        cr.move_to(h_border, self.height - v_border)
272
 
        cr.line_to(h_border, v_border)
273
 
        cr.stroke()
274
 
 
275
 
        cr.move_to(h_border, self.height - v_border)
276
 
        cr.line_to(self.width - h_border, self.height - v_border)
277
 
        cr.stroke()
278
 
    
279
 
    def render_labels(self):
280
 
        self.context.set_font_size(self.font_size * 0.8)
281
 
        
282
 
        self.render_horz_labels()
283
 
        self.render_vert_labels()
284
 
    
285
 
    def render_horz_labels(self):
286
 
        cr = self.context
287
 
        labels = self.labels[HORZ]
288
 
        if not labels:
289
 
            labels = [str(i) for i in range(self.bounds[HORZ][0], self.bounds[HORZ][1])]
290
 
        border = self.borders[HORZ]
291
 
        
292
 
        step = float(self.width - 2 * border) / len(labels)
293
 
        x = border
294
 
        for item in labels:
295
 
            cr.set_source_rgb(*self.label_color)
296
 
            width = cr.text_extents(item)[2]
297
 
            cr.move_to(x, self.height - self.borders[VERT] + 5)
298
 
            cr.rotate(self.h_label_angle)
299
 
            cr.show_text(item)
300
 
            cr.rotate(-self.h_label_angle)
301
 
            #FIXME: render grid in a separate method
302
 
            if self.grid and x != border:
303
 
                cr.set_source_rgb(*self.grid_color)
304
 
                cr.move_to(x, self.height - self.borders[VERT])
305
 
                cr.line_to(x, self.borders[VERT])
306
 
                cr.stroke()
307
 
            x += step
308
 
    
309
 
    def render_vert_labels(self):
310
 
        cr = self.context
311
 
        labels = self.labels[VERT]
312
 
        if not labels:
313
 
            amplitude = self.bounds[VERT][1] - self.bounds[VERT][0]
314
 
            #if vertical labels need floating points
315
 
            if amplitude % 10:
316
 
                labels = ["%.2lf" % (float(self.bounds[VERT][0] + (amplitude * i / 10.0))) for i in range(11) ]
317
 
            else:
318
 
                labels = [str(int(self.bounds[VERT][0] + (amplitude * i / 10.0))) for i in range(11) ]
319
 
        border = self.borders[VERT]
320
 
        
321
 
        step = (self.height - 2 * border)/( len(labels) - 1 )
322
 
        y = self.height - border
323
 
        for item in labels:
324
 
            cr.set_source_rgb(*self.label_color)
325
 
            width = cr.text_extents(item)[2]
326
 
            cr.move_to(self.borders[HORZ] - width - 5,y)
327
 
            cr.show_text(item)
328
 
            #FIXME: render grid in a separate method
329
 
            if self.grid and y != self.height - border:
330
 
                cr.set_source_rgb(*self.grid_color)
331
 
                cr.move_to(self.borders[HORZ], y)
332
 
                cr.line_to(self.width - self.borders[HORZ], y)
333
 
                cr.stroke()
334
 
            y -=step
335
 
 
336
 
        #TODO move titles to a new function
337
 
        if self.v_title:
338
 
            cr.set_source_rgb(*self.label_color)
339
 
            cr.set_font_size(self.font_size)
340
 
            cr.move_to(5,y + step - self.font_size)
341
 
            cr.show_text(self.v_title)
342
 
    
 
282
        self.horizontal_step = float (self.plot_width) / ( largest_series_length - 1 )
 
283
 
343
284
    def render(self):
344
285
        self.calc_all_extents()
345
286
            
348
289
        
349
290
        if self.axis:
350
291
            self.render_axis()
 
292
        
 
293
        if self.grid:
 
294
            self.render_grid()
351
295
 
352
296
        self.render_labels()
353
297
        
355
299
        
356
300
        if self.series_legend and self.series_labels:
357
301
            self.render_legend()
358
 
        
 
302
 
 
303
    def render_axis(self):
 
304
        cr = self.context
 
305
        cr.set_source_rgb(*self.line_color)
 
306
        cr.move_to(self.borders[HORZ], self.height - self.borders[VERT])
 
307
        cr.line_to(self.borders[HORZ], self.borders[VERT])
 
308
        cr.stroke()
 
309
 
 
310
        cr.move_to(self.borders[HORZ], self.height - self.borders[VERT])
 
311
        cr.line_to(self.width - self.borders[HORZ], self.height - self.borders[VERT])
 
312
        cr.stroke()
 
313
 
 
314
        cr.set_source_rgb(*self.label_color)
 
315
        self.context.set_font_size( 1.2 * self.font_size )
 
316
        if self.titles[HORZ]:
 
317
            title_width,title_height = cr.text_extents(self.titles[HORZ])[2:4]
 
318
            cr.move_to( self.width/2 - title_width/2, self.borders[VERT] - title_height/2 )
 
319
            cr.show_text( self.titles[HORZ] )
 
320
 
 
321
        if self.titles[VERT]:
 
322
            title_width,title_height = cr.text_extents(self.titles[VERT])[2:4]
 
323
            cr.move_to( self.width - self.borders[HORZ] + title_height/2, self.height/2 - title_width/2)
 
324
            cr.rotate( math.pi/2 )
 
325
            cr.show_text( self.titles[VERT] )
 
326
            cr.rotate( -math.pi/2 )
 
327
        
 
328
    def render_grid(self):
 
329
        cr = self.context
 
330
        horizontal_step = float( self.plot_height ) / ( len( self.labels[VERT] ) - 1 )
 
331
        vertical_step = float( self.plot_width ) / ( len( self.labels[HORZ] ) - 1 )
 
332
        
 
333
        x = self.borders[HORZ] + vertical_step
 
334
        y = self.plot_top - horizontal_step
 
335
        
 
336
        for label in self.labels[HORZ][:-1]:
 
337
            cr.set_source_rgb(*self.grid_color)
 
338
            cr.move_to(x, self.height - self.borders[VERT])
 
339
            cr.line_to(x, self.borders[VERT])
 
340
            cr.stroke()
 
341
            x += vertical_step
 
342
        for label in self.labels[VERT][:-1]:
 
343
            cr.set_source_rgb(*self.grid_color)
 
344
            cr.move_to(self.borders[HORZ], y)
 
345
            cr.line_to(self.width - self.borders[HORZ], y)
 
346
            cr.stroke()
 
347
            y -= horizontal_step
 
348
    
 
349
    def render_labels(self):
 
350
        self.context.set_font_size(self.font_size * 0.8)
 
351
        self.render_horz_labels()
 
352
        self.render_vert_labels()
 
353
    
 
354
    def render_horz_labels(self):
 
355
        cr = self.context
 
356
        step = float( self.plot_width ) / ( len( self.labels[HORZ] ) - 1 )
 
357
        x = self.borders[HORZ]
 
358
        for item in self.labels[HORZ]:
 
359
            cr.set_source_rgb(*self.label_color)
 
360
            width = cr.text_extents(item)[2]
 
361
            cr.move_to(x, self.height - self.borders[VERT] + 5)
 
362
            cr.rotate(self.h_label_angle)
 
363
            cr.show_text(item)
 
364
            cr.rotate(-self.h_label_angle)
 
365
            x += step
 
366
    
 
367
    def render_vert_labels(self):
 
368
        cr = self.context
 
369
        step = ( self.plot_height ) / ( len( self.labels[VERT] ) - 1 )
 
370
        y = self.plot_top
 
371
        for item in self.labels[VERT]:
 
372
            cr.set_source_rgb(*self.label_color)
 
373
            width = cr.text_extents(item)[2]
 
374
            cr.move_to(self.borders[HORZ] - width - 5,y)
 
375
            cr.show_text(item)
 
376
            y -= step
 
377
 
359
378
    def render_legend(self):
360
379
        cr = self.context
361
380
        cr.set_font_size(self.font_size)
434
453
                x += self.horizontal_step
435
454
                last = value
436
455
 
437
 
 
438
 
 
439
456
class ScatterPlot( DotLinePlot ):
440
457
    def __init__(self, 
441
458
                 surface=None,
454
471
                 v_labels = None,
455
472
                 h_bounds = None,
456
473
                 v_bounds = None,
 
474
                 h_title  = None,
457
475
                 v_title  = None,
458
476
                 series_colors = None,
459
477
                 circle_colors = None,
467
485
        
468
486
        DotLinePlot.__init__(self, surface, data, width, height, background, border, 
469
487
                             axis, dash, dots, grid, series_legend, h_labels, v_labels, 
470
 
                             h_bounds, v_bounds, v_title, series_colors)
 
488
                             h_bounds, v_bounds, h_title, v_title, series_colors)
471
489
        
472
490
        if hasattr(radius, "__delitem__") == 2:
473
491
            self.bounds[NORM] = radius
509
527
        elif len(data[0]) == 3:
510
528
            self.variable_radius = True
511
529
    
512
 
        Plot.load_series(self, data, h_labels, v_labels, series_colors)
513
 
        self.calc_boundaries()
 
530
        DotLinePlot.load_series(self, data, h_labels, v_labels, series_colors)
 
531
        #self.calc_boundaries()
514
532
    
515
533
    def calc_boundaries(self):
516
534
        min_data_value = [0,0,0]
537
555
        if not self.bounds[NORM]:
538
556
            self.bounds[NORM] = (min_data_value[NORM], max_data_value[NORM])
539
557
 
 
558
    def calc_labels(self):
 
559
        if not self.labels[HORZ]:
 
560
            amplitude = self.bounds[HORZ][1] - self.bounds[HORZ][0]
 
561
            if amplitude % 10: #if vertical labels need floating points
 
562
                self.labels[HORZ] = ["%.2lf" % (float(self.bounds[HORZ][0] + (amplitude * i / 10.0))) for i in range(11) ]
 
563
            else:
 
564
                self.labels[HORZ] = [str(int(self.bounds[HORZ][0] + (amplitude * i / 10.0))) for i in range(11) ]
 
565
        DotLinePlot.calc_labels(self)
 
566
 
540
567
    def calc_all_extents(self):
541
568
        self.calc_extents(HORZ)
542
569
        self.calc_extents(VERT)
544
571
        self.plot_height = self.height - 2 * self.borders[VERT]
545
572
        self.plot_width = self.width - 2* self.borders[HORZ]
546
573
        
 
574
        self.plot_top = self.height - self.borders[VERT]
 
575
        
547
576
        series_amplitude = [0,0,0]
548
577
        series_amplitude[HORZ] = self.bounds[HORZ][1] - self.bounds[HORZ][0]
549
578
        series_amplitude[VERT] = self.bounds[VERT][1] - self.bounds[VERT][0]
550
579
        if self.variable_radius :
551
580
            series_amplitude[NORM] = self.bounds[NORM][1] - self.bounds[NORM][0]
552
581
        
553
 
        self.vertical_step = float (self.plot_height) / series_amplitude[VERT]
554
 
        self.horizontal_step = float (self.plot_width) / series_amplitude[HORZ]
555
 
        if self.variable_radius:
556
 
            self.z_step = float (self.bounds[NORM][1]) / series_amplitude[NORM]
557
 
        if self.circle_colors:
558
 
            r = float( self.circle_colors[1][0] - self.circle_colors[0][0] ) / series_amplitude[NORM]
559
 
            g = float( self.circle_colors[1][1] - self.circle_colors[0][1] ) / series_amplitude[NORM]
560
 
            b = float( self.circle_colors[1][2] - self.circle_colors[0][2] ) / series_amplitude[NORM]
561
 
            a = float( self.circle_colors[1][3] - self.circle_colors[0][3] ) / series_amplitude[NORM]
562
 
            self.circle_color_step = ( r, g, b, a )
 
582
        if series_amplitude[HORZ]:
 
583
            self.horizontal_step = float (self.plot_width) / series_amplitude[HORZ]
 
584
        else:
 
585
            self.horizontal_step = 0.00
 
586
            
 
587
        if series_amplitude[VERT]:
 
588
            self.vertical_step = float (self.plot_height) / series_amplitude[VERT]
 
589
        else:
 
590
            self.vertical_step = 0.00
 
591
 
 
592
        if series_amplitude[NORM]:
 
593
            if self.variable_radius:
 
594
                self.z_step = float (self.bounds[NORM][1]) / series_amplitude[NORM]
 
595
            if self.circle_colors:
 
596
                r = float( self.circle_colors[1][0] - self.circle_colors[0][0] ) / series_amplitude[NORM]
 
597
                g = float( self.circle_colors[1][1] - self.circle_colors[0][1] ) / series_amplitude[NORM]
 
598
                b = float( self.circle_colors[1][2] - self.circle_colors[0][2] ) / series_amplitude[NORM]
 
599
                a = float( self.circle_colors[1][3] - self.circle_colors[0][3] ) / series_amplitude[NORM]
 
600
                self.circle_color_step = ( r, g, b, a )
 
601
        else:
 
602
            self.z_step = 0.00
 
603
            self.circle_color_step = ( 0.0, 0.0, 0.0, 0.0 )
563
604
    
564
605
    def get_circle_color(self, value):
565
606
        r = self.circle_colors[0][0] + value*self.circle_color_step[0]
620
661
                        cr.set_dash([])
621
662
                    last_tuple = tuple
622
663
 
623
 
 
624
664
class FunctionPlot(DotLinePlot):
625
665
    def __init__(self, 
626
666
                 surface=None,
637
677
                 v_labels = None,
638
678
                 h_bounds = None,
639
679
                 v_bounds = None,
 
680
                 h_title  = None,
 
681
                 v_title  = None,
640
682
                 series_colors = None, 
641
683
                 step = 1):
642
684
 
648
690
 
649
691
        DotLinePlot.__init__(self, surface, data, width, height, background, border, 
650
692
                             axis, False, dots, grid, False, h_labels, v_labels, 
651
 
                             h_bounds, v_bounds, None,series_colors)
 
693
                             h_bounds, v_bounds, h_title, v_title, series_colors)
652
694
    
653
695
    def load_series_from_function( self, function, h_bounds ):
 
696
        #TODO: Add the possibility for the user to define multiple functions with different discretization parameters
 
697
        
654
698
        #This function converts a function, a list of functions or a dictionary
655
699
        #of functions into its corresponding array of data
656
700
        
657
 
        #return variable
658
701
        data = None
659
702
        
660
703
        #if no bounds are provided
691
734
                
692
735
        return data, h_bounds
693
736
 
694
 
    def render_horz_labels(self):
695
 
        cr = self.context
696
 
        labels = self.labels[HORZ]
697
 
        if not labels:
698
 
            labels = []
 
737
    def calc_labels(self):
 
738
        if not self.labels[HORZ]:
 
739
            self.labels[HORZ] = []
699
740
            i = self.bounds[HORZ][0]
700
 
            while i<self.bounds[HORZ][1]:
701
 
                labels.append(str(i*self.step))
 
741
            while i<=self.bounds[HORZ][1]:
 
742
                self.labels[HORZ].append(str(i))
702
743
                i += float(self.bounds[HORZ][1] - self.bounds[HORZ][0])/10
703
 
        border = self.borders[HORZ]
704
 
        
705
 
        step = (self.width - 2 * border) / len(labels)
706
 
        x = border
707
 
        for item in labels:
708
 
            cr.set_source_rgb(*self.label_color)
709
 
            width = cr.text_extents(item)[2]
710
 
            cr.move_to(x, self.height - self.borders[VERT] + 10)
711
 
            cr.rotate(self.h_label_angle)
712
 
            cr.show_text(item)
713
 
            cr.rotate(-self.h_label_angle)
714
 
            #FIXME: render grid in a separate method
715
 
            if self.grid and x != border:
716
 
                cr.set_source_rgb(*self.grid_color)
717
 
                cr.move_to(x, self.height - self.borders[VERT])
718
 
                cr.line_to(x, self.borders[VERT])
719
 
                cr.stroke()
720
 
            x += step
 
744
        DotLinePlot.calc_labels(self)
721
745
 
722
746
    def render_plot(self):
723
747
        if not self.discrete:
724
748
            DotLinePlot.render_plot(self)
725
749
        else:
726
 
            #render_series_labels
727
 
            largest_series_length = max(len(x) for x in self.data)
728
 
            #FIXME: plot_width and plot_height should be object properties and be re-used.
729
 
            plot_width = self.width - 2* self.borders[HORZ]
730
 
            plot_height = self.height - 2 * self.borders[VERT]
731
 
            plot_top = self.height - self.borders[VERT]
732
 
 
733
 
            series_amplitude = self.bounds[VERT][1] - self.bounds[VERT][0]
734
 
 
735
 
            horizontal_step = float (plot_width) / largest_series_length
736
 
            vertical_step = float (plot_height) / series_amplitude
737
750
            last = None
738
751
            cr = self.context
739
752
            for number, series in  enumerate (self.data):
740
753
                cr.set_source_rgb(*self.series_colors[number])
741
754
                x = self.borders[HORZ]
742
755
                for value in series:
743
 
                    cr.move_to(x, plot_top - int((value - self.bounds[VERT][0]) * vertical_step))
744
 
                    cr.line_to(x, plot_top)
 
756
                    cr.move_to(x, self.plot_top - int((value - self.bounds[VERT][0]) * self.vertical_step))
 
757
                    cr.line_to(x, self.plot_top)
745
758
                    cr.set_line_width(self.series_widths[number])
746
759
                    cr.stroke()
747
760
                    if self.dots:
748
761
                        cr.new_path()
749
 
                        cr.arc(x, plot_top - int((value - self.bounds[VERT][0]) * vertical_step), 3, 0, 2.1 * math.pi)
 
762
                        cr.arc(x, self.plot_top - int((value - self.bounds[VERT][0]) * self.vertical_step), 3, 0, 2.1 * math.pi)
750
763
                        cr.close_path()
751
764
                        cr.fill()
752
 
                    x += horizontal_step
753
 
 
754
 
 
755
 
 
 
765
                    x += self.horizontal_step
756
766
 
757
767
class BarPlot(Plot):
758
768
    def __init__(self, 
945
955
        y0 = self.borders[VERT]
946
956
        
947
957
        horizontal_step = float (plot_width) / len(self.data)
948
 
        vertical_step = float (plot_height) / series_amplitude
 
958
        if series_amplitude:
 
959
            vertical_step = float (plot_height) / series_amplitude
 
960
        else:
 
961
            vertical_step = 0.00
949
962
 
950
963
        for i,series in enumerate(self.data):
951
964
            inner_step = horizontal_step/(len(series) + 0.4)
1292
1305
                                      self.borders[VERT] + number*self.vertical_step + 3.0*self.vertical_step/4.0, 
1293
1306
                                      self.series_colors[number])
1294
1307
 
1295
 
 
 
1308
# Function definition
1296
1309
 
1297
1310
def scatter_plot(name,
1298
1311
                 data,
1310
1323
                 v_labels = None,
1311
1324
                 h_bounds = None,
1312
1325
                 v_bounds = None,
 
1326
                 h_title  = None,
1313
1327
                 v_title  = None,
1314
1328
                 series_colors = None,
1315
1329
                 circle_colors = None,
1332
1346
    
1333
1347
    plot = ScatterPlot( name, data, width, height, background, border,
1334
1348
                        axis, dash, discrete, dots, grid, series_legend, h_labels, v_labels,
1335
 
                        h_bounds, v_bounds, v_title, series_colors, circle_colors, radius )
 
1349
                        h_bounds, v_bounds, h_title, v_title, series_colors, circle_colors, radius )
1336
1350
    plot.render()
1337
1351
    plot.commit()
1338
1352
 
1339
 
 
1340
 
 
1341
1353
def dot_line_plot(name,
1342
1354
                  data,
1343
1355
                  width,
1353
1365
                  v_labels = None,
1354
1366
                  h_bounds = None,
1355
1367
                  v_bounds = None,
 
1368
                  h_title  = None,
1356
1369
                  v_title  = None,
1357
1370
                  series_colors = None):
1358
1371
    '''
1375
1388
        series_legend - Whether or not the legend is to be drawn;
1376
1389
        h_labels, v_labels - lists of strings containing the horizontal and vertical labels for the axis;
1377
1390
        h_bounds, v_bounds - tuples containing the lower and upper value bounds for the data to be plotted;
 
1391
        h_title - Whether or not to plot a title over the x axis.
1378
1392
        v_title - Whether or not to plot a title over the y axis.
1379
1393
 
1380
1394
        - Examples of use
1389
1403
    '''
1390
1404
    plot = DotLinePlot( name, data, width, height, background, border,
1391
1405
                        axis, dash, dots, grid, series_legend, h_labels, v_labels,
1392
 
                        h_bounds, v_bounds, v_title, series_colors )
 
1406
                        h_bounds, v_bounds, h_title, v_title, series_colors )
1393
1407
    plot.render()
1394
1408
    plot.commit()
1395
1409
 
1407
1421
                  v_labels = None,
1408
1422
                  h_bounds = None,
1409
1423
                  v_bounds = None,
 
1424
                  h_title  = None,
 
1425
                  v_title  = None,
1410
1426
                  series_colors = None,
1411
1427
                  step = 1):
1412
1428
 
1439
1455
    
1440
1456
    plot = FunctionPlot( name, data, width, height, background, border,
1441
1457
                         axis, discrete, dots, grid, h_labels, v_labels,
1442
 
                         h_bounds, v_bounds, series_colors, step )
 
1458
                         h_bounds, v_bounds, h_title, v_title, series_colors, step )
1443
1459
    plot.render()
1444
1460
    plot.commit()
1445
1461
 
1446
 
 
1447
1462
def pie_plot( name, data, width, height, background = None, gradient = False, shadow = False, colors = None ):
1448
1463
 
1449
1464
    '''