Merge lp:~kolmis/cairoplot/speedup into lp:cairoplot
- speedup
- Merge into trunk
Proposed by
Karel Kolman
Status: | Merged |
---|---|
Merged at revision: | 41 |
Proposed branch: | lp:~kolmis/cairoplot/speedup |
Merge into: | lp:cairoplot |
Diff against target: |
161 lines 4 files modified
trunk/cairoplot.py (+15/-6) trunk/seriestests.py (+21/-7) trunk/testscripts/compare.sh (+22/-0) trunk/testscripts/timeit.sh (+3/-0) |
To merge this branch: | bzr merge lp:~kolmis/cairoplot/speedup |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Rodrigo Moreira Araújo | Pending | ||
Review via email: mp+12980@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Karel Kolman (kolmis) wrote : | # |
Revision history for this message
Karel Kolman (kolmis) wrote : | # |
and i meant a minor improvement, not major :)
Revision history for this message
Rodrigo Moreira Araújo (alf-rodrigo) wrote : | # |
Hello Karel,
I'm sorry for the long time, but I'd like to let you know I just merged your
code onto the main branch.
Thanks a lot for the contribution.
Cheers,
Rodrigo Araujo
On Wed, Oct 7, 2009 at 7:07 AM, Karel Kolman <email address hidden> wrote:
> and i meant a minor improvement, not major :)
> --
> https:/
> You are requested to review the proposed merge of
> lp:~kolmis/cairoplot/speedup into lp:cairoplot.
>
Revision history for this message
Karel Kolman (kolmis) wrote : | # |
Thanks for merging the branch.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'trunk/cairoplot.py' | |||
2 | --- trunk/cairoplot.py 2009-07-09 21:57:24 +0000 | |||
3 | +++ trunk/cairoplot.py 2009-10-07 10:00:26 +0000 | |||
4 | @@ -510,9 +510,10 @@ | |||
5 | 510 | if self.titles[VERT]: | 510 | if self.titles[VERT]: |
6 | 511 | title_width,title_height = cr.text_extents(self.titles[VERT])[2:4] | 511 | title_width,title_height = cr.text_extents(self.titles[VERT])[2:4] |
7 | 512 | cr.move_to( self.dimensions[HORZ] - self.borders[HORZ] + title_height/2, self.dimensions[VERT]/2 - title_width/2) | 512 | cr.move_to( self.dimensions[HORZ] - self.borders[HORZ] + title_height/2, self.dimensions[VERT]/2 - title_width/2) |
8 | 513 | cr.save() | ||
9 | 513 | cr.rotate( math.pi/2 ) | 514 | cr.rotate( math.pi/2 ) |
10 | 514 | cr.show_text( self.titles[VERT] ) | 515 | cr.show_text( self.titles[VERT] ) |
12 | 515 | cr.rotate( -math.pi/2 ) | 516 | cr.restore() |
13 | 516 | 517 | ||
14 | 517 | def render_grid(self): | 518 | def render_grid(self): |
15 | 518 | cr = self.context | 519 | cr = self.context |
16 | @@ -544,21 +545,29 @@ | |||
17 | 544 | cr = self.context | 545 | cr = self.context |
18 | 545 | step = float( self.plot_width ) / ( len( self.labels[HORZ] ) - 1 ) | 546 | step = float( self.plot_width ) / ( len( self.labels[HORZ] ) - 1 ) |
19 | 546 | x = self.borders[HORZ] | 547 | x = self.borders[HORZ] |
20 | 548 | y = self.dimensions[VERT] - self.borders[VERT] + 5 | ||
21 | 549 | |||
22 | 550 | # store rotation matrix from the initial state | ||
23 | 551 | rotation_matrix = cr.get_matrix() | ||
24 | 552 | rotation_matrix.rotate(self.x_label_angle) | ||
25 | 553 | |||
26 | 554 | cr.set_source_rgba(*self.label_color) | ||
27 | 555 | |||
28 | 547 | for item in self.labels[HORZ]: | 556 | for item in self.labels[HORZ]: |
29 | 548 | cr.set_source_rgba(*self.label_color) | ||
30 | 549 | width = cr.text_extents(item)[2] | 557 | width = cr.text_extents(item)[2] |
33 | 550 | cr.move_to(x, self.dimensions[VERT] - self.borders[VERT] + 5) | 558 | cr.move_to(x, y) |
34 | 551 | cr.rotate(self.x_label_angle) | 559 | cr.save() |
35 | 560 | cr.set_matrix(rotation_matrix) | ||
36 | 552 | cr.show_text(item) | 561 | cr.show_text(item) |
38 | 553 | cr.rotate(-self.x_label_angle) | 562 | cr.restore() |
39 | 554 | x += step | 563 | x += step |
40 | 555 | 564 | ||
41 | 556 | def render_vert_labels(self): | 565 | def render_vert_labels(self): |
42 | 557 | cr = self.context | 566 | cr = self.context |
43 | 558 | step = ( self.plot_height ) / ( len( self.labels[VERT] ) - 1 ) | 567 | step = ( self.plot_height ) / ( len( self.labels[VERT] ) - 1 ) |
44 | 559 | y = self.plot_top | 568 | y = self.plot_top |
45 | 569 | cr.set_source_rgba(*self.label_color) | ||
46 | 560 | for item in self.labels[VERT]: | 570 | for item in self.labels[VERT]: |
47 | 561 | cr.set_source_rgba(*self.label_color) | ||
48 | 562 | width = cr.text_extents(item)[2] | 571 | width = cr.text_extents(item)[2] |
49 | 563 | cr.move_to(self.borders[HORZ] - width - 5,y) | 572 | cr.move_to(self.borders[HORZ] - width - 5,y) |
50 | 564 | cr.show_text(item) | 573 | cr.show_text(item) |
51 | 565 | 574 | ||
52 | === modified file 'trunk/seriestests.py' | |||
53 | --- trunk/seriestests.py 2009-07-09 21:57:24 +0000 | |||
54 | +++ trunk/seriestests.py 2009-10-07 10:00:26 +0000 | |||
55 | @@ -1,8 +1,16 @@ | |||
57 | 1 | import cairo, math, random | 1 | import cairo, math, sys |
58 | 2 | 2 | ||
59 | 3 | import cairoplot | 3 | import cairoplot |
60 | 4 | from series import Series | 4 | from series import Series |
61 | 5 | 5 | ||
62 | 6 | # non-random data for needs of visual comparison of changes | ||
63 | 7 | if '--non-random' in sys.argv: | ||
64 | 8 | random = lambda : 1.0 | ||
65 | 9 | print 'Plotting nonrandom data' | ||
66 | 10 | else: | ||
67 | 11 | import random | ||
68 | 12 | random = random.random | ||
69 | 13 | |||
70 | 6 | # Line plotting | 14 | # Line plotting |
71 | 7 | test_scatter_plot = 1 | 15 | test_scatter_plot = 1 |
72 | 8 | test_dot_line_plot = 1 | 16 | test_dot_line_plot = 1 |
73 | @@ -48,8 +56,8 @@ | |||
74 | 48 | f = [math.exp(x) for x in t] | 56 | f = [math.exp(x) for x in t] |
75 | 49 | g = [10*math.cos(x) for x in t] | 57 | g = [10*math.cos(x) for x in t] |
76 | 50 | h = [10*math.sin(x) for x in t] | 58 | h = [10*math.sin(x) for x in t] |
79 | 51 | erx = [0.1*random.random() for x in t] | 59 | erx = [0.1*random() for x in t] |
80 | 52 | ery = [5*random.random() for x in t] | 60 | ery = [5*random() for x in t] |
81 | 53 | data = Series({"exp" : [t,f], "cos" : [t,g], "sin" : [t,h]}) | 61 | data = Series({"exp" : [t,f], "cos" : [t,g], "sin" : [t,h]}) |
82 | 54 | series_colors = [ (1,0,0), (0,0,0), (0,0,1) ] | 62 | series_colors = [ (1,0,0), (0,0,0), (0,0,1) ] |
83 | 55 | cairoplot.scatter_plot ( 'cross_r_exponential_series.png', data = data, errorx = [erx,erx], errory = [ery,ery], width = 800, height = 600, border = 20, | 63 | cairoplot.scatter_plot ( 'cross_r_exponential_series.png', data = data, errorx = [erx,erx], errory = [ery,ery], width = 800, height = 600, border = 20, |
84 | @@ -77,6 +85,12 @@ | |||
85 | 77 | cairoplot.dot_line_plot( 'dot_line_3_series_legend_series.png', data, 400, 300, x_labels = x_labels, | 85 | cairoplot.dot_line_plot( 'dot_line_3_series_legend_series.png', data, 400, 300, x_labels = x_labels, |
86 | 78 | axis = True, grid = True, series_legend = True ) | 86 | axis = True, grid = True, series_legend = True ) |
87 | 79 | 87 | ||
88 | 88 | #Speed test, many x_labels | ||
89 | 89 | data = range(1000) | ||
90 | 90 | x_labels = [str(x) for x in data] | ||
91 | 91 | cairoplot.dot_line_plot( 'dot_line_4_many_x_labels.png', data, 14000, 300, x_labels = x_labels, | ||
92 | 92 | axis = True, grid = True, series_legend = True ) | ||
93 | 93 | |||
94 | 80 | if test_function_plot : | 94 | if test_function_plot : |
95 | 81 | #Default Plot | 95 | #Default Plot |
96 | 82 | data = lambda x : x**2 | 96 | data = lambda x : x**2 |
97 | @@ -142,7 +156,7 @@ | |||
98 | 142 | cairoplot.vertical_bar_plot ( 'vbar_8_hy_labels_series.png', data, 600, 200, border = 20, display_values = True, grid = True, x_labels = x_labels, y_labels = y_labels ) | 156 | cairoplot.vertical_bar_plot ( 'vbar_8_hy_labels_series.png', data, 600, 200, border = 20, display_values = True, grid = True, x_labels = x_labels, y_labels = y_labels ) |
99 | 143 | 157 | ||
100 | 144 | #Large data set | 158 | #Large data set |
102 | 145 | data = Series([[10*random.random()] for x in range(50)]) | 159 | data = Series([[10*random()] for x in range(50)]) |
103 | 146 | x_labels = ["large label name oh my god it's big" for x in data] | 160 | x_labels = ["large label name oh my god it's big" for x in data] |
104 | 147 | cairoplot.vertical_bar_plot ( 'vbar_9_large_series.png', data, 1000, 800, border = 20, grid = True, rounded_corners = True, x_labels = x_labels ) | 161 | cairoplot.vertical_bar_plot ( 'vbar_9_large_series.png', data, 1000, 800, border = 20, grid = True, rounded_corners = True, x_labels = x_labels ) |
105 | 148 | 162 | ||
106 | @@ -182,7 +196,7 @@ | |||
107 | 182 | cairoplot.horizontal_bar_plot ( 'hbar_8_hy_labels_series.png', data, 600, 200, border = 20, series_labels = series_labels, display_values = True, grid = True, x_labels = x_labels, y_labels = y_labels ) | 196 | cairoplot.horizontal_bar_plot ( 'hbar_8_hy_labels_series.png', data, 600, 200, border = 20, series_labels = series_labels, display_values = True, grid = True, x_labels = x_labels, y_labels = y_labels ) |
108 | 183 | 197 | ||
109 | 184 | #Large data set | 198 | #Large data set |
111 | 185 | data = Series([[10*random.random()] for x in range(25)]) | 199 | data = Series([[10*random()] for x in range(25)]) |
112 | 186 | x_labels = ["large label name oh my god it's big" for x in data] | 200 | x_labels = ["large label name oh my god it's big" for x in data] |
113 | 187 | cairoplot.horizontal_bar_plot ( 'hbar_9_large_series.png', data, 1000, 800, border = 20, grid = True, rounded_corners = True, x_labels = x_labels ) | 201 | cairoplot.horizontal_bar_plot ( 'hbar_9_large_series.png', data, 1000, 800, border = 20, grid = True, rounded_corners = True, x_labels = x_labels ) |
114 | 188 | 202 | ||
115 | @@ -242,8 +256,8 @@ | |||
116 | 242 | f = [math.exp(x) for x in t] | 256 | f = [math.exp(x) for x in t] |
117 | 243 | g = [10*math.cos(x) for x in t] | 257 | g = [10*math.cos(x) for x in t] |
118 | 244 | h = [10*math.sin(x) for x in t] | 258 | h = [10*math.sin(x) for x in t] |
121 | 245 | erx = [0.1*random.random() for x in t] | 259 | erx = [0.1*random() for x in t] |
122 | 246 | ery = [5*random.random() for x in t] | 260 | ery = [5*random() for x in t] |
123 | 247 | data = Series({"exp" : [t,f], "cos" : [t,g], "sin" : [t,h]}) | 261 | data = Series({"exp" : [t,f], "cos" : [t,g], "sin" : [t,h]}) |
124 | 248 | series_colors = [ (1,0,0), (0,0,0) ] | 262 | series_colors = [ (1,0,0), (0,0,0) ] |
125 | 249 | cairoplot.scatter_plot ( 'scatter_color_themes_series.png', data = data, errorx = [erx,erx], errory = [ery,ery], width = 800, height = 600, border = 20, | 263 | cairoplot.scatter_plot ( 'scatter_color_themes_series.png', data = data, errorx = [erx,erx], errory = [ery,ery], width = 800, height = 600, border = 20, |
126 | 250 | 264 | ||
127 | === added directory 'trunk/testscripts' | |||
128 | === added file 'trunk/testscripts/compare.sh' | |||
129 | --- trunk/testscripts/compare.sh 1970-01-01 00:00:00 +0000 | |||
130 | +++ trunk/testscripts/compare.sh 2009-10-07 10:00:26 +0000 | |||
131 | @@ -0,0 +1,22 @@ | |||
132 | 1 | #!/bin/sh | ||
133 | 2 | |||
134 | 3 | if [ $# -ne 3 ] | ||
135 | 4 | then | ||
136 | 5 | echo "Compare .png files in two directories" | ||
137 | 6 | echo "Usage: ./compare.sh path1 path2 diffdir" | ||
138 | 7 | echo "Example: ./compare.sh . ../other ./diff" | ||
139 | 8 | exit | ||
140 | 9 | fi | ||
141 | 10 | |||
142 | 11 | for dir in $1 $2 | ||
143 | 12 | do | ||
144 | 13 | for i in $dir/*.png | ||
145 | 14 | do | ||
146 | 15 | convert $i $i.tiff | ||
147 | 16 | done | ||
148 | 17 | done | ||
149 | 18 | |||
150 | 19 | for i in `(cd $1; ls *.tiff)` | ||
151 | 20 | do | ||
152 | 21 | perceptualdiff $1/$i $2/$i -output $3/$i.ppm | ||
153 | 22 | done | ||
154 | 0 | 23 | ||
155 | === added file 'trunk/testscripts/timeit.sh' | |||
156 | --- trunk/testscripts/timeit.sh 1970-01-01 00:00:00 +0000 | |||
157 | +++ trunk/testscripts/timeit.sh 2009-10-07 10:00:26 +0000 | |||
158 | @@ -0,0 +1,3 @@ | |||
159 | 1 | #!/bin/sh | ||
160 | 2 | DIRNAME=`dirname $0` | ||
161 | 3 | (cd $DIRNAME/..; python -m timeit -n 1 -v "import seriestests") |
Hi, i'm experimenting with using cairoplot to render plots in the wxbanker project and i stumbled upon some performance related problems which lead me to examining cairoplot's code. Summary of changes proposed in this branch:
- speed up x_labels rendering
+++ (create the rotation matrix once only, apply it for each x_label - this is a major improvement)
- added a timer.sh script and a test plot with 1000 x_labels to show the performance difference
- replace rotate(angle), rotate(-angle) pairs with save(), rotate(angle), restore() triples
+++ (i have absolutely none experience in graphics programming, but i think this is the way to go, since i'd say these two rotations added don't have to result in an identity matrix due to floating number arithmetics and rounding errors)
- added a script for visual comparison of outputs, it diffs two outputs from seriestests.py and creates diff images in PPM format
+++ i performed the following test: i created two cairoplot versions:
====== 1. all show_text() references removed, the rotate(angle), rotate(-angle) statements stayed
====== 2. all show_text() references removed, all rotate() pairs removed
====== comparing these two some plots were different whereas they should be exactly the same