A PPP Rendering Script

This post is a partially obsolete now because I added the ability to save SVG and PNG images directly into the PPP app, but the method here may still be usuful for retrieving cleaner resulting output SVGs, in some cases.


Here’s a minimal Python script that saves Pretty Parametric Plots images to your local hard drive as either a rasterized PNG file or a scalable SVG file. Before running this, the user needs to install Inkscape, Firefox, the Python bindings for Selenium, and the Selenium web driver for Firefox. The easiest way to install the latter two is by using pip:

$ pip install selenium

The minimal script (ppp.py) is here:

# ppp.py
from selenium import webdriver
import subprocess
import os


def start_browser(url=""):
    global web_browser

    web_browser = webdriver.Firefox()

    web_browser.maximize_window()

    if url is "":
        web_browser.get("https://www.nrstickley.phd/ppp")
    else:
        web_browser.get(url)


def save_as_svg(filename):

    path = web_browser.find_element_by_tag_name("path")

    svg_path = path.get_attribute("d")

    svg = web_browser.find_element_by_id("display_image")

    stops = web_browser.find_elements_by_tag_name("stop")

    stop_tags = ['<stop stop-color="' + str(x.get_attribute("stop-color"))
                 + '" offset="' + str(x.get_attribute("offset")) + '"/>'
                 for x in stops]

    outfile = open(filename + ".svg", "w")

    values = web_browser.find_elements_by_tag_name("input")

    comments = [v.get_attribute("value") for v in values]

    comment = ['<!--', "\n".join(comments) ,'-->']

    defs = ['    <defs>',
            '        <linearGradient y2="50%" x2="100%" y1="0%" x1="0%" id="Gradient">',
            '       ' + stop_tags[0],
            '       ' + stop_tags[1],
            '        </linearGradient>',
            '     </defs>']

    header = ['<?xml version="1.0" standalone="no"?>',
              '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"',
              '"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">',
              "\n".join(comment),
              '<svg',
              '    width="' + str(svg.get_attribute("width")) + '"',
              '    height="' + str(svg.get_attribute("height")) + '"',
              '    xmlns="http://www.w3.org/2000/svg" version="1.1">',
              '    <title>' + filename + '</title>',
              "\n".join(defs),
              '<path d="']

    footer = ['"\n',
              'style=\'fill:none;',
              str(svg.get_attribute("style")),
              'stroke-linecap:round;',
              'stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;',
              'stroke-dasharray:none;stroke-dashoffset:0\'/>\n',
              '</svg>']

    outfile.write("\n".join(header) + svg_path + "".join(footer))

    outfile.close()


def save_as_png(filename, res=150):
    temp_file = filename + "__temp"
    save_as_svg(temp_file)
    subprocess.call(["inkscape",
                    "-D",
                    "-d" + str(res),
                    "-e=" + filename + ".png",
                    temp_file + ".svg"])
    os.remove(temp_file + ".svg")

Example:

import ppp

ppp.start_browser()

# a Firefox window opens to the page https://www.nrstickley.phd/ppp

# design your plot. When you are ready to save it, go back to 
# the Python interpreter...

# save a 400 dpi resolution image of the plot as example.png
ppp.save_as_png("example", 400) # (base filename, resolution in DPI)

# save as an SVG image named example.svg:
ppp.save_as_svg("example")

# close Firefox when you're finished

Example 2:

import ppp

# already know what plot you want to save? put it here:
url="https://www.nrstickley.phd/ppp/?A=1.15&B=1.107&C=-0.01&D=0.9&E=4.45&F=1.3&G=-0.004&H=0&ti=0&tf=40&A1=1&B1=1&C1=1&D1=1&E1=1&F1=1&G1=1&H1=1&lineWidth=0.8&colorMode=1&plotColor=c30038&bgColor=000000&startColor=c0ce85&stopColor=a71919"

ppp.start_browser(url) # a Firefox window opens to the url

# save a 600 dpi resolution image of the plot as example2.png
ppp.save_as_png("example2", 600) # (base filename, resolution in DPI)

# OR

# save as an SVG image named example2.svg:
ppp.save_as_svg("example2")

# close Firefox when you're finished

Note that the default DPI is 150. Also, note that background colors are not saved (the background is transparent), so some post-processing with a photo editor or graphics software is typically required.