18
18
from matplotlib import _png , rcParams
19
19
from matplotlib import font_manager
20
20
from matplotlib .ft2font import FT2Font
21
+ from matplotlib .cbook import is_string_like , is_writable_file_like
21
22
22
23
###############################################################################
23
24
@@ -623,12 +624,7 @@ def __init__(self, *args):
623
624
def get_default_filetype (self ):
624
625
return 'pdf'
625
626
626
- def print_pgf (self , filename , * args , ** kwargs ):
627
- """
628
- Output pgf commands for drawing the figure so it can be included and
629
- rendered in latex documents.
630
- """
631
-
627
+ def _print_pgf_to_fh (self , fh ):
632
628
header_text = r"""%% Creator: Matplotlib, PGF backend
633
629
%%
634
630
%% To include the figure in your LaTeX document, write
@@ -658,37 +654,50 @@ def print_pgf(self, filename, *args, **kwargs):
658
654
# get figure size in inch
659
655
w , h = self .figure .get_figwidth (), self .figure .get_figheight ()
660
656
661
- # start a pgfpicture environment and set a bounding box
662
- with codecs .open (filename , "w" , encoding = "utf-8" ) as fh :
663
- fh .write (header_text )
664
- fh .write (header_info_preamble )
665
- fh .write ("\n " )
666
- writeln (fh , r"\begingroup" )
667
- writeln (fh , r"\makeatletter" )
668
- writeln (fh , r"\begin{pgfpicture}" )
669
- writeln (fh , r"\pgfpathrectangle{\pgfpointorigin}{\pgfqpoint{%fin}{%fin}}" % (w ,h ))
670
- writeln (fh , r"\pgfusepath{use as bounding box}" )
671
-
672
- renderer = RendererPgf (self .figure , fh )
673
- self .figure .draw (renderer )
674
-
675
- # end the pgfpicture environment
676
- writeln (fh , r"\end{pgfpicture}" )
677
- writeln (fh , r"\makeatother" )
678
- writeln (fh , r"\endgroup" )
679
-
680
- def print_pdf (self , filename , * args , ** kwargs ):
657
+ # create pgfpicture environment and write the pgf code
658
+ fh .write (header_text )
659
+ fh .write (header_info_preamble )
660
+ fh .write ("\n " )
661
+ writeln (fh , r"\begingroup" )
662
+ writeln (fh , r"\makeatletter" )
663
+ writeln (fh , r"\begin{pgfpicture}" )
664
+ writeln (fh , r"\pgfpathrectangle{\pgfpointorigin}{\pgfqpoint{%fin}{%fin}}" % (w ,h ))
665
+ writeln (fh , r"\pgfusepath{use as bounding box}" )
666
+ renderer = RendererPgf (self .figure , fh )
667
+ self .figure .draw (renderer )
668
+
669
+ # end the pgfpicture environment
670
+ writeln (fh , r"\end{pgfpicture}" )
671
+ writeln (fh , r"\makeatother" )
672
+ writeln (fh , r"\endgroup" )
673
+
674
+ def print_pgf (self , fname_or_fh , * args , ** kwargs ):
681
675
"""
682
- Use LaTeX to compile a Pgf generated figure to PDF.
676
+ Output pgf commands for drawing the figure so it can be included and
677
+ rendered in latex documents.
683
678
"""
684
- w , h = self .figure .get_figwidth (), self .figure .get_figheight ()
679
+ if kwargs .get ("dryrun" , False ): return
680
+
681
+ # figure out where the pgf is to be written to
682
+ if is_string_like (fname_or_fh ):
683
+ with codecs .open (fname_or_fh , "w" , encoding = "utf-8" ) as fh :
684
+ self ._print_pgf_to_fh (fh )
685
+ elif is_writable_file_like (fname_or_fh ):
686
+ raise ValueError ("saving pgf to a stream is not supported, " + \
687
+ "consider using the pdf option of the pgf-backend" )
688
+ else :
689
+ raise ValueError ("filename must be a path" )
685
690
686
- target = os .path .abspath (filename )
691
+ def _print_pdf_to_fh (self , fh ):
692
+ w , h = self .figure .get_figwidth (), self .figure .get_figheight ()
687
693
688
694
try :
695
+ # create and switch to temporary directory
689
696
tmpdir = tempfile .mkdtemp ()
690
697
cwd = os .getcwd ()
691
698
os .chdir (tmpdir )
699
+
700
+ # print figure to pgf and compile it with latex
692
701
self .print_pgf ("figure.pgf" )
693
702
694
703
latex_preamble = get_preamble ()
@@ -704,45 +713,72 @@ def print_pdf(self, filename, *args, **kwargs):
704
713
\centering
705
714
\input{figure.pgf}
706
715
\end{document}""" % (w , h , latex_preamble , latex_fontspec )
707
- with codecs .open ("figure.tex" , "w" , "utf-8" ) as fh :
708
- fh .write (latexcode )
716
+ with codecs .open ("figure.tex" , "w" , "utf-8" ) as fh_tex :
717
+ fh_tex .write (latexcode )
709
718
710
719
texcommand = get_texcommand ()
711
720
cmdargs = [texcommand , "-interaction=nonstopmode" , "-halt-on-error" , "figure.tex" ]
712
721
try :
713
- stdout = subprocess .check_output (cmdargs , stderr = subprocess .STDOUT )
722
+ subprocess .check_output (cmdargs , stderr = subprocess .STDOUT )
714
723
except subprocess .CalledProcessError as e :
715
724
raise RuntimeError ("%s was not able to process your file.\n \n Full log:\n %s" % (texcommand , e .output ))
716
- shutil .copyfile ("figure.pdf" , target )
725
+
726
+ # copy file contents to target
727
+ with open ("figure.pdf" , "rb" ) as fh_src :
728
+ shutil .copyfileobj (fh_src , fh )
717
729
finally :
718
730
os .chdir (cwd )
719
731
try :
720
732
shutil .rmtree (tmpdir )
721
733
except :
722
734
sys .stderr .write ("could not delete tmp directory %s\n " % tmpdir )
723
735
724
- def print_png (self , filename , * args , ** kwargs ):
736
+ def print_pdf (self , fname_or_fh , * args , ** kwargs ):
725
737
"""
726
- Use LaTeX to compile a pgf figure to pdf and convert it to png .
738
+ Use LaTeX to compile a Pgf generated figure to PDF .
727
739
"""
740
+ # figure out where the pdf is to be written to
741
+ if is_string_like (fname_or_fh ):
742
+ with open (fname_or_fh , "wb" ) as fh :
743
+ self ._print_pdf_to_fh (fh )
744
+ elif is_writable_file_like (fname_or_fh ):
745
+ self ._print_pdf_to_fh (fname_or_fh )
746
+ else :
747
+ raise ValueError ("filename must be a path or a file-like object" )
728
748
749
+ def _print_png_to_fh (self , fh ):
729
750
converter = make_pdf_to_png_converter ()
730
751
731
- target = os .path .abspath (filename )
732
752
try :
753
+ # create and switch to temporary directory
733
754
tmpdir = tempfile .mkdtemp ()
734
755
cwd = os .getcwd ()
735
756
os .chdir (tmpdir )
757
+ # create pdf and try to convert it to png
736
758
self .print_pdf ("figure.pdf" )
737
759
converter ("figure.pdf" , "figure.png" , dpi = self .figure .dpi )
738
- shutil .copyfile ("figure.png" , target )
760
+ # copy file contents to target
761
+ with open ("figure.png" , "rb" ) as fh_src :
762
+ shutil .copyfileobj (fh_src , fh )
739
763
finally :
740
764
os .chdir (cwd )
741
765
try :
742
766
shutil .rmtree (tmpdir )
743
767
except :
744
768
sys .stderr .write ("could not delete tmp directory %s\n " % tmpdir )
745
769
770
+ def print_png (self , fname_or_fh , * args , ** kwargs ):
771
+ """
772
+ Use LaTeX to compile a pgf figure to pdf and convert it to png.
773
+ """
774
+ if is_string_like (fname_or_fh ):
775
+ with open (fname_or_fh , "wb" ) as fh :
776
+ self ._print_png_to_fh (fh )
777
+ elif is_writable_file_like (fname_or_fh ):
778
+ self ._print_png_to_fh (fname_or_fh )
779
+ else :
780
+ raise ValueError ("filename must be a path or a file-like object" )
781
+
746
782
def _render_texts_pgf (self , fh ):
747
783
# TODO: currently unused code path
748
784
0 commit comments