Source code for pymor.analyticalproblems.text
# This file is part of the pyMOR project (http://www.pymor.org).
# Copyright 2013-2020 pyMOR developers and contributors. All rights reserved.
# License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
from pymor.analyticalproblems.domaindescriptions import RectDomain
from pymor.analyticalproblems.elliptic import StationaryProblem
from pymor.analyticalproblems.functions import ConstantFunction, LincombFunction, BitmapFunction
from pymor.core.defaults import defaults
from pymor.parameters.functionals import ProjectionParameterFunctional
[docs]@defaults('font_name')
def text_problem(text='pyMOR', font_name=None):
import numpy as np
from PIL import Image, ImageDraw, ImageFont
from tempfile import NamedTemporaryFile
font_list = [font_name] if font_name else ['DejaVuSansMono.ttf', 'VeraMono.ttf', 'UbuntuMono-R.ttf', 'Arial.ttf']
font = None
for filename in font_list:
try:
font = ImageFont.truetype(filename, 64) # load some font from file of given size
except (OSError, IOError):
pass
if font is None:
raise ValueError('Could not load TrueType font')
size = font.getsize(text) # compute width and height of rendered text
size = (size[0] + 20, size[1] + 20) # add a border of 10 pixels around the text
def make_bitmap_function(char_num): # we need to genereate a BitmapFunction for each character
img = Image.new('L', size) # create new Image object of given dimensions
d = ImageDraw.Draw(img) # create ImageDraw object for the given Image
# in order to position the character correctly, we first draw all characters from the first
# up to the wanted character
d.text((10, 10), text[:char_num + 1], font=font, fill=255)
# next we erase all previous character by drawing a black rectangle
if char_num > 0:
d.rectangle(((0, 0), (font.getsize(text[:char_num])[0] + 10, size[1])), fill=0, outline=0)
# open a new temporary file
with NamedTemporaryFile(suffix='.png') as f: # after leaving this 'with' block, the temporary
# file is automatically deleted
img.save(f, format='png')
return BitmapFunction(f.name, bounding_box=[(0, 0), size], range=[0., 1.])
# create BitmapFunctions for each character
dfs = [make_bitmap_function(n) for n in range(len(text))]
# create an indicator function for the background
background = ConstantFunction(1., 2) - LincombFunction(dfs, np.ones(len(dfs)))
# form the linear combination
dfs = [background] + dfs
coefficients = [1] + [ProjectionParameterFunctional('diffusion', len(text), i) for i in range(len(text))]
diffusion = LincombFunction(dfs, coefficients)
return StationaryProblem(
domain=RectDomain(dfs[1].bounding_box, bottom='neumann'),
neumann_data=ConstantFunction(-1., 2),
diffusion=diffusion,
parameter_ranges=(0.1, 1.)
)