'How to resize / rescale a SVG graphic in an iPython / Jupyter Notebook?
I've a large SVG (.svg graphic) object to display in a iPython / Jupyter Notebook. In fact, I've a large neural network model graphic created with Keras to display.
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
SVG(model_to_dot(model,show_shapes=True).create(prog='dot', format='svg'))
So, I want to resize / rescale / shrink the SVG graphic to fit in my Notebook page (particularly horizontally, since the page width is limited).
Solution 1:[1]
Another option is to use the "dpi" (dots per inch) property. A little hacky but this allowed me to shrink my SVG. Tensorflow: model_to_doc
from IPython.display import SVG
from keras.utils import model_to_dot
SVG(model_to_dot(model, show_shapes= True, show_layer_names=True, dpi=65).create(prog='dot', format='svg'))
Solution 2:[2]
A new improved solution particularly useful using spaCy, (tested with the version 2.2.4). In order to be able to scale the .svg without cropping, we must add a viewBox to the XML / HTML svg representation.
Before scaling:
import spacy
import re
from spacy import displacy
nlp_model = spacy.load("en_core_web_sm")
doc = nlp_model(u"To be or not to be, that is the question")
svg = displacy.render(doc, style='dep', page=True, jupyter=False)
def add_viewbox_svg(svg):
regex = r'class="displacy" width="([\d\.]*)" height="([\d\.]*)'
match_results = re.findall(regex,svg)
new_svg = svg.replace("<svg ","<svg viewBox='0 0 "+
match_results[0][0]+" "+
match_results[0][1]+
"' preserveAspectRatio='none' ")
return new_svg
new_svg = add_viewbox_svg(svg)
Then using style:
style = "<style>svg{width:100% !important;height:100% !important;</style>"
display(HTML(style))
display(HTML(new_svg))
After scaling:
Solution 3:[3]
This is what worked for me:
from IPython.display import SVG, display, HTML
import base64
_html_template='<img width="{}" src="data:image/svg+xml;base64,{}" >'
def svg_to_fixed_width_html_image(svg, width="100%"):
text = _html_template.format(width, base64.b64encode(svg))
return HTML(text)
svg_to_fixed_width_html_image(svg)
Solution 4:[4]
Above CSS-based workaround does not seem to work for me, as both width= and height= were directly set in attribute of generated SVG element.
As an additional workaround, here's what I got:
iv1_dot = model_to_dot(iv1_model, show_shapes=False, show_layer_names=False, rankdir='LR')
iv1_dot.set_size('48x8')
SVG(iv1_dot.create(prog=['dot'], format='svg'))
This allowed me to specify size of graphviz drawing in inch (48x8, in above case).
Solution 5:[5]
The answers above and below are really good but depends upon the system. They might or might not work for you always depending upon your browser plugins, Jupyter version, Colab environment, etc. Generally, SVG() converts the dot image to an SVG file but it is tricky to adjust the size of that by customizing the associating HTML. What I'd suggest is using this:
from keras.utils import plot_model
plot_model(model, to_file='model.png')
You can then use the snippet in the above answer by user48956 to adjust the size of the image generated. But most of the time, it scales on its own.
Further Reference: Here
Solution 6:[6]
The other solutions all had some issues for my use case. I thus propose this solution which manipulates the svg data directly using BeautifulSoup:
from IPython.display import SVG
from bs4 import BeautifulSoup
import re
def scale_svg(svg_object, scale=1.0):
soup = BeautifulSoup(svg_object.data, 'lxml')
svg_elt = soup.find("svg")
w = svg_elt.attrs["width"].rstrip("pt")
h = svg_elt.attrs["height"].rstrip("pt")
ws = float(w)*scale
hs = float(h)*scale
svg_elt.attrs["width"] = f"{ws}pt"
svg_elt.attrs["height"] = f"{hs}pt"
svg_elt.attrs["viewbox"] = f"0.00 0.00 {ws} {hs}"
g_elt = svg_elt.find("g")
tf = g_elt.attrs["transform"]
# non-greedy regex-search-and-replace
tf2 = re.sub(
"scale\(.*?\)",
f"scale({scale} {scale})",
tf
)
g_elt.attrs["transform"] = tf2
svg_object.data = str(svg_elt)
return svg_object
s1 = SVG("""
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="103.0pt" viewbox="0.00 0.00 170.0 103.0" width="170.0pt">
<g class="graph" id="graph0" transform="scale(1.0 1.0) rotate(0) translate(4 199)">
<title>G</title>
<polygon fill="#ffffff" points="-4,4 -4,-199 166,-199 166,4 -4,4" stroke="transparent"/>
<!-- node0000 -->
<g class="node" id="node1">
<title>node0000</title>
<ellipse cx="81" cy="-159" fill="none" rx="36" ry="36" stroke="#000000"/>
<text fill="#000000" font-family="Times,serif" font-size="10.00" text-anchor="middle" x="81" y="-156.5">ABCDEFGH</text>
</g>
</g>
</svg>
""")
scale_svg(s1, 3.2)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Kristina Milkovich |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | Taisuke Yamada |
| Solution 5 | Amitrajit Bose |
| Solution 6 | cknoll |



