1 ############################################################################
2 # Copyright (C) 2005 by Reithinger GmbH
5 # This file is part of faces.
7 # faces is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # faces is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the
19 # Free Software Foundation, Inc.,
20 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 ############################################################################
23 import matplotlib
.figure
as figure
24 import matplotlib
.font_manager
as font
32 class ChartPrinter(object):
34 Prints out a chart to a specific format
37 _point_factor
= { "cm" : 72.0/2.54,
42 _extensions
= ( "eps", "svg", "bmp", "png", "pdf" )
44 def __init__(self
, chart
, **kwargs
):
45 self
.unit
= kwargs
.get("unit", 'point')
46 self
._type
= kwargs
.get("type", "eps")
47 self
.linewidth
= kwargs
.get("linewidth", 1.0)
48 self
.edgecolor
= kwargs
.get("edgecolor", 'black')
49 dpi
= kwargs
.get("dpi", 72)
50 size
= kwargs
.get("size", (10, 10))
51 self
._figure
= figure
.Figure(size
, dpi
, linewidth
=0.0)
53 self
._chart
_instance
= None
54 self
._default
_font
_size
= font
.fontManager
.get_default_size()
56 self
.orientation
= "portrait"
64 self
._figure
.set_canvas(None)
68 def to_point(self
, value
):
69 if self
.unit
== "pixel":
70 return (72 * value
) / self
.dpi
72 return value
* self
._point
_factor
[self
.unit
]
75 def from_point(self
, value
):
76 if self
.unit
== "pixel": return (value
* self
.dpi
) / 72
77 return value
/ self
._point
_factor
[self
.unit
]
81 return self
._figure
.get_dpi()
84 def set_dpi(self
, dpi
):
85 if self
._type
== "eps": dpi
= 72
86 self
._figure
.set_dpi(dpi
)
87 widgets
.LazyText
.height_cache
.clear()
90 dpi
= property(get_dpi
, set_dpi
)
93 def set_filename(self
, filename
):
94 self
._filename
= filename
96 for e
in self
._extensions
:
97 if self
._filename
.endswith(e
) \
98 or self
._filename
.endswith(e
.upper()):
104 if not self
._filename
.endswith(self
._type
) \
105 and not self
._filename
.endswith(self
._type
.upper()):
106 self
._filename
+= "." + self
._type
109 def get_filename(self
):
110 return self
._filename
112 filename
= property(get_filename
, set_filename
)
115 def set_type(self
, type):
116 if type not in self
._extensions
:
117 raise ValueError("type '%s' not known" % type)
121 if type == "eps" and self
.dpi
!= 72:
124 self
._chart
_instance
= None
130 type = property(get_type
, set_type
)
133 def set_font_size(self
, font_size
):
134 tools
.set_default_size(font_size
)
135 self
._chart
_instance
= None
138 def get_font_size(self
):
139 return font
.fontManager
.get_default_size()
141 font_size
= property(get_font_size
, set_font_size
)
145 return bool(self
._chart
_instance
)
148 valid
= property(get_valid
)
151 canvas
= renderer
.PatchedFigureCanvasAgg
152 from charts
import _figure_manager
154 _figure_manager
.canvas
= canvas(self
._figure
)
155 self
._figure
.set_canvas(_figure_manager
.canvas
)
156 self
._chart
_instance
= self
._chart
(self
._figure
)
160 if not self
.valid
: self
.refresh()
161 self
._chart
_instance
._check
_limits
(False)
163 self
._figure
.figurePatch
.set_linewidth(self
.linewidth
)
164 canvas
= self
._figure
.canvas
166 if self
.type == "pdf":
167 from matplotlib
.backends
.backend_pdf
import FigureCanvasPdf
168 canvas
= canvas
.switch_backends(FigureCanvasPdf
)
170 canvas
.print_figure(self
.filename
, self
.dpi
,
171 facecolor
=self
._figure
.get_facecolor(),
172 edgecolor
=self
.edgecolor
,
173 orientation
=self
.orientation
)
176 def check_valid(self
):
177 if self
.valid
: return
178 raise RuntimeError("The printer state is invalid call 'refresh' "\
183 tools
.set_default_size(self
._default
_font
_size
)
184 widgets
.LazyText
.height_cache
.clear()
187 def get_margins(self
):
191 def _set_frame(self
):
195 class FreePrinter(ChartPrinter
):
196 #equally to 1024 x 786 pixels with 64 dpi
200 def __init__(self
, chart
, **kwargs
):
201 ChartPrinter
.__init
__(self
, chart
, **kwargs
)
202 size
= kwargs
.get("size")
204 self
._width
= size
[0] * 72
205 self
._height
= size
[1] * 72
213 return self
.from_point(self
._width
)
216 def set_width(self
, width
):
217 self
._width
= self
.to_point(width
)
218 self
._figure
.set_figsize_inches(self
._width
/72.0, self
._height
/72.0)
221 width
= property(get_width
, set_width
)
224 def get_height(self
):
225 return self
.from_point(self
._height
)
228 def set_height(self
, height
):
229 self
._height
= self
.to_point(height
)
230 self
._figure
.set_figsize_inches(self
._width
/72.0, self
._height
/72.0)
233 height
= property(get_height
, set_height
)
237 class TimePlotPrinter(FreePrinter
):
238 def __init__(self
, chart
, **kwargs
):
239 FreePrinter
.__init
__(self
, chart
, **kwargs
)
240 self
.set_ylimits(*kwargs
.get("ylimits", (None, None)))
241 self
.set_xlimits(*kwargs
.get("xlimits", (None, None)))
245 FreePrinter
.refresh(self
)
246 self
.autoscale(False)
250 def _set_limits(self
):
251 if not self
.valid
: return False
252 chart
= self
._chart
_instance
253 chart
._set
_ylim
(ymin
=self
._ylimits
[0], ymax
=self
._ylimits
[1])
254 chart
._set
_time
_lim
(*self
._time
_limits
)
258 def set_time_limits(self
, min=None, max=None):
259 self
._time
_limits
= (min, max)
263 def get_time_limits(self
):
265 return self
._chart
_instance
._get
_time
_lim
()
268 def set_xlimits(self
, min=None, max=None):
269 self
._time
_limits
= (min and int(min), max and int(max))
273 def get_xlimits(self
):
275 return self
._chart
_instance
._get
_xlim
()
278 def get_ylimits(self
):
280 return self
._chart
_instance
._get
_ylim
()
283 def set_ylimits(self
, ymin
=None, ymax
=None):
284 self
._ylimits
= (ymin
, ymax
)
288 def _set_frame(self
):
289 chart
= self
._chart
_instance
290 patch
= chart
._axes
_patch
291 chart
._set
_frame
_on
(True)
292 patch
.set_fill(False)
293 self
._figure
.set_facecolor(patch
.get_facecolor())
294 patch
.set_linewidth(self
.linewidth
)
295 patch
.set_edgecolor(self
.edgecolor
)
298 def autoscale(self
, set=True):
299 if not self
.valid
: self
.refresh()
300 chart
= self
._chart
_instance
301 chart
._set
_autoscale
_on
(True)
302 chart
._autoscale
_view
()
304 self
._ylimits
= chart
._get
_ylim
()
305 self
._time
_limits
= chart
._get
_time
_lim
()
309 class WidgetPrinter(ChartPrinter
):
310 def __init__(self
, chart
, **kwargs
):
311 ChartPrinter
.__init
__(self
, chart
, **kwargs
)
312 self
._ylimits
= kwargs
.get("ylimits", (None, None))
315 self
.set_xlimits(*kwargs
.get("xlimits", (None, None)))
323 def set_height(self
, value
):
325 value
= self
.to_point(value
)
326 chart
= self
._chart
_instance
327 ymin
, ymax
= chart
._get
_ylim
()
328 bottom
= chart
._right
_margin
.get()
329 top
= chart
._top
_margin
.get()
330 value
-= (bottom
+ top
)
331 self
._ylimits
= (ymax
- value
, ymax
)
335 def set_ylimits(self
, ymin
=None, ymax
=None):
336 ymin
= ymin
and -self
.to_point(ymin
)
337 ymax
= ymax
and -self
.to_point(ymax
)
338 self
._ylimits
= (ymax
, ymin
)
342 def get_height(self
):
344 chart
= self
._chart
_instance
345 margin
= chart
._top
_margin
.get() + chart
._bottom
_margin
.get()
346 return self
.from_point(chart
._view
_lim
.height() + margin
)
348 height
= property(get_height
, set_height
)
351 def get_ylimits(self
):
353 ymin
, ymax
= self
._chart
_instance
._get
_ylim
()
354 return self
.from_point(-ymax
), self
.from_point(-ymin
)
357 def set_ylimits(self
, ymin
=None, ymax
=None):
358 ymin
= ymin
and -self
.to_point(ymin
)
359 ymax
= ymax
and -self
.to_point(ymax
)
360 self
._ylimits
= (ymax
, ymin
)
365 ChartPrinter
.refresh(self
)
366 self
.autoscale(False)
371 def get_margins(self
):
373 chart
= self
._chart
_instance
374 left
= chart
._left
_margin
.get()
375 right
= chart
._right
_margin
.get()
376 top
= chart
._top
_margin
.get()
377 bottom
= chart
._bottom
_margin
.get()
378 return map(self
.from_point
, (left
, top
, right
, bottom
))
381 def _set_frame(self
):
382 chart
= self
._chart
_instance
383 patch
= chart
._axes
_patch
384 chart
._set
_frame
_on
(True)
385 patch
.set_fill(False)
386 self
._figure
.set_facecolor(patch
.get_facecolor())
387 patch
.set_linewidth(self
.linewidth
)
388 patch
.set_edgecolor(self
.edgecolor
)
391 def _set_limits(self
):
392 if not self
.valid
: return False
393 chart
= self
._chart
_instance
394 chart
._set
_ylim
(ymin
=self
._ylimits
[0], ymax
=self
._ylimits
[1])
398 def autoscale(self
, set=True):
399 if not self
.valid
: self
.refresh()
400 chart
= self
._chart
_instance
401 chart
._set
_autoscale
_on
(True)
402 chart
._set
_auto
_scale
_y
(False)
403 chart
._autoscale
_view
(False)
404 chart
._set
_ylim
(chart
._data
_lim
.intervaly().get_bounds())
405 if set: self
._ylimits
= chart
._get
_ylim
()
408 def _correct_size(self
):
409 raise RuntimeError("abstract")
412 class TimeWidgetPrinter(WidgetPrinter
):
415 def __init__(self
, chart
, **kwargs
):
416 WidgetPrinter
.__init
__(self
, chart
, **kwargs
)
417 size
= kwargs
.get("size")
419 self
._width
= size
[0] * 72
423 return self
.from_point(self
._width
)
426 def set_width(self
, width
):
427 self
._width
= self
.to_point(width
)
428 height
= self
._figure
.get_figheight()
429 self
._figure
.set_figsize_inches(self
._width
/72.0, height
)
431 width
= property(get_width
, set_width
)
434 def set_time_limits(self
, min=None, max=None):
435 self
._time
_limits
= (min, max)
439 def get_time_limits(self
):
441 return self
._chart
_instance
._get
_time
_lim
()
444 def set_xlimits(self
, min=None, max=None):
445 self
._time
_limits
= (min and int(min), max and int(max))
449 def get_xlimits(self
):
451 return self
._chart
_instance
._get
_xlim
()
454 def _set_limits(self
):
455 if WidgetPrinter
._set
_limits
(self
):
456 chart
= self
._chart
_instance
457 chart
._set
_time
_lim
(*self
._time
_limits
)
461 def _correct_size(self
):
462 if not self
.valid
: return
463 chart
= self
._chart
_instance
464 margin
= chart
._top
_margin
.get() + chart
._bottom
_margin
.get()
465 height
= chart
._view
_lim
.height() + margin
466 self
._figure
.set_figsize_inches(self
._width
/72.0, height
/72.0)
467 self
._chart
_instance
._check
_limits
(False)
470 def autoscale(self
, set=True):
471 WidgetPrinter
.autoscale(self
, set)
473 chart
= self
._chart
_instance
474 self
._time
_limits
= chart
._get
_time
_lim
()
478 class PointPrinter(WidgetPrinter
):
479 def __init__(self
, chart
, **kwargs
):
480 WidgetPrinter
.__init
__(self
, chart
, **kwargs
)
483 def set_width(self
, value
):
485 chart
= self
._chart
_instance
486 xmin
, xmax
= self
.get_xlimits()
487 left
= chart
._left
_margin
.get()
488 right
= chart
._right
_margin
.get()
489 value
-= (left
+ right
)
490 self
.set_xlimits(xmin
, xmin
+ value
)
495 chart
= self
._chart
_instance
496 margin
= chart
._left
_margin
.get() + chart
._right
_margin
.get()
497 return self
.from_point(chart
._view
_lim
.width() + margin
)
499 width
= property(get_width
, set_width
)
502 def get_xlimits(self
):
504 xmin
, xmax
= self
._chart
_instance
._get
_xlim
()
505 return self
.from_point(xmin
), self
.from_point(xmax
)
508 def set_xlimits(self
, xmin
=None, xmax
=None):
509 xmin
= xmin
and self
.to_point(xmin
)
510 xmax
= xmax
and self
.to_point(xmax
)
511 self
._xlimits
= (xmin
, xmax
)
515 def _set_limits(self
):
516 if WidgetPrinter
._set
_limits
(self
):
517 chart
= self
._chart
_instance
518 chart
._set
_xlim
(xmin
=self
._xlimits
[0], xmax
=self
._xlimits
[1])
522 def _correct_size(self
):
523 chart
= self
._chart
_instance
524 hmargin
= chart
._left
_margin
.get() + chart
._right
_margin
.get()
525 vmargin
= chart
._top
_margin
.get() + chart
._bottom
_margin
.get()
526 width
= chart
._view
_lim
.width() + hmargin
527 height
= chart
._view
_lim
.height() + vmargin
528 self
._figure
.set_figsize_inches(width
/72.0, height
/72.0)
529 self
._chart
_instance
._check
_limits
(False)
532 def autoscale(self
, set=True):
533 chart
= self
._chart
_instance
534 chart
._set
_xlim
(chart
._data
_lim
.intervalx().get_bounds())
535 chart
._set
_ylim
(chart
._data
_lim
.intervaly().get_bounds())
537 self
._xlimits
= chart
._get
_xlim
()
538 self
._ylimits
= chart
._get
_ylim
()