#!/usr/bin/env python
# coding: utf-8
# # Siemens Star
#
# The [Siemens Star](https://en.wikipedia.org/wiki/Siemens_star) is a radial starburst pattern commonly used to adjust internal focus settings in camera lens and for measuring camera resolution. This notebook produces a Siemens Star test chart in the form in [Scalable Vector Graphics (svg)[(https://en.wikipedia.org/wiki/Scalable_Vector_Graphics) that can be rendered by most modern web browsers. The idea for this notebook was motivated by this [post](http://www.dpreview.com/forums/post/57422062) on a forum at [Digital Photography Review (DPReview)](http://www.dpreview.com/).
#
# ## References
#
# * [Digital Camera Resolution Measurement Using Sinusoidal Siemens Stars](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.470.2385&rep=rep1&type=pdf)
# * [Wikipedia: Siemens star](https://en.wikipedia.org/wiki/Siemens_star)
# * [Image Engineering: Resolution measurement with siemens stars](https://github.com/jckantor/Siemens-Star)
# * [A/D Photography: Resolution Test Chart – Siemens star](https://claclaclack.wordpress.com/2015/05/17/resolution/)
# * [Lens Rentals: Setting Up an Optical Testing Station](https://www.lensrentals.com/blog/2014/02/setting-up-an-optical-testing-station/)
# * [Imatest: Star Chart](http://www.imatest.com/docs/starchart/)
#
#
# ## Usage
#
# This is a [Jupyter notebook](http://jupyter.org/) containing Python functions. An executable version of this notebook is available from the [http://mybinder.org/](http://mybinder.org/) by clicking on the following button. There may be a longish pause as the notebook loads.
#
# [![Binder](http://mybinder.org/badge.svg)](http://mybinder.org/repo/jckantor/Siemens-Star)
#
# To use the notebook after it has been loaded in an executable environment:
#
# 1. First run the code in the following cell. Do this by clicking in the cell to highlight it, then entering 'shift-return' from the keyboard, or clicking on the run button in the toolbar menu (looks like >|), or the 'Cell>Run Cells' menu item.
# 2. Execute the second cell below to create the desired chart interactively. The controls adjust the colors and number of spokes displayed in the chart.
# ## Imports
# In[10]:
get_ipython().system('pip install svglib')
# ## Function Definitions
#
# The following cell defines functions that create SVG markup. Run this cell first!
# In[11]:
from math import pi, sin, cos, sqrt
# page width
page_width = 900
# xrite passport rgb color table
# https://xritephoto.com/ph_product_overview.aspx?ID=820&Action=support&SupportID=5159
rgb = [
[115, 82, 68], # 1. dark skin
[194,150,130], # 2. light skin
[ 98,122,157], # 3. blue sky
[ 87,108, 67], # 4. folliage
[133,128,177], # 5. blue flower
[103,189,170], # 6. bluish green
[214,126, 44], # 7. orange
[ 80, 91,166], # 8. purplish blue
[193, 90, 99], # 9. moderate red
[ 94, 60,108], # 10. purple
[157,188, 64], # 11. yellow green
[224,163, 46], # 12. orange yellow
[ 56, 61,150], # 13. blue
[ 70,148, 73], # 14. green
[175, 54, 60], # 15. red
[231,199, 31], # 16. yellow
[187, 86,149], # 17. magenta
[ 8,133,161], # 18. cyan
[243,243,242], # 19. white (0.05*)
[200,200,200], # 20. neutral 8 (0.23*)
[160,160,160], # 21. neutral 6.5 (0.44*)
[122,122,121], # 22. neutral 5 (0.70*)
[ 85, 85, 85], # 23. neutral 3.5 (1.05*)
[ 52, 52, 52], # 24. black (1.50*)
]
def star(xc, yc, radius, cycles=72, colors=['black', 'white']):
"""Return an svg string containing of polygons in the form of a star."""
phi = pi/cycles/len(colors)
xy = [xc, yc, xc - radius*sin(phi), yc + radius*cos(phi), xc + radius*sin(phi), yc + radius*cos(phi)]
fmt = '\n'.format(xc, yc)
return ''.join([fmt.format(colors[k], 360.0*(n + float(k)/len(colors))/cycles)
for n in range(0, int(cycles)) for k in range(0, len(colors))])
def lphcircles(xc, yc, radius, cycles, colors, bb_height):
lph = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000]
r = [bb_height*cycles*len(colors)/(2*pi*lph) for lph in lph]
fmt = '\n' +\
'{5:4.0f}'
return '\n'.join([fmt.format(xc, yc, r, xc+r*cos(13*pi/8), yc + r*sin(13*pi/8), lph)
for (lph,r) in zip(lph,r) if 10 < r < radius]) + '\n'
def colorchecker(bw, bh):
return ''.join(['1)), bh*(7+row)) +
' style="fill:rgb({0},{1},{2});stroke-width:2;stroke:black"/>\n'.format(*rgb[row + 6*col])
for col in range(0,4) for row in range (0,6)])
def SiemensStar(cycles=144, aspect=4/3, colors=['black','white'], colorcheck='True', cstars='True', lph='True'):
bb_width = page_width
bb_height = bb_width/aspect
r = bb_height*min(0.5, (sqrt(1+aspect**2))/4)
svg = ''
# ## Manually Create and Display the Siemens Star
#
# The following cell creates a simple resolution chart consisting of a central Siemens Star and additional elements. The central star consists of alternating radial spokes of color from a specified list `colors`. If omitted, the default is black and white. The list may contain two or more colors. The list of colors is repeated a number of times as determined by the parameter `cycles`.
#
# A list of svg commands is generated, stored in a file [star.svf](star.svg), and displayed as an inline graphic within the notebook. To download the resulting file, right click on the link and choose the `Save Link As ...` option.
# In[14]:
from IPython.display import SVG
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPDF, renderPM
svg = SiemensStar(cycles=144, colors = ['blue', 'yellow'])
with open('star.svg', 'w') as f:
f.write(svg)
chart = svg2rlg('star.svg')
renderPDF.drawToFile(chart, 'star.pdf')
renderPM.drawToFile(chart, 'star.png', fmt='PNG')
SVG(svg)
# ## Interactively Create and Display Siemens Star
#
# The following interactive cell creates a simple resolution chart consisting of a central Siemens Star and additional elements. Use the dropdown menus to set the colors of the radial spokes, and the cycles slider to set the number of spokes.
#
# A list of svg commands is generated and stored in a file [star.html](star.html). To download the resulting file, right click on the link and choose the `Save Link As ...` option.
# In[15]:
from IPython.display import SVG
from ipywidgets import interact, Dropdown, IntSlider, Checkbox
from IPython.display import display
svg_colors = ['black', 'white', 'red', 'blue', 'green', 'cyan', 'yellow', 'magenta']
def makestar(cycles, aspect, color1, color2, colorcheck, cstars, clines):
svg = SiemensStar(cycles, aspect=eval(aspect), colors=[color1,color2], colorcheck=colorcheck, cstars=cstars, lph=clines)
display(SVG(svg))
with open('star.html','w') as f:
f.write(svg)
interact(makestar,
cycles = IntSlider(min=12, max=600, value = 144, step=2, description='Color Cycles'), \
aspect = Dropdown(options=['16/9', '3/2', '4/3', '1/1'], value='4/3', description='Aspect Ratio'), \
color1 = Dropdown(options=svg_colors, value='black', description='Color A'), \
color2 = Dropdown(options=svg_colors, value='white', description='Color B'), \
colorcheck = Checkbox(value=True, description='Color Checker'), \
cstars = Checkbox(value=True, description='Corner Stars'), \
clines = Checkbox(value=True, description='LPH Lines'))
# In[ ]: