Creating No Mo Grams With Py No Mo
Creating No Mo Grams With Py No Mo
Creating No Mo Grams With Py No Mo
It
is written by Leif Roschier, and it provides a solution to one of the most vexing of problems in
nomography: actually drawing the nomogram once the mathematical layout is derived. The output
is in vector form in a PDF or EPS file, so it can be enlarged for printing and still retain its sharpness. If
additional artwork is desired, the vector file can be edited in vector form in, say, Adobe Illustrator, Microsoft
Visio or LaTeX. PyNomo directly supports nine basic types of nomograms based simply on the format of the
equation, so for these types there is no need to convert the equation to the standard nomographic determinant
or use geometric relations. But it also supports more complicated equations that have been cast into general
determinant form, so it can produce output for any equation that can be plotted as a nomogram. In fact,
PyNomo is an excellent tool for experimenting with parameters to get the best nomogram for the problem at
hand. This essay discusses the use of PyNomo for creating a variety of sophisticated types of nomograms.1
Joe Marasco and Scott Finegan for reviewing drafts of this essay and providing suggestions that
have considerably improved it. If you have any questions or suggestions, please feel free to email me at doerfpub@myreckonings.com
required this process to be repeated. The Isopleth feature draws lines directly between specified
values on the scales, calculating the points on intermediate scales as needed. As before, various styles
and colors of lines are supported.
3. Text format of scale values The previous version of PyNomo assigned the value $%3.2f$ as the
default text_format for label values (as in 'text_format':r"$%3.2f$",), which displayed up to 3
digits to the left of the decimal point, and in all cases 2 digits to the right of the decimal point even if
the last digit were 0. The trailing zeros on the text labels are now eliminated by changing the default
text format to $%4.4g$. The g print format produces a decimal number of up to 4 digits left of the
decimal point and 4 to the right only as needed, unless the number is 0.0001 or less in which case it is
printed in exponential form (e.g., 1e-4). This provides a cleaner nomogram, as unnecessary digits are
not shown. As before, this default can be changed by specifying a different text format.
A nomogram is a diagram that provides a graphical way of calculating the result of a mathematical
formula. Sometimes called an alignment chart, a nomogram consists of a set of numbered scales, usually one
for each variable in the formula, arranged so that a straightedge can be placed across known values to find the
unknown value that solves the formula. Since an equation in two variables is usually represented by a graph,
most nomograms represent formulas that involve three or more variables. These graphical calculators were
invented in 1880 by Philbert Maurice dOcagne and used extensively for many years to provide engineers
with fast graphical calculations of complicated formulas to a practical precision. Electronic calculators and
computers have made nomograms much less common today, but when a fast, handy calculator of a particular
formula is needed they can be very useful. The cost to produce one is a sheet of paper, and they are fun to
design, easy to use, and can be beautiful designs that engage people.2
The simplest nomogram, one we often encounter, is a single scale with numbers on both sides of it.
This is called a conversion scale, and some people would hesitate to call it a nomogram at all. It provides
conversion between two functions such as units of measurement. The most frequently seen example is
probably a Fahrenheit to Celsius scale. We will inspect a single-scale nomogram as our first example.
The most common type of multi-scale nomogram consists of three parallel straight scales. It is used to
solve an equation in which functions of three variables are added. The simplest such formula is u1 +u2 +u3 =
0 for the three variables u1 , u2 and u3 . An example of this type of nomogram from the PyNomo website3 is
shown below, annotated with terms used to describe the parts of a nomogram. A line (called an index line
or isopleth) or a straightedge will cross the three scales at values that solve this equation, so if you know the
values of any two of the variables you can find the third very easily.
There are many (out-of-print) books on the mathematics of nomography, but PyNomo allows us to design
nearly all nomograms with very little mathematics background. A knowledge of algebra is necessary in order
to arrange the formula into a standard type of equation that PyNomo supports. Then a PyNomo script for
creating the nomogram can be copied from a standard example of that type and edited to match the terms in
the formula. The script is run and a PDF file is created with the nomogram laid out for printing. Copying and
modifying a standard example is easy and fast, and I do it all the time. Once you start making nomograms you
may want to customize how they lookthe spacing of tick marks on the scales, the scale titles, the location
of the nomogram title, and so forth. You may want to draw a sample isopleth and add color to the scales and
their labels. PyNomo offers many such features, and this paper tries to cover them all, but dont be put off by
these extra details sprinkled in the examples here. They may make the scripts appear more complicated, but
they are totally optional and can be ignored until the day you decide you really would like that one scale to
be red. Thats the point where you look in the index at the end of this essay for scale parameters that involve
color.
A knowledge of logarithms is sometimes helpful to convert your formula to a standard type recognized
by PyNomo. For example, suppose you have a typical formula in which three variables are multiplied or
divided, and maybe one or two are raised to a power. You can convert it to a formula of simple additions by
taking the logarithms of both sides of the equation. You only need to know a few properties of logarithms:
log(a b) = log a + log b
log(a/b) = log a log b
log(ab ) = b log a
So a formula such as V = r2 h for the volume of a cylinder can be expressed as an equation with simple
sums as
logV = log(r2 h)
logV = log(r2 ) + log h
logV = log() + log(r2 ) + log h
logV = log() + 2 log(r) + log h
logV log() 2 log(r) log h = 0
So now we have an equation of a sum of
terms, resulting in a parallel three-scale Type
1 nomogram as in our previous example. We
replace u1 , u2 and u3 in our script with the
functions logV , { log() 2 log(r)} and
log h, and this creates the scales for V , r and
h that form the nomogram. The output of
the PyNomo script for a Type 1 nomogram
with these variable functions looks like the
one to the right. The scales have logarithmic
spacing now, where the powers of 10 are the
major tick marks and the intermediate values
are spaced unevenly. The volume is easily
found from this nomogram for a given radius
and height, and the radius corresponding to a
given volume and height is found just as easily. Try itit works!
V = r2 h
0.01
V
1000
400
300
0.02
200
0.03
100
0.04
0.05
0.06
0.07
0.08
0.1
20
10
0.2
0.3
0.4
4
2
0.5
0.6
0.7
0.8
0.4
0.2
0.2
0.1
3
0.8
0.6
0.4
0.3
0.1
0.04
0.02
0.01
8
6
4
3
10
4 http://pynomo.org/wiki/index.php?title=Installation
80
60
40
30
5
If a formula cannot be manipulated alge6
7
braically into one of the standard equations
8
10
supported by PyNomo, it can be created using the Type 9 Determinant form supported
by PyNomo. Sufficient information on determinants is provided in the Type 9 section of this essay to use this
form without any prior knowledge of determinants.
800
600
0.08
0.06
0.04
0.03
0.02
0.01
It is worth the time to install, as it produces beautiful nomograms without all the effort required to draw them
by other means.
This article is based on Release 0.2.2 of PyNomo, the latest release as of this writing. There are two ways
to install any files updated since the last release. First, you can go to the PyNomo development webpage5 .
Then click on the revision numbers in low-to-high order. For each filename listed for a revision, click on the
filename, click on the download link along the top, and save the file to the folder containing the PyNomo files,
choosing to replace the file when prompted. The PyNomo files are located in the Lib\site-packages\pynomo
subfolder under the folder where you installed Python. Alternatively, on a Linux/OS X operating system or
on a Windows system with cygwin installed, you can fetch all the revisions with the svn command:
svn co https://pynomo.svn.sourceforge.net/svnroot/pynomo pynomo
5 http://sourceforge.net/projects/pynomo/develop
If you are not familiar with PyNomo, you really should see the Basics6 and Examples7 links off the
main PyNomo webpage. You will be amazed at what this program can do. If you go to the Software
Documentation page8 you will find 10 different general types of nomograms it can create, including the most
common one of 3 parallel scales for addition or multiplication, N or Z for division, proportions, sum of
reciprocals, and so forth. It can also handle general determinant forms, even with more than 3 variables, so
it can really handle any type of nomogram. The types of nomograms supported by PyNomo and the sections
that these are covered in here are shown in the table below. Section 10 deals exclusively with adding color
to your nomogram. This paper concludes with Section 18 discussing some ways you can edit your PyNomo
nomogram with external image tools if you wish, followed by an index of terms and parameters in this essay.
Type
Form of Equation
Form of Nomogram
Covered In
Type 1
3 Parallel Scales
Section 6
Type 2
N or Z
Section 7
Type 3
Section 8
Section 11
Proportion
Section 13
Type 4
f1 (u1 )
f2 (u2 )
f3 (u3 )
f4 (u4 )
Type 5
f1 (v) = f2 (x, u)
Contour
Section 17
Type 6
u=u
Ladder
Section 12
Reciprocal/Angle
Section 14
Type 7
1
f3 (u3 )
1
f1 (u1 )
1
f2 (u2 )
Type 8
y = f (u)
Single Scale
Sections 4 & 9
Type 9
Determinant
General Nomogram
Section 16
Type 10
Section 15
6 http://www.pynomo.org/wiki/index.php/Basics
7 http://www.pynomo.org/wiki/index.php/Examples
8 http://pynomo.org/wiki/index.php?title=Software_documentation
Here we will inspect a simple PyNomo script for overall structure without delving into the details. More
complicated scripts are just variations on this basic structure of scales and their parameters.
A script specifies the type of nomogram and the functions, titles and tick levels of each scale. Lets look
at a script to create a simple conversion scale between miles and kilometers. This nomogram consists of a
pair of scales that are assigned tags to cause them to overlay each other. A single scale is a Type 8 nomogram
in PyNomo, so we will create two Type 8 nomogram blocks with the same tag name.
Its usually best to copy an existing script for a nomogram of the same type into a new text file and edit it
for our needs. Each type of nomogram has an example on the PyNomo website, and there are also a number
of examples presented in this paper. Each scale has its own set of parameters (function, title, etc.), and each
set of scales that make up a nomogram type have a set of block parameters (the scale names, type and size).
Compound nomograms will have multiple blocks. Finally, there is a set of main parameters (the block names,
title, paper size and transformations to apply).
Below is the PyNomo script and output PDF graphic for the conversion scale. The top line is a comment
line as it starts with a # sign. The next line and the last line are common to all scripts. A set of scale
parameters is provided first for the Miles scale. This includes a tag name to share with the Kilometers scale
so the two scale axes line up on top of one other. Then the minimum and maximum values are provided, the
function is provided for the scale in terms of u, the title is given and shifted over to that side of the scale, the
levels of tick marks to draw and the level of tick labels to display are indicated, and finally the side of the
scale axis to draw the tick marks and labels is given. A set of block parameters identifies the PyNomo type
for the scale and the name of the set of scale parameters.
This is repeated for the Kilometers scale, but the ranges are obviously different by a factor of 1.609 and
its function u is multiplied by 1.609. A new parameter provides the alignment function so the scales will
overlay, which is the inverse or u/1.609. These ticks are placed on the right side of the scale axis.
The main parameters consist of the output filename, the paper height and width, and transformations to
apply, here simply to scale the nomogram to the specified paper size.
If you want to make a conversion scale, just copy this script, change the titles, range values and functions,
and run the script as described in the next section. Copying the script directly out of the PDF form of this
essay will cause the indents to disappear and the script to fail, but the script and PDF output are available
online for download.9
9 http://www.myreckonings.com/pynomo11/Type8-Sample.py
and http://www.myreckonings.com/pynomo11/Type8-Sample.pdf
'u_max':1.609*100.0,
'function':lambda u:1.609*u,
'align_func':lambda u:u/1.609,
'title':r'Km',
'title_x_shift':0.5,
'tick_levels':3,
'tick_text_levels':2,
'tick_side':'right',
}
block_2_params={
'block_type':'type_8',
'f_params':Kilometers_params,
}
main_params={
'filename':'Type8-Sample.pdf',
'paper_height':20.0,
'paper_width':0.5,
'block_params':[block_1_params,block_2_params],
'transformations':[('scale paper',)],
}
block_1_params={
'block_type':'type_8',
'f_params':Miles_params,
}
Kilometers_params={
'tag':'myscale',
'u_min':0.0,
Nomographer(main_params)
Mi
Km
100
160
155
95
150
90
145
140
85
135
130
80
125
75
120
115
70
110
105
65
100
60
95
90
55
85
50
80
75
45
70
65
40
60
35
55
50
30
45
40
25
35
20
30
25
15
20
10
15
10
5
5
PyNomo scripts are written in text files saved with the suffix .py since they are interpreted by Python.
Any text editor such as WordPad can be used as long as you save the output as a plain text file.
You can double-click on the .py file to build and display the output. A black command window appears
for a little bit, and about 20 seconds later the PDF (or EPS) output file is written in your folder, and you
can double-click on it to open it in your default PDF viewer (say, Adobe Acrobat). This is a vector-drawn
nomogram that can be printed out or converted to another image format and inserted into a document. Note
that you have to exit a previously-built PDF file of the same name before you build another or it will fail in
overwriting the file. If the output file fails to materialize, there is an error in the script.
In order to see any error messages, its much
better to open a Command Prompt window in Windows or a Terminal application in Linux or OS X.
For Windows, you can launch a Command Prompt
window from the Start menu on the taskbar (Start
>Programs>Accessories>Command Prompt). Then
navigate to the folder with your PyNomo file (say,
cd C:\PyNomoScripts). Then enter python <filename>.py and a carriage return. Note that you enter
python, not pynomo. Now as the build is occurring
any error message will appear in the Command Prompt window. You should build the output file often as
you write a PyNomo script in order to isolate errors as soon as they occur. Here is a typical Command
Prompt window showing the navigation to the folder containing scripts (using the cd command to change the
directory). In this case a syntax error is noted in the script because u should be followed by a number that
u is multiplied by.
As you use PyNomo more, you may be interested in using a text editor designed for writing and building
Python files, such as EasyEclipse for Python.10 I have only used WordPad and a Command Prompt window
so far, though.
I dont know Python, but there are just a few things to remember about Python scripts. First, we are
mostly filling in a dictionary of key:value parameters, where the key is a string in single quotes and the
value can be a string in single quotes, a True or False, or a number. The parameters do not need to be in
a particular order and most have default values. Also, you need to indent the list of parameters after the
initial line containing the parameter set name, as Python uses indentation to determine the scope of a code
construct. The amount of indentation is not important. Dont mix tabs and spacesI would suggest using
spaces only. Finally, a simple scale function is usually expressed as a local lambda function, but you will
see that when a function is long its cleaner to define it at the top of the script using the def command and
give the function name in the scale parameters.
If youre like me, these are by far the most common errors you will encounter in a build:
The output file cannot be opened, because I didnt close the PDF output file from the previous run.
A syntax error where the offending line shown appears just fine, because the problem is really that I
forgot to add a comma at the end of the previous line.
10 http://www.easyeclipse.org/site/distributions/python.html
A divide-by-zero error, because my scale range included a value that produces zero in a denominator
in the scale function. This can sometimes occur due to a similar internal problem resolving the curves
in a Type 5 Contour nomogram.
A general hang-up where the program does not stop working and no error messages are output. You
can end the program with a Ctrl-c key combination. Ive found that this usually means Ive made some
sort of mistake in entering my scale function. It also occurred when I had a singularity in a particular
Type 9 Determinant nomogram (see the Type 9 section).
An undefined scale or block name, because I had copied and pasted a parameter section from another
example and I forgot to change the name to the one called for in the block or main parameter section.
One solution to the divide-by-zero error is shown in an online PyNomo example11 , where the variable u
in the scale function can be replaced by a function of u, say limit_u(u), that makes sure the divide-by-zero
situation does not occur. This function can be defined at the beginning of the script as
def limit_u(u):
u1=u
if not u1>0.0:
u1=0.0001
return u1
\Huge
If a title string spans more than one line of your script, you have to add a backslash \ at the end of the line
to indicate that the string continues on the next line (the \ produces a space, so place it immediately at the
end without a space). To get a carriage return in a title you have three options:
1. Size the title box to force a return at the right place
2. Insert the \par command (does not work in the primary scale title title_str)
3. Use separate title texts placed to simulate a carriage return
If you precede a title with \bf then any title text will be printed in bold. Preceding it with \it will print it in
italic, but both of these revert to normalsize font. A copyright symbol is generated by \copyright.
11 http://www.pynomo.org/wiki/index.php/Photography_exposure
10
The following symbols in title text are special characters and must be preceded by a backslash, as in \$
$
&
TeX takes care of spaces between letters words, so even if you leave a few spaces between words in a title
or between symbols in a math expression you will find that no extra space appears in the output nomogram.
To add space you can use one of these commands that add 1/12em, 1/2em, 1em and 2em, respectively:
\thinspace
\enspace
\quad
\qquad
11
12
The vast majority of nomograms are of Type 1, that is, composed of three parallel scales. The form of
the equation for this nomogram is f1 (u1 ) + f2 (u2 ) + f3 (u3 ) = 0, so it can be used for addition of individual
functions of three variables. But as we described in Section 1, it can also be used to multiply functions when
they are expressed as logarithms. As our example, we will use this type of nomogram to graph the equation
(S + 0.64)0.58 (0.74V ) = P
We also assume that the engineering ranges we are interested in are 1.0 < S < 3.5 and 1.0 < V < 2.0. From
the equation above we calculate the minimum P as (1.0 + 0.64)0.58 (0.74 1.0) = 0.986 and the maximum P
as (3.5 + 0.64)0.58 (0.74 2.0) = 3.374. Discussions of plotting this same nomogram by geometrical means
and by the use of determinants have been detailed elsewhere.14 15 Now we will see how it can be drawn
using PyNomo.
Taking the logarithm of both sides of the equation under consideration and re-arranging the terms, we
can express it as a simple sum of functions of the variables.
0.58 log(S + 0.64) + log 0.74V = log P
0.58 log(S + 0.64) + log 0.74 + logV = log P
0.58 log(S + 0.64) + logV log P + log 0.74 = 0
From the general form above, you can see that this is a Type 1 nomogram where
f1 (S) = 0.58 log(S + 0.64)
f2 (V ) = logV
f3 (P) = log P + log 0.74
We could have included the log 0.74 term in f1 (S) or f2 (V ) instead of f3 (P) if we had wished. The Type
1 link on the Software Documentation page of the PyNomo site16 shows an example script for this type of
nomogram for the equation u1 + u2 + u3 = 0. This is the case f1 (u1 ) = u1 , f2 (u2 ) = u2 and f3 (u3 ) = u3 , so
its a simple matter to modify this example for what we need. We find that if we plot the nomogram scales
in the left-to-right order SVP, the V-scale is quite small even after the polygon transformation, so we plot the
scales in the order SPV.
The PyNomo script and output PDF graphic are shown on page 16. The PyNomo script and the PDF
output are available online for download.17
Lets look over the PyNomo script. First, a set of parameters for each of the three scales is defined. There
are quite a number of parameters available, as shown on Software Documentation page for this type, but the
ones we mention here are
14
http://myreckonings.com/wordpress/2008/01/09/the-art-of-nomography-i-geometric-design/
15 http://myreckonings.com/wordpress/2008/01/09/the-art-of-nomography-ii-designing-with-determinants/
16 http://www.pynomo.org/wiki/index.php/Type_1
17 http://www.myreckonings.com/pynomo11/Type1-Example1.py
and http://www.myreckonings.com/pynomo11/Type1-Example1.pdf
13
u_min and u_max: the minimum and maximum values for the scale
function: the function of the variable for the scale
title: the title to place above the scale (remember to add the r between the colon and the string)
tick_levels: the level to which the tick marks are printed
tick_text_levels: the level to which the tick labels are printed
tick_side: the side of the scale to print the tick marks and labels (right side by default, but I like to
place them on the side with the most space available)
text_format: the number of digits to the left and right of the decimal point in the tick labels (r"$%4.4g$"
is the default, displaying up to 4 digits left of the decimal point and 4 to the right only as needed, unless
the number is 0.0001 or less in which case it is printed in exponential form (e.g., 1e-4)
There are a few other options for scale titles that are not used here but will be seen later in our Type 4
example:
title_draw_center (True or False): locate the title at the center of the scale point of the scale
title_distance_center: distance of the title from the scale center (0.5cm by default)
title_opposite_tick (True or False): place the centered title on the opposite side from the tick marks
These sets of scale parameters are followed by a set of parameters for the whole block of scales. The
block parameters include
block_type: the PyNomo Type of the block as defined in the previous section
height and width: the height and width of the block, the overall size of which will be changed if the
scale paper transformation is chosen in the main parameters (this is a rough value, as tick marks and
texts may extend this)
f#_params: the previously defined scales to include in the block, with # being nothing or a number for
each scale included, depending on the Type of the nomogram
mirror_x: if True, flip the scales of the finished block left-to-right to change their order (False by
default)
mirror_y: if True, flip the scales of the finished block top-to-bottom to change the direction that the
scales increase or decrease (False by default)
In this simple nomogram there is only one block, but a compound nomogram can contain additional blocks
as we will see later.
We can also specify a proportional spacing between the scales in the Type 1 block parameters if we dont
use the scaling transformation, by using the proportion parameter with a default of 1.0, as in 'proportion':1.0.
A set of overall main parameters for the nomogram appears at the end. These parameters include
filename: the output filename with a .pdf or .eps suffix
paper_height and paper_width: the paper size to scale the nomogram to if scaling is specified (this is
a rough value, as tick marks and texts may extend this)
14
15
'title':r'$V$',
'tick_levels':3,
'tick_text_levels':1,
}
block_1_params={
'block_type':'type_1',
'width':10.0,
'height':10.0,
'f1_params':S_params,
'f2_params':P_params,
'f3_params':V_params,
}
P_params={
'u_min':1.0,
'u_max':3.35,
'function':lambda u:-log10(u)+log10(0.74),
'title':r'$P$',
'tick_levels':3,
'tick_text_levels':1,
'tick_side':'left',
}
main_params={
'filename':'Type1-Example1.pdf',
'paper_height':10.0,
'paper_width':10.0,
'block_params':[block_1_params],
'transformations':[('rotate',0.01),('scale paper',),
('polygon',)],
'title_x':5.0,
'title_y':-1.0,
'title_box_width': 10.0,
'title_str':r'$(S+0.64)^{0.58}(0.74V) = P$'
}
Nomographer(main_params)
V_params={
'u_min':1.0,
'u_max':2.0,
'function':lambda u:log10(u),
S
3.5
3.4
3.3
3.2
3.1
3
2.9
2.8
2.7
2.6
2.5
2.4
2.3
2.2
2.1
2
1.9
1.8
1.7
1.6
P
3.3
3.2
3.1
3
2.9
2.8
2.7
2.6
2.5
2.4
2.3
2.2
2.1
2
1.9
1.8
1.7
1.8
1.7
1.6
1.5
1.4
1.3
1.5
1.4
1.4
1.3
1.2
1.2
1.1
1.2
1.1
1
2
1.9
1.6
1.5
1.3
1.1
1
(S + 0.64)0.58 (0.74V ) = P
16
17
The isopleth_params parameter is optionally included in the main parameters and applies the following
characteristics to each isopleth calculated in order in the blocks listed in the main parameters. For example,
if a compound nomogram of several blocks had one isopleth calculated through all the blocks, the first
isopleth_params parameter would apply to this entire set. However, if another set were begun and calculated
(with a different character string to differentiate them), the second isopleth_params parameter would apply
to this second set.
linestyle: the style of the isopleth, consisting of solid, dashed, dotted or dashdotted as illustrated in the
figure below, with a default of dashed, e.g., 'linestyle':'dashed',
linewidth: the style of the isopleth, consisting of the values illustrated in the figure below), with a
default of thick, e.g., 'linewidth':'THick',
transparency: the transparency of the isopleth, consisting of a value between 0.0 and 1.0, with a default
of 0.0, e.g., 'transparency':0.4,
circle_size: the radius in cm of circles on the isopleth where it intersects the scales, with 0.0 producing
no circles and a default of 0.05, e.g., 'circle\_size':0.2,
color: the color of the isopleth as listed on page 37, with a default of black, e.g., 'color':'OrangeRed',
The set of characteristics for each isopleth is listed in isopleth_params within a set of braces, and the
sets are listed in order within square brackets, as shown in the next script. Only isopleth parameters that are
different from the default values need to be listed. Also, there is no reason to repeat the isopleth parameters
if they are unchanged between isopleths, as the previous values are maintained. The linewidth and linestyle
names are provided in the figure below.18 The example script on the next page shows values for all the
isopleth parameters to demonstrate their use.
This PyNomo script along with its PDF output are available online for download.19
18 From
19 http://www.myreckonings.com/pynomo11/Type1-Isopleth.py
18
block_1_params={
'block_type':'type_1',
'width':10.0,
'height':10.0,
'f1_params':S_params,
'f2_params':P_params,
'f3_params':V_params,
'isopleth_values':[[3.0,'x',1.19]],
}
main_params={
'filename':'Type1-Isopleth.pdf',
'paper_height':20.0,
'paper_width':20.0,
'block_params':[block_1_params],
'transformations':[('rotate',0.01),('scale paper',),
('polygon',)],
'title_x':11.0,
'title_y':-1.0,
'title_box_width': 10.0,
'title_str':r'\Large $(S+0.64)^{0.58}(0.74V) = P$',
'isopleth_params':[
{'color':'black',
'linewidth':'thick',
'linestyle':'dashed',
'circle_size':0.10,
'transparency':0.0,
},
],
}
P_params={
'u_min':1.0,
'u_max':3.35,
'function':lambda u:-log10(u)+log10(0.74),
'title':r'\Large $P$',
'tick_levels':3,
'tick_text_levels':1,
'tick_side':'left',
}
V_params={
'u_min':1.0,
'u_max':2.0,
'function':lambda u:log10(u),
'title':r'\Large $V$',
'tick_levels':3,
'tick_text_levels':1,
}
3.5
3.4
3.3
3.2
3.1
3
2.9
2.8
2.7
2.6
2.5
2.4
2.3
Nomographer(main_params)
3.3
3.2
3.1
1.9
3
2.9
2.8
1.8
2.7
2.6
2.5
1.7
2.4
2.3
1.6
2.2
2.1
2.2
1.5
2.1
1.9
2
1.8
1.9
1.8
1.7
1.4
1.7
1.6
1.6
1.5
1.5
1.4
1.3
1.2
1.4
1.3
1.3
1.2
1.1
1.2
1.1
1.1
(S + 0.64)0.58 (0.74V ) = P
19
Nomograms categorized as Type 2 by PyNomo are also quite common. The form of this nomogram is
f1 (u1 ) = f2 (u2 ) f3 (u3 ), although it is often expressed as a Division nomogram as in f3 (u3 ) = f1 (u1 )/ f2 (u2 ).
It is called an N or Z nomogram because of its shape. We can use the same equation here as we used in the
Type 1 nomogram for multiplication:
(S + 0.64)0.58 (0.74V ) = P
(1)
Again we assume that the engineering ranges we are interested in are 1.0 < S < 3.5 and 1.0 < V < 2.0 and
from the equation calculate the range of P as 0.986 < P < 3.374.
From the general form above, you can see that this can be drawn as a Type 2 nomogram if
f1 (P) = P
f2 (V ) = 0.74V
f3 (S) = (S + 0.64)0.58
The Type 2 link on the Software Documentation page of the PyNomo site20 shows an example script
for this type of nomogram for the equation u1 = u2 u3 . This is the case f1 (u1 ) = u1 , f2 (u2 ) = u2 and
f3 (u3 ) = u3 , so again its a simple matter to modify this example for what we need. To express the 0.58
as a power in f3 we can write the expression as (u + 0.64)**0.58 or we can use the Python math function
pow(u + 0.64,0.58).
The PyNomo script and output PDF graphic are shown on the next page. Originally I had f2 = (S +
0.64)0.58 and f3 = 0.74V , but the S scale was very short as the diagonal so I switched f2 and f3 . Trying
variations to see which works best can be done very quickly with this software. Here the nomogram appears
the same with and without the polygon transformation, since the outer scales are scaled to the paper size
anyway. For this equation it appears to me that the earlier Type 1 version will provide greater practical
accuracy for the user. The PyNomo script and output PDF graphic are available online for download.21
20 http://www.pynomo.org/wiki/index.php/Type_2
21 http://www.myreckonings.com/pynomo11/Type2-Example.py
and http://www.myreckonings.com/pynomo11/Type2-Example.pdf
20
'tick_levels':3,
'tick_text_levels':1,
'tick_side':'left',
}
block_1_params={
'block_type':'type_2',
'width':10.0,
'height':10.0,
'f1_params':P_params,
'f2_params':V_params,
'f3_params':S_params,
}
V_params={
'u_min':1.0,
'u_max':2.0,
'function':lambda u:0.74*u,
'title':r'$V$',
'tick_levels':3,
'tick_text_levels':1,
}
main_params={
'filename':'Type2-Example.pdf',
'paper_height':10.0,
'paper_width':10.0,
'block_params':[block_1_params],
'transformations':[('rotate',0.01),('scale paper',),
('polygon',)],
'title_x':5.0,
'title_y':-1.0,
'title_box_width': 10.0,
'title_str':r'$(S+0.64)^{0.58}(0.74V) = P$'
}
Nomographer(main_params)
S_params={
'u_min':1.0,
'u_max':3.5,
'function':lambda u:(u+0.64)**(0.58),
'title':r'$S$',
P
3.3
3.2
3.1
3
2.9
2.8
2.7
2.6
2.5
2.4
2.3
2.2
2.1
2
1.9
1.8
1.7
1.6
1.5
1.4
1.3
1.2
1.1
1
S
1
1.1
V
2
1.9
1.8
1.7
1.6
1.5
1.4
1.3
1.2
1.1
1
(S + 0.64)0.58 (0.74V ) = P
21
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
2
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
3
3.1
3.2
3.3
3.4
3.5
For situations where we have the sum of more than three functions of single variables, a nomogram with
pivot lines can be drawn. The form of this equation is f1 (u1 ) + f2 (u2 ) + ... + fn (un ) = 0 for any number n of
variables. A pivot line is a blank scale that serves as a intermediate turning point for the straightedge. For
example, if we have f1 (u1 ) + f2 (u2 ) + f3 (u3 ) + f4 (u4 ) = 0, we can write this as a system of two equations
f1 (u1 ) + f2 (u2 ) + R = 0
f3 (u3 ) + f4 (u4 ) R = 0
So we can create a nomogram block for the first equation consisting of three parallel lines with no scale
drawn on the R-scale, then use the same R-scale to create a block for the second equation. The nomogram
ends up as two concatenated blocks. To find u4 the user lays a straightedge across the scale values for u1 and
u2 and marks a point on the R-scale. Then the straightedge is placed across that mark and the scale value for
u3 to find u4 . Remember, you can find any unknown variable by working from the known variables.
PyNomo directly supports compound parallel lines for any number of variables, automatically sizing and
placing the pivot lines appropriately. An example is provided on the Type 3 Software Documentation page.22
The example on the next page is drawn from electro-optics. It shows the relationship for a camera system
of the target range, the number N of picture element cycles, the lens focal length, the target size, and the
resolution achieved:
N Range
Resolution =
Focal Length Target Size
or
log (Resolution) + log (Focal Length) + log (Target Size) log N log (Range) = 0
The new parameters that we introduce in this example are
title_y_shift and title_x_shift: shifts in cm in a scale title for readability
text_format: we changed the number display default of 2 digits to the right of the decimal point to 0 or
1 depending on the scale
scale_type: The type of scaling (spacing) of the tick marks and labels of the scale. The options are:
linear: linear scaling (the default when no scale type is specified)
log: logarithmic scaling
linear smart: linear scaling with smart tick mark spacing
log smart: logarithmic scaling with smart tick mark spacing
manual line: manual selection of tick marks
manual arrow: manual selection using tick arrows
manual point: manual selection using tick points
We will see the use of smart scale types later, but the following example shows the use of logarithmic
scaling rather than the default linear scaling for all scales except the N scale, for which we will use
manual scaling (see below)
reference_titles: A list of titles to place over the pivot lines. For no titles at all, place no text between
the single quotes. If this parameter is omitted, a default title of R is placed over each pivot line.
22 http://www.pynomo.org/wiki/index.php/Type_3
22
It happens here that N is an integer from 1 to 10, so we only want to have ticks for those specific values.
We can limit the tick marks on a scale to a predefined list of values through the scale_type and manual_axis_data parameters. The scale_type parameter can be set to manual line, manual arrow or manual point
depending on whether we want a tick drawn, an arrow drawn or, as here, just the points drawn. In the
manual_axis_data set we include a list of values to mark and a title text for each mark, which can be very
useful for special labeling. Here we have no title for some of the points because they are so close the titles
would collide. In this nomogram we also changed the overall paper size to get a nice horizontal layout of the
scales.
This PyNomo script and output PDF graphic are available online for download.23
23 http://www.myreckonings.com/pynomo11/Type3-Example1.py
and http://www.myreckonings.com/pynomo11/Type3-Example1.pdf
23
Target_Size_meters_params={
'u_min':0.5,
'u_max':20.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'Target Size (m)',
'title_y_shift':0.4,
'tick_side':'left',
'title_x_shift':-0.5,
'tick_levels':2,
'text_format':r"$%3.1f$",
'tick_text_levels':2,
'scale_type':'log',
}
Resolution_params={
'u_min':1.0,
'u_max':40.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'Resolution (line pairs/mm)',
'title_y_shift':0.4,
'text_format':r"$%3.1f$",
'tick_levels':3,
'tick_text_levels':3,
}
block_1_params={
'block_type':'type_3',
'width':10.0,
'height':10.0,
'reference_titles':['Ref. 1','Ref. 2'],
'f_params':[Range_meters_params,Number_of_Cycles_params,
Focal_Length_mm_params,Target_Size_meters_params,
Resolution_params],
}
main_params={
'filename':'Type3-Example1.pdf',
'paper_height':11.0,
'paper_width':20.0,
'block_params':[block_1_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x':10.0,
'title_y':-1.0,
'title_box_width': 20.0,
'title_str':r'Resolution = (N $\times$ Range) \
/ (Focal Length $\times$ Target Size)',
}
Focal_Length_mm_params={
'u_min':1.0,
'u_max':1000.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'Lens Focal Length (mm)',
'title_y_shift':0.4,
'tick_side':'left',
'tick_levels':2,
'text_format':r"$%3.0f$",
'tick_text_levels':2,
'scale_type':'log',
}
Nomographer(main_params)
24
25
1000
100
5000
4000
3000
2500
1200
1400
1600
1800
2000
10
6
4
600
700
800
900
500
400
300
250
120
140
160
180
200
60
70
80
90
50
Range (m)
10
100
1000
9
8
7
6
5
4
3
20
90
80
70
60
50
40
30
200
900
800
700
600
500
400
300
Ref. 2
Ref. 1
10.0
1.0
20.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
2.0
0.5
0.6
0.7
0.8
0.9
2.0
1.8
1.6
1.4
1.2
2.5
3.0
4.0
5.0
9.0
8.0
7.0
6.0
20.0
18.0
16.0
14.0
12.0
25.0
30.0
40.0
1.0
10.0
10
A Type 8 nomogram is a single, simple function scale. It provides a means of aligning (or
overlaying) a scale right on top of another scale. This is useful if a scale in the nomogram is to
be marked in two different units, with one set of tick marks on the left side and the other on the
right. A single-scale example is provided on the Type 8 Software Documentation page.24 The
use of two aligned Type 8 scales for a Celsius/Fahrenheit temperature conversion scale is also
provided as an examplea piece of it is shown on the right.25
In our previous electro-optics nomogram the Range scale was in meters. We will modify
this script to align a Type 8 scale to this Range scale with tick marks and labels on the other
side in units of feet. We will also add an inch scale to the mm scale for Lens Focal Length and
a feet scale to the meter scale of the Target Size. This is shown on the following pages.
The new parameters that we introduce in this example are
tag: scales with the same tag are aligned (overlaid) in the final nomogram
extra_titles: additional titles to add to the scale beyond title. For each additional title,
dx and dy specify the offsets in cm from the upper right corner of the scale, text is the
title (remember to add the r between the colon and the string), and width is the title box width. We
will see another parameter pyx_extra_defs in the next section to specify the color of the title. This last
parameter also provides another way of specifying the text size rather than adding, say, \small in the
text itself.
align_func: the function used to align a Type 8 scale with another scale with the same
tag, as described below
extra_texts: additional titles to add to the overall nomogram. For each additional title, x
and y specify the center of the title in cm from the lower left of the nomogram (y can be
negative), text is the title (remember to add the r between the colon and the string), and
width is the title box width. We will see another parameter pyx_extra_defs in the next
section to specify the color of the title. This last parameter also provides another way of
specifying the text size rather than adding, say, \large in the text itself.
We assign three tags to the scales, range, focal and size. Two scales are given each tag. The first is a scale
from the previous example with the same title plus an extra title specifying the original units, shifted to left
to lie over the side of the scale with those tick marks. The amounts dx and dy to shift the extra titles has to
be done by experimenting. The second scale with the same tag is an aligned Type 8 scale with the tick marks
and labels on the other side and its title (giving the other units) shifted right to lie over those tick marks. We
make the font size of the units titles a bit smaller here by preceding the text with \small. The Lens Focal
Length title is also broken into two titles to show the format of adding more than one extra title.
When we align a Type 8 scale to an existing scale, we have to specify the scale function and the minimum
and maximum values that will provide a correct alignment. Lets look at the Range scale. The existing scale
was in meters and had a minimum of 50.0m and a maximum of 5000.0m. Since there are 3.28 feet in a
meter, the minimum in feet must be 50.0 3.28 and the maximum must be 5000.0 3.28. There is a new
align_func parameter here that provides the scaling needed in the new units to produce the same scale length
24 http://www.pynomo.org/wiki/index.php/Type_8
25 http://www.pynomo.org/wiki/index.php/Temperature_converter
26
as the original one. In this example the align function should be u/3.28 so that the overall length of the scale
is the same.
Instead of the single-line nomogram title in the previous section, this example shows the equation as a
fraction, where the dividing line is simulated with a string of connected dashes. TeX assumes that two or
three dashes are single longer dashes (endashes or emdashes), so to prevent an odd-looking extra dash at the
end of the line, the number of dashes should not be 1 more than a multiple of 3. A backslash \ is used after
Resolution = to indicate that the title text continues on the next script line.
Here we also set the titles above the pivot lines to blanks in the reference_titles parameter in block_1_params. Notice that the isopleth_values parameter for the Type 3 block includes all the intersected scale
values within a single set of square brackets, and that a calculated value (denoted by x) is required for each
overlaid Type 8 scale.
This PyNomo script and output PDF graphic are available online for download.26
### Type3-DualScale.py ###
Focal_Length_mm_params={
'tag':'focal',
'u_min':1.0,
'u_max':1000.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'Lens',
'title_y_shift':1.2,
'tick_side':'left',
'tick_levels':2,
'text_format':r"$%3.0f$",
'tick_text_levels':2,
'extra_titles':[
{'dx':-1.75,
'dy':0.8,
'text':'Focal Length',
'width':5,
},
{'dx':-1.4,
'dy':0.25,
'text':r'\small $mm$',
'width':5,
}]
}
Target_Size_meters_params={
'tag':'size',
'u_min':0.5,
'u_max':20.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'Target Size',
'title_y_shift':0.8,
'tick_side':'left',
'tick_levels':2,
'text_format':r"$%3.1f$",
'tick_text_levels':2,
'extra_titles':[
{'dx':-1.25,
'dy':0.25,
'text':r'\small $m$',
'width':5,
}]
}
26 http://www.myreckonings.com/pynomo11/Type3-DualScale.py
and http://www.myreckonings.com/pynomo11/Type3-DualScale.pdf
27
Resolution_params={
'tick_levels':2,
'tag':'resolution',
'tick_text_levels':2,
'u_min':1.0,
}
'u_max':40.0,
block_3_params={
'function':lambda u:log10(u),
'block_type':'type_8',
'scale_type':'log',
'f_params':Focal_Length_inches_params,
'title':r'Resolution',
'isopleth_values':[['x']],
'title_y_shift':0.8,
}
'text_format':r"$%3.1f$",
'tick_levels':3,
### TYPE 8 SINGLE-SCALE BLOCK ###
'tick_text_levels':3,
Target_Size_feet_params={
'extra_titles':[
'tag':'size',
{'dx':-2.0,
'u_min':0.5*3.281,
'dy':0.25,
'u_max':20.0*3.281,
'text':r'\small $(line \enspace pairs/mm)$',
'function':lambda u:log10(u),
'width':5,
'scale_type':'log',
}]
'align_func':lambda u:u/3.281,
}
'title':r'\small $ft$',
'title_x_shift':0.35,
block_1_params={
'tick_side':'right',
'block_type':'type_3',
'text_format':r"$%3.0f$",
'width':10.0,
'tick_levels':2,
'height':10.0,
'tick_text_levels':2,
'reference_titles':['',''],
}
'f_params':[Range_meters_params,
Number_of_Cycles_params,
block_4_params={
Focal_Length_mm_params,
'block_type':'type_8',
Target_Size_meters_params,
'f_params':Target_Size_feet_params,
Resolution_params],
'isopleth_values':[['x']],
'isopleth_values':[[300,2,40,'x',10]],
}
}
main_params={
'filename':'Type3-DualScale.pdf',
'paper_height':11.0,
'paper_width':20.0,
'block_params':[block_1_params,block_2_params,
block_3_params,block_4_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x':10.0,
'title_y':-1.5,
'title_box_width': 20.0,
'title_str':r'\large Resolution =\
---------------------------------------',
'extra_texts':[
{'x':9.5,
'y':-1.2,
'text':r'\large $N$ $\times$ Range',
'width':5,
},
{'x':8.1,
'y':-1.85,
'text':r'\large Focal Length $\times$ Target Size',
'width':7,
}],
'isopleth_params':[
{'color':'Gray',
'linewidth':'thin',
'linestyle':'dashed',
'circle_size':0.05,
'transparency':0.0,
},
],
}
Nomographer(main_params)
28
29
1000
100
5000
4000
3000
2500
1200
1400
1600
1800
2000
600
700
800
900
500
400
300
250
120
140
160
180
200
60
70
80
90
50
12000
14000
16000
6000
7000
8000
9000
5000
4000
3000
2500
1200
1400
1600
1800
2000
600
700
800
900
500
400
300
250
180
200
ft
Range
10000
1000
10
6
4
9
8
7
6
5
4
3
20
90
80
70
60
50
40
30
200
900
800
700
600
500
400
300
mm
0.09
0.08
0.07
0.06
0.05
0.04
0.20
0.90
0.80
0.70
0.60
0.50
0.40
0.30
2.00
9.00
8.00
7.00
6.00
5.00
4.00
3.00
20.00
30.00
in
0.10
1.00
10.00
N Range
Resolution =
Focal Length Target Size
10
100
1000
Lens
Focal Length
10.0
1.0
20.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
2.0
0.5
0.6
0.7
0.8
0.9
30
40
50
60
20
3
4
5
6
7
8
9
ft
Target Size
10
2.0
1.8
1.6
1.4
1.2
2.5
3.0
4.0
5.0
9.0
8.0
7.0
6.0
20.0
18.0
16.0
14.0
12.0
25.0
30.0
40.0
1.0
10.0
(line pairs/mm)
Resolution
Its also possible with Type 8 to create a curved set of scales for dial faces or for scales to be used in
making a circular slide rule. Just for fun, lets create a set of circular scales that can be used as a dial face
pasted behind a knob from which a clear plastic overlay is attached with a pointer line inscribed, or simply
tacked in the center to a bulletin board with a thread tied to the pin of the tack.
The new parameters that we introduce in this example are
function_x: a function that provides the x coordinate of a particular value of u along the scale
function_y: a function that provides the y coordinate of a particular value of u along the scale
turn_relative: if True, determine the left/right side of the scale for the tick_side parameter by the
progression of values along the scale rather than the left/right side of the page. This is important only
for curved scales as in this example, where if we did not set this value to True the side that the ticks is
drawn on would change as the scale curved left or right. (False by default)
base_start and base_stop: if present, use this minimum and maximum value rather than u_min and
u_max to determine the settings of the tick_levels, useful for logarithmic scales. By setting these to a
smaller range than provided for u, finer tick levels occur and setting tick_level to 1, for example, can
produce finer spacing than would otherwise be possible.
The function_x and function_y parameters allow the scale curvature to be defined by functions of u in
terms of x and y. For example, if we want a linear scale from 1.0 to 10.0 to be laid out in a circle of radius
7.0cm, we would write
'function_x':lambda u:7.0*cos(2*pi*u/(10.0-1.0),
'function_y':lambda u:7.0*sin(2*pi*u/(10.0-1.0),
Since u/10.01.0 is u divided by the overall range of u, then 2 u/(10.0 1.0) will range from 0 to
2, or a complete circle in radians. By using the same radius but with the ticks on the opposite side we can
overlay two scales. The example
on the next page has a scale for N for a radial pointer to be placed on. Then
the other scales provide 3 N, N, 1/N , N 2 , N 3 , the area and volume of a circle of radius N, and the radius of
a circle with an area or volume N.
All the scales repeat the same basic set of parameters, which made it easy to write the script, but I had to
test it a number of times to get the x and y offsets for the scale titles just right to fit in the available openings.
The carriage return in the overall nomogram title in this example is forced by the width in cm of the text_box_width parameter rather than using \par or separating it into two texts with the extra_texts parameter as
we did in the previous example.
The N scale ranges from 1 to 10 here, so if N lies outside this range the decimal point can be moved to
place it in this range, the calculation can be completed, and then the decimal point can them be moved back
appropriately. For example, the square root of 223 can be found by moving the decimal point two places to
the left to get 2.23, the square root can be found as 1.49, and the decimal point can be moved right by one
place to get 14.9 as the answer. The accuracy can be vastly improved by printing this on a large sheet of
paperzoom in to see what it would look like. Very complicated engineering formulas can be laid out on
such a circular scale.
Many of the tick marks in this nomogram are a bit small to read very well. The size and orientation of
the labels also dictate the minimum spacing between scales and therefore the overall size of the nomogram.
We will see how to adjust all of these when we return to this circular dial in color form in the next section.
30
This PyNomo script and output PDF graphic are available online for download.27
### Type8-Dial-Smart.py ###
'tick_text_levels':5,
'scale_type':'log smart',
'turn_relative':True,
}
Square_Root_block_params={
'block_type':'type_8',
'f_params':Square_Root_params,
'width':15.0,
'height':15.0,
}
Inverse_N_params={
'u_min':0.101,
'u_max':1.0,
'base_start':0.1,
'base_stop':1.0,
'function_x':lambda u:
7.0*cos(-2*pi*(log10(u)-log10(0.1))/
(log10(1.0)-log10(0.1))),
'function_y':lambda u:
7.0*sin(-2*pi*(log10(u)-log10(0.1))/
(log10(1.0)-log10(0.1))),
'title':r'\LARGE $1/N$',
'title_x_shift':-0.2,
'title_y_shift':-1.35,
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'linear smart',
'turn_relative':True,
}
CenterHole_block_params={
'block_type':'type_8',
'f_params':CenterHole_params,
'width':15.0,
'height':15.0,
}
Cube_Root_params={
'u_min':1.0,
'u_max':2.09,
'base_start':1.0,
'base_stop':10.0,
'function_x':lambda u:
3.0*cos(2*pi*(log10(u)-log10(1.0))/
(log10(2.1544)-log10(1.0))),
'function_y':lambda u:
3.0*sin(2*pi*(log10(u)-log10(1.0))/
(log10(2.1544)-log10(1.0))),
'title':r'\Large $N^{1/3}$',
'title_x_shift':-0.05,
'title_y_shift':-1.35,
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'log smart',
'tick_side':'left',
'turn_relative':True,
}
Inverse_N_block_params={
'block_type':'type_8',
'f_params':Inverse_N_params,
'width':15.0,
'height':15.0,
}
N_params={
'u_min':1.0,
'u_max':9.9999,
'base_start':1.0,
'base_stop':9.9999,
'function_x':lambda u:
7.0*cos(2*pi*log10(u)/log10(10.0)),
'function_y':lambda u:
7.0*sin(2*pi*log10(u)/log10(10.0)),
'title':r'\huge $N$',
'title_x_shift':-0.15,
'title_y_shift':0.8,
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'linear smart',
'turn_relative':True,
}
Cube_Root_block_params={
'block_type':'type_8',
'f_params':Cube_Root_params,
'width':15.0,
'height':15.0,
}
Square_Root_params={
'u_min':1.0,
'u_max':3.1623,
'base_start':1.0,
'base_stop':10.0,
'function_x':lambda u:
3.0*cos(2*pi*(log10(u)-log10(1.0))/
(log10(3.1623)-log10(1.0))),
'function_y':lambda u:
3.0*sin(2*pi*(log10(u)-log10(1.0))/
(log10(3.1623)-log10(1.0))),
'title':r'\Large $\sqrt{N}$',
'title_x_shift':-0.1,
'title_y_shift':0.80,
'tick_levels':5,
N_block_params={
'block_type':'type_8',
'f_params':N_params,
'width':15.0,
'height':15.0,
}
27 http://www.myreckonings.com/pynomo11/Type8-Dial-Smart.py
and http://www.myreckonings.com/pynomo11/Type8-Dial-Smart.pdf
31
Square_params={
'u_min':1.0,
'u_max':99.999,
'base_start':1.0,
'base_stop':100.0,
'function_x':lambda u:
11.0*cos(2*pi*(log10(u)-log10(1.0))/
(log10(100.0)-log10(1.0))),
'function_y':lambda u:
11.0*sin(2*pi*(log10(u)-log10(1.0))/
(log10(100.0)-log10(1.0))),
'title':r'\LARGE $N^2$',
'title_x_shift':-0.5,
'title_y_shift':-1.3,
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'linear smart',
'tick_side':'left',
'turn_relative':True,
}
'tick_text_levels':5,
'scale_type':'linear smart',
'turn_relative':True,
}
Inverse_Area_block_params={
'block_type':'type_8',
'f_params':Inverse_Area_params,
'width':15.0,
'height':15.0,
}
Area_params={
'u_min':3.14159,
'u_max':314.15,
'base_start':3.14159,
'base_stop':314.15,
'function_x':lambda u:
15.0*cos(2*pi*(log10(u)-log10(3.14159))/
(log10(314.159)-log10(3.14159))),
'function_y':lambda u:
15.0*sin(2*pi*(log10(u)-log10(3.14159))/
(log10(314.159)-log10(3.14159))),
'title':r'\Large $R \Rightarrow Area$',
'title_x_shift':-0.75,
'title_y_shift':0.8,
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'linear smart',
'turn_relative':True,
}
Square_block_params={
'block_type':'type_8',
'f_params':Square_params,
'width':15.0,
'height':15.0,
}
Cube_params={
'u_min':1.0,
'u_max':999.999,
'base_start':1.0,
'base_stop':1000.0,
'function_x':lambda u:
11.0*cos(2*pi*(log10(u)-log10(1.0))/
(log10(1000.0)-log10(1.0))),
'function_y':lambda u:
11.0*sin(2*pi*(log10(u)-log10(1.0))/
(log10(1000.0)-log10(1.0))),
'title':r'\LARGE $N^3$',
'title_x_shift':2.2,
'title_y_shift':0.9,
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'log smart',
'turn_relative':True,
}
Area_block_params={
'block_type':'type_8',
'f_params':Area_params,
'width':15.0,
'height':15.0,
}
Inverse_Volume_params={
'u_min':0.62035,
'u_max':1.3365,
'base_start':0.1,
'base_stop':1.0,
'function_x':lambda u:
19.0*cos(-2*pi*(log10(u)-log10(0.62035))/
(log10(1.3365)-log10(0.62035))),
'function_y':lambda u:
19.0*sin(-2*pi*(log10(u)-log10(0.62035))/
(log10(1.3365)-log10(0.62035))),
'title':r'\Large $Volume N \Rightarrow R$',
'title_x_shift':-0.15,
'title_y_shift':-1.2,
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'log smart',
'turn_relative':True,
}
Cube_block_params={
'block_type':'type_8',
'f_params':Cube_params,
'width':15.0,
'height':15.0,
}
Inverse_Area_params={
'u_min':0.5642,
'u_max':1.7841,
'base_start':0.5642,
'base_stop':1.7841,
'function_x':lambda u:
15.0*cos(-2*pi*(log10(u)-log10(0.5642))/
(log10(1.7841)-log10(0.5642))),
'function_y':lambda u:
15.0*sin(-2*pi*(log10(u)-log10(0.5642))/
(log10(1.7841)-log10(0.5642))),
'title':r'\Large $Area N \Rightarrow R$',
'title_x_shift':0.0,
'title_y_shift':-1.4,
'tick_levels':5,
Inverse_Volume_block_params={
'block_type':'type_8',
'f_params':Inverse_Volume_params,
'width':15.0,
'height':15.0,
}
Volume_params={
'u_min':4.1888,
'u_max':4188.8,
'base_start':1.0,
32
'base_stop':1000.0,
'function_x':lambda u:
19.0*cos(2*pi*(log10(u)-log10(4.1888))/
(log10(4188.8)-log10(4.1888))),
'function_y':lambda u:
19.0*sin(2*pi*(log10(u)-log10(4.1888))/
(log10(4188.8)-log10(4.1888))),
'title':r'\Large $R \Rightarrow Volume$',
'title_x_shift':3.8,
'title_y_shift':1.5,
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'log smart',
'turn_relative':True,
}
}
main_params={
'filename':'Type8-Dial-Example-Smart.pdf',
'paper_height':30.0,
'paper_width':30.0,
'block_params':[CenterHole_block_params,
Cube_Root_block_params,Square_Root_block_params,
Inverse_N_block_params,N_block_params,
Square_block_params,Cube_block_params,
Inverse_Area_block_params,Area_block_params,
Inverse_Volume_block_params,Volume_block_params,],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x': 2,
'title_y': 1.5,
'title_box_width': 6,
'title_str':r'\huge Powers, Roots and Circle Formulas',
}
Volume_block_params={
'block_type':'type_8',
'f_params':Volume_params,
'width':15.0,
'height':15.0,
Nomographer(main_params)
33
15
14
.5
13
.5
14
13
11
.5
1.
18
12
1.
17
0.755
700
0.76
10
.5
1.
2
7.5
1.39
1.
21
6.
5
6.
4
6.
3
6.
2
6.
1
1.
48
1.
51
1.
49
1.
52
1.
53
1.5
2
1.
8
1.
9
2.
4
2.
8
2.
7
2.
6
2.
5
2.
1
2.
2
2.
9
2.3
1.
54
3.5
1 .5
1.
45
1.
35
1.
4
0.7
5.
5. 9
5. 8
5. 7
6
1 .4
1.
47
1.
46
1.4
1.4
1.4
1.4
1.4
4
2.4
2.5
2.6
1.5
5
11
1.
19
8.5
1.36
1.37
1.38
4.5
2.7
2.8
1.65
1.6
0.6
5
1.
2
90
0.765
650
0.77
600
0.755
95
0.76
0.77
0.765
0.78
5
85
0.78
0.775
0.79
80
0.77
5
10
6
1.1
12
.5
16.5
1.1
16
15
.5
18
17.5
1.14
17
19.5
1.13
19
18.5
21.5
21
20.5
1.12
20
23.5
23
22.5
22
9.5
1.34
1.35
5.5
2.9
3.1
1.75
1.7
0.57
0.58
0.59
0.6
1.3
1.2
5
1.1
1.2
1.75
5.6
5.5
31
0.8
5
0.7
9
75
0.7
8
510
520
530
540
550
500
0.18
0.185
5.4
30
160
28
29
170
130
135
140
145
5
11
120
125
150
155
25
26
27
22
.
23 5
23
.5
24
10
11
0.8
05
0.
82
5
0.
82
0.8
15
0.8
1
0.7
8
0.7
9
0
49
2.35
1.
65
1.7
2.3
2.2
0.2
0.19
5
0.19
5.1
5.2
5.3
4.8
4.9
4.
6
4.
7
20
.
21 5
21
.
22 5
90
95
0
10
0.
84
5
0.
84
0.
83
5
0.
83
64
70
0.
79
5
45
50
50
14
00
15
00
00
12
50
12
46
15
0
16
95
50
16
00
17
5
17
00
3300
0.64
3200
3100
0.6
4
300
0
290
0.6
5
20
0
19
18
18
85
6
0.
50
13
00
14
13
110
1000
850
900
750
800
950
105
50
11
6
0.
69
0.
0.7
71
0.
47
75
0.
68
0
16
05
7
0.
15
0.7
0.7
0.73
2
0.7
0.74
0.735
0.75
0.745
48
0.
6
0
17
65
2.2
2.
1
2.
15
0.
23
0.
23 5
0.
22
5
0.
22
0.
21
0.2 5
1
0.2
05
4.
3
4.
4
4.
5
20
18
18
.5
19
19
.5
75
80
85
0.
86
0.
5
86
0.
85
5
85
0.
16
61
62
63
18
0
15
0 .8
19
17
140
15
5
130
120
18
3400
280
0
27
50
27
00
0.6
26
55
50
26
00
25
50
25
0.
0
66
24 0
5
24 0
0
0.
23 0
66
5
5
23 0
00
22
50
22
0.
67
00
21
50
21
00
20
50
20
65
21
19
55
6
0.
67
0.
14
125
20
35
45
65
6
0.
66
0.
75
6
0.
69
0.
85
6
0.
68
0.
135
110
43
0
5
0.71
0.7
0
0.7
9
0.6
0.7
115
100
44
35
56
0
40
0.
0
30
57
55
50
0.
6
0.
63
0.
6
0.
64
260
220
21
25
3600
3500
0.635
250
230
22
5
50
19
50
00
3900
3800
3700
0.63
280
240
235
0.
62
0.
6
45
0
58
29
59
0.6
1
15
0.625
270
255
4000
290
275
265
245
0.
6
4100
300
295
0.59
4.3
310
285
0.585
0.6
0
4.4
4.2
0.58
55
4.5
305
0.575
0.5
95
4.6
1.33
3.2
0.57
0.6
4.7
3.3
1.78
0.565
50
45
250
60
65
0
27
260
28
1.77
44
43
42
41
0.73
0.72
0.735
0.72
0.
80
5
1.05
65
4.8
1.32
3.4
900
75
240
210
220
230
105
45
39
0.
81
14
0.
35
40
0.
82
1.1
700
4.9
3.5
1.76
60
0
60
6.5
0.74
0.75
34
0.745
42
1
0.
1
0.
7.
35
36
37
38
180
190
200
0.
81
1.75
6
32
33
34
1.15
750
70
0.1
55
0.1
0 .1
5.7
5.8
38
1.74
800
80
8 .5
25
5.9
6
2.
0.17
0.175
39
1.2
850
0.
12
0.
1
0.
13
0.16
40
0
1.25
1.31
3.6
1.72
950
5.1
3.7
1.71
85
1.3
3.8
1.73
90
7
2.
2.4
2.45
41
9.5
0.1
1
1.7
5.5
5.4
5.3
5.2
3.9
1.3
6
9
1.2
4
8
95
0.11
2.
8
5
2.5
2.5
2.
9
95
1.
1.8
1.8
2
9
1.
37
3
1.
1.25
0.
82
5
1.
1.35
1.4
45
1.
36
0.5
.5
17
0.56
0.55
0.54
0.53
0.52
0.51
32
0
1.8
1.85
1.9
1.95
3.2
3.3
3.7
3.6
3.5
3.4
33
6.5
45
34
1.11
10
1.33
1.3
2.0
.5
16
17
70
5
89
0.
89
0.
5
88
0.
88
51
5
0.
87
52
0.
87
53
0.
54
35
0
1.1
1.31
3.8
3.9
0.9
1.32
7.5
65
24
11
10.5
11.5
.5
15
16
60
2
4.
0.105
.28
4.1
1.6
6.5
7
1.2
1.6
1.4
1.35
26
1.
8
4.
7
4.
6
61
4.
1.
5
62
4.
1.
4
63
4.
.
1
64
4.3
1.
4.2
.65
1.6
5
1.5
1.5
5
1.4
1.1
9
4.
7
1.6
1.05
0.95
1.6
1.2
5
7.
25
1.
1.3
5
1.1
24
1.
1
5.
7
1.
0.9
05
2.
8
1.
1.1
1.05
2.0
6
1.
9
1.
4
1.
5
0 .8
3.1
2 5
24
0. 24
0.
15
55
24.5
1.09
1.08
44
0.
43
0.
31
95
1.
25
1.
1
1.
5
1.0
5
1.5
1.9
1.6
2
1.
1
1.
56
1.
1
2.
5
8.
5
5. 4
5.
3
5.
2
5.
55
2
2.
3
1.
0.8
1.5
0.
1
4.
55
0.
50
9
0.4
8
0.4
47
0.
46
0.
0
23
5
85
23
0.
0
24
5
5
24
84
0
0.
25
5
5
2
0
84
26 5
0.
26 0
5
27 5
83
0.
27 0
8
2
83
0
0.
29
5
4.
N 1/3
3
2.
5
1.
75
9
23
1.
57
1.
58
1.
59
1.
6
1.
15
1.
1.85
0.295
0.29
85
0.2
8
0.2 5
7
0.2
7
3.6
0.2 5
26
0. 6
3.7
2
0. 55
2
8
.
0.
3
5
9
3.
14
25
25.5
26
26.5
27
27.5
28
15
2.
49
0
30
0.3
0.
5
9.
22
1.
1.
7
1.
1.45
1.8
0.31
.5
13
50
48
2.1
13
0.95
5
85
0.
86
0.
8.5
25
35
2.
22
2
2.
25
2.
3
2.
21
4
4.1
4.2
4.3
4.4
5
4.
21
5
9.
65
0.8
5
20
12.5
35
0.9
41
3
0.9
42
25
0.9
43
92
0.
5
44
91
0.
5
91
4
0.
5
6
90
4
0.
47
1.7
3.5
12
45
45
0.9
4
0.9
200
195
12
1.2
7
0.8
5
5.
7
0.8
190
40
5
185
40
1.4
1.75
3.4
11.5
5
0.95
39
0.88
180
11
0.96
38
11
175
3.3
35
5
0.96
37
5
0.88
170
.5
165
10.5
0.97
36
0.89
10
160
0.32
3.2
1/N
1.
35
1.6
0.33
3.1
0.98
1.
6
0.34
9.5
10
0.975
10
29
30
13
1.
55
0.35
2.9
2.95
28
N2
0.4
0.985
35
0.
2.
42
2. 5
0.
55
41
2.
6
2.
0.
65
39
2.7
0.
38
2.7
0.3
5
7
2.8
0.3
2.8
6
5
8.5
27
0.99
34
0.895
155
33
0.9
150
.5
145
12
0.905
AreaN R
12
23
0.995
140
2.
4
2.
45
24
25
26
32
6.
5
7.5
1.005
31.5
0.91
.5
20
1.01
31
14
17
21
1.015
30.5
.5
0.915
130
.5
.5
16
22
1.02
30
125
15
15
18
1.025
29.5
13
14
19
1.03
29
11
28.5
1.
15
1.1
28
0.92
135
.5
1.04
5
1.04
1.035
27
27.5
120
1.
1.2
0.93
0.925
1.29
5
1.28
1.28
5
1.27
7
1.2
65
1.2
6
1.2 5
5
1.2
13
45
1.2
4
1.2 5
3
1.2
23
1. 25
2
1. 2
2
1. 15
2
1. 1
2
1. 05
2
1.
.5
110
115
.5
0.94
0.93
5
5
19
1. 9
1
1. 85
1
1. 8
1
1. 175
1. 17
5
1. 16
1. 16
1.
.5
19
.5
1.
09
1.0 5
9
23
1.0
.5
8
1.0 5
24
8
1.0
24.5
75
1.0
7
25
1.0
65
25.5
1.0
6
26
1.05
5
26.5
1.0
0.9
4
105
19
23
0.9
5
95
100
16
22
15
15
0.9
5
18
1.
5
1. 145
1. 14
1
1. 35
20
1
1. 3
.5
12
1.
21
1 5
1. 2
1
21
.5
1. 15
1
1. 1
22
10
5
0.9
6
90
.5
0.
96
.5
17
18
20
80
R Area
17
0.
98
0.
97
85
16
0.
97
75
12.5
.5
13
14
14
01
1.
55
70
V olumeN R
04
1.
54
0.
99
0.
98
30
1.07
6
1.0
5
1.0
41
03
1.
52
53
65
29
33
32
31
34
36
35
39
38
37
40
42
43
44
45
02
1.
46
47
48
49
50 1
60
0.
99
5
R V olume
11
Introducing Color
I think I have only ever seen a color nomogram once, and I made it.28 But the most recent version of
PyNomo supports color for scale axes, labels, titles, lines, pivot lines and arrows. In this age when people
are used to splashy, colorful infographics, I think that adding color to nomograms is one way of lifting these
graphical calculators from their dry, retro look to something that seems relevant and interesting today.
Scale parameters specifying color are:
axis_color: the color of the axis (scale line) and tick marks in scale parameters
text_color: the color of the numbers in scale parameters
title_color: the color of the main scale title
pyx_extra_defs: the text color in extra_titles in scale parameters
arrow_color: the color of arrows in a manual arrow scale type
reference_color: the color of the pivot lines and their titles in a Type 3 nomogram
u_line_color: The color of the u-scale lines in a grid in a Type 9 Determinant nomogram
u_text_color: The color of the u-scale labels of a grid in a Type 9 Determinant nomogram
v_line_color: The color of the v-scale lines of a grid in a Type 9 Determinant nomogram
v_text_color: The color of the v-scale labels of a grid in a Type 9 Determinant nomogram
Block parameters specifying color are:
reference_color: the color of the diagonal reference line of a Type 4 Proportion nomogram
ladder_color: the color of the ladder lines of a Type 6 Ladder nomogram
u_axis_color: The color of the u-scale axis in a Type 5 Contour block
u_title_color: The color of the title text of the u-scale in a Type 5 Contour block
u_text_color: The color of the u-scale labels in a Type 5 Contour block
v_axis_color: The color of the v-scale family of curves in a Type 5 Contour block
v_title_color: The color of the title text of the v-scale in a Type 5 Contour block
v_text_color: The color of the v-scale labels in a Type 5 Contour block
wd_axis_color: The color of the wd-scale axis in a Type 5 Contour block
wd_title_color: The color of the title text of the wd-scale in a Type 5 Contour block
wd_text_color: The color of the wd-scale labels in a Type 5 Contour block
Main parameters specifying color are:
title_color: the color of the main nomogram title
pyx_extra_defs: the text color in extra_texts in the main parameters
color: the color of an isopleth in the isopleth_params parameter, with a default of black (note that
unlike the other parameters listed here, the name of the color is directly used, as in Dandelion.
28 http://myreckonings.com/wordpress/2008/02/24/a-zoomorphic-nomogram/
35
circle_color: the color of circles at the starting and ending points of line segments in the line_params
parameter, with a default of black
(the color of the line segments in the line_params parameter is specified as part of the line_style subparameter)
On the next page is the available color palette, where color. precedes the selected color, as for example
color.cmyk.BurntOrange or color.rgb.blue.29 Its possible to specify the fraction (0.0 to 1.0) of
red, green and blue as in color.rgb(0.9,0.0,0.3) or color.cmyk(0.5,0.0,0.8,0.1). This is how
I specified the very light red for the titles in the next example. You can also specify a shade of gray, as in
color.gray(0.8) for 80% white (20% black), which is done in the next example for the pivot lines. The
default color for all items is black (color.rgb.black) unless specified differently, so all PyNomo scripts
are backward-compatible. The one exception to this color naming convention is the color parameter within
isopleth_params, which directly uses the color name with no prefix, as in GreenYellow.
An example of a nomogram with color is a version of the Type 3 nomogram shown on the pages following
the color palette. The scale_type parameter has a new value manual arrow introduced here in order to show
how the texts and colors are set for arrows. The scale parameter extra_params is used to place the arrows:
extra_params: one or more additional sets of values to plot along a scale, which can specify new values
for all scale parameters except function and title, useful to plot individual ranges, to increase tick levels
in a particular range of a scale, or to add tick marks or arrows to specific values along the scale.
The nomogram doesnt exactly have a pleasing mix of colors (the blue and green are supposed to indicate
metric vs. English scales), but its just a demonstration of how different colors are applied. Its also a
dry engineering formula in electro-optics, so it doesnt benefit much from a color design as, say, lighter
nomograms on exercise time vs. calories or social statistics.
Also shown here is another way to size text in extra titlesrather than precede the text with, say, \small,
you can specify the text size in the pyx_extra_defs parameter as text.size.small instead.
The PyNomo script and output PDF graphic for the color Type 3 nomogram are available online for
download.30
29 From
30 http://www.myreckonings.com/pynomo11/Type3-Color.py
and http://www.myreckonings.com/pynomo11/Type3-Color.pdf
36
APPENDIX
Named colors
grey.black
cmyk.RubineRed
cmyk.Cerulean
grey.white
cmyk.WildStrawberry
cmyk.Cyan
cmyk.Salmon
cmyk.ProcessBlue
rgb.red
cmyk.CarnationPink
cmyk.SkyBlue
rgb.green
cmyk.Magenta
cmyk.Turquoise
rgb.blue
cmyk.VioletRed
cmyk.TealBlue
rgb.white
cmyk.Rhodamine
cmyk.Aquamarine
rgb.black
cmyk.Mulberry
cmyk.BlueGreen
cmyk.RedViolet
cmyk.Emerald
cmyk.GreenYellow
cmyk.Fuchsia
cmyk.JungleGreen
cmyk.Yellow
cmyk.Lavender
cmyk.SeaGreen
cmyk.Goldenrod
cmyk.Thistle
cmyk.Green
cmyk.Dandelion
cmyk.Orchid
cmyk.ForestGreen
cmyk.Apricot
cmyk.DarkOrchid
cmyk.PineGreen
cmyk.Peach
cmyk.Purple
cmyk.LimeGreen
cmyk.Melon
cmyk.Plum
cmyk.YellowGreen
cmyk.YellowOrange
cmyk.Violet
cmyk.SpringGreen
cmyk.Orange
cmyk.RoyalPurple
cmyk.OliveGreen
cmyk.BurntOrange
cmyk.BlueViolet
cmyk.RawSienna
cmyk.Bittersweet
cmyk.Periwinkle
cmyk.Sepia
cmyk.RedOrange
cmyk.CadetBlue
cmyk.Brown
cmyk.Mahogany
cmyk.CornflowerBlue
cmyk.Tan
cmyk.Maroon
cmyk.MidnightBlue
cmyk.Gray
cmyk.BrickRed
cmyk.NavyBlue
cmyk.Black
cmyk.Red
cmyk.RoyalBlue
cmyk.White
cmyk.OrangeRed
cmyk.Blue
69
37
'title_color':color.rgb(1.0,0.6,0.6),
'extra_titles':[
{'dx':0.1,
'dy':-2.95,
'text':r'Focal',
'width':5,
'pyx_extra_defs':[color.rgb(1.0,0.6,0.6),\
text.size.LARGE],
},
{'dx':0.45,
'dy':-3.9,
'text':r'Length',
'width':5,
'pyx_extra_defs':[color.rgb(1.0,0.6,0.6),\
text.size.LARGE],
},
{'dx':-1.4,
'dy':0.25,
'text':r'$mm$',
'width':5,
'pyx_extra_defs':[color.rgb.blue,\
text.size.small],
}],
}
Target_Size_meters_params={
'tag':'size',
'u_min':0.5,
'u_max':20.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'\LARGE Target',
'title_x_shift':-1.7,
'title_y_shift':0.8,
'tick_side':'left',
'tick_levels':2,
'text_format':r"$%3.1f$",
'tick_text_levels':2,
'axis_color':color.rgb.blue,
'text_color':color.rgb.blue,
'title_color':color.rgb(1.0,0.6,0.6),
'extra_titles':[
{'dx':-2.5,
'dy':0.15,
'text':r'Size',
'width':5,
'pyx_extra_defs':[color.rgb(1.0,0.6,0.6),\
text.size.LARGE],
},
{'dx':-1.25,
'dy':0.25,
'text':r'$m$',
'width':5,
'pyx_extra_defs':[color.rgb.blue,\
text.size.small],
}],
}
Number_of_Cycles_params={
'u_min':1.0,
'u_max':10.0,
'function':lambda u:-log10(u),
'scale_type':'log',
'title':r'\Large $N$',
'title_x_shift':-0.5,
'title_y_shift':-2.6,
'text_format':r"$3.0f$",
'tick_levels':2,
'tick_text_levels':1,
'title_color':color.rgb(1.0,0.6,0.6),
'scale_type':'manual point',
'manual_axis_data': {1.0:'one',
2.0:'two',
3.0:'',
4.0:'four',
5.0:'',
6.0:'six',
7.0:'',
8.0:'',
9.0:'',
10.0:'ten'
},
}
Focal_Length_mm_params={
'tag':'focal',
'u_min':1.0,
'u_max':1000.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'\LARGE Lens',
'title_x_shift':-1.3,
'title_y_shift':-2.7,
'tick_side':'left',
'tick_levels':2,
'text_format':r"$%3.0f$",
'tick_text_levels':2,
'axis_color':color.rgb.blue,
'text_color':color.rgb.blue,
Resolution_params={
'tag':'resolution',
'u_min':1.0,
'u_max':40.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'\Huge Resolution',
'title_x_shift':-1.2,
'title_y_shift':-7.2,
'tick_side':'left',
'text_format':r"$%3.1f$",
'tick_levels':3,
38
'tick_text_levels':3,
'axis_color':color.rgb.blue,
'text_color':color.rgb.blue,
'title_color':color.rgb(1.0,0.6,0.6),
'extra_titles':[
{'dx':-2.0,
'dy':0.25,
'text':r'$(line \enspace pairs/mm)$',
'width':5,
'pyx_extra_defs':[color.rgb.blue,\
text.size.small],
}],
'extra_params':[{
'tick_side':'right',
'scale_type':'manual arrow',
'manual_axis_data':{4.0:'\large Req. C',
20.0:'\large Req. B',
34.0:'\large Req. A'},
'arrow_color':color.cmyk.Red,
'text_color':color.cmyk.Red,
}],
}
'title_x_shift':0.4,
'tick_side':'left',
'text_format':r"$%3.2f$",
'tick_levels':2,
'tick_text_levels':2,
'axis_color':color.cmyk.OliveGreen,
'text_color':color.cmyk.OliveGreen,
'title_color':color.cmyk.OliveGreen,
}
block_3_params={
'block_type':'type_8',
'f_params':Focal_Length_inches_params,
'isopleth_values':[['x']],
}
### TYPE 8 SINGLE-SCALE BLOCK ###
Target_Size_feet_params={
'tag':'size',
'u_min':0.5*3.281,
'u_max':20.0*3.281,
'function':lambda u:log10(u),
'scale_type':'log',
'align_func':lambda u:u/3.281,
'title':r'\small $ft$',
'title_x_shift':0.35,
'tick_side':'right',
'text_format':r"$%3.0f$",
'tick_levels':2,
'tick_text_levels':2,
'axis_color':color.cmyk.OliveGreen,
'text_color':color.cmyk.OliveGreen,
'title_color':color.cmyk.OliveGreen,
}
block_1_params={
'block_type':'type_3',
'width':10.0,
'height':10.0,
'reference_titles':['',''],
'reference_color':color.gray(0.8),
'f_params':[Range_meters_params,
Number_of_Cycles_params,
Focal_Length_mm_params,
Target_Size_meters_params,
Resolution_params],
'isopleth_values':[[300,2,40,'x',10]],
}
block_4_params={
'block_type':'type_8',
'f_params':Target_Size_feet_params,
'isopleth_values':[['x']],
}
main_params={
'filename':'Type3-Color.pdf',
'paper_height':11.0,
'paper_width':25.0,
'block_params':[block_1_params,block_2_params,
block_3_params,block_4_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x':10.0,
'title_y':-1.5,
'title_box_width': 20.0,
'title_color':color.cmyk.RedOrange,
'title_str':r'\Large Resolution =\
------------------------------------------',
}
'extra_texts':[
{'x':9.5,
'y':-1.2,
'text':r'\Large $N$ $\times$ Range',
'width':5,
'pyx_extra_defs':[color.cmyk.RedOrange],
},
{'x':7.9,
'y':-1.85,
'text':r'\Large Focal Length $\times$ Target Size',
'width':7,
'pyx_extra_defs':[color.cmyk.RedOrange],
}],
'isopleth_params':[
{'color':'RedOrange',
'linewidth':'THick',
block_2_params={
'block_type':'type_8',
'f_params':Range_feet_params,
'isopleth_values':[['x']],
}
### TYPE 8 SINGLE-SCALE BLOCK ###
Focal_Length_inches_params={
'tag':'focal',
'u_min':1000.0/25.4,
'u_max':1.0/25.4,
'function':lambda u:log10(u),
'scale_type':'log',
'align_func':lambda u:u*25.4,
'title':r'\small $in$',
39
1000
100
40
5000
4000
3000
2500
1200
1400
1600
1800
2000
600
700
800
900
500
400
300
250
120
140
160
180
200
60
70
80
90
50
12000
14000
16000
6000
7000
8000
9000
5000
4000
3000
2500
1200
1400
1600
1800
2000
600
700
800
900
500
400
300
250
180
200
ft
10000
1000
Range
one
two
ten
six
four
9
8
7
6
5
4
3
20
90
80
70
60
50
40
30
200
900
800
700
600
500
400
300
mm
0.09
0.08
0.07
0.06
0.05
0.04
0.20
0.90
0.80
0.70
0.60
0.50
0.40
0.30
2.00
9.00
8.00
7.00
6.00
5.00
4.00
3.00
10.00
0.10
Length
Focal
1.00
20.00
30.00
in
N Range
Resolution =
Focal Length Target Size
10
Lens
100
1000
10.0
1.0
Target
Size
20.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
2.0
0.5
0.6
0.7
0.8
0.9
30
40
50
60
20
3
4
5
6
7
8
9
ft
1.0
10.0
2.0
1.8
1.6
1.4
1.2
2.5
3.0
4.0
5.0
9.0
8.0
7.0
6.0
Resolution
10
20.0
18.0
16.0
14.0
12.0
25.0
30.0
40.0
Req. C
Req. B
Req. A
(line pairs/mm)
'linestyle':'dotted',
'circle_size':0.10,
'transparency':0.5,
},
],
}
Nomographer(main_params)
Lets return to our previous Type 8 example of a dial face. First we want to add rainbow colors for the
scales. To each Type 8 scale we add the lines
'axis_color':color.cmyk.Red,
'text_color':color.cmyk.Red,
'title_color':color.cmyk.Red,
31 http://www.myreckonings.com/pynomo11/Type8-ColorDial-Smart.py
and http://www.myreckonings.com/pynomo11/Type8-ColorDial-Smart.pdf
41
Square_Root_params={
'u_min':1.0,
'u_max':3.1623,
'base_start':1.0,
'base_stop':10.0,
'function_x':lambda u:
3.0*cos(2*pi*(log10(u)-log10(1.0))/
(log10(3.1623)-log10(1.0))),
'function_y':lambda u:
3.0*sin(2*pi*(log10(u)-log10(1.0))/
(log10(3.1623)-log10(1.0))),
'title':r'\Large $\sqrt{N}$',
'title_x_shift':-0.1,
'title_y_shift':0.75,
'tick_levels':5,
'tick_text_levels':4,
'scale_type':'log smart',
'turn_relative':True,
# new script added below
'grid_length_0':1.20,
'grid_length_1':0.90,
'grid_length_2':0.6,
'grid_length_3':0.45,
'grid_length_4':0.3,
'grid_length_5':0.25,
'text_distance_0':1.25,
'text_distance_1':0.95,
'text_distance_2':0.65,
'text_distance_3':0.45,
'text_distance_4':0.35,
'text_distance_5':0.3,
'text_size_0': text.size.scriptsize,
'text_size_1': text.size.tiny,
'extra_angle':90,
'text_horizontal_align_center':True,
'full_angle':True,
'axis_color':color.cmyk.Red,
'text_color':color.cmyk.Red,
'title_color':color.cmyk.Red,
}
Square_Root_block_params={
'block_type':'type_8',
'f_params':Square_Root_params,
'width':15.0,
'height':15.0,
}
Inverse_N_params={
'u_min':0.101,
'u_max':1.0,
'base_start':0.1,
'base_stop':1.0,
'function_x':lambda u:
7.0*cos(-2*pi*(log10(u)-log10(0.1))/
(log10(1.0)-log10(0.1))),
'function_y':lambda u:
7.0*sin(-2*pi*(log10(u)-log10(0.1))/
(log10(1.0)-log10(0.1))),
'title':r'\LARGE $1/N$',
'title_x_shift':-0.2,
'title_y_shift':-1.65,
'tick_levels':5,
'tick_text_levels':2,
'scale_type':'linear smart',
'turn_relative':True,
# new script added below
'grid_length_0':1.20,
'grid_length_1':0.90,
'grid_length_2':0.6,
Cube_Root_block_params={
'block_type':'type_8',
'f_params':Cube_Root_params,
'width':15.0,
'height':15.0,
}
42
'grid_length_3':0.45,
'grid_length_4':0.3,
'grid_length_5':0.25,
'text_distance_0':1.25,
'text_distance_1':0.95,
'text_distance_2':0.65,
'text_distance_3':0.45,
'text_distance_4':0.35,
'text_distance_5':0.3,
'text_size_0': text.size.scriptsize,
'text_size_1': text.size.tiny,
'extra_angle':90,
'text_horizontal_align_center':True,
'full_angle':True,
'axis_color':color.cmyk.Orange,
'text_color':color.cmyk.Orange,
'title_color':color.cmyk.Orange,
}
}
Square_params={
'u_min':1.0,
'u_max':99.999,
'base_start':1.0,
'base_stop':100.0,
'function_x':lambda u:
11.0*cos(2*pi*(log10(u)-log10(1.0))/
(log10(100.0)-log10(1.0))),
'function_y':lambda u:
11.0*sin(2*pi*(log10(u)-log10(1.0))/
(log10(100.0)-log10(1.0))),
'title':r'\LARGE $N^2$',
'title_x_shift':-0.5,
'title_y_shift':-1.2,
'tick_levels':5,
'tick_text_levels':4,
'scale_type':'linear smart',
'tick_side':'left',
'turn_relative':True,
# new script added below
'grid_length_0':1.20,
'grid_length_1':0.90,
'grid_length_2':0.6,
'grid_length_3':0.45,
'grid_length_4':0.3,
'grid_length_5':0.25,
'text_distance_0':1.25,
'text_distance_1':0.95,
'text_distance_2':0.65,
'text_distance_3':0.45,
'text_distance_4':0.35,
'text_distance_5':0.3,
'text_size_0': text.size.scriptsize,
'text_size_1': text.size.tiny,
'extra_angle':90,
'text_horizontal_align_center':True,
'full_angle':True,
'axis_color':color.cmyk.OliveGreen,
'text_color':color.cmyk.OliveGreen,
'title_color':color.cmyk.OliveGreen,
}
Inverse_N_block_params={
'block_type':'type_8',
'f_params':Inverse_N_params,
'width':15.0,
'height':15.0,
}
N_params={
'u_min':1.0,
'u_max':9.9999,
'base_start':1.0,
'base_stop':9.9999,
'function_x':lambda u:
7.0*cos(2*pi*log10(u)/log10(10.0)),
'function_y':lambda u:
7.0*sin(2*pi*log10(u)/log10(10.0)),
'title':r'\huge $N$',
'title_x_shift':-0.15,
'title_y_shift':0.95,
'tick_levels':5,
'tick_text_levels':4,
'scale_type':'linear smart',
'turn_relative':True,
# new script added below
'grid_length_0':1.20,
'grid_length_1':0.90,
'grid_length_2':0.6,
'grid_length_3':0.45,
'grid_length_4':0.3,
'grid_length_5':0.25,
'text_distance_0':1.25,
'text_distance_1':0.95,
'text_distance_2':0.65,
'text_distance_3':0.45,
'text_distance_4':0.35,
'text_distance_5':0.3,
'text_size_0': text.size.scriptsize,
'text_size_1': text.size.tiny,
'extra_angle':90,
'text_horizontal_align_center':True,
'full_angle':True,
'axis_color':color.cmyk.Orange,
'text_color':color.cmyk.Orange,
'title_color':color.cmyk.Orange,
}
Square_block_params={
'block_type':'type_8',
'f_params':Square_params,
'width':15.0,
'height':15.0,
}
Cube_params={
'u_min':1.0,
'u_max':999.999,
'base_start':1.0,
'base_stop':1000.0,
'function_x':lambda u:
11.0*cos(2*pi*(log10(u)-log10(1.0))/
(log10(1000.0)-log10(1.0))),
'function_y':lambda u:
11.0*sin(2*pi*(log10(u)-log10(1.0))/
(log10(1000.0)-log10(1.0))),
'title':r'\LARGE $N^3$',
'title_x_shift':2.2,
'title_y_shift':1.2,
'tick_levels':5,
'tick_text_levels':4,
'scale_type':'log smart',
'turn_relative':True,
# new script added below
N_block_params={
'block_type':'type_8',
'f_params':N_params,
'width':15.0,
'height':15.0,
43
'grid_length_0':1.20,
'grid_length_1':0.90,
'grid_length_2':0.6,
'grid_length_3':0.45,
'grid_length_4':0.3,
'grid_length_5':0.25,
'text_distance_0':1.25,
'text_distance_1':0.95,
'text_distance_2':0.65,
'text_distance_3':0.45,
'text_distance_4':0.35,
'text_distance_5':0.3,
'text_size_0': text.size.scriptsize,
'text_size_1': text.size.tiny,
'extra_angle':90,
'text_horizontal_align_center':True,
'full_angle':True,
'axis_color':color.cmyk.OliveGreen,
'text_color':color.cmyk.OliveGreen,
'title_color':color.cmyk.OliveGreen,
}
Inverse_Area_block_params={
'block_type':'type_8',
'f_params':Inverse_Area_params,
'width':15.0,
'height':15.0,
}
Area_params={
'u_min':3.14159,
'u_max':314.15,
'base_start':3.14159,
'base_stop':314.15,
'function_x':lambda u:
15.0*cos(2*pi*(log10(u)-log10(3.14159))/
(log10(314.159)-log10(3.14159))),
'function_y':lambda u:
15.0*sin(2*pi*(log10(u)-log10(3.14159))/
(log10(314.159)-log10(3.14159))),
'title':r'\Large $R \Rightarrow Area$',
'title_x_shift':-0.75,
'title_y_shift':0.85,
'tick_levels':5,
'tick_text_levels':4,
'scale_type':'linear smart',
'turn_relative':True,
# new script added below
'grid_length_0':1.20,
'grid_length_1':0.90,
'grid_length_2':0.6,
'grid_length_3':0.45,
'grid_length_4':0.3,
'grid_length_5':0.25,
'text_distance_0':1.25,
'text_distance_1':0.95,
'text_distance_2':0.65,
'text_distance_3':0.45,
'text_distance_4':0.35,
'text_distance_5':0.3,
'text_size_0': text.size.scriptsize,
'text_size_1': text.size.tiny,
'extra_angle':90,
'text_horizontal_align_center':True,
'full_angle':True,
'axis_color':color.cmyk.RoyalBlue,
'text_color':color.cmyk.RoyalBlue,
'title_color':color.cmyk.RoyalBlue,
}
Cube_block_params={
'block_type':'type_8',
'f_params':Cube_params,
'width':15.0,
'height':15.0,
}
Inverse_Area_params={
'u_min':0.5642,
'u_max':1.7841,
'base_start':0.5642,
'base_stop':1.7841,
'function_x':lambda u:
15.0*cos(-2*pi*(log10(u)-log10(0.5642))/
(log10(1.7841)-log10(0.5642))),
'function_y':lambda u:
15.0*sin(-2*pi*(log10(u)-log10(0.5642))/
(log10(1.7841)-log10(0.5642))),
'title':r'\Large $Area N \Rightarrow R$',
'title_x_shift':0.0,
'title_y_shift':-1.5,
'tick_levels':5,
'tick_text_levels':3,
'scale_type':'linear smart',
'turn_relative':True,
# new script added below
'grid_length_0':1.20,
'grid_length_1':0.90,
'grid_length_2':0.6,
'grid_length_3':0.45,
'grid_length_4':0.3,
'grid_length_5':0.25,
'text_distance_0':1.25,
'text_distance_1':0.95,
'text_distance_2':0.65,
'text_distance_3':0.45,
'text_distance_4':0.35,
'text_distance_5':0.3,
'text_size_0': text.size.scriptsize,
'text_size_1': text.size.tiny,
'extra_angle':90,
'text_horizontal_align_center':True,
'full_angle':True,
'axis_color':color.cmyk.RoyalBlue,
'text_color':color.cmyk.RoyalBlue,
'title_color':color.cmyk.RoyalBlue,
}
Area_block_params={
'block_type':'type_8',
'f_params':Area_params,
'width':15.0,
'height':15.0,
}
Inverse_Volume_params={
'u_min':0.62035,
'u_max':1.3365,
'base_start':0.1,
'base_stop':1.0,
'function_x':lambda u:
19.0*cos(-2*pi*(log10(u)-log10(0.62035))/
(log10(1.3365)-log10(0.62035))),
'function_y':lambda u:
19.0*sin(-2*pi*(log10(u)-log10(0.62035))/
(log10(1.3365)-log10(0.62035))),
'title':r'\Large $Volume N \Rightarrow R$',
'title_x_shift':-0.15,
'title_y_shift':-1.2,
'tick_levels':5,
44
'tick_text_levels':4,
'scale_type':'log smart',
'turn_relative':True,
# new script added below
'grid_length_0':1.20,
'grid_length_1':0.90,
'grid_length_2':0.6,
'grid_length_3':0.45,
'grid_length_4':0.3,
'grid_length_5':0.25,
'text_distance_0':1.25,
'text_distance_1':0.95,
'text_distance_2':0.65,
'text_distance_3':0.45,
'text_distance_4':0.35,
'text_distance_5':0.3,
'text_size_0': text.size.scriptsize,
'text_size_1': text.size.tiny,
'extra_angle':90,
'text_horizontal_align_center':True,
'full_angle':True,
'axis_color':color.cmyk.RedViolet,
'text_color':color.cmyk.RedViolet,
'title_color':color.cmyk.RedViolet,
}
'turn_relative':True,
# new script added below
'grid_length_0':1.20,
'grid_length_1':0.90,
'grid_length_2':0.6,
'grid_length_3':0.45,
'grid_length_4':0.3,
'grid_length_5':0.25,
'text_distance_0':1.25,
'text_distance_1':0.95,
'text_distance_2':0.65,
'text_distance_3':0.45,
'text_distance_4':0.35,
'text_distance_5':0.3,
'text_size_0': text.size.scriptsize,
'text_size_1': text.size.tiny,
'extra_angle':90,
'text_horizontal_align_center':True,
'full_angle':True,
'axis_color':color.cmyk.RedViolet,
'text_color':color.cmyk.RedViolet,
'title_color':color.cmyk.RedViolet,
}
Volume_block_params={
'block_type':'type_8',
'f_params':Volume_params,
'width':15.0,
'height':15.0,
}
Inverse_Volume_block_params={
'block_type':'type_8',
'f_params':Inverse_Volume_params,
'width':15.0,
'height':15.0,
}
main_params={
'filename':'Type8-ColorDial-Smart.pdf',
'paper_height':30.0,
'paper_width':30.0,
'block_params':[CenterHole_block_params,
Cube_Root_block_params,Square_Root_block_params,
Inverse_N_block_params,N_block_params,
Square_block_params,Cube_block_params,
Inverse_Area_block_params,Area_block_params,
Inverse_Volume_block_params,Volume_block_params,],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x': 2,
'title_y': 1.5,
'title_box_width': 6,
'title_color':color.cmyk.Sepia,
'title_str':r'\huge Powers, Roots and Circle Formulas',
}
Volume_params={
'u_min':4.1888,
'u_max':4188.8,
'base_start':1.0,
'base_stop':1000.0,
'function_x':lambda u:
19.0*cos(2*pi*(log10(u)-log10(4.1888))/
(log10(4188.8)-log10(4.1888))),
'function_y':lambda u:
19.0*sin(2*pi*(log10(u)-log10(4.1888))/
(log10(4188.8)-log10(4.1888))),
'title':r'\Large $R \Rightarrow Volume$',
'title_x_shift':3.8,
'title_y_shift':1.5,
'tick_levels':5,
'tick_text_levels':3,
'scale_type':'log smart',
Nomographer(main_params)
45
R V olume
25
30
35
40
10
5
9.
5
8.
5
7.
5
5.
0.7
9
0.7
8
0.75
0.74
0.77
0.76
950
650
46
850
750
700
800
900
1000
7
6.5
6
5.5
5
4.5
4000
305
295
3500
285
275
270
260
265
255
245
300
240
23
5
5
230
22
0
00
25
0
22
5
21
5
20
0
5
19
5
18
0
18
00
15
280 290
300 310
1.3
1.2
1.1
950
900
850
800
750
700
60
0
0.73
550
600
55
0
0
50
2
0.7
500
3.5
1.5
1.4
0
65
0.79
250
9
1.
8
1.
7
1.
1.6
1.1
9.5
9
8.5
45
15
.5
15
.5 16
16
5 7
7. 1
0.
83
45
120
110
20
3
2.
2
2.
1
2.
3
1.
25
1.
2
1.
1.05
0.
4
5
1.1
0.35
7.5
8
8.5
9.5
1
1.
1.
15
6.
5
0.
82
0.
8
105
100
14
130
71
0.
1.
14
1.
13
25
0.
0.78
0.77
89
0.
7.
5
0.76
1
1.
12
10
1.5
0.75
0.74
0.
98
1.1
.5 13
13
.5 14
14
0.73
1.0
9
0.8
1
0.72
0.
99
12.5 12
3.1
1
0.7
0.
86
0.
85
0.
84
0.8
1.4
0.7
69
0.
26
29 28
27
1.05
10.5
0.3
6
1.
34 33 32 31
95
90
16
15
7
0.
35
37 36
11
68
0.
23
24 .5 2
23 2.5
2
22 1.5
21 20.
5
25
30
39 38
0.
97
11.5
2.
9
67
0.
9
0.
2.
8
66
0.
24
0.
82
0.
81
5
13
115
17
15
5
14
125
85
17
5
16
0.
68
30
75
80
40
30
69
0.
40
4
43
19
.5
19 18
.5
18
88
0.
44
20
87
0.
45
27
260
240 50
2
0 230
210 22
200
65
70
50
55
140
150
64
55
3
0.9
0.2
92
0.
15
0.
91
0.
1.7
1.8
0.96
9
1.
0.98 0.99
5
1.
0.97
1.4
5
0.9
1.3
1.
2
1.0
8
35
2.
1.0
6 1
.07
3
25 2.
2.
4
0.9
1.
35
1.
11
15 2.2
2.
5
2.0 2.1
54
130
029
028
120
0.
67
53
0.
65
52
50
51
83
0.
1.5
5
1.
45
1.
4
13
49
11
10
40
0
35
0.
66
0.
64
48
25
84
0.
1.95
0.9
6
1.85
1.75
12
0.9
5
1.
5
1.65
17
.5
17
11
1.9
5.5
0.6
5
6.5
5.65.75.85.9
0.6
1
2 5.35.4
0.
63
47
70
46
45
5.1 5.
0.
62
4.9
0.64
0.6
4.8
60
65
44
85
0.
0.59
75
2
4.
65
1
4.
60
43
95
4.
7
0.63
80
70
9
3.
55
42
85
4.
6
0.58
85
8
3.
50
41
86
0.
1.6
.5
16
0.94
10
5
9.
1.8
16
0.93
3.5
1.7
15
.5
15
7.5
90
3.7
39
200
75
4.
4
4.
5
0.57
95
3.6
38
40
7
0.8
6.5
55
14
.5
14
8.5
2.
4
2. 2
5 .6
2.
72
.8
2.
9
3.5
2.5
1.3
0.95
2.1
3.4
1.9
3.3
45
37
2.4
1.78
1.77
1.74 1.76
721.73
1.711.
1.75
0.9
1.8
3.2
40
36
6
2.
2.3
1.7
5
0.8
1
1.
1.7
3.1
35
35
7
2.
2.
1
2.2
9
81.6
71.6
61.6
8
0.
1.
6
N 1/3
1.6
64
5
31.
1.6
.6
621
1.
61
1.
0.
7
1.2
3
1.
5
1.
0.6
5
75
0.
2.
55
2. 2.6
6
5
2.7 2.75
2
2.8 .85 2.95
2.9
0.92
4.5
0.55
2. 2
4 .4
5
2.
5
19
0.91
5.5
2.5
6
1.
15
18
24
30
34
0.9
.5
13
14
17
21
22
23
26 27
28 29
33
0.89
1/N 0.6
0.5
45
0.
1.
51
1.
52
1.
53
1.
5
1.
5
16
20
25
30
150
0.88
1.
46
1.
47
1.
48
1.
49
59
1.
58
1.
57
1.
56
1.
20
.5
21 21
.5
22 22.
5
23 2
3.5
2
24 4.5
25.5
26.5
26
27.5
25
28.5 29.5
27
30.5 31.5
28
29
31
32
100
63
6.
5
1.4
5
1.4
21
13
7.5
1.4
11.4
21.4
31.4
4
55
1.
N2
4.
3
90
62
1.
2
1.381.
39
5
4.
12.5
1.361.37
N3
5
4.
5
5.
59
61
1.35
20
12
11.5
4
1.2 1.25
1.34
AreaN R
1.3
3.5
80
60
8.5
2
1.
23
1.
1.29
1.28
19
0
50
11
19
18
.5
19
.5
20
75
85
95
58
10.5
19
1.
18
1.
9.5
18
17
1.
22
1.
7
1.2
10
45
R Area
65
70
80
90
57
35
15
60
6
1.2
21
1.
16
1.
56
20
1.1
V olumeN R
Notice that in this last color dial script we repeat a certain set of scale parameters in nearly every scale.
Normally a nomogram would consist of fewer scales, so repeating the parameters is not an issue, but there
is a way to define a set of default parameters that can be loaded into each scale. The scale can then override
any default parameter by simpy re-defining it. This can save some lines in the script.
The default parameters are listed at the beginning of the script in a new set of parameters called default_params. Each scale that loads these defaults has a line of script that copies them in, and then the script uses an
update command to define the rest of its parameters (or re-define any default parameters). Below is the first
part of the previous color dial script that has been modified for default values. The CenterHole scale does not
use these default parameters at all, so it does not use the copy and update mechanism. The Cube_Root scale,
like all the other scales, does load the defaults, so Cube_Root_params=copy.deepcopy(default_params)
is added prior to defining the scale parameters. The scale parameters name now has .update added at the
end, which is not included when the scale is included in the block parameters, and the list of parameters
in braces is now inserted between the parentheses of the update function. The parameters for this scale are
now expressed as Cube_Root_params.update({...}) rather than Cube_Root_params={...}, and this
procedure is followed for all the other scales.
To reduce page count, the full script and PDF graphic output are not listed here, but they are available
online for download.32 You will see that the nomogram is identical to our previous color dial but the script
size has been reduced from 519 to 360 lines.
### Type8-ColorDial-Smart-Defaults.py ###
'f_params':CenterHole_params,
'width':15.0,
'height':15.0,
}
Cube_Root_params=copy.deepcopy(default_params)
Cube_Root_params.update({
'u_min':1.0,
'u_max':2.15,
'base_start':1.0,
'base_stop':10.0,
'function_x':lambda u:
3.0*cos(2*pi*(log10(u)-log10(1.0))/
(log10(2.1544)-log10(1.0))),
'function_y':lambda u:
3.0*sin(2*pi*(log10(u)-log10(1.0))/
(log10(2.1544)-log10(1.0))),
'title':r'\Large $N^{1/3}$',
'title_x_shift':-0.05,
'title_y_shift':-1.3,
'tick_levels':5,
'tick_text_levels':4,
'scale_type':'log smart',
'tick_side':'left',
'axis_color':color.cmyk.Red,
'text_color':color.cmyk.Red,
'title_color':color.cmyk.Red,
})
CenterHole_params={
'u_min':0.0,
'u_max':1.0,
'function_x':lambda u:0.05*cos(2*pi*u),
'function_y':lambda u:0.05*sin(2*pi*u),
'title':r'',
'tick_levels':0,
'tick_text_levels':0,
}
Cube_Root_block_params={
'block_type':'type_8',
'f_params':Cube_Root_params,
'width':15.0,
'height':15.0,
}
CenterHole_block_params={
'block_type':'type_8',
32 http://www.myreckonings.com/pynomo11/Type8-ColorDial-Smart-Defaults.py
and http://www.myreckonings.com/pynomo11/Type8-ColorDial-Smart-Defaults.pdf
47
12
Weve seen in earlier sections nomograms with pivot lines for an equation of the form f1 (u1 ) + f2 (u2 ) +
... + fn (un ) = 0. This is a Type 3 nomogram directly supported by PyNomo. However, there are times when
the scale values on the pivot lines are important. For example, consider another relationship in electro-optics
between the camera Photocathode Illuminance, Scene Exitance (the reflected light off the target) and the Lens
F/No. when the lens transmission is 90% and the image magnification on the focal plane is approximately
zero:
Scene Exitance 90%
Photocathode Illuminance =
4 Lens F/No.2
But we also have a relationship between the Scene Exitance, Target Reflectivity, and Scene Illuminance:
Scene Exitance = Scene Illuminance Target Reflectivity
So we have two three-variable equations sharing one variable. If substitute the second equation into the
first to get a single equation, we can use the Type 3 format with pivot lines to draw it (after converting it to a
sum of logarithms) but weve lost the intermediate variable Scene Exitance which is an important parameter
of the engineering problem.
Therefore, for each equation we need to create a separate Type 1 three-line nomogram block, and then
tag the Scene Exitance scale in each of the two nomogram blocks with the same name so they align on top
of each other. This is simply a procedure to connect two Type 1 nomograms, so there is no separate Type
number in PyNomo for this combination.
The example for the equations above is shown on the next two pages. It defines two blocks of Type 1,
with the tag exitance assigned to the Scene Exitance scale in each block. Only one of these blocks provides
the title, and one has the tick marks on the left side and the other on the right. The main parameters list
both blocks as part of the nomogram. The scale parameter extra_params is used to place additional arrows at
specific scale values by specifying manual arrow as the scale_type. We also introduce a new parameter here:
arrow_length: the length in cm of the arrows (default is 1.0)
Here the second line of the title is printed with the extra_texts parameter.
The tick marks and labels are printed on the Scene Exitance scale by both Type 1 blocks in order to make
sure that they are identically aligned. Once we see that this is the case, we can comment out these lines in one
of the blocks so we only have one set of tick marks. The result is shown in the second example on the third
and fourth pages after this, where tick_levels and tick_text_levels are set to 0 for the Scene Exitance scale
in the second block. The tick labels also seem excessively dense in the first example, so the tick_text_levels
parameters are reduced to 1 instead of 2. As you can see, the second nomogram is much cleaner than the first
one without any loss of precision.
These PyNomo scripts and output PDF graphics are available online for download.33
33 http://www.myreckonings.com/pynomo11/CompoundType1-Example.py
and http://www.myreckonings.com/pynomo11/CompoundType1-Example.pdf
34 http://www.myreckonings.com/pynomo11/CompoundType1-Final.py
and http://www.myreckonings.com/pynomo11/CompoundType1-Final.pdf
48
34
}],
}
},
Target_Reflectivity_params={
'u_min':1.0,
'u_max':100.0,
'function':lambda u:-log10(0.01*u),
'scale_type':'log',
'title':r'Target Reflectivity (\%)',
'title_y_shift':0.7,
'tick_levels':2,
'tick_text_levels':2,
}
FNumber_params={
'u_min':0.5,
'u_max':5.0,
'function':lambda u:2*log10(u),
'scale_type':'log',
'title':r'Lens F/No.',
'title_y_shift':0.7,
'tick_levels':2,
'tick_text_levels':2,
}
Scene_Exitance_2_params={
'tag':'exitance',
'u_min':0.00001,
'u_max':1.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'',
'title_y_shift':0.7,
'tick_side':'left',
# Duplicate labels
'tick_levels':2,
# Duplicate labels
'tick_text_levels':2,
# Duplicate labels
}
Scene_Exitance_1_params={
'tag':'exitance',
'u_min':0.00001,
'u_max':1.0,
'function':lambda u:-log10(0.225*u),
'scale_type':'log',
'title':r'Scene Exitance (lumen/m$^2$)',
'title_y_shift':0.7,
'tick_side':'right',
'tick_levels':2,
'tick_text_levels':2,
}
block_12_params={
'block_type':'type_1',
'width':15.0,
'height':15.0,
'f1_params':Scene_Exitance_2_params,
'f2_params':Target_Reflectivity_params,
'f3_params':Scene_Illuminance_params,
}
block_11_params={
'block_type':'type_1',
'width':15.0,
'height':15.0,
'f1_params':Scene_Exitance_1_params,
'f2_params':FNumber_params,
'f3_params':Photocathode_Illuminance_params,
}
Nomographer(main_params)
49
50
005
005
005
005
005
0.0001
0.001
0.01
0.1
1e 005
2e 005
3e 005
4e 005
9e
8e
7e
6e
5e
0.0002
0.0003
0.0004
0.0009
0.0008
0.0007
0.0006
0.0005
0.002
0.003
0.004
0.009
0.008
0.007
0.006
0.005
0.02
0.03
0.04
0.09
0.08
0.07
0.06
0.05
0.2
10
100
10
0.1
0.01
0.001
0.0005
0.0006
0.0007
0.0008
0.0009
0.4
0.5
0.6
0.7
0.8
0.9
0.4
0.5
0.6
0.7
0.8
0.9
0.3
0.05
0.06
0.07
0.08
0.09
0.05
0.06
0.07
0.08
0.09
0.3
0.04
0.04
0.2
0.03
0.03
0.2
0.02
0.005
0.006
0.007
0.008
0.009
0.02
0.004
0.005
0.006
0.007
0.008
0.009
0.003
0.004
0.003
0.002
0.0004
0.0005
0.0006
0.0007
0.0008
0.0009
0.002
0.0003
0.0004
0.0002
0.0003
0.0002
0.1
0.01
0.001
0.0001
005
005
005
005
005
0.5
0.6
0.7
0.8
0.9
Lens F/No.
30
40
50
60
70
80
90
20
3
4
5
6
7
8
9
0.0001
4e 005
5e
6e
7e
8e
9e
3e 005
005
005
005
005
005
4e 005
3e 005
5e
6e
7e
8e
9e
2e 005
1e 005
2e 005
1e 005
005
005
005
005
005
0.0001
0.001
0.01
0.1
1e 005
006
006
006
006
006
1e 006
007
007
007
007
007
1e 007
2e 007
3e 007
4e 007
9e
8e
7e
6e
5e
2e 006
3e 006
4e 006
9e
8e
7e
6e
5e
2e 005
3e 005
4e 005
9e
8e
7e
6e
5e
0.0002
0.0003
0.0004
0.0009
0.0008
0.0007
0.0006
0.0005
0.002
0.003
0.004
0.009
0.008
0.007
0.006
0.005
0.02
0.03
0.04
0.09
0.08
0.07
0.06
0.05
Photocathode Illuminance = (Scene Exitance 90% Lens Transmission) / (4 Lens F/No.2 (1 + 0.0 Magnification))
Clear No Moon
0.3
0.4
0.9
0.8
0.7
0.6
0.5
9
8
7
6
5
}],
}
},
Target_Reflectivity_params={
'u_min':1.0,
'u_max':100.0,
'function':lambda u:-log10(0.01*u),
'scale_type':'log',
'title':r'Target Reflectivity (\%)',
'title_y_shift':0.7,
'tick_levels':2,
'tick_text_levels':1,
}
FNumber_params={
'u_min':0.5,
'u_max':5.0,
'function':lambda u:2*log10(u),
'scale_type':'log',
'title':r'Lens F/No.',
'title_y_shift':0.7,
'tick_levels':2,
'tick_text_levels':2,
}
Scene_Exitance_2_params={
'tag':'exitance',
'u_min':0.00001,
'u_max':1.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'',
'title_y_shift':0.7,
'tick_side':'left',
'tick_levels':0,
# Don't draw duplicate ticks
'tick_text_levels':0, # Don't draw duplicate labels
}
Scene_Exitance_1_params={
'tag':'exitance',
'u_min':0.00001,
'u_max':1.0,
'function':lambda u:-log10(0.225*u),
'scale_type':'log',
'title':r'Scene Exitance (lumen/m$^2$)',
'title_y_shift':0.7,
'tick_side':'right',
'tick_levels':2,
'tick_text_levels':1,
}
block_12_params={
'block_type':'type_1',
'width':15.0,
'height':15.0,
'f1_params':Scene_Exitance_2_params,
'f2_params':Target_Reflectivity_params,
'f3_params':Scene_Illuminance_params,
}
block_11_params={
'block_type':'type_1',
'width':15.0,
'height':15.0,
'f1_params':Scene_Exitance_1_params,
'f2_params':FNumber_params,
'f3_params':Photocathode_Illuminance_params,
}
Nomographer(main_params)
51
52
1e 005
0.0001
0.001
0.01
0.1
0.1
0.01
0.001
0.5
0.6
0.7
0.8
0.9
Lens F/No.
100
10
0.0001
1e 005
1e 007
1e 006
1e 005
0.0001
0.001
0.01
0.1
Photocathode Illuminance = (Scene Exitance 90% Lens Transmission) / (4 Lens F/No.2 (1 + 0.0 Magnification))
Clear No Moon
10
13
53
The order of blocks and the order of scales in each block are important for arranging the scales, and the
tick side for the ladder determines which side the curves originate on, so you may have to build the nomogram
up in pieces and experiment to get these correct. I found I had to set the mirror_x block parameter to True
in the block parameters for the ladder. The T-scale was broken into two parts using the extra_params scale
parameter in order to swap the label sides for better readability. Notice also that the T-scale, which has a 1/u
function associated with it, is drawn as a log scale, which reduces the size of the labels other than 0.10, 1.00
and 10.00 so they dont collide with each other.
We have drawn isopleths on this nomogram, which always produces straight lines connecting the two
sides of the ladder. If we had omitted the isopleth commands the connections would have been curved lines
as in the example above (which I prefer, but I wanted to show how to add isopleths to a Type 6 nomogram).
Notice that since we defined the isopleth intersection value at the ladder end of the first block, the ladder
block must include an isopleth_values parameter in which the two values are the calculated (denoted by x).
The PyNomo scripts and output PDF graphics are available online for download.37
'tag':'r1-scale',
'u_min':1.0,
'u_max':10.0,
'function':lambda u:log(u),
'title':r'\Large $R$',
'tick_levels':0,
'tick_text_levels':0,
}
Type2_params={
'block_type':'type_2',
'width':10.0,
'height':10.0,
'f1_params':S_params,
'f2_params':T_params,
'f3_params':R1_params,
'isopleth_values':[[6,'x',3.5]],
}
T_params={
'u_min':0.1,
'u_max':20.0,
'function':lambda u:1.0/u,
'scale_type':'log',
'title':r'\Large $T$',
'tick_levels':0,
'tick_text_levels':0,
'title_distance_center':0.75,
'title_draw_center':True,
'extra_params':[
{
'u_min':0.1,
'u_max':0.9,
'tick_levels':3,
'tick_text_levels':2,
'tick_side':'left',
},
{'u_min':1.0,
'u_max':20.0,
'tick_levels':4,
'tick_text_levels':2,
'tick_side':'right'
},
]
}
R1_params={
37 http://www.myreckonings.com/pynomo11/Type6-Isopleths.py
and http://www.myreckonings.com/pynomo11/Type6-Isopleths.pdf
54
'f1_params':R1_Ladder_params,
'f2_params':R2_Ladder_params,
'width':5.0,
'height':10.0,
'mirror_x':True,
'isopleth_values':[['x','x']],
}
Type3_params={
'block_type':'type_1',
'width':10.0,
'height':10.0,
'f1_params':R2_params,
'f2_params':W_params,
'f3_params':Q_params,
'isopleth_values':[[3.5,'x',6]],
}
main_params={
'filename':'Type6-Isopleths.pdf',
'paper_height':13.0,
'paper_width':20.0,
'block_params':[Type2_params,Ladder_params,Type3_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x':10.0,
'title_y':-1.5,
'title_box_width': 5.0,
'title_str':r'\LARGE $R = S^T$',
'extra_texts':[
{'x':7.6,
'y':-2.7,
'text':'\LARGE $Q = R + W$',
'width':5,
}],
'isopleth_params':[
{'color':'black',
'linewidth':'thin',
'linestyle':'dashed',
'circle_size':0.07,
'transparency':0.25,
},
],
}
W_params={
'u_min':-10.0,
'u_max':10.0,
'function':lambda u:-u,
'title':r'\Large $W$',
'tick_levels':3,
'tick_text_levels':1,
}
Q_params={
'u_min':0.0,
'u_max':10.0,
'function':lambda u:u,
'title':r'\Large $Q$',
'tick_levels':3,
'tick_text_levels':1,
}
Nomographer(main_params)
55
56
10
20
8
9
10
0.
9
0.
8
0.
7
0.
6
0.
5
0.
4
0.
3
10
9.5
8.5
7.5
6.5
5.5
4.5
3.5
2.5
R = ST
Q=R+W
9.5
8.5
7.5
6.5
5.5
4.5
3.5
2.5
1.5
1.5
0.
2
R
0.5
0.1
10
10
10
10
14
A Type 4 nomogram represents a proportional relationship between four functions of individual variables.
The form of equation for this nomogram is
f1 (u1 )
f3 (u3 )
=
f2 (u2 )
f4 (u4 )
We will use this type of nomogram to graph the Law of Sines for a triangle:
B
A
=
sin
sin
where A and B are two sides of a triangle and and are the vertex angles opposite A and B. All three sides
have this relationship A/sin = B/sin = C/sin , so the complete triangle can be defined if two angles and a side
are known, a common problem when doing triangulation as part of a survey.
Again, we can simply modify the Type 4 example given on the PyNomo site.38 The following two pages
show the script and nomogram. To use it, a straightedge is placed across the known values of, say, A and
in degrees, and a pencil mark is made on the diagonal pivot line. Then the straightedge is placed across the
third known value (say B) and the mark, and the fourth value is found by its intersection with that scale.
Once is found, we can find the third angle as = 180 , and then we can use that angle on either
scale and the same mark on the diagonal to find the remaining side C.
We are using here the title_draw_center scale parameter that moves the title along the scale to its center,
and the title_distance_center that places it a distance from the scale (by default 0.5cm but I felt the and
symbols were too close to the scale with this default value). I also felt that the degree sign was too close to
those symbols, so I added a thin space (\thinspace) between them. The title_opposite_tick parameter places
the title on the opposite side of the scale from the ticks. The \ symbol preceding sin and cos in the title simply
prints them out as non-italic text even within math mode (i.e., within $ signs).
As described in the section on color on page 35, we have also set the reference_color parameter in
block_1_params to define the color of the diagonal reference line (to orange here).
There are two new block parameters for this Type 4 nomogram that are omitted in this example to accept
their default values:
float_axis: if set to F1 or F2 scaling is done based on those two scales, otherwise its based on the F3
and F4 scales (default is F1 or F2)not set in this example
padding: the length of the scales as a fraction of the width and height, providing some space between
the upper ends of the scales (default = 0.9)not set in this example
Earlier we saw how to add an isopleth to a nomogram as a guide for using it. This example shows how a
pair of sample isopleths are added to a proportion nomogram.
Adding a Key
Another very common guide, of particular use when the isopleth or isopleths make the nomogram harder
to read or use, is to provide a key in the nomogram. A key is a small graphic showing the scale lines and
38 http://www.pynomo.org/wiki/index.php/Type_4
57
15
14
13
12
11
10
14.5
13.5
12.5
11.5
10.5
9.5
8.5
7.5
6.5
5.5
4.5
3.5
2.5
1.5
0.5
0.5
1.5
2.5
23
22.5
22
30
40
50
60
70
80
19.5
20
sample isopleths (and sometimes there is helpful text as well). In this example the line_params entries in
main parameters produce a key for the use of the nomogram. The key is drawn inside the nomogram
21
because theres room for it there. Theres no reason to include both the sample isopleths and the key on a
20.5nomogram, but they are both included here simply as a demonstration. This nomogram is shown with only
the key included in the example on page 98.
20
21.5the
can
The new parameters introduced here for creating lines for thekey
be included in the main parameters of any nomogram type:
19
18.5
18
10
17.5
17
16.5
16
make_grid: if True, overlay a grid in cm and mm over the nomogram so that start and end coordinates of lines can be easily determined by zooming in, as shown in the figure on this page (False by
15.5
15
14.5
default)
14
13.5
13
12.5
12
11.5
11
10.5
9.5
8.5
circle_size:
5 the radius in cm of circles centered on the starting and ending points of the line segments,
with a default of 0.0 for no circles
7.5
circle_color: the color of circles at the starting and ending points of the line segments, with a default
of black
9
8
7
6
5
line_style:6 the style of the line segments, consisting of their color (e.g., color.cmyk.Gray), linewidth
(e.g., style.linewidth.thin), and form (e.g., style.linestyle.dashed), with defaults of black,
thick and dashed
10
coords: the
7 x-y coordinates from the grid overlay of one or more line segments, the starting and ending
coordinates specified in square brackets for each segment, separated by commas. Connected segments
should include the ending coordinates of the previous segment as the starting coordinates of the new
segment, as in 'coords':[[0,6.33,6.67,4.82],[6.67,4.82,13.33,7.0],[13.33,7.0,20.0,6.29]],
There can be multiple line_params defined, each with different sub-parameters. The default values sup6.5
port standard black, dashed lines with no circles at their endpoints, in which case only coords needs to be
defined. The format of the color sub-parameters are described in the earlier section devoted to color. The
5.5
3
linewidth and linestyle
names are provided in the figure on page 18. The example script on the next page
shows values for all the sub-parameters to demonstrate their use.
4.5
4
3.5
This PyNomo script and output PDF graphic are available online for download.39
2
3
2.5
1
1.5
0
0.5
2.5
1.5
58
1
'f2_params':Alpha_params,
'f3_params':B_params,
'f4_params':Beta_params,
'isopleth_values':[[9,50,'x',23]],
}
main_params={
'filename':'Type4-Isopleths.pdf',
'paper_height':20.0,
'paper_width':20.0,
'block_params':[block_1_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x':10,
'title_y': -3.5,
'title_box_width': 10,
'title_str':r'\LARGE Law of Sines: \
$A / \sin \alpha=B / \sin \beta$',
'isopleth_params':[
{'color':'Blue',
'linewidth':'thin',
'linestyle':'dashed',
'circle_size':0.1,
'transparency':0.0,
},
],
'make_grid':False,
'draw_lines':True,
'line_params': [
{'coords':[[13,3.4,13,6.6],[17,3.4,17,7],
[13.4,3,16.6,3],[13.4,7,17,7]],
'line_style':[color.cmyk.Black,
style.linewidth.thick,
style.linestyle.solid],
'circle_size':0.0,
'circle_color':color.cmyk.Black,
},
{'coords':[[13,3,17,7]],
'line_style':[color.cmyk.Orange,
style.linewidth.thin,
style.linestyle.solid],
'circle_size':0.0,
'circle_color':color.cmyk.Orange,
},
{'coords':[[13,6,17,4],[14.5,3,15.5,7]],
'line_style':[color.cmyk.Blue,
style.linewidth.thin,
style.linestyle.dashed],
'circle_size':0.08,
'circle_color':color.cmyk.Blue,
},
],
}
block_1_params={
'block_type':'type_4',
'reference_color':color.cmyk.Orange,
'f1_params':A_params,
Nomographer(main_params)
59
10
20
30
40
50
60
70
80
10
10
9
8
20
30
5
40
4
50
3
60
2
70
80
1
10
60
15
is
1
1
1
=
+
f3 (u3 )
f1 (u1 ) f2 (u2 )
Here we will create a classic nomogram of this form for the equivalent resistance R of two resistors placed
in parallel:
1
1
1
+
=
R R1 R2
This relationship also exists for capacitors in series. Another common occurrence is the equivalent focal
length of lenses in series, and there are many others.
Again, we can simply modify the Type 7 example given on the PyNomo site.40 To extend this example
we will draw a nomogram for the equivalent resistance of either two or three resistors in parallel, where it
can be seen from extending the above formula that R1 = R11 + R12 + R13 . We simply create two Type 7 blocks
with the u3 scale of the first block aligned by a tag with the u1 block of the second block.
The following two pages show the script and nomogram. If we decide to scale it to a larger paper size,
the scales will likely not be the same length anymore and we would have to adjust the paper width or length
if we want them the same length (although they would work fine otherwise). A straightedge across R1 and
R2 crosses the middle scale R1 k R2 at the value of the equivalent resistance of these two resistors. Then if
there is a third resistor the straightedge is placed across that point on the R1 k R2 scale and the R3 scale, with
the intersection on the R1 k R2 k R3 scale (which happens to line up with the R2 scale because we chose 60
angles) providing the equivalent resistance of all three resistors.
We are introducing the following new parameters specific to a Type 7 nomogram:
angle_u: the angle in degrees between the u1 scale and the center u3 scale
angle_v: the angle in degrees between the u2 scale and the center u3 scale
When both angles are set to 60 the scales are identical on all three axes of a block, the most common
implementation of this type of nomogram. I was pleased to see that the two angles can be set independently,
as Ive spent quite a bit of time in the past trying to find out how to design a reciprocal nomogram with
unequal angles.
The \parallel TeX command produces the symbol for parallel in the scale titles. You can also see that the
x offset in the extra_titles parameter for the second row of the title is set to a negative number, as x = 0 for
an extra title lines up with the center of the first title.
Im rather tempted to add two more of these aligned blocks to get a full snowflake nomogram! Then we
could continue going around the snowflake as many times as needed for any number of resistors to find the
equivalent resistance.
This PyNomo script and output PDF graphic are available online for download.41
40 http://www.pynomo.org/wiki/index.php/Type_7
41 http://www.myreckonings.com/pynomo11/Type7-Isopleths.py
and http://www.myreckonings.com/pynomo11/Type7-Isopleths.pdf
61
'u_max':1000.0,
'function':lambda u:u,
'title':r'\Large $R_3$',
'text_format':r"$%4.0f$",
'title_x_shift':-10.0,
'tick_levels':4,
'tick_text_levels':2,
}
R1R2R3_params={
'u_min':0.0,
'u_max':1000.0,
'function':lambda u:u,
'title':r'\Large $R_1 \parallel R_2 \parallel R_3$',
'text_format':r"$%4.0f$",
'title_x_shift':0.5,
'title_y_shift':-4.0,
'tick_levels':0,
'tick_text_levels':0,
}
R2_params={
'u_min':5.0,
'u_max':1000.0,
'function':lambda u:u,
'title':r'\Large $R_2$',
'text_format':r"$%4.0f$",
'title_y_shift':0.5,
'tick_levels':4,
'tick_text_levels':2,
}
block_2_params={
'block_type':'type_7',
'width':20.0,
'height':20.0,
'angle_u':60,
'angle_v':60,
'f1_params':R1R2_params_2,
'f2_params':R3_params,
'f3_params':R1R2R3_params,
'isopleth_values':[['x',600,'x']],
}
R1R2_params_1={
'tag':'r1r2',
'u_min':5.0,
'u_max':1000.0,
'function':lambda u:u,
'title':r'\Large $R_1 \parallel R_2$',
'text_format':r"$%4.0f$",
'tick_levels':4,
'tick_text_levels':2,
}
main_params={
'filename':'Type7-Isopleths.pdf',
'paper_height':20.0,
'paper_width':20.0,
'block_params':[block_1_params,block_2_params],
'transformations':[('rotate',0.01)],
'title_x': 0.0,
'title_y': -3.0,
'title_box_width': 12,
'title_str':r'\Large Equivalent Resistance of 3\
Resistors in Parallel',
'extra_texts':[
{'x':-3.5,
'y':-3.7,
'text':r'\large $1/R = 1/R_1 + 1/R_2 + 1/R_3$',
'width':12.0,
}],
'isopleth_params':[
{'color':'Red',
'linewidth':'thin',
'linestyle':'dashed',
'circle_size':0.0,
'transparency':0.0,
},
],
}
block_1_params={
'block_type':'type_7',
'width':20.0,
'height':20.0,
'angle_u':60,
'angle_v':60,
'f1_params':R1_params,
'f2_params':R2_params,
'f3_params':R1R2_params_1,
'isopleth_values':[[650,900,'x']],
}
R1R2_params_2={
'tag':'r1r2',
'u_min':0.0,
'u_max':1000.0,
'function':lambda u:u,
'title':r'',
'text_format':r"$%4.0f$",
'tick_levels':0,
'tick_text_levels':0,
}
R3_params={
'u_min':0.0,
Nomographer(main_params)
62
R3
95
0
85
50
0
90
0
10
R1 k R2 k R3
R2
0
65
0
80
55
0
70
45
0
60
35
0
50
25
0
40
63
0
15
0
30
50
0
20
0
10
15
0
20
0
30
0
40
0
50
0
60
0
70
80
500
450
400
350
250
300
200
50
50
150
100
200
250
350
300
400
450
500
550
650
600
700
750
850
800
900
950
1000
10
0
100
150
50
25
0
35
0
45
0
55
0
65
0
75
0
85
95
90
00
10
R1 k R2
950
R1
1000
900
850
750
800
700
650
550
600
16
A Type 10 nomogram consists of two straight scales and one curved scale. The form of this nomogram
is f1 (u) + f2 (v) f3 (w) + f4 (w) = 0. We will use this type of nomogram to graph the equation
M=
T N
T2
If we multiply both sides of this equation by T 2 and arrange the terms on the left side, we get
N + MT 2 T = 0
From the general form above, you can see that this is a Type 10 nomogram where
u=N
v=M
w=T
f1 (u) = N
f2 (v) = M
f3 (w) = T 2
f4 (w) = T
Selecting the Type 10 link on the Software Documentation page42 shows an example script for this type of
nomogram for the equation u + vw + w = 0. Its fairly simple to modify the example for what we need.
However, the equation under consideration is not a friendly one, as the variable M can range from to ,
so the required ranges of the variables are very important in the design of the nomogram.
Lets assume a range of 10 < N < 10 and 4 < T < 4. Then M must range from to , so lets limit
it to 10 < M < 10. The script and nomogram are found on the next page.
Now lets change our ranges to 0 < N < 10 and 0 < T < 4 and limit M to 20 < M < 0. This nomogram
is shown on the second page following this one. Here PyNomo did much more for us than it first appears.
As we will see in the next section when we plot this nomogram in determinant form, the T-scale would
be expected to be roughly horizontal. But in addition to the scaling transformation to the paper size weve
discussed earlier, PyNomo actually performed a shear on the T-scale and M-scale upward so the M-scale is
aligned horizontally with the N-scale in order to maximize the size of the nomogram on the paper. (We also
had to shift the T-scale title to place it correctly in the output.)
The PyNomo script and output PDF graphic for both nomograms are available online for download.4344
42 http://pynomo.org/wiki/index.php?title=Type_10
43 http://www.myreckonings.com/pynomo11/Type10-Range1.py
44 http://www.myreckonings.com/pynomo11/Type10-Range2.py
and http://www.myreckonings.com/pynomo11/Type10-Range1.pdf
and http://www.myreckonings.com/pynomo11/Type10-Range2.pdf
64
'title_y_shift':1.5,
'tick_levels':5,
'tick_text_levels':5,
}
block_1_params={
'block_type':'type_10',
'width':10.0,
'height':10.0,
'f1_params':N_params,
'f2_params':M_params,
'f3_params':T_params,
'isopleth_values':[[-4.5,5.0,'x']],
}
M_params={
'u_min':-10.0,
'u_max':10.0,
'function':lambda u:u,
'title':r'$M$',
'title_y_shift':0.5,
'tick_levels':3,
'tick_text_levels':2,
'tick_side':'right',
}
main_params={
'filename':'Type10-Range1.pdf',
'paper_height':15.0,
'paper_width':15.0,
'block_params':[block_1_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_y':2.5,
'title_str':r'$M = (T - N) / T^2$',
'isopleth_params':[
{'color':'black',
'linewidth':'thick',
'linestyle':'dashed',
'circle_size':0.07,
'transparency':0.0,
},
],
}
Nomographer(main_params)
T_params={
'u_min':-4.0,
'u_max':4.0,
'function_3':lambda u:u*u,
'function_4':lambda u:-u,
'scale_type':'log smart',
'title':r'$T$',
'title_x_shift':-1.0,
65
10
10
9.5
9.5
8.5
8.5
7.5
7.5
6.5
6.5
5.5
5.5
4.5
4.5
3.5
3.5
4
3
2.5
2.5
2
3.5
1
4
2.5
1.7
1.8
1.9
1.5
1.6
1.3
1.5
1.4
1.15
1.2
1.25
1.05
0.9
0.95
0.8
0.85
0.7
0.75
0.6
0.65
0.5
0.45
0.35
0.5
0.25
0.55
1.5
1.1
0.5
0
0.9
0.95
0.8
0.85
0.7
0.75
0.6
0.65
0.5
0.55
0.45
0.35
3.5
2.5
1.9
1.6
1.7
1.8
10
1.4
1.5
1.25
1.3
1.1
1.15
1.2
2.5
1.5
1.05
0.5
0.25
0
0.5
1.5
2.5
3.5
3.5
4.5
4.5
5.5
5.5
6.5
M = (T N )/T 2
6.5
7.5
7.5
8.5
8.5
9.5
9.5
66
1
2
3
4
5
6
7
8
9
10
'title_y_shift':-6.0,
'tick_levels':5,
'tick_text_levels':5,
}
block_1_params={
'block_type':'type_10',
'width':10.0,
'height':10.0,
'f1_params':N_params,
'f2_params':M_params,
'f3_params':T_params,
'isopleth_values':[[6,-13,'x']],
}
M_params={
'u_min':-20.0,
'u_max':0.0,
'function':lambda u:u,
'title':r'$M$',
'title_y_shift':0.5,
'tick_levels':3,
'tick_text_levels':2,
'tick_side':'right',
}
main_params={
'filename':'Type10-Range2.pdf',
'paper_height':15.0,
'paper_width':15.0,
'block_params':[block_1_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_y':2.5,
'title_str':r'$M = (T - N) / T^2$',
'isopleth_params':[
{'color':'black',
'linewidth':'thin',
'linestyle':'dotted',
'circle_size':0.08,
'transparency':0.2,
},
],
}
Nomographer(main_params)
T_params={
'u_min':0.01,
'u_max':4.0,
'function_3':lambda u:u*u,
'function_4':lambda u:-u,
'scale_type':'log smart',
'title':r'$T$',
'title_x_shift':-7.5,
67
10
43.5
3
9.5
5
2.
2.5
8.5
5
1.
4
1. 35
1. 3
1. 25
1.
2
1.
15
1.
8
7.5
1
1.
05
1.
7
0.
9
85
0.
0.
8
75
0.
5.5
0.
0.
65
4.5
0.
4
3.5
0.
2.5
0.
1.5
0.
0.5
8.5
9.5
13.5
14.5
15.5
M = (T N )/T 2
16.5
17.5
18.5
0.
15
0.01
7.5
0.
25
6.5
12.5
0.
35
5.5
11.5
0.
45
4.5
10.5
0.
55
0.
3.5
95
0.
6.5
1.5
0.5
19.5
0.
1
68
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
17
If an equation does not fall into one of the standard equation types supported directly by PyNomo, we can
convert the equation into a general determinant form for PyNomo. This provides us with the ability to draw
any nomogram, because an equation can be drawn as a classic nomogram (i.e, alignment chart) if and only
if it can be put into determinant form.45 As a benefit, there is generally no need to manipulate a determinant
into Standard Nomographic Form for PyNomo as long as no variable appears in more than one row. PyNomo
also supports equations with more than three variables in which case two variables share a rowthis is called
a grid nomogram. A grid nomogram is shown in the example of this type on the PyNomo site.46
A determinant represents a particular operation on a matrix, and it is
denoted by vertical bars on the sides of the matrix. The determinant of a
3x3 matrix is given by
a11 a22 a33 + a12 a23 a31 + a13 a21 a32 a13 a22 a31 a11 a23 a32 a12 a21 a33
But there are visual ways of deriving this result. In the figure on the right
the first two columns of the determinant are repeated to the right of the
original, and then the products of all terms on diagonals from upper left to
lower right are added and the products of all terms on diagonals from upper right to lower left are subtracted.
A convenient mental shortcut is to find these diagonal products by
wrapping around to get the three components of each term. Here the
first product we add is the main diagonal a11 a22 a33 , then the second is
a12 a23 a31 where we follow the curve around after we pick up a12 and a23
to pick up the a31 , then a13 a32 a21 by starting at a13 and wrapping around
to pick up the a32 and a21 . We do the same thing right-to-left for the
subtracted terms. This is much easier to visualize than to describe. Determinants of larger matrices are not considered here.
Lets create the determinant form of the equation we discussed in the previous section, N + MT 2 T = 0.
By arranging terms in the determinant positions we can find this solution:
N + MT 2 T = 0
T 2 1 T
1 0 M = 0
0 1 N
If you multiply out this determinant this equation becomes T 2 0 (N) +{1 (M) 0}+{T 1 1}
{T 0 0} T 2 1 (M) {1 1 (N)} = 0 which simplifies to our original equation, so this
is a valid determinant to use for this equation.
Now historically a determinant such as this has to be manually transformed into Standard Nomographic
Form in order to be plotted, in which the determinant has only 1s in the last column and no variable in more
45 For more details, see http://myreckonings.com/wordpress/2008/01/09/the-art-of-nomography-ii-designing-with-determinants/ or
the webpages on the determinant forms of nomograms at http://www.projectrho.com/nomogram/
46 http://www.pynomo.org/wiki/index.php/Type_9
69
than one row.47 But PyNomo can handle a determinant like this that is not in standard form as long as no
variable is in more than one row.
New scale parameters specific to a Type 9 Determinant nomogram are
grid: set to False to indicate that this scale (row of the determinant) contains only one variable
f : the function in u given by the first column in the determinant row corresponding to the scale
g: the function in u given by the second column in the determinant row corresponding to the scale
h: the function in u given by the third column in the determinant row corresponding to the scale
We will let 10 < N < 10, 4 < T < 4 and 10 < M < 10 as we did in the previous section. However,
there is a problem for the case T = 0 in our range. In the original equation M = TTN
2 you can see that M
is infinity when T = 0, a singularity. You can also see this in the way the equation is expressed above as
N + MT 2 T = 0, where a value T = 0 will result in N = 0 and M being any number at all.
This is an indication that we should perform an initial transformation on the scales. Another clue is
when the PyNomo build does not end because it is encountering large numbers due to the singularity. Here
PyNomo uses matrix multiplication to transform the nomogram such that four points on the paper end up at
a different set of four points on the paper. The values of u_min_trafo and u_max_trafo indicate the points
that will be transformed to the corners of a rectangle with sides along the x- and y-axes.
So here we specify this initial transformation by introducing the following new parameters:
u_min_trafo: the mininum value for the transformation, which should be set to the value of u_min in
each of the outer two scales
u_max_trafo: the maximum value for the transformation, which should be set to the value of u_max in
each of the outer two scales
transform_ini: a block parameter to set to True to indicate that an initial transformation should be
performed
The PyNomo script and output nomogram are shown on the following page. The nomogram that is
produced matches the first Type 10 nomogram from the previous section. For an equation like this that can
be expressed in one of the basic types that PyNomo recognizes, we have the great advantage that we do not
need to derive the determinant form as we did here.
This PyNomo script and output PDF graphic are available online for download.48
47 See
http://myreckonings.com/wordpress/2008/01/09/the-art-of-nomography-ii-designing-with-determinants/ for the rules for transforming a determinant to standard form. By adding the first column to the second column, dividing the first row by T 2 + 1, swapping
the first and third columns, multiplying the second column by -1, and moving the third row to the top row, the determinant would end
up as
0
N
1
2
T
T
1 = 0
T 2 +1
T 2 +1
1
M
1
48 http://www.myreckonings.com/pynomo11/Type9-Range1.py
and http://www.myreckonings.com/pynomo11/Type9-Range1.pdf
70
}
T_params={
M_params={
'u_min':-10.0,
'u_max':10.0,
'u_min_trafo':-10.0,
'u_max_trafo':10.0,
'f':lambda u:0,
'g':lambda u:1,
'h':lambda u:-u,
'title':r'$N$',
'scale_type':'linear',
'tick_levels':3,
'tick_text_levels':2,
'tick_side':'left',
'grid':False
'f':lambda u:1,
'g':lambda u:0,
'h':lambda u:-u,
'title':r'$M$',
'scale_type':'linear',
'tick_levels':3,
'tick_text_levels':2,
'grid':False
block_params={
'block_type':'type_9',
'f1_params':N_params,
'f2_params':T_params,
'f3_params':M_params,
'transform_ini':True,
'isopleth_values':[[-4.5,'x',5.0]],
}
main_params={
'u_min':-4.0,
'u_max':4.0,
'f':lambda u:u*u,
'g':lambda u:1,
'h':lambda u:-u,
'title':r'$T$',
'title_x_shift':-1.0,
'title_y_shift':1.5,
'scale_type':'log smart',
'tick_levels':5,
'tick_text_levels':5,
'grid':False
}
'u_min':-10.0,
'u_max':10.0,
'u_min_trafo':-10.0,
'u_max_trafo':10.0,
'filename':'Type9-Range1.pdf',
'paper_height':15.0,
'paper_width':15.0,
'block_params':[block_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_y':2.5,
'title_str':r'$M = (T - N) / T^2$',
'isopleth_params':[
{'color':'black',
'linewidth':'thick',
'linestyle':'dashed',
'circle_size':0.07,
'transparency':0.0,
},
],
}
Nomographer(main_params)
71
10
10
9.5
9.5
8.5
8.5
7.5
7.5
6.5
6.5
5.5
5.5
4.5
4.5
3.5
3.5
4
3
2.5
2.5
2
3.5
1
4
2.5
1.7
1.8
1.9
1.5
1.6
1.3
1.5
1.4
1.15
1.2
1.25
1.05
0.9
0.95
0.8
0.85
0.7
0.75
0.6
0.65
0.5
0.45
0.35
0.5
0.25
0.55
1.5
1.1
0.5
0
0.9
0.95
0.8
0.85
0.7
0.75
0.6
0.65
0.5
0.55
0.45
0.35
3.5
2.5
1.9
1.6
1.7
1.8
10
1.4
1.5
1.25
1.3
1.1
1.15
1.2
2.5
1.5
1.05
0.5
0.25
0
0.5
1.5
2.5
3.5
3.5
4.5
4.5
5.5
5.5
6.5
M = (T N )/T 2
6.5
7.5
7.5
8.5
8.5
9.5
9.5
72
1
2
3
4
5
6
7
8
9
10
Now well change our ranges to 0 < N < 10, 0 < T < 4 and 20 < M < 0 as we did in the second Type
10 example of the previous section. This nomogram is shown on the following page. You can see that unlike
our Type 10 plot there is no automatic shearing of the T-scale and M-scale upward so the M-scale is aligned
horizontally with the N-scale. We would like to have this in order to maximize the size of the nomogram on
the paper.
To adjust our determinant to do this involves looking up the most general form of the standard determinant
for this equation, one that provides individual scale factors for M and N so they can be made the same
length, and then applying a mathematical operation for a shear transformation to the determinant. The shear
effectively slides the outer scales vertically, pushing the right scale up until the outer scales are aligned leftto-right, with the center scale rotating along with them as if the scales were linkages. Its not a lot of fun to
do this, really.
But heres where the polygon transformation of PyNomo helps us so much. In the script on the following
page, if we were to replace the transformations line from
'transformations':[('rotate',0.01),('scale paper',)],
to
'transformations':[('rotate',0.01),('scale paper',),('polygon',)],
we would find that we get the same sheared result as we obtained in the previous section.
This PyNomo script and output PDF graphic are available online for download.49
49 http://www.myreckonings.com/pynomo11/Type9-Range2.py
and http://www.myreckonings.com/pynomo11/Type9-Range2.pdf
73
}
T_params={
M_params={
'u_min':0.0,
'u_max':10.0,
'u_min_trafo':-10.0,
'u_max_trafo':10.0,
'f':lambda u:0,
'g':lambda u:1,
'h':lambda u:-u,
'title':r'$N$',
'scale_type':'linear',
'tick_levels':3,
'tick_text_levels':2,
'tick_side':'left',
'grid':False
'f':lambda u:1,
'g':lambda u:0,
'h':lambda u:-u,
'title':r'$M$',
'scale_type':'linear',
'tick_levels':3,
'tick_text_levels':2,
'grid':False
block_params={
'block_type':'type_9',
'f1_params':N_params,
'f2_params':T_params,
'f3_params':M_params,
'transform_ini':True,
'isopleth_values':[[6,'x',-13]],
}
main_params={
'u_min':0.1,
'u_max':4.0,
'f':lambda u:u*u,
'g':lambda u:1,
'h':lambda u:-u,
'title':r'$T$',
'title_x_shift':-1.0,
'title_y_shift':0.5,
'scale_type':'log smart',
'tick_levels':5,
'tick_text_levels':5,
'grid':False
}
'u_min':-20.0,
'u_max':0.0,
'u_min_trafo':-10.0,
'u_max_trafo':10.0,
'filename':'Type9-Range2.pdf',
'paper_height':15.0,
'paper_width':15.0,
'block_params':[block_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_y':2.5,
'title_str':r'$M = (T - N) / T^2$',
'isopleth_params':[
{'color':'black',
'linewidth':'thin',
'linestyle':'dotted',
'circle_size':0.08,
'transparency':0.2,
},
],
}
Nomographer(main_params)
74
M
3
3.5
2.5
0.95
0.85
0.9
0.75
0.8
0.65
0.7
0.55
0.6
0.45
0.5
0.35
0.4
0.25
0.3
0.1
1.7
0.5
0.2
1.5
1.8
2.5
1.9
3.5
1.5
4.5
1.6
5.5
1.2
6.5
1.3
1.35
1.4
7.5
1.25
8.5
1.1
1.05
9.5
1.15
10
0.5
1.5
2.5
3.5
4.5
5.5
6.5
7.5
8.5
9.5
10.5
11.5
12.5
13.5
M = (T N )/T 2
14.5
15.5
16.5
17.5
18.5
19.5
75
0
1
10
11
12
13
14
15
16
17
18
19
20
A Grid Nomogram
We can plot a nomogram for an equation of up to six variables using this Type 9 determinant form if we
can find a way to express the determinant with no more than two variables per row and no variables used in
more than one row. Each row having two variables is plotted as a grid rather than a curvilinear scalethe
Type 9 example on the PyNomo site shows how the grid parameters are specified.50 The celestial navigation
example on the PyNomo site is also a grid nomogram created as a Type 9 determinant form.51 This is a very
useful capabilitygrid nomograms are striking in appearance but very tedious to draw by hand!
Lets draw a nomogram for the following relation based on its determinant form. Notice that no variables
appear in more than one row, and the second row contains two variables. This second row will result in a
grid where the effective scale point is the intersection of the curves for the given values of k and .
0
100 cos
1+cos
100
m = k sin + l cos
m
1
=0
k sin +100 cos
1
1+cos
100 l
1
This nomogram was designed by Liunian Li, and his derivation is provided in another essay,52 but you
can expand the determinant to verify that it produces the same equation given above it.
New scale parameters specific to a Type 9 Determinant nomogram with at least one grid are:
f_grid: the function in u and v given by the first column in the determinant row corresponding to the
grid scale
g_grid: the function in u and v given by the second column in the determinant row corresponding to
the grid scale
h_grid: the function in u and v given by the third column in the determinant row corresponding to the
grid scale
u_start: the starting value of u in the grid scale
u_stop: the ending value of u in the grid scale
v_start: the starting value of v in the grid scale
v_stop: the ending value of v in the grid scale
u_values: values of u (if specified) in the grid scale
v_values: values of v (if specified) in the grid scale
text_prefix_u: text to add before every value of u in the grid scale
text_prefix_v: text to add before every value of v in the grid scale
u_texts: text to add before each value of u specified by u_values in the grid scale
50 http://www.pynomo.org/wiki/index.php/Type_9
51 http://www.pynomo.org/wiki/index.php/Example:Star_navigation
52 http://myreckonings.com/wordpress/2008/03/13/a-4-variable-nomogram-%e5%9b%9b%e5%8f%98%e9%87%8f%e8%af%ba%e6%a8%a1%e5%9b%be/
Also see the comments at the bottom of this post and the paper on applying shear transformations to the nomogram at
http://www.myreckonings.com/wordpress/wp-content/uploads/FourVariableNomogram/FourVariableNomogramShaping033008.pdf
76
v_texts: text to add before each value of u specified by v_values in the grid scale
u_texts_v_start: set to True if the labels for u should lie at the starting values of the v curves in the grid
scale
u_texts_v_stop: set to True if the labels for u should lie at the ending values of the v curves in the grid
scale
v_texts_u_start: set to True if the labels for v should lie at the starting values of the u curves in the grid
scale
v_texts_u_stop: set to True if the labels for v should lie at the ending values of the u curves in the grid
scale
text_distance: the space between the label and the grid
u_line_color: the color of the u curves
u_text_color: The color of the u-scale labels
v_line_color: the color of the u curves
v_text_color: The color of the v-scale labels
The PyNomo script and nomogram are shown on the following two pages. The grid parameter is set to
True to indicate a grid scale and f , g and h parameters are replaced by f_grid, g_grid and h_grid. We will
assign to u and k to v. The start and stop values for these are specified in u_start, u_stop, v_start and v_stop,
while u_min and u_max are still needed in case we align (tag) another curve to the u-scale (which we are
not doing). The u_values and v_values parameters are specified because we only want the grid curves to be
constructed for those specific values of and k. I could have chosen a common text prefix to add to the labels
using text_prefix_u and text_prefix_v, but I didnt want = and k = for every value so I commented out
these lines and specified the complete label for each value of u and v with u_texts and v_texts, where only
one value has the prefix. (For some reason using \theta produces in the text prefix parameters but not in
the individual text values, so there I set it to the word theta.) We set the True/False values of u_texts_v_start,
u_texts_v_stop, v_texts_u_start and v_texts_u_start to place the grid labels where we want them, as well as
text_distance. Here we also set u_line_color and v_line_color to better distinguish the grid lines.
Notice that it happens that the scale values of m and k line up with each other at = 90, so there really is
no need to have both sets of labels. To clean up this nomogram we could set u_texts to all empty '' strings in
theta_k_params to remove the k-scale labels. Then we could change the title of the m-scale to m,k and add
'tick_side':'left', in m_params to move its labels to the left side of the scale, resulting in a nomogram
with better readability.
This PyNomo script and output PDF graphic are available online for download.53
53 http://www.myreckonings.com/pynomo11/Type9-Grid-Isopleth.py
and http://www.myreckonings.com/pynomo11/Type9-Grid-Isopleth.pdf
77
#'text_prefix_u':r'$\theta$=',
#'text_prefix_v':r'$k$=',
'grid':True,
}
l_params={
'u_min':0.0,
'u_max':100.0,
'f':lambda u:100.0,
'g':lambda u:100.0-u,
'h':lambda u:1.0,
'title':r'\Large $l$',
'title_x_shift':0.4,
'scale_type':'linear',
'tick_levels':3,
'tick_text_levels':2,
'grid':False,
}
theta_k_params={
'u_min':10.0,
'u_max':90.0,
'f_grid':lambda u,v:100.0*cos(u*pi/180.0)/
(1+cos(u*pi/180.0)),
'g_grid':lambda u,v:(v*sin(u*pi/180.0)+
100.0*cos(u*pi/180.0))/(1+cos(u*pi/180.0)),
'h_grid':lambda u,v:1.0,
'u_start':10.0,
'u_stop':90.0,
'v_start':0.0,
'v_stop':150.0,
'u_values':[10.0,20.0,30.0,40.0,50.0,60.0,70.0,
80.0,90.0],
'v_values':[0.0,10.0,20.0,30.0,40.0,50.0,60.0,
70.0,80.0,90.0,100.0,110.0,120.0,
130.0,140.0,150.0],
'u_texts':['','20','30','40','50','theta = 60',
'70','80','90'],
'v_texts':['0','10','20','30','40','50','60',
'k = 70','80','90','100','110','120',
'130','140','150'],
'v_texts_u_start':False, # default value
'v_texts_u_stop':True,
# default value
'u_texts_v_start':False, # default value
'u_texts_v_stop':True,
# default value
'text_distance':0.5,
'u_line_color':color.cmyk.Green,
'u_text_color':color.cmyk.Green,
'v_line_color':color.cmyk.Red,
'v_text_color':color.cmyk.Red,
block_params={
'block_type':'type_9',
'f1_params':m_params,
'f2_params':theta_k_params,
'f3_params':l_params,
'transform_ini':False,
'isopleth_values':[[135,[60,130],'x']]
}
main_params={
'filename':'Type9-Grid-Isopleth.pdf',
'paper_height':15.0,
'paper_width':15.0,
'block_params':[block_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x': 8,
'title_y': 0.5,
'title_box_width': 6,
'title_str':r'\Large $m = k sin \theta + l cos \theta$',
'isopleth_params':[
{'color':'black',
'linewidth':'thin',
'linestyle':'dashed',
'circle_size':0.08,
'transparency':0.0,
},
],
}
Nomographer(main_params)
78
90
150
130
130
125
120
70
140
135
theta = 60
140
80
150
145
120
50
115
110
110
40
105
100
100
30
95
10
90
90
15
85
20
80
80
30
70
35
65
40
60
60
45
55
50
40
20
25
75
k = 70
50
50
55
45
60
40
65
35
70
30
30
25
20
15
10
75
80
20
85
10
m = ksin + lcos
90
95
100
79
A Circular Nomogram
Lets do one more nomogram from the determinant form. We are going to create a circular nomogram,
a form in which one scale on a circle provides two values when the straightedge crosses it. This nomogram
provides the roots of the quadratic equation q2 aq + b = 0. The determinant appears overly complicated
for this simple formula, but when expressed in this form the first scale becomes a circle. The derivation of
this form of the determinant is provided elsewhere54 , but you can expand the determinant here if you want to
verify that it does indeed produce our equation.
q2 aq + b = 0
q
q2 +1 q21+1 1
1
0
1 = 0
a
0
1
1
b1
The script and nomogram are found on the following pages. The scale parameter extra_params is used to
break the scales into different ranges to change from linear to logarithmic scaling and to avoid intervals where
values go to infinity (a = 0 or b = 1). Finally, ranges with no tick marks or labels are provided for the q-scale
and a-scale to extend their lines closer to the origin to bring the circle closer to closure (full closure would
require the variables to go to infinity). The q-scale curves until it is upside down, which would normally
switch the side of the ticks and labels on the bottom half of the circle to keep the labels mostly upright, so we
also set the turn_relative parameter to True for that scale to allow them to follow around the circle.
The page size to scale to was originally set to 2525cm, but this is a rough estimate of the final size of
the nomogram, so in the end I tweaked the values to 25.530.4cm to get the q-scale to be perfectly circular
(which I did by overlaying the nomogram with a grid by setting make_grid to True in the main parameters).
Otherwise it would be an ellipse, which works perfectly well but doesnt look nearly as striking as a circle.
When a straightedge is placed across particular values of a and b, three things can happen. If it intersects
the circle in two places, those two values of q are the two real roots of the equation (the values of q from
the quadratic formula that solve the equation). If it grazes the edge of the circle as a tangent, that value is
the one repeated real root (where the discriminant B2 4AC in the quadratic formula is zero). If it misses
the circle entirely there are no real roots, or no real solutions to the equation (B2 4AC < 0). Actually, the
b-scale value turns out to always be the product of the two values on the q-scale.
This PyNomo script and output PDF graphic are available online for download.55
54 http://myreckonings.com/wordpress/2008/01/09/the-art-of-nomography-iii-transformations/
55 http://www.myreckonings.com/pynomo11/Type9-Circular.py
and http://www.myreckonings.com/pynomo11/Type9-Circular.pdf
80
}
]
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'log smart',
B_params={
'u_min':-10.0,
'u_max':-0.1,
'f':lambda u:0,
'g':lambda u:-1/(u-1),
'h':lambda u:1,
'title':r'\huge $b$',
'title_x_shift':-1.0,
'title_y_shift':-2.5,
'scale_type':'log smart',
'tick_levels':5,
'tick_text_levels':5,
'grid_length_0':0.5,
'text_distance_0':0.55,
'grid_length_1':0.3,
'text_distance_1':0.35,
'grid_length_2':0.25,
'text_distance_2':0.30,
'grid_length_3':0.15,
'text_distance_3':0.20,
'grid_length_4':0.15,
'text_distance_4':0.20,
'extra_params':
[{
'u_min':0.01,
'u_max':0.25,
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'log smart',
},
{
'u_min':4.0,
'u_max':15.0,
'tick_levels':5,
'tick_text_levels':5,
'scale_type':'log smart',
}]
}
A_params={
'u_min':1.0,
'u_max':50.0,
'f':lambda u:1/u,
'g':lambda u:0,
'h':lambda u:1,
'title':r'\huge $a$',
'title_x_shift':-7.0,
'title_y_shift':0.8,
'scale_type':'log smart',
'tick_levels':5,
'tick_text_levels':5,
'grid_length_0':0.5,
'text_distance_0':0.55,
'grid_length_1':0.3,
'text_distance_1':0.35,
'grid_length_2':0.25,
'text_distance_2':0.30,
'grid_length_3':0.15,
'text_distance_3':0.20,
'grid_length_4':0.15,
'text_distance_4':0.20,
'extra_params':
[{
'u_min':-50.0,
'u_max':-1.0,
block_params={
'block_type':'type_9',
'f1_params':Q_params,
'f2_params':A_params,
'f3_params':B_params,
'transform_ini':False,
}
main_params={
'filename':'Type9-Circular.pdf',
'paper_height':25.4,
'paper_width':30.4,
'block_params':[block_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x':7.5,
'title_y': 21.0,
'title_box_width': 6,
'title_str':r'\Huge $q^2-aq+b=0$',
'make_grid':False,
}
Nomographer(main_params)
81
0.25
0.2
0.15
0.1
q 2 aq + b = 0
0.1
5
0.
0.1
0.
25
0.2
0.1
0.05
.2
0
.
0
25
0.
0.1
q
0.
35
0.15
0.2
0.
0.
35
0.
0.
45
.15
0
0.
0.05
0.07
0.05
0.03
0.01
45
0.
0.25
0.
55
0
.6
0.
0.3
5
55
0.
0.35
0 .6
0.4
0
.65
5
0.6
0.45
0.5
0.7
0.7
0.55
0.7
5
0.7
0.6
0.8
0.65
0.8
0.7
0.85
0.85
0.75
0.9
0.95
0.8
0.9
0.9
0.95
1.05
1
1.05
1.1
1.1
1.1
1.2
1.15
1.3
1.15
1.2
1.2
1.25
1.3
1.3
5
1.4
1.4
5
1.5
1.4
1.5
1.25
3
1.
.35
1
.4
1
.45
1 .5
1
.6
1
7
1.
8
1.
9
1.
1.6
2.5
1.
7
1.
8
3.5
1.
9
4.5
2.
5
50
20
15
6
7
8
5
.5
10
3.
5
4
.5
1.05
1.15
1.1
1.25
1.2
1.35
1.3
1.5
1.4
1.6
1.55
1.45
1.7
1.75
1.8
1.65
2.1
1.9
2.4
2.5
2.3
2.2
3.5
5.5
4.5
82
5.5
4.5
5
4.5
10
6
5.5
6
7
8
20
6.5
15
50
50
10
8
7
6
7
8
15
20
50
10
20
15
8
7
6
5.5
4.5
3.5
2.3
2.5
2.4
2.2
1.9
2.1
1.8
1.75
1.7
1.5
1.6
1.65
1.45
1.55
1.3
1.35
1.4
1.2
1.25
1.1
1.15
1.05
15
10
10
5
3.
5
2.
5
6
18
A Type 5 nomogram consists of an x-y plot of a family of curves, where the y-value is found from a
particular x-value by the curve for a particular value of a third variable. This is often seen by itself as a graph
with multiple curves as shown in the figure below, but it can also be part of a larger nomogram. There are a
few examples involving contour blocks on the PyNomo site.56
A well-known electro-optic nomogram from the
RCA Electro-Optics Handbook shown on the next
page includes this contour block in the upper-right
corner. This contour block provides the relationship
between the Photocathode Illuminance, the Scene
Contrast, and the Contrast-Limiting Resolution of a
camera. If youre navigating the nomogram from below with a straightedge and encounter the x-axis, you
simply move parallel to the y-axis until you hit the
curve for the particular Contrast value, then horizontally to meet the y-axis, at which time you continue
navigating the nomogram with the straightedge. You do the reverse if navigating from the left.
You may notice that weve already created the nomogram portion to the left of the contour block (see
page 29) and the portion below the contour block (see page 52). After we create the contour block here well
connect all three parts together (using tags to align the outer scales) to recreate this entire nomogram in vector
form with PyNomo.
56 http://www.pynomo.org/wiki/index.php/Type_5
and http://www.pynomo.org/wiki/index.php/Example:Amortized_loan_calculator
and http://www.pynomo.org/wiki/index.php/Photography_exposure
and http://www.pynomo.org/wiki/index.php/Example:Radio-frequency_single_electron_transistor
83
84
The construction of the nomogram for this contour block turned out to take some effort. First, I didnt
have the equation for the family of curves since it was derived from experimental data. Therefore, I needed
to do some curve fitting to find an equation that would provide the x-y curve for every value of the Contrast,
denoted here by the variable v. There are tools for fitting a single curve as y = f (x), but here we also have
this third variable v, so I had to make educated guesses and make adjustments to find a good fit.
Each curve is made up of a relatively straight section followed by a flattened section. I figured that a
sinusoidal curve might be the simplest type of function to fit, although Id have to add something near the yaxis to prevent it from dropping back down again. With an easy-to-use shareware package called Advanced
Grapher that Ive happily used for at least 10 years,57 I started experimenting by plotting equations and
adjusting constants and terms until I had a close match (Advanced Grapher can do curve-fitting, but again
only for one dependent variable). My initial results are shown in the screen capture below. We are interested
in the curves to the left of the y-axis. The small squares are the actual values I read off of the contour block,
and the colored curves are my best fit to them:
y = 1.5 sin(0.36(x + 4.25 200.134 )) +
v/150
(x + 0.2)2
where x is the exponent of 10 from the original contour block and v = 10, 20, 30, 50 and 100 is the Contrast
variable. This equation took quite a while to come up with. Do you see how the second term gets large as x
approaches zero to give a boost so the sine term doesnt drop off there?
57 http://www.alentum.com/agrapher/
85
The final PyNomo script will be seen shortly, but heres the result of using the equation above in it:
100 %
50 %
30 %
t = 20 %
tras
Con
%
10
40
30
20
10
2.80
2.90
2.60
2.70
2.40
2.50
2.20
2.30
2.10
1.90
2.00
1.70
1.80
1.50
1.60
1.30
1.40
1.20
1.00
1.10
0.80
0.90
0.60
0.70
0.40
0.50
0.30
Contrast Limiting Resolution vs. Photocathode Illuminance for an Image-Intensifier Photocathode Responsivity of 200A/lm
You can see that it plotted the curves from the x > 0 part of the curve, not the ones I wanted from x < 0.
The way the Type 5 nomogram is constructed is to take the y-value and the v-value and find the x-value that
produces it. Here there is more than one x, and the wrong set is chosen. So I changed x to x in the equation,
realizing that the resulting x-axis would be the negative of the exponent in the original contour block. It
worked for only two of the v-values:
40
t
%%
20
30
10
50
100% Contras
30
20
10
2.00
3.00
4.00
5.00
6.00
7.00
Contrast Limiting Resolution vs. Photocathode Illuminance for an Image-Intensifier Photocathode Responsivity of 200A/lm
Its plotting the correct set, but the curves stop where they curve upward, or in other words, where there
86
are two values of x for a given y. So I played around with my original curve-fitting equation until the curves
were sufficiently flat in that area that they did not curve upward.
y = 1.5 sin(0.36(x + 4.25 200.134 )) +
v/150
(x + 0.15 + v/200)2
Finally it worked. The script and output nomogram are shown on the following page. The lesson here is
to use a simple, non-undulating function for the contour block. For example, polynomial functions will not
work if a local minimum or maximum occurs in the range covered by the contour block.
You can see how constants and formulas can be defined at the top of the script for convenience. There
are also a number of new parameters specific to this Type 5 nomogram. First, there is only one parameter set
(a block parameter set) rather than separate ones for the block and individual scales. Here the variable u is
the y-axis, and its given the tag resolution so we can attach the nomogram on the left to it later. The variable
wd is the x-axis, and its given the tag illum so we can attach the nomogram below it. The variable v is the
Contrast value. These variable names are defined in PyNomo and must be the ones used.
There are no scale parameters for a Type 5 Contour block, only block and main parameters. New block
parameters specific to this are:
manual_x_scale: if True, define the minimum and maximum values of x with x_min and x_max (this
scale is normally wd)
x_min: minimum value of x (this scale is normally wd)
x_max: maximum value of x (this scale is normally wd)
u_scale_opposite: place the u-scale on the opposite side of the block
u_func: the function of the variable for the u-scale
u_values: values to plot for the u-scale
u_manual_axis_data: a list of custom labels to write for each u_value
draw_line: if True, draw a line between the tick mark and the label for manual axis data
x_corr and y_corr: x and y offsets in cm of the labels for manual axis data
u_title: the title of the u-scale
scale_type_u: type of scale (linear, log, manual line, manual arrow or manual point) for the u-scale
u_tick_side: the side of the scale to print the tick marks and labels for the u-scale
u_tag: scales with the same tag are aligned (overlaid) in the final nomogram
u_reference: if True, axis is treated as reference line that is a turning point
u_tick_levels: the level to which the tick marks are printed for the u-scale
u_tick_text_levels: the level to which the tick labels are printed for the u-scale
u_title_opposite_tick: if True, place the centered title on the opposite side from the tick marks for the
u-scale
u_title_distance_center: distance of the title from the u-scale center (0.5cm by default)
u_title_draw_center: if True, locate the title at the center of the scale point of the u-scale
u_text_format: the number of digits to the left and right of the decimal point in the tick labels (r%3.2 f
or nnn.nn is the default) for the u-scale
87
u_align_func: the function used to align the u-scale with another scale with the same
horizontal_guides: if True, draw equally-spaced horizontal grid lines (not related to values on the
y-axis) as a visual aid (False by default)
vertical_guides: if True, draw equally-spaced vertical grid lines (not related to values on the y-axis) as
a visual aid (True by default)
u_axis_color: The color of the u-scale axis (or family of curves if the v-scale is specified)
u_title_color: The color of the title text of the u-scale
u_text_color: The color of the u-scale labels
Also, for each parameter above that contains u, there are also analogous parameters for the v and wd scales.
Here we set u_func to log10(u) to make the y-axis a simple logarithmic scale, and we set v_func to the
equation above in x and v (this may not seem to make sense but thats the way it works). We set u_values and
v_values to specific values we want plotted for the Resolution and the Contrast.
In order to prevent the Contrast curve labels from overlapping, we use the v_manual_axis_data parameter
to specify the specific label text for each curve, the x and y offset of the label, and the draw_line flag to draw
a line between the end of the curve and the label. It works very nicely.
The wd-scale (the x-axis) has the same title, tick level and tick text levels weve seen for all scales before.
I had to indicate in its title that the value is actually the negative of the exponent of the actual Photocathode
Illuminance, or log(Illuminance). The minimum and maximum values of wd, however, are set by the x_min and x_max parameters. I left the wd-scale as a default linear scale, but I could have made it logarithmic
by setting the parameter scale_type_wd to log.
I left the colors of the u/v/wd scales at their default color of black. To get the contour block oriented
as I wanted required setting the mirror_x parameter to True, where mirror_x flips the wd-scale (if it were
used, mirror_y would flip the u-scale). The u_scale_opposite parameter is also set to True to move the labels
on the u-scale to the left side of the block rather than the right. The paper width and height in the main
parameters give the contour block the size ratio I was looking for. The isopleth_values entries are for u, v
and wd, respectively (where the x entry for wd value means that it is computed from the other two values).
This PyNomo script and output PDF graphic are available online for download.58
58 http://www.myreckonings.com/pynomo11/Type5-Isopleth.py
and http://www.myreckonings.com/pynomo11/Type5-Isopleth.pdf
88
100.0:['$100 \%$',
{'x_corr':0.3,
'y_corr':.3,
'draw_line':True}],
=
=
=
=
=
=
1.5
0.36
4.25
.134
150
0.15
},
'u_title':r'Contrast Limiting Resolution \
(Line Pairs/mm)',
'v_title':r'Contrast',
'wd_title':r'Photocathode Illuminance \
(-log$_{10}$(lux))',
'wd_tick_side':'right',
'wd_text_format':r"$%3.2f$",
'wd_tick_levels':3,
'wd_tick_text_levels':1,
'wd_title_distance_center':2.2,
'manual_x_scale':True,
'x_min':1.5,
'x_max':7.0,
'mirror_x':True,
'u_scale_opposite':True,
'isopleth_values':[[15.0,20.0,'x']],
}
def f1(x,v):
return const_A*sin(const_B*(-x+const_C*v**const_D))+ \
(v/const_E)/(-x+const_F+(v/200))**2
block_20_params={
'block_type':'type_5',
'u_tag':'resolution',
'wd_tag':'illum',
'width':10.0,
'height':13.0,
'u_func':lambda u:log10(u),
'u_values':[1.0,2.0,3.0,4.0,5.0,
6.0,7.0,8.0,9.0,
10.0,20.0,30.0,40.0],
'u_text_format':r"$%3.0f$ ",
'v_func':f1,
'v_values':[10.0,20.0,30.0,50.0,100.0],
'v_manual_axis_data':
{
10.0:['$10 \%$',
{'x_corr':0.22,
'y_corr':-.45,
'draw_line':True}],
20.0:['$20 \%$',
{'x_corr':0.2,
'y_corr':-.22,
'draw_line':True}],
30.0:['$30 \%$',
{'x_corr':0.1,
'y_corr':0.0,
'draw_line':True}],
50.0:['$50 \%$',
{'x_corr':0.1,
'y_corr':0.0,
'draw_line':True}],
main_params={
'filename':'Type5-Isopleth.pdf',
'paper_height':10.0,
'paper_width':20.0,
'block_params':[block_20_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_y': -4,
'title_box_width':20,
'title_str':r'Contrast Limiting Resolution vs.\
Photocathode Illuminance for an Image-Intensifier\
Photocathode Responsivity of 200$\mu$A/lm',
'isopleth_params':[
{'color':'black',
'linewidth':'thin',
'linestyle':'dashed',
'circle_size':0.08,
'transparency':0.0,
},
],
}
Nomographer(main_params)
89
100%
40
30
50%
rast
30% Cont
20%
10%
20
10
9
8
7
6
5
4
3
2
Contrast Limiting Resolution vs. Photocathode Illuminance for an Image-Intensifier Photocathode Responsivity of 200A/lm
An Electro-Optic Nomogram
Now we have the three nomograms needed to recreate the entire electro-optic nomogram on page 84: the
nomogram on the left side found on page 29, the nomogram on the lower right found on page 52, and the
contour block we just designed.
So we take the three scripts and put them together into one very large script. We add tags to the end scales
of the earlier two nomograms so they will align with the x-axis and y-axis of the contour block. For those
aligned scales we also remove the titles, tick marks and tick labels so we dont duplicate those on the contour
block (after we verify that they match). Because the x-axis of the contour block is now a linear scale of the
exponent of the actual value, we replace log(u) in that scale of the lower nomogram with -u over the same
range 1.5 to 7.0 and plot it as a linear scale.
The order of the blocks listed in the main parameters turns out to be important in orienting the blocks
in the overall nomogram. I suggest listing the contour block first in order to lock in the orientation of its
axes. Then the other nomogram blocks will line up as we want relative to those axes. I found originally that
the lower nomogram blocks proceeded vertically upward from the x-axis of the contour block rather than
downward, but changing the order of those blocks in the main parameters caused them to proceed downward
instead.
Beyond the change of units of the x-axis in the contour block the individual nomograms combine to make
up the nomogram in the Electro-Optics Handbook. Weve constructed a very complicated nomogram here
by building smaller pieces and connecting them together. A good number of lines of the script are added here
simply to place text onto the nomogramthis is a heavily annotated nomogram. Isopleths are also drawn as
guidelines. It looks very nice when printed on large paper, as you can see if you zoom in on it.
The PyNomo script and output PDF graphic are shown below and are available online for download.59
59 http://www.myreckonings.com/pynomo11/EO-Isopleths.py
and http://www.myreckonings.com/pynomo11/EO-Isopleths.pdf
90
},
{'dx':-1.4,
'dy':0.25,
'text':r'\small $mm$',
'width':5,
}]
}
Target_Size_meters_params={
'tag':'size',
'u_min':0.5,
'u_max':20.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'Target Size',
'title_y_shift':0.8,
'tick_side':'left',
'tick_levels':2,
'text_format':r"$%3.1f$",
'tick_text_levels':2,
'extra_titles':[
{'dx':-1.25,
'dy':0.25,
'text':r'\small $m$',
'width':5,
}]
}
Range_meters_params={
'tag':'range',
'u_min':5000.0,
'u_max':50.0,
'function':lambda u:-log10(u),
'scale_type':'log',
'title':r'Range',
'title_y_shift':0.8,
'text_format':r"$%3.0f$",
'tick_levels':4,
'tick_text_levels':3,
'extra_titles':[
{'dx':-1.25,
'dy':0.25,
'text':r'\small $m$',
'width':5,
}]
}
Resolution_params={
'tag':'resolution',
'u_min':1.0,
'u_max':40.0,
'function':lambda u:log10(u),
'scale_type':'log',
# Remove titles, ticks marks and tick labels as they
# duplicate those on the y-axis of the Contour Block.
#'title':r'Resolution',
#'title_y_shift':0.8,
#'text_format':r"$%3.1f$",
#'tick_levels':3,
#'tick_text_levels':3,
'tick_levels':0,
'tick_text_levels':0,
}
Number_of_Cycles_params={
'u_min':1.0,
'u_max':10.0,
'function':lambda u:-log10(u),
'scale_type':'log',
'title':r'$N$',
'title_y_shift':0.4,
'text_format':r"$3.0f$",
'tick_levels':2,
'tick_text_levels':1,
'scale_type':'manual point',
'manual_axis_data': {1.0:'1',
2.0:'2',
3.0:'',
4.0:'4',
5.0:'',
6.0:'6',
7.0:'',
8.0:'',
9.0:'',
10.0:'10'
},
}
block_1_params={
'block_type':'type_3',
'width':10.0,
'height':10.0,
'reference_titles':['',''],
'f_params':[Range_meters_params,
Number_of_Cycles_params,
Focal_Length_mm_params,
Target_Size_meters_params,
Resolution_params],
'isopleth_values':[[700,2,40,'x',15]],
}
Focal_Length_mm_params={
'tag':'focal',
'u_min':1.0,
'u_max':1000.0,
'function':lambda u:log10(u),
'scale_type':'log',
'title':r'Lens',
'title_y_shift':1.2,
'tick_side':'left',
'tick_levels':2,
'text_format':r"$%3.0f$",
'tick_text_levels':2,
'extra_titles':[
{'dx':-1.75,
'dy':0.8,
'text':r'Focal Length',
'width':5,
91
'tick_levels':4,
'tick_text_levels':3,
}
'block_type':'type_5',
'u_tag':'resolution',
'wd_tag':'illum',
'width':10.0,
'height':13.0,
'u_func':lambda u:log10(u),
'u_values':[1.0,2.0,3.0,4.0,5.0,
6.0,7.0,8.0,9.0,
10.0,20.0,30.0,40.0],
'u_text_format':r"$%3.0f$ ",
'v_func':f1,
'v_values':[10.0,20.0,30.0,50.0,100.0],
'v_manual_axis_data':
{
10.0:['$10 \%$',
{'x_corr':0.22,
'y_corr':-.45,
'draw_line':True}],
20.0:['$20 \%$',
{'x_corr':0.2,
'y_corr':-.22,
'draw_line':True}],
30.0:['$30 \%$',
{'x_corr':0.1,
'y_corr':0.0,
'draw_line':True}],
50.0:['$50 \%$',
{'x_corr':0.1,
'y_corr':0.0,
'draw_line':True}],
100.0:['$100 \%$',
{'x_corr':0.3,
'y_corr':.3,
'draw_line':True}],
},
#'v_text_format':r"$%3.0f$ \%% ",
'u_title':r'Contrast Limiting Resolution \
(Line Pairs/mm)',
'v_title':r'Contrast',
'wd_title':r'Photocathode Illuminance \
(-log$_{10}$(lux))',
'wd_tick_side':'right',
'wd_text_format':r"$%3.2f$",
'wd_tick_levels':3,
'wd_tick_text_levels':1,
'wd_title_distance_center':2.2,
'manual_x_scale':True,
'x_min':1.5,
'x_max':7.0,
'mirror_x':True,
'u_scale_opposite':True,
'isopleth_values':[['x',20.0,'x']],
}
block_2_params={
'block_type':'type_8',
'f_params':Range_feet_params,
'isopleth_values':[['x']],
}
### TYPE 8 SINGLE-SCALE BLOCK ###
Focal_Length_inches_params={
'tag':'focal',
'u_min':1000.0/25.4,
'u_max':1.0/25.4,
'function':lambda u:log10(u),
'scale_type':'log',
'align_func':lambda u:u*25.4,
'title':r'\small $in$',
'title_x_shift':0.4,
'tick_side':'left',
'text_format':r"$%3.2f$",
'tick_levels':2,
'tick_text_levels':2,
}
block_3_params={
'block_type':'type_8',
'f_params':Focal_Length_inches_params,
'isopleth_values':[['x']],
}
### TYPE 8 SINGLE-SCALE BLOCK ###
Target_Size_feet_params={
'tag':'size',
'u_min':0.5*3.281,
'u_max':20.0*3.281,
'function':lambda u:log10(u),
'scale_type':'log',
'align_func':lambda u:u/3.281,
'title':r'\small $ft$',
'title_x_shift':0.35,
'tick_side':'right',
'text_format':r"$%3.0f$",
'tick_levels':2,
'tick_text_levels':2,
}
block_4_params={
'block_type':'type_8',
'f_params':Target_Size_feet_params,
'isopleth_values':[['x']],
}
########################################################
########### Previous Type 5 Example Nomogram ###########
########################################################
########################################################
###### Previous Compound Type 1 Example Nomogram #######
########################################################
const_A
const_B
const_C
const_D
const_E
const_F
=
=
=
=
=
=
1.5
0.36
4.25
.134
150
0.15
def f1(x,v):
return const_A*sin(const_B*(-x+const_C*v**const_D))+ \
(v/const_E)/(-x+const_F+(v/200))**2
block_20_params={
92
},
}],
}
Target_Reflectivity_params={
'u_min':1.0,
'u_max':100.0,
'function':lambda u:log10(0.01*u),
'scale_type':'log',
'title':r'Target',
'title_y_shift':-0.7,
'title_x_shift':-0.85,
'tick_side':'left',
'text_format':r"$%3.0f$",
'tick_levels':2,
'tick_text_levels':1,
'extra_titles':[
{'dx':-2.45,
'dy':-1.15,
'text':r'Reflectivity',
'width':5,
},
{'dx':-1.8,
'dy':-1.6,
'text':r'(\%)',
'width':5,
}]
}
FNumber_params={
# Replace 2*log10(u) with -2*log10(u)
'u_min':0.5,
'u_max':5.0,
'function':lambda u:-2*log10(u),
'scale_type':'log',
'title':r'Lens F/No.',
'title_y_shift':0.4,
'text_format':r"$%3.1f$",
'tick_levels':2,
'tick_text_levels':2,
}
Scene_Exitance_1_params={
# Replace -log10(0.225*u) with log10(0.225*u)
# Replace 2*log10(u) with -2*log10(u)
'tag':'exitance',
'u_min':0.00001,
'u_max':1.0,
'function':lambda u:log10(0.225*u),
'scale_type':'log',
'title':r'Scene Exitance (lumen/m$^2$)',
'title_x_shift':1.2,
'title_y_shift':-0.9,
'tick_side':'left',
'text_format':r"$%2.5G$",
'tick_levels':2,
'tick_text_levels':1,
}
Scene_Exitance_2_params={
'tag':'exitance',
'u_min':0.00001,
'u_max':1.0,
'function':lambda u:-log10(u),
'scale_type':'log',
'title':r'',
'text_format':r"$%2.5G$",
'tick_levels':0,
# Don't draw duplicate ticks
'tick_text_levels':0, # Don't draw duplicate labels
}
block_11_params={
'block_type':'type_1',
'width':15.0,
'height':15.0,
'f1_params':Scene_Exitance_1_params,
'f2_params':FNumber_params,
'f3_params':Photocathode_Illuminance_params,
'isopleth_values':[['x',3,'x']],
}
block_12_params={
'block_type':'type_1',
'width':15.0,
'height':15.0,
'f1_params':Scene_Exitance_2_params,
'f2_params':Target_Reflectivity_params,
'f3_params':Scene_Illuminance_params,
'isopleth_values':[['x','x',0.01]],
}
########################################################
######## Main Parameters of Overall Nomogram ##########
########################################################
main_params={
'filename':'EO-Isopleths.pdf',
'paper_height':24.0,
'paper_width':32.0,
'block_params':[block_20_params,block_11_params,
block_12_params,block_1_params,block_2_params,
block_3_params,block_4_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x': 10,
'title_y': 0,
'title_box_width': 22,
'title_str':r'\LARGE Nomogram for determining\
93
94
1000
100
10000
6
4
10
10
100
0.10
1.00
10.00
10.0
1.0
20.0
4.0
5.0
6.0
7.0
8.0
9.0
3.0
2.0
0.5
0.6
0.7
0.8
0.9
40
50
60
30
20
4
5
6
7
8
9
ft
Target Size
95
10
9
8
7
6
5
4
Lens F/No.
2.0
3.0
4.0
5.0
where:
Scene Exitance = Scene Illuminance Target Reflectivity
Lens Transmission = 90%
Magnification (of scene onto focal plane) 0
10
20
30
1.0
0.09
0.08
0.07
0.06
0.05
0.04
0.20
0.30
0.90
0.80
0.70
0.60
0.50
0.40
2.00
3.00
9.00
8.00
7.00
6.00
5.00
4.00
20.00
30.00
40
Image-Intensifier Photocathode
Responsivity = 200 A/lm
0.5
0.6
0.7
0.8
0.9
9
8
7
6
5
4
20
30
90
80
70
60
50
40
200
300
900
800
700
600
500
400
in
N Range
Contrast Limiting Resolution =
Focal Length Target Size
16000
14000
12000
8000
9000
7000
6000
1000
1000
mm
Lens
Focal Length
0.001
100
10
Target
Reflectivity
(%)
5000
4000
3000
2500
1600
1800
2000
5000
4000
1200
1400
3000
2500
1600
1800
2000
1400
1200
800
900
700
600
800
900
700
600
500
400
300
250
160
180
200
500
400
120
140
300
250
180
200
80
90
70
60
50
ft
Range
m
100%
%
50 Contrast
30%
20%
10%
1E 005
10
0.0001
Clear Full Moon at Zenith
0.1
0.01
0.01
Clear No Moon
0.001
0.1
No Moon Heavy Clouds
0.0001
7
1
1E 005
19
You may want to embellish the nomogram beyond what has been described here, such as adding another
graphic showing the machine part or a geometrical figure to which the nomogram applies. One option is to
use directly in PyNomo the drawing commands available in the PyX package installed as part of the PyNomo
installation. Another option is to import your PyNomo nomogram into an image editor.
Editing with PyX
PyNomo offers two main parameters that provide access to the lower-level PyX drawing commands:
pre_func: execute the PyX commands as defined in the named function before drawing the nomogram,
using coordinates in cm defined in PyNomo for the nomogram
post_func: execute the PyX commands as defined in the named function after drawing the nomogram,
using coordinates in cm defined in PyNomo for the nomogram
The PyX website and Reference Manual describe a number of commands for editing your nomogram.60
We can define a function before the main parameters that contains any PyX drawing commands to perform
before PyNomo draws the nomogram, say, pre(c). We can also define a function, say post(c), containing
PyX drawing commands to perform after PyNomo draws the nomogram. Setting make_grid to True overlays
a grid on the nomogram, which is critical for determining the coordinates needed by the PyX commands
while writing the script. Then we add the lines 'post_func':post, and 'pre_func':pre, to the main
parameters.
On the next page is an example of a nomogram, our earlier Type 4 Proportion nomogram, that has a
variety of PyX drawing commands added to it. The logo in the lower right corner is drawn only to show
some more drawing commands. More details are found in the PyX references.
rect: a background rectangle in pre(c), the only PyX drawing prior to the nomogram, with its starting
x,y coordinates and its width and height, with a Sepia-colored line of width 0.15cm and filled with a
light ivory color61
line: a line segment with starting and ending x,y coordinates, here a Sepia-colored thick line (which
could also be drawn in PyNomo by the line_params parameter)
text: text with an x-y coordinate, here Sepia-colored (which could also be drawn in PyNomo by the
extra_texts parameter)
arc: an arc with the x,y coordinates of the center, the radius in cm, and the initial and final angle in
degrees, specified here as Sepia-colored and thick (note the additional path.path operation required)
arrow: a line with an arrow decoration, with its starting and ending x,y coordinates specified
rect: another rectangle with its starting x,y coordinates and its width and height, filled because c.fill
was used instead of c.stroke, and colored Sepia
circle: a circle with its center x,y coordinates and its radius, in a filled version using c.fill and a hollow
version using c.stroke.
The PyNomo script and output PDF graphic below and are available online for download.62
60 http://pyx.sourceforge.net/
and http://pyx.sourceforge.net/manual.pdf
White, with the rgb fractions calculated from http://www.tayloredmktg.com/rgb/
62 http://www.myreckonings.com/pynomo11/Type4-PyX.py and http://www.myreckonings.com/pynomo11/Type4-PyX.pdf
61 Floral
96
main_params={
'filename':'Type4-Pyx.pdf',
'paper_height':20.0,
'paper_width':20.0,
'block_params':[block_1_params],
'transformations':[('rotate',0.01),('scale paper',)],
'title_x':10,
'title_y': -3.5,
'title_box_width': 10,
'title_str':r'\LARGE Law of Sines: \
$A / \sin \alpha=B / \sin \beta$',
'make_grid':False,
'draw_lines':True,
'line_params': [
{'coords':[[13,3.4,13,6.6],[17,3.4,17,7],
[13.4,3,16.6,3],[13.4,7,17,7]],
'line_style':[color.cmyk.Black,
style.linewidth.thick,
style.linestyle.solid],
'circle_size':0.0,
'circle_color':color.cmyk.Black,
},
{'coords':[[13,3,17,7]],
'line_style':[color.cmyk.Orange,
style.linewidth.thin,
style.linestyle.solid],
'circle_size':0.0,
'circle_color':color.cmyk.Orange,
},
{'coords':[[13,6,17,4],[14.5,3,15.5,7]],
'line_style':[color.cmyk.Blue,
style.linewidth.thin,
style.linestyle.dashed],
'circle_size':0.08,
'circle_color':color.cmyk.Blue,
},
],
'pre_func':pre,
'post_func':post,
}
block_1_params={
'block_type':'type_4',
'reference_color':color.cmyk.Orange,
'f1_params':A_params,
'f2_params':Alpha_params,
'f3_params':B_params,
'f4_params':Beta_params,
}
def pre(c):
c.stroke(path.rect(-3, -4, 27, 27),
[style.linewidth(0.15),
color.cmyk.Sepia,
deco.filled([color.rgb(1.0,0.98,0.94)])])
def post(c):
# Draw and triangle and labels
c.stroke(path.line(3, 13, 8, 13) +
Nomographer(main_params)
97
10
20
30
40
50
60
70
80
10
10
9
20
30
5
40
4
50
3
60
2
70
80
1
10
98
63 http://www.gimp.org/
64 http://www.coolutils.com/Online-PDF-Converter.php
65 http://www.inkscape.org/
66 See
99
20
As Ive tried to point out in the examples here, PyNomo offers significant advantages in creating precision
nomograms. PyNomo supports a number of common types of nomograms in equation form without having to
derive the standard determinants, while offering the determinant form as another more general type. PyNomo
can also provide transformations and optimization. And perhaps its most amazing capability is to create grid
and compound nomograms for more than three variables. The examples of these on the PyNomo website
are outstanding. PyNomo provides a fast way of testing and fine-tuning the layout and optimizations very,
very quickly.71 I relied on it extensively in preparing a variety of nomograms for a math journal article and
a PowerPoint presentation. I continue to try things with PyNomo and I am surprised at what it can produce.
Dr. Roschier has provided a software tool of real benefit to those of us with an interest in nomography.
71 Joe
Marasco provides an example of how he improved one of his nomogram designs by experimenting with PyNomo at
http://www.barbecuejoe.com/scan.htm
100
Index
vertical_guides, 88
wd_axis_color, 35
wd_text_color, 35
wd_title_color, 35
x_corr, 87
x_max, 87, 88
x_min, 87, 88
y_corr, 87
Type 6 only:
curve_const, 53
ladder_color, 35, 53
building the output, 9
errors, 9
101
key, 17, 57
logarithms, 3
main parameters
block_params, 15
draw_lines, 58
extra_texts, 26, 35, 48, 96
pyx_extra_defs, 26, 35
text, 26
width, 26
x, 26
y, 26
filename, 14
isopleth_params, 17, 35
circle_size, 18
color, 18, 35
linestyle, 18
transparency, 18
line_params, 17, 36, 58, 96
circle_color, 36, 58
circle_size, 58
coords, 58
line_style, 36, 58
make_grid, 1, 58, 80, 96
paper_height, 14, 17
paper_width, 14, 17
post_func, 96
pre_func, 96
title_box_width, 15
title_color, 35
title_str, 15
title_x, 15
title_y, 15
transformations, 15
polygon, 15, 73
rotate, 73
rotation, 15
scale paper, 15, 73
math functions, 11
common log, or log10(u), 12
e e, 12
natural log, or log(u), 12
pi , 12
math titles, 11
fractions, 27
italic letters between $, 11
102
v_start, 76
v_stop, 76
v_text_color, 35, 77
v_texts, 77
v_texts_u_start, 77
v_texts_u_stop, 77
v_values, 76
smart axes, 1
spaces
\enspace, 11
\qquad, 11
\quad, 11
\thinspace, 11, 57
structure of scripts, 7
symbols
ampersand &, 11
approximately equals , 11
backslash \ 57
copyright , 10
degrees , 11
division , 11
dollar sign $, 11
Greek letters, 11
parallel k, 61
percent %, 11
pi , 11
pound #, 11
square root , 11
tick , 11
times , 11
underscore _, 11
text_distance, 41
text_distance_#, 41
text_format, 2, 14, 22
f vs. G, 2
text_size_#, 41
text_color, 41
tick_levels, 14, 48
tick_side, 14
tick_text_levels, 14, 48
title, 14
title_color, 35
title_distance_center, 14, 57
title_draw_center, 14, 57
title_opposite_tick, 14, 57
title_x_shift, 22
title_y_shift, 22
title_color, 41
turn_relative, 30
u_max, 14, 30, 70, 77
u_min, 14, 30, 70, 77
Type 1 only:
proportion, 14
Type 3 only:
reference_color, 35
Type 9 only:
f, 70, 77
f_grid, 76
g, 70, 77
g_grid, 76
grid, 70, 77
h, 70, 77
h_grid, 76
text_distance, 77
text_prefix_u, 76
text_prefix_v, 76
transform_ini, 70
u_line_color, 35, 77
u_max_trafo, 70
u_min_trafo, 70
u_start, 76
u_stop, 76
u_text_color, 35, 77
u_texts, 76
u_texts_v_start, 77
u_texts_v_stop, 77
u_values, 76
v_line_color, 35, 77
titles, 10
bold, 10
carriage return, 10
italic, 10
size, 10, 36
spanning script lines \, 10, 27
transformation
initial, 70
polygon, 15, 73
rotation, 15
scale paper, 15
shear, 64, 73, 76
types of nomogram
listing by section, 6
supported by PyNomo, 6
103
104