def join(self, verbose=True): """ join :class:`matplotlib.figure.Figure` objects contained in the object. Currently supports only joining into a single horizontal row. ARGS: verbose (boolean): if True, print a message to stdout as each figure is added to the SVG file. .. warning:: for now assumes that all figures are the same size. """ # TODO ([email protected]): sniff out the figure sizes and # size the SVG figure to accommodate all the figures. # TODO ([email protected]): allow user to specify rows, # columns of combined SVG figures. layout = VerticalLayout() sz = map(int, sg.from_mpl(self.figs[0]).get_size()) sz[1] *= len(self.figs) sz = map(str, sz) layout.set_size(sz) for f in self.figs: layout.add_figure(sg.from_mpl(f)) if verbose: print('saving {}'.format(self.fname_svg)) layout.save(self.fname_svg)
def load_clouds(cloud_file, figure_size=(8, 6)): plt.axis('off') fig = plt.gcf() fig.set_size_inches(figure_size[0], figure_size[1]) img = mpimg.imread(cloud_file) imgplot = plt.imshow(img) fig_svg = (sg.from_mpl(plt.gcf(), savefig_kw={ 'pad_inches': 0, 'bbox_inches': 'tight' })) plt.clf() return fig_svg
def load_clouds(cloud_file, figure_size=(8, 6)): plt.axis("off") fig = plt.gcf() fig.set_size_inches(figure_size[0], figure_size[1]) img = mpimg.imread(cloud_file) plt.imshow(img) fig_svg = sg.from_mpl(plt.gcf(), savefig_kw={ "pad_inches": 0, "bbox_inches": "tight" }) plt.clf() return fig_svg
def compose_svg_figure(figure_spec, filename, size, display=False): """Compose a figure from multiple SVG components. Parameters ---------- figure_spec : dict Structure describing subfigures to compose (see below). filename : str File name to save composed SVG size : tuple Size of final SVG document like ("16cm", "10cm") display : bool If True, display the complete SVG in Jupyter notebook. Each item in *figure_spec* is a dict containing:: { 'figure': <matplotlib Figure>, 'pos': (x, y), 'scale': 1.0, 'label': 'A', 'label_opts': {'size': 16, 'weight': 'bold'}, } """ import svgutils.transform as svg fig = svg.SVGFigure(*size) for item in figure_spec: subfig = svg.from_mpl(item['figure'], savefig_kw={'bbox_inches':'tight', 'pad_inches':0}) root = subfig.getroot() root.moveto(item['pos'][0], item['pos'][1], scale=item.get('scale', 1.0)) label = svg.TextElement(item['pos'][0], item['pos'][1], item['label'], **item.get('label_opts', {})) fig.append([root, label]) fig.save(filename) if display: from IPython.display import SVG, display display(SVG(filename=filename))
def __init__(self, fig, **kws): svg = _transform.from_mpl(fig, savefig_kw=kws) self.root = svg.getroot().root
import svgutils.transform as sg from svgutils.templates import VerticalLayout import matplotlib.pyplot as plt import numpy as np import os import os.path try: figs = [] for i in range(2): figs.append(plt.figure()) plt.plot(np.random.random(100)) layout = VerticalLayout() sz = map(int, sg.from_mpl(figs[0]).get_size()) sz[1] *= 3 sz = map(str, sz) layout.set_size(sz) layout.add_figure(sg.from_mpl(figs[0])) layout.add_figure(sg.from_mpl(figs[1])) txt1 = sg.TextElement(50, 50, "HELLO", size=12) layout.append([txt1]) layout.save(os.path.join('/', 'tmp', 'stack_plots.svg')) try: print('converting to pdf') subprocess.call( '/Applications/Inkscape.app/Contents/Resources/bin/inkscape --export-pdf=/tmp/stack_plots.pdf /tmp/stack_plots.svg', shell=True) except:
def addColorbar_to_svg(svgtext_or_filename,data2color=None, scratchpath=None, colorbarlimits=None, colorbar_ylabel=None, colorbar_ticks_side=None, colorbar_aspectratio=6, ticks=None,colorbar_filename=None, # Following set of parameters describes location of colorbar. These used to be frameon=True,colorbar_location=None,): """ colorbar_filename: If you want to get access to the colorbar by itself, set this. Otherwise, a tempfile is used. The return value is the full svg text with colorbar added. """ if colorbar_location is None: colorbar_location={} cblocation=dict(expandx=1, movebartox='auto',movebartoy='auto',scalebar=.75) cblocation.update(colorbar_location) def isdec(cc): return(cc.isdigit() or cc in '.') # Determine enough information to draw a colorbar: """ Add a colorbar. However, there are various possibilities for how; see above. """ import svgutils.transform as sg import sys # First, save svgtext to a file, if it is not one, and choose a (temporary) filename for the colorbar svg: # (Why can we use sg.fromfile no problem, but sg.fromtext causes Unicode trouble?) import tempfile to_delete=[] # Collect list of temp files that must be deleted explicitly if '\n' not in svgtext_or_filename: insvgfn=svgtext_or_filename else: tmpfh,insvgfn=tempfile.mkstemp() to_delete += [insvgfn] os.write(tmpfh, svgtext_or_filename) os.close(tmpfh) # see http://stackoverflow.com/questions/9944135/how-do-i-close-the-files-from-tempfile-mkstemp tmpfinalfh,outfilename=tempfile.mkstemp() to_delete += [outfilename] os.close(tmpfinalfh) # see #153. Otherwise, we have a file descriptor leak. But this way we get the file name if colorbar_filename is None: tmpcbfh,CBfilename=tempfile.mkstemp() to_delete += [CBfilename] os.close(tmpcbfh) else: CBfilename = colorbar_filename # Load svg into svgutils; determine units of the layout base_svg=sg.fromfile(insvgfn) def _getSizeWithUnits(svgbase): from cpblUtilities.mathgraph import tonumeric # Assume measure is digits then units: ww,hh=svgbase.get_size() ww,unitsSuffix=''.join([cc for cc in ww if isdec(cc)]),''.join([cc for cc in ww if not isdec(cc)]) hh,unitsSuffix2=''.join([cc for cc in hh if isdec(cc)]),''.join([cc for cc in hh if not isdec(cc)]) return(tonumeric(ww),tonumeric(hh),unitsSuffix,unitsSuffix2) ww,hh,u1,u2=_getSizeWithUnits(base_svg) # ww,hh=base_svg.get_size() # This is sometimes just numbers, but sometimes there are units too (px). unitsSuffix='' #if 1:#any(not isdec(cc) for cc in ww): # What to do when there are units? .. .isdigit() # ww,unitsSuffix=''.join([cc for cc in ww if isdec(cc)]),''.join([cc for cc in ww if not isdec(cc)]) # hh,unitsSuffix2=''.join([cc for cc in hh if isdec(cc)]),''.join([cc for cc in hh if not isdec(cc)]) # assert unitsSuffix==unitsSuffix2 # Create a dummy axis to hang the colorbar on: plt.figure(6354) hax=plt.gca() from cpblUtilities.color import addColorbarNonImage if 'fontsize' in colorbar_location: # This is measured in points. plt.rcParams.update({ 'font.size': colorbar_location['fontsize'],}) hbax=addColorbarNonImage(data2color,ylabel=colorbar_ylabel,ticks=ticks, colorbar_ticks_side=colorbar_ticks_side) # data2color=None,data=None,datarange=None,cmap=None,useaxis=None,ylabel=None,colorbarfilename=None,location=None,ticks=None): plt.setp(hax,'visible',False) # In fact, I think I've seen example where this hax was even in a different figure, already closed! hbax.ax.set_aspect(colorbar_aspectratio) plt.gcf().frameon=frameon plt.savefig(CBfilename+'.svg', bbox_inches='tight', pad_inches=0.1,frameon=frameon) #plt.savefig(CBfilename+'.png', bbox_inches='tight', pad_inches=0.1) # for testing # Or, I can just grab it directly! So above saving is no longer needed, except that I want one colorbar created at some point for each standard variable... from svgutils.transform import from_mpl cbsvg=sg.from_mpl(plt.gcf()) if cblocation['movebartox']=='auto': assert cblocation['movebartoy']=='auto' # Try to put it in the bottom right?? cbww,cbhh,u1,u2=_getSizeWithUnits(base_svg) # ww,hh=base_svg.get_size() # This is sometimes just numbers, but sometimes there are units too (px)self. ###cbsvg=sg.fromfile(CBfilename+'.svg') svg1,svg2 = base_svg.getroot(),cbsvg.getroot() #cbsize=[int(''.join([cc for cc in ss if cc.isdigit()])) for ss in cbsvg.get_size()] # Strip off the "pt" units that I have from this MPL colorbar at the moment :( #cbw,cbh= int(ww)/10, int(ww)/10 * cbsize[1]/cbsize[0] if 0: # should I fix the colorbar to be a certain fraction of the map size? Or keep it fixed the same for all maps? cbsvg.set_size(cbw,cbh) cblocation['movebartox']=ww-cbww cblocation['movebartoy']=hh-cbhh # if 0: # This was old "auto" code. All junk now? # # Try new method with svg_stack rather than svgutils: # import svg_stack as ss # # doc = ss.Document() # # A='____tmp_tmppart1.svg' # B='../okai/scratch/analysisTIGERcountiesMap_delta12_fourway.svg-tmpCB.svg' # C='trash/red_ball.svg' # layout1 = ss.HBoxLayout() # layout1.addSVG(insvgfn,alignment=ss.AlignTop|ss.AlignHCenter) # layout1.addSVG(CBfilename+'.svg',alignment=ss.AlignCenter)#,stretch=0.5) # noThisIsDrafty # #layout2 = ss.VBoxLayout() # # #layout2.addSVG(C,alignment=ss.AlignCenter) # #layout2.addSVG(C,alignment=ss.AlignCenter) # #layout2.addSVG(C,alignment=ss.AlignCenter) # #layout1.addLayout(layout2) # # doc.setLayout(layout1) # print(' Saving (auto mode in cblocation) '+outfilename) # doc.save(outfilename) # # else: # Use cblocation values # get the plot objects from constituent figures. I don't know why using the cbsvg from above doesn't work cbsvg=sg.fromfile(CBfilename+'.svg') if colorbar_filename is None: os.remove(CBfilename+'.svg') # no longer needed svg1,svg2 = base_svg.getroot(),cbsvg.getroot() """ if cblocation['movebartox']=='auto': assert cblocation['movebartoy']=='auto' # Below is old debug code working on using more automated fatures of svgutils. I switched to svg_stack, above, instead. impoosible_to_get_here cbw,cbh=cbsvg.get_size() from svgutils.transform import from_mpl from svgutils.templates import VerticalLayout,ColumnLayout ###svg = fromfile('../tests/circle.svg') layout = VerticalLayout#ColumnLayout(2) layout.add_figure(base_svg) layout.add_figure(cbsvg) layout.save('stack_svg.svg') oiuoiu layout = VerticalLayout() fig1 = plt.figure() plt.plot([1,2]) fig2 = plt.figure() plt.plot([2,1]) layout.add_figure(from_mpl(fig1)) layout.add_figure(from_mpl(fig2)) print from_mpl(fig1).get_size() layout.save('stack_plots.svg') fofoiu """ svg2.moveto(cblocation['movebartox'],cblocation['movebartoy'], scale=cblocation['scalebar']) #create new SVG figure fsvg = sg.SVGFigure(str(float(ww)*cblocation['expandx'])+unitsSuffix,str(float(hh)*cblocation['expandx'])+unitsSuffix) #fsvg = sg.SVGFigure(ww,hh) # append plots and labels to figure fsvg.append([svg1, svg2]) # save generated SVG files fsvg.save(outfilename) # This is a temporary file! It's supposed to include the whole fig, but bug: 2015May: only includes colorbar!! # Something is broken, May 2015. #Does this work: # N.B.!!! This is a kludge. Not sure why the above broke. base_svg=sg.fromfile(insvgfn) base_svg.append(svg2) base_svg.save(outfilename) print(' Wrote '+outfilename) plt.close(6354) try: # Some old version don't have to_str() svgstr = base_svg.to_str() except AttributeError: with open(outfilename, 'r') as f: svgstr = f.read() for fname in to_delete+[insvgfn, outfilename]: # list following + is redundant? if os.path.exists(fname): os.remove(fname) return svgstr
#!/usr/bin/env python # coding=utf-8 import numpy as np import matplotlib.pyplot as plt from svgutils.transform import from_mpl from svgutils.templates import VerticalLayout layout = VerticalLayout() fig1 = plt.figure() plt.plot([1, 2]) fig2 = plt.figure() plt.plot([2, 1]) layout.add_figure(from_mpl(fig1)) layout.add_figure(from_mpl(fig2)) layout.save("stack_plots.svg")
#!/usr/bin/env python #coding=utf-8 import numpy as np import matplotlib.pyplot as plt from svgutils.transform import from_mpl from svgutils.templates import VerticalLayout layout = VerticalLayout() fig1 = plt.figure() plt.plot([1,2]) fig2 = plt.figure() plt.plot([2,1]) layout.add_figure(from_mpl(fig1)) layout.add_figure(from_mpl(fig2)) print(from_mpl(fig1).get_size()) layout.save('stack_plots.svg')
def setMainSVG(self, **kwargs): if "filename" in kwargs: self.main_svg = sg.fromfile(kwargs["filename"]) elif "mpl_fig" in kwargs: self.main_svg = sg.from_mpl(kwargs["mpl_fig"])
#!/usr/bin/env python #coding=utf-8 import numpy as np import matplotlib.pyplot as plt from svgutils.transform import from_mpl from svgutils.templates import VerticalLayout layout = VerticalLayout() fig1 = plt.figure() plt.plot([1,2]) fig2 = plt.figure() plt.plot([2,1]) layout.add_figure(from_mpl(fig1)) layout.add_figure(from_mpl(fig2)) print from_mpl(fig1).get_size() layout.save('stack_plots.svg')
import svgutils.transform as sg from svgutils.templates import VerticalLayout import matplotlib.pyplot as plt import numpy as np import os import os.path try: figs = [] for i in range(2): figs.append(plt.figure()) plt.plot(np.random.random(100)) layout = VerticalLayout() sz = map(int, sg.from_mpl(figs[0]).get_size()) sz[1] *= 3 sz = map(str, sz) layout.set_size(sz) layout.add_figure(sg.from_mpl(figs[0])) layout.add_figure(sg.from_mpl(figs[1])) txt1 = sg.TextElement(50, 50, "HELLO", size=12) layout.append([txt1]) layout.save(os.path.join('/', 'tmp', 'stack_plots.svg')) try: print('converting to pdf') subprocess.call('/Applications/Inkscape.app/Contents/Resources/bin/inkscape --export-pdf=/tmp/stack_plots.pdf /tmp/stack_plots.svg', shell=True) except: print('unable to run inkscape') finally: