100% found this document useful (2 votes)
66 views

Numerical Python in Astronomy and Astrophysics: A Practical Guide to Astrophysical Problem Solving (Undergraduate Lecture Notes in Physics) Wolfram Schmidt - Download the complete ebook in PDF format and read freely

The document presents 'Numerical Python in Astronomy and Astrophysics: A Practical Guide to Astrophysical Problem Solving' by Wolfram Schmidt and Marcel Völschow, which is part of the Undergraduate Lecture Notes in Physics series. It aims to teach students how to use Python for numerical computations and data analysis in the context of astronomy and astrophysics, emphasizing practical problem-solving skills. The book includes worked examples, exercises, and is designed for beginners as well as those with some programming experience.

Uploaded by

tayishiam
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
66 views

Numerical Python in Astronomy and Astrophysics: A Practical Guide to Astrophysical Problem Solving (Undergraduate Lecture Notes in Physics) Wolfram Schmidt - Download the complete ebook in PDF format and read freely

The document presents 'Numerical Python in Astronomy and Astrophysics: A Practical Guide to Astrophysical Problem Solving' by Wolfram Schmidt and Marcel Völschow, which is part of the Undergraduate Lecture Notes in Physics series. It aims to teach students how to use Python for numerical computations and data analysis in the context of astronomy and astrophysics, emphasizing practical problem-solving skills. The book includes worked examples, exercises, and is designed for beginners as well as those with some programming experience.

Uploaded by

tayishiam
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 71

Read Anytime Anywhere Easy Ebook Downloads at ebookmeta.

com

Numerical Python in Astronomy and Astrophysics: A


Practical Guide to Astrophysical Problem Solving
(Undergraduate Lecture Notes in Physics) Wolfram
Schmidt
https://ebookmeta.com/product/numerical-python-in-astronomy-
and-astrophysics-a-practical-guide-to-astrophysical-problem-
solving-undergraduate-lecture-notes-in-physics-wolfram-
schmidt/

OR CLICK HERE

DOWLOAD EBOOK

Visit and Get More Ebook Downloads Instantly at https://ebookmeta.com


Undergraduate Lecture Notes in Physics

Wolfram Schmidt
Marcel Völschow

Numerical
Python in
Astronomy and
Astrophysics
A Practical Guide to Astrophysical
Problem Solving
Undergraduate Lecture Notes in Physics

Series Editors
Neil Ashby, University of Colorado, Boulder, CO, USA
William Brantley, Department of Physics, Furman University, Greenville, SC, USA
Matthew Deady, Physics Program, Bard College, Annandale-on-Hudson, NY, USA
Michael Fowler, Department of Physics, University of Virginia, Charlottesville,
VA, USA
Morten Hjorth-Jensen, Department of Physics, University of Oslo, Oslo, Norway
Michael Inglis, Department of Physical Sciences, SUNY Suffolk County
Community College, Selden, NY, USA
Barry Luokkala , Department of Physics, Carnegie Mellon University, Pittsburgh,
PA, USA
Undergraduate Lecture Notes in Physics (ULNP) publishes authoritative texts
covering topics throughout pure and applied physics. Each title in the series is
suitable as a basis for undergraduate instruction, typically containing practice
problems, worked examples, chapter summaries, and suggestions for further reading.
ULNP titles must provide at least one of the following:
• An exceptionally clear and concise treatment of a standard undergraduate
subject.
• A solid undergraduate-level introduction to a graduate, advanced, or
non-standard subject.
• A novel perspective or an unusual approach to teaching a subject.
ULNP especially encourages new, original, and idiosyncratic approaches to physics
teaching at the undergraduate level.
The purpose of ULNP is to provide intriguing, absorbing books that will continue
to be the reader’s preferred reference throughout their academic career.

More information about this series at http://www.springer.com/series/8917


Wolfram Schmidt Marcel Völschow

Numerical Python
in Astronomy
and Astrophysics
A Practical Guide to Astrophysical Problem
Solving

123
Wolfram Schmidt Marcel Völschow
Hamburg Observatory Hamburg University of Applied Sciences
University of Hamburg Hamburg, Germany
Hamburg, Germany

ISSN 2192-4791 ISSN 2192-4805 (electronic)


Undergraduate Lecture Notes in Physics
ISBN 978-3-030-70346-2 ISBN 978-3-030-70347-9 (eBook)
https://doi.org/10.1007/978-3-030-70347-9
© Springer Nature Switzerland AG 2021
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part
of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations,
recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission
or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar
methodology now known or hereafter developed.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this
publication does not imply, even in the absence of a specific statement, that such names are exempt from
the relevant protective laws and regulations and therefore free for general use.
The publisher, the authors and the editors are safe to assume that the advice and information in this
book are believed to be true and accurate at the date of publication. Neither the publisher nor the
authors or the editors give a warranty, expressed or implied, with respect to the material contained
herein or for any errors or omissions that may have been made. The publisher remains neutral with regard
to jurisdictional claims in published maps and institutional affiliations.

This Springer imprint is published by the registered company Springer Nature Switzerland AG
The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
Preface

Over the last decades the work of astronomers and astrophysicists has undergone
great changes. Making observations is an essential part of astronomy, but most
researchers do not operate instruments directly any longer. Most of the time they
receive huge amounts of data from remote or even space-bound telescopes and
make heavy use of computing power to filter, process, and analyse these data. This
requires sophisticated algorithms and, these days, increasingly utilizes machine
learning. On the theoretical side of astrophysics, making important discoveries just
with pencil and paper belongs to the past (with the occasional exception from the
rule). Scientific questions in contemporary astrophysics are often too complex to
allow for analytic solutions. As a consequence, numerical computations with a great
wealth of physical details play a major role in research now. Back-of-the-envelope
calculations still serve their purpose to guide researchers, but at the end of the day it
is hardly possible to make progress without writing and running code on computers
to gain a deeper understanding of the physical processes behind observed
phenomena.
In this regard, it is surprising that the education of students at the undergraduate
level is still largely focused on traditional ways of problem solving. It is often
argued that being able to program comes along the way, for example, when students
engage with their research project for a Bachelor’s thesis. It is said that problems in
introductory courses can be solved mostly with analytic techniques, and there is no
need to bother students with programming languages. However, we are convinced
that there is a great deal of computer-based problem solving that can be done right
from the beginning. As a result, connections to contemporary science can be made
earlier and more lively. One of the obvious merits of becoming acquainted with a
programming language is that you can learn how to address a question by devel-
oping and implementing an algorithm that provides the answer.
There are two major avenues toward learning a programming language. One
follows the systematic teaching model, where the language is laid out in all details
and you are guided step by step through its elements and concepts. Surely, this is
the preferable method if you want to master a programming language. For the
beginner, however, this can become tiresome and confusing, especially since the

v
vi Preface

relevance of most of the stuff you learn becomes clear only later (if at all). The
alternative approach is to learn mainly from examples, to grasp the language in an
intuitive way and to gradually pick up what you need to know for practical
applications. We believe that Python is quite suitable for this approach. Of course,
there is always a downside. This textbook is far from covering everything there is to
know about Python. We focus on numerical computation and data analysis and
make use of libraries geared toward these applications.
Problem solving is an art that requires a lot of practice. The worked-out
examples in this book revolve around basic concepts and problems encountered in
undergraduate courses introducing astronomy and astrophysics. The complete
source code is provided on the web via uhh.de/phy-hs-pybook. We briefly reca-
pitulate essential formulas and basic knowledge, but our recaps are by no means
intended to replace lecture courses and textbooks on astronomy and astrophysics.
This is highlighted by frequently referring to introductory textbooks for further
reading. Our book is mainly intended for readers who want to learn Python from
scratch. In the beginning, code examples are explained in detail, and exercises start
at a rather elementary level. As topics become more advanced, you are invited to
work on problems that require a certain amount of effort, time, and innovative
thinking. If you have already experience with programming and know some
Python, you can concentrate on topics you are interested in. Our objective is that
examples as well as exercises not only help you in understanding and using Python
but also offer intriguing applications in astronomy and astrophysics.

Hamburg, Germany Wolfram Schmidt


December 2020 Marcel Völschow
Acknowledgements

This book was inspired by introductory courses on astronomy and astrophysics at


the University of Hamburg. We incorporated Python on the fly into problem classes
accompanying the lectures. We thank Robi Banerjee, Jochen Liske, and Francesco
de Gasperin for supporting this learning concept, and we are very grateful for the
enthusiasm and feedback of many students. Special thanks goes to Bastian R.
Brückner, Henrik Edler, Philipp Grete, and Caroline Heneka for reading and
commenting the manuscript. Moreover, we thank Bastian R. Brückner for drawing
numerous illustrative figures that are invaluable for explaining important concepts
in the book.

vii
Contents

1 Python Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 Using Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Understanding Expressions and Assignments . . . . . . . . . . . . . . . . 3
1.3 Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.4 Working with Modules and Objects . . . . . . . . . . . . . . . . . . . . . . . 14
2 Computing and Displaying Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.1 Spherical Astronomy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.1.1 Declination of the Sun . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.1.2 Diurnal Arc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.1.3 Observation of Celestial Objects . . . . . . . . . . . . . . . . . . . . 35
2.2 Kepler’s Laws of Planetary Motion . . . . . . . . . . . . . . . . . . . . . . . 42
2.3 Tidal Forces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3 Functions and Numerical Methods . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.1 Blackbody Radiation and Stellar Properties . . . . . . . . . . . . . . . . . 55
3.1.1 Stefan–Boltzmann Law . . . . . . . . . . . . . . . . . . . . . . . . . . 56
3.1.2 Planck Spectrum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.2 Physics of Stellar Atmospheres . . . . . . . . . . . . . . . . . . . . . . . . . . 77
3.2.1 Thermal Excitation and Ionization . . . . . . . . . . . . . . . . . . 78
3.2.2 The Balmer Jump . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.3 Planetary Ephemerides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
4 Solving Differential Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
4.1 Numerical Integration of Initial Value Problems . . . . . . . . . . . . . . 105
4.1.1 First Order Differential Equations . . . . . . . . . . . . . . . . . . . 105
4.1.2 Second Order Differential Equations . . . . . . . . . . . . . . . . . 116
4.2 Radial Fall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
4.3 Orbital Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
4.4 Galaxy Collisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151

ix
x Contents

4.5 Stellar Clusters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167


4.6 Expansion of the Universe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
5 Astronomical Data Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
5.1 Spectral Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
5.2 Transit Light Curves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
5.3 Survey Data Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
5.4 Image Processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
5.5 Machine Learning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
5.5.1 Image Classification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
5.5.2 Spectral Classification . . . . . . . . . . . . . . . . . . . . . . . . . . . 216

Appendix A: Object-Oriented Programming in a Nutshell . . . . . . . . . . . 225


Appendix B: Making Python Faster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
Chapter 1
Python Basics

Abstract This chapter explains basic programming concepts. After an overview of


common Python distributions, we show how to use Python as a simple calculator. As
a first step toward programming, variables and expressions are introduced. The arith-
metic series and Fibonacci numbers illustrate the concepts of iteration and branching.
We conclude this chapter with a program for the computation of a planet’s orbital
velocity around the Sun, using constants and functions from libraries and giving a
small glimpse at objects in Python.

1.1 Using Python

There is quite a variety of Python installations. Depending on the operating system


of your computer, you might have some basic Python preinstalled. Typically, this is
the case on Linux computers. However, you might find it rather cumbersome to use,
especially if you are not well experienced with writing source code in elementary
text editors and executing the code on the command line. What is more, installing
additional packages typically requires administrative privileges. If you work, for
example, in a computer lab it is likely that you do not have the necessary access rights.
Apart from that, Python version 2.x (that is major version 2 with some subversion
x) is still in use, while this book is based on version 3.x.
Especially as a beginner, you will probably find it convenient to work with a a GUI
(graphical user interface). Two popular choices for Python programming are Spyder
and Jupyter. Spyder (www.spyder-ide.org) is a classical IDE (integrated development
environment) which allows you to edit code, execute it and view the output in different
frames. Jupyter (jupyter.org) can be operated via an arbitrary web browser. It allows
you to run an interactive Python session with input and output cells (basically, just
like the console-based ipython). Apart from input cells for typing Python source
code, there are so-called markdown cells for writing headers and explanatory text.
This allows you to use formatting similar to elementary HTML for webpages. A
valuable feature is the incorporation of LaTeX to display mathematical expressions.
The examples in this book can be downloaded as Jupyter notebooks and Python
source code in zipped archives from uhh.de/phy-hs-pybook.
© Springer Nature Switzerland AG 2021 1
W. Schmidt and M. Völschow, Numerical Python in Astronomy and Astrophysics,
Undergraduate Lecture Notes in Physics,
https://doi.org/10.1007/978-3-030-70347-9_1
2 1 Python Basics

Since it depends on your personal preferences which software suits you best, we do
not presume a particular GUI or Python distribution here. If you choose to work with
Spyder or Jupyter, online documentation and tutorials will help you to install the soft-
ware and to get started (browse the official documentation under docs.spyder-ide.org
and jupyter-notebook.readthedocs.io/en/stable). For a comprehensive guideline, see
also [1, appendices A and B]. A powerful all-in-one solution is Anaconda, a Python
distribution and package manager that can be installed under Windows, macOS or
Linux by any user (see docs.anaconda.com for more information). Anaconda pro-
vides a largely autonomous environment with all required components and libraries
on a per-user basis. Of course, this comes at the cost of large resource consumption
(in particular, watch your available disk space).
As a first step, check if you can run the traditional “Hello, World!” example with
your favorite Python installation. Being astronomers, we use a slightly modified
version:
1 print("Hello, Universe!")
In this book Python source code is listed in frames with lines numbered on the left (in
the above example, there is just one line). Although these line numbers are not part
of the source code (that’s why they are shown outside of the frame), they are useful
for referring to particular parts of a code example. You might be able to display line
numbers in your code editor (in Jupyter notebooks, for example, line numbering can
be switched on and off in the View menu), but you should not confuse these numbers
with the line numbers used in this book. Usually we will continue the numbering
over several frames if the displayed pieces of code are related to each other, but we
also frequently reset line numbers to 1 when a new program starts or a new idea is
introduced. Whenever you encounter a code line with number 1 it should alert you:
at this point something new begins.
After executing the print statement in line 1 above, you should see somewhere on
your screen the output1

Hello, Universe!

The quotes in the source code are not shown in the output. They are used to signify
that the enclosed characters form a string. As you might have guessed, the print()
function puts the string specified in parentheses on the screen (more precisely, in a
window or frame that is used by Python for output).2

1 How to execute Python code depends on the software you are using (consult the documentation).
In a notebook, for example, all you need to do is to simultaneously press the enter and shift keys of
your keyboard in the cell containing the code.
2 Enclosing the string in parentheses is obligatory in Python 3. You may find versions of “Hello,

World!” without parentheses on the web, which work only with Python 2.
1.2 Understanding Expressions and Assignments 3

1.2 Understanding Expressions and Assignments

Apart from printing messages on the screen, which is not particularly exciting by
itself, Python can be used as a scientific calculator. Let us begin right away with an
example from astronomy. Suppose we want to calculate the velocity at which Earth
is moving along its orbit around the Sun. For simplicity, we treat the orbit as circular
(in fact, it is elliptical with a small eccentricity of 0.017). From the laws of circular
motion it follows that we can simply calculate the velocity as the circumference 2π r
of the orbit divided by the period P, which happens to be one year for Earth. After
having looked up the value of π, the orbital radius r (i.e. the distance to the Sun) in
km, and the length of a year in seconds,3 we type
1 2*3.14159*1.496e8/3.156e7
and, once evaluated by Python, we obtain

29.783388086185045

for the orbital velocity in km/s. Line 1 is an example for a Python expression con-
sisting of literal numbers and the arithmetic operators * and / for multiplication
and division, respectively. The factor of two in the formula for the circumference
is simply written as the integer 2, while the number π is approximately expressed
in fixed-point decimal notation as 3.14159.4 The radius r = 1.496 × 108 km is
expressed as 1.496e8, which is a so-called floating point literal . The character
e followed by an integer indicates the exponent of the leading digit in the decimal
system. In this case, e8 corresponds to the factor 108 . Negative exponents are indi-
cated by a minus sign after e. For example, 10−3 can be expressed as 1.0e-3 or
just 1e-3 (inserting + for positive exponents is optional).
Of course, there is much more to Python than evaluating literal expressions like
a calculator. To get an idea how this works, we turn the example shown above into a
little Python program:
1 radius = 1.496e8 # orbital radius in km
2 period = 3.156e7 # orbital period in s
3
4 # calculate orbital velocity
5 velocity = 2*3.14159*radius/period
Lines 1, 2, and 5 are examples for assignments. Each assignment binds the value of
the expression on the right-hand side of the equality sign = to a name on the left-hand
side. A value with a name that can be used to refer to that value is in essence what is

3 Strictlyspeaking, the time needed by Earth to complete one revolution around the Sun is the
sidereal year, which has about 365.256 d. One day has 86400 s.
4 In many programming languages, integers such as 2 are treated differently than floating point

numbers. For example, using 2.0 instead of the integer 2 in a division might produce a different
result. In Python 3, it is usually not necessary to make this distinction. Alas, Python 2 behaves
differently in this respect.
4 1 Python Basics

called a variable in Python.5 In line 5, the variables radius and period are used
to compute the orbital velocity of Earth from the formula

2π r
v= (1.1)
P
and the result is in turn assigned to the variable velocity. Any text between the
hash character # and the end of a line is not Python code but a comment explaining
the code to someone other than the programmer (once in a while, however, even
programmers might be grateful for being reminded in comments about code details
in long and complex programs). For example, the comments in line 1 and 2 provide
some information about the physical meaning (radius and period of an orbit) and
specify the units that are used (km and s). Line 4 comments on what is going on in
the following line.
Now, if you execute the code listed above, you might find it surprising that there
is no output whatsoever. Actually, the orbital velocity is computed by Python, but
assignments do not produce output. To see the value of the velocity, we can append
the print statement
6 print(velocity)
to the program (since this line depends on code lines 1–5 above, we continue the
numbering and will keep doing so until an entirely new program starts), which results
in the output6

29.783388086185045

This is the same value we obtained with the calculator example at the beginning of
this section.
However, we can do a lot better than that by using further Python features. First
of all, it is good practice to print the result of a program much in the same way as,
hopefully, you would write the result of a handwritten calculation: It should be stated
that the result is a velocity in units of km/s. This can be achieved quite easily by using
string literals as in the very first example in Sect. 1.1:
7 print("orbital velocity =", velocity, "km/s")
producing the output

orbital velocity = 29.783388086185045 km/s

5 The concept of a variable in Python is different from variables in programming languages such as
C, where variables have a fixed data type and can be declared without assigning a value. Basically, a
variable in C is a placeholder in memory whose size is determined by the data type. Python variables
are objects that are much more versatile.
6 In interactive Python, just writing the variable name in the final line of a cell would also result in

its value being displayed in the output.


1.2 Understanding Expressions and Assignments 5

It is important to distinguish between the word ‘velocity’ appearing in the string


"orbital velocity =" on the one hand and the variable velocity sepa-
rated by commas on the other hand. In the output produced by print the two strings
are concatenated with the value of the variable. Using such a print statement may
seem overly complicated because we know, of course, that the program computes
the orbital velocity and, since the radius is given in km and the period in seconds, the
resulting velocity will be in units of km/s. However, the meaning of a numerical value
without any additional information might not be obvious at all in complex, real-world
programs producing a multitude of results. For this reason, we shall adhere to the
practice of precisely outputting results throughout this book. The simpler version
shown in line 6 may come in useful if a program does not work as expected and you
want to check intermediate results.
An important issue in numerical computations is the precision of the result. By
default, Python displays a floating point value with machine precision (i.e. the maxi-
mal precision that is supported by the way a computer stores numbers in memory and
performs operations on them). However, not all of the digits are necessarily signifi-
cant. In our example, we computed the orbital velocity from parameters (the radius
and the period) with only four significant digits, corresponding to a relative error
of the order 10−4 . Although Python performs arithmetical operations with machine
precision, the inaccuracy of our data introduces a much larger error. Consequently,
it is pointless to display the result with machine precision. Insignificant digits can be
discarded in the output by appropriately formatting the value:
8 print("orbital velocity = {:5.2f} km/s".format(velocity))

Let us see how this works:


• The method format() inserts the value of the variable in parentheses into the
preceding string (mind the dot in between). You will learn more about methods in
Sect. 1.4.
• The placeholder {:5.2f} controls where and in which format the value of the
variable velocity is inserted. The format specifier 5.2f after the colon :
indicates that the value is to be displayed in fixed-point notation with 5 digits
altogether (including the decimal point) and 2 digits after the decimal point. The
colon before the format specifier is actually not superfluous. It is needed if several
variables are formatted in one print statement (examples will follow later).
Indeed, the output now reads

orbital velocity = 29.78 km/s

Optionally, the total number of digits in the formatting command can be omitted.
Python will then just fill in the leading digits before the decimal point (try it; also
change the figures in the command and try to understand what happens). A fixed
number of digits can be useful, for example, when printing tabulated data.
As the term variable indicates, the value of a variable can be changed in subsequent
lines of the program by assigning a new value. For example, you might want to
6 1 Python Basics

calculate the orbital velocity of a hypothetical planet at ten times the distance of
the Earth from the Sun, i.e. r = 1.496 × 109 km. To that end, we could start with
the assignment radius=1.496e9. Alternatively, we can make use of the of the
current value based on the assignment in line 1 and do the following:
9 radius = 10*radius
10 print("new orbital radius = {:.3e} km".format(radius))
Although an assignment may appear as the equivalent of a mathematical equality, it is
of crucial importance to understand that it is not. Transcribing line 9 into the algebraic
equation r = 10r is nonsense because one would obtain 1 = 10 after dividing through
r , which is obviously a contradiction. Keep in mind:

The assignment operator = in Python means set to, not is equal to.

The code in line 9 thus encompasses three steps:


(a) Take the value currently assigned to radius,
(b) multiply this value by ten
(c) and reassign the result to radius.
Checking this with the print statement in line 10, we find that the new value of the
variable radius is indeed 10 times larger than the original value from line 1:

new orbital radius = 1.496e+09 km

The radius is displayed in exponential notation with three digits after the decimal
point, which is enabled by the formatting type e in place of f in the placeholder
{:.3e} for the radius (check what happens if you use type f in line 10). You must
also be aware that repeatedly executing the assignment radius = 10*radius
in interactive Python increases the radius again and again by a factor of 10, which is
possibly not what you might want. However, repeated operation on the same variable
is done on purpose in iterative constructions called loops (see Sect. 1.3).
After having defined a new radius, it would not be correct to go straight to the
computation of the orbital velocity since the period of the orbit changes, too. The
relation between period and radius is given by Kepler’s third law of planetary motion,
which will be covered in more detail in Sect. 2.2. For a planet in a circular orbit around
the Sun, this relation can be expressed as7

4π2 3
P2 = r , (1.2)
GM

7 Hereit is assumed that the mass of the planet is negligible compared to the mass of the Sun. For
the general formulation of Kepler’s third law see Sect. 2.2.
1.2 Understanding Expressions and Assignments 7

where M=1.989 × 1030 kg is the mass of the Sun and G=6.674 × 10−11 N kg−2 m2
is the gravitational constant. To calculate P for given r , we rewrite this equation in
the form
P = 2π (G M)−1/2 r 3/2 .

This formula can be easily turned into Python code by using the exponentiation
operator ** for calculating the power of an expression:
11 # calculate period in s from radius in km (Kepler’s third law)
12 period = 2*3.14159 * (6.674e-11*1.989e30)**(-1/2) * \
13 (1e3*radius)**(3/2)
14 # print period in yr
15 print("new orbital period = {:.1f} yr".format(period/3.156e7))
16
17 velocity = 2*3.14159*radius/period
18 print("new orbital velocity = {:.2f} km/s".format(velocity))

The results are

new orbital period = 31.6 yr


new orbital velocity = 9.42 km/s

Hence, it would take more than thirty years for the planet to complete its orbit around
the Sun, as its orbital velocity is only about one third of Earth’s velocity. Actually,
these parameters are quite close to those of the planet Saturn in the solar system.
The backslash character \ in line 12 is used to continue an expression that does not
fit into a single line in the following line (there is no limitation on the length of a
line in Python, but code can become cumbersome to read if too much is squeezed
into a single line). An important lesson taught by the code listed above is that you
always need to be aware of physical units when performing numerical calculations.
Since the radius is specified in km, we obtain the orbital velocity in km/s. However,
the mass of the Sun and the gravitational constants in the expression for the orbital
period in lines 12–13 are defined in SI units. For the units to be compatible, we
need to convert the radius from km to m. This is the reason for the factor 103 in the
expression (1e3*radius)**(3/2). Of course, this does not change the value of
the variable radius itself. To avoid confusion, it is stated in the comment in line 11
which units are assumed. Another unit conversion is applied when the resulting period
is printed in units of a year in line 15, where the expression period/3.156e7 is
evaluated and inserted into the output string via format. As you may recall from
the beginning of this section, a year has 3.156 × 107 s.
Wrong unit conversion is a common source of error, which may have severe con-
sequences. A famous example is the loss of NASA’s Mars Climate Orbiter due to
the inconsistent use of metric and imperial units in the software of the spacecraft.8
As a result, more than $100 million were quite literally burned on Mars. It is there-
fore extremely important to be clear about the units of all physical quantities in a

8 See mars.jpl.nasa.gov/msp98/orbiter/.
8 1 Python Basics

program. Apart from the simple, but hardly foolproof approach of using explicit con-
version factors and indicating units in comments, you will learn different strategies
for ensuring the consistency of units in this book.

1.3 Control Structures

The computation of the orbital velocity of Earth in the previous section is a very
simple example for the implementation of a numerical algorithm in Python.9 It
involves the following steps:
1. Initialisation of all data needed to perform the following computation.
2. An exactly defined sequence of computational rules (usually based on mathe-
matical formulas), unambiguously producing a result in a finite number of steps
given the input from step 1.
3. Output of the result.
In our example, the definition of the variables radius and period provides the
input, the expression for the orbital velocity is a computational rule, and the result
assigned to the variable velocity is printed as output.
A common generalization of this simple scheme is the repeated execution of the
same computational rule in a sequence of steps, where the outcome of one step is
used as input for the next step. This is called iteration and will be explained in the
remainder of this section. The independent application of the same operations to
multiple elements of data is important when working with arrays, which will be
introduced in Chap. 2.
Iteration requires a control structure for repeating the execution of a block of
statements a given number of times or until a certain condition is met and the iteration
terminates. Such a structure is called a loop. For example, let us consider the problem
of summing up the first 100 natural numbers (this is a special case of an arithmetic
series, in which each term differs by the previous one by a constant):


n
sn ≡ k = 1 + 2 + 3 + ... + n. (1.3)
k=1

9 The term algorithm derives from the astronomer and mathematician al-Khwarizmi whose name
was transcribed to Algoritmi in Latin (cf. [2] if you are interested in the historical background).
al-Khwarizmi worked at the House of Wisdom, a famous library in Bagdad in the early 9th century.
Not only was he the founder of the branch of mathematics that became later known as algebra, he
also introduced the decimal system including the digit 0 in a book which was preserved until the
modern era only in a Latin translation under the title Algoritmi de numero Indorum (this refers to
the origin of the number zero in India). The digit 0 is quintessential to the binary system used on
all modern computers.
1.3 Control Structures 9

Fig. 1.1 Illustration of the Initialization


computation of the sum s100 sum=0
defined by Eq. (1.3) via a
for loop. The box on the Iteration
top of the figure contains the k=1 sum=0+1 = 1
initialization statement prior
to the loop (sum is set to k=2 sum=1+2 = 3
zero). The middle box shows
k=3 sum=3+3 = 6
iterations of sum in the body

...

...

...
of the for loop with the
counter k, resulting in the k=99 sum=4851+99 = 4950
sum shown at the bottom.
The arrows indicate how k=100 sum=4950+100 = 5050
values from one iteration are
Result
used in the next iteration.
sum=5050
Values of the loop counter
are shown in red

where n = 100. In Python, we can perform the summation using a for loop:
1 sum = 0 # initialization
2 n = 100 # number of iterations
3
4 for k in range(1,n+1): # k running from 1 to n
5 sum = sum + k # iteration of sum
6
7 print("Sum =", sum)
The result is

Sum = 5050

The keywords for and in indicate that the loop counter k runs through all integers
defined by range(1,n+1), which means the sequence 1, 2, 3, . . . , n in mathe-
matical notation. It is a potential source of confusion that Python includes the start
value 1, but excludes the stop value n+1 in range(1,n+1).10
The indented block of code following the colon is executed subsequently for each
value of the loop counter. You need to be very careful about indentations in Python!
They must be identical for all statements in a block, i.e. you are not allowed to use
more or less white space or mix tabs and white spaces. We recommend to use one tab
per indentation. The block ends with the first non-indented statement. In the example
above, only line 5 is indented, so this line constitutes the body of the loop, which
adds the value of the loop counter to the variable sum. The initial value of sum must
be defined prior to the loop (see line 1). Figure 1.1 illustrates how the variables are
iterated in the loop.

10 Thereis a reason for the stop value being excluded. The default start value is 0 and range(n)
simply spans the n integers 0, 1, 2, . . . , n − 1.
10 1 Python Basics

Actually, our Python program computes the sum exactly in the way intended by
the teacher of nine-year old Carl Friedrich Gauss11 in school, just by summing up the
numbers from 1 to 100. However, Gauss realized that there is a completely different
solution to the problem and he came up with the correct answer much faster than
expected by his teacher, while his fellow students were still tediously adding up
numbers. The general formula discovered by Gauss is (the proof can be found in any
introductory calculus textbook or on the web):


n
n(n − 1)
sn = k= . (1.4)
k=1
2

We leave it as an exercise to check with Python that this formula yields the same
value as direct summation.
A slightly more demanding example is the calculation of the Fibonacci sequence12
using the recursion formula

Fn+1 = Fn + Fn−1 for n ≥ 1, (1.5)

with the first two elements


F1 = 1 , F0 = 0 . (1.6)

The meaning of Eq. (1.5) is that any Fibonacci number is the sum of the two preceding
ones, starting from 0 and 1. The following Python program computes and prints the
Fibonacci numbers F1 , F2 , . . . , F10 (or as many as you like):
1 # how many numbers are computed
2 n_max = 10
3
4 # initialize variables
5 F_prev = 0 # 0. number
6 F = 1 # 1. number
7
8 # compute sequence of Fibonacci numbers
9 for n in range(1,n_max+1):
10 print("{:d}. Fibonacci number = {:d}".format(n,F))
11
12 # next number is sum of F and the previous number
13 F_next = F + F_prev
14

11 German mathematician, physicist, and astronomer who is known for the Gauss theorem, the

normal distribution, and many other import contributions to algebra, number theory, and geometry.
12 Named after Leonardo de Pisa, also known as Fibonacci, who introduced the sequence to European

mathematics in the early 13th century. However, the Fibonacci sequence was already known to
ancient Greeks. It was used to describe growth processes and there is a remarkable relation to the
golden ratio.
1.3 Control Structures 11

15 # prepare next iteration


16 F_prev = F # first reset F_prev
17 F = F_next # then assign next number to F
The three variables F_prev, F, and F_next correspond to Fn−1 , Fn , and Fn+1 ,
respectively. The sequence is initialized in lines 5 and 6 (definition of F0 and F1 ).
The recursion formula (1.5) is implemented in line 13. Without lines 16 and 17,
however, the same value (corresponding to F0 + F1 ) would be assigned again and
again to F_next. For the next iteration, we need to re-assign the values of F (Fn )
and F_next (Fn+1 ) to F_prev (Fn−1 ) and F (Fn ), respectively. The loop counter
n merely controls how many iterations are executed. Figure 1.2 shows a schematic
view of the algorithm (you can follow the values of the variables in the course of the
iteration by inserting a simple print statement into the loop). The output produced
by the program is13

1. Fibonacci number = 1
2. Fibonacci number = 1
3. Fibonacci number = 2
4. Fibonacci number = 3
5. Fibonacci number = 5
6. Fibonacci number = 8
7. Fibonacci number = 13
8. Fibonacci number = 21
9. Fibonacci number = 34
10. Fibonacci number = 55

Since two variables are printed, we need two format fields where the values of the
variables are inserted (see line 10). As an alternative to using format(), the same
output can be produced by means of a formatted string literal (also called f-string)14 :
print(f"{n:d}. Fibonacci number = {F:d}")
Here, the variable names are put directly into the string. The curly braces indicate
that the values assigned to the names n and F are to be inserted in the format defined
after the colons (in this example, as integers with arbitrary number of digits). This is a
convenient shorthand notation. Nevertheless, we mostly use format() in this book
because the syntax maintains a clear distinction between variables and expressions
on the one hand and formatted strings on the other hand. If you are more inclined to
f-strings, make use of them as you please.
Suppose we would like to know all Fibonacci numbers smaller than, say, 1000.
We can formally write this as Fn < 1000. Since it is not obvious how many Fibonacci
numbers exist in this range, we need a control structure that repeats a block of code

13 As you can see from Fig. 1.2, F11 is computed as final value of F_next. But it is not used. You
can try to modify the program such that only 9 iterations are needed to print the Fibonacci sequence
up to F10 .
14 This feature was introduced with Python 3.6.
12 1 Python Basics

Fig. 1.2 Illustration of the Initialization


recursive computation of the F_prev=0 F=1
Fibonacci sequence (see
Eq. 1.5). In each iteration of Iteration
the loop, the sum of n=1 F_prev=0 F=1 F_next=0+1 = 1
F_prev and F is assigned to
the variable F_prev. The n=2 F_prev=1 F=1 F_next=1+1 = 2
resulting number is shown in
n=3 F_prev=1 F=2 F_next=1+2 = 3
the rightmost column. For

...

...

...

...

...
the next iteration, this
number is re-assigned to F, n=9 F_prev=21 F=34 F_next=21+34 = 55
and the value of F to
F_prev, as indicated by the n=10 F_prev=34 F=55 F_next=34+55 = 89
arrows
Result
F=55

as long as a certain condition is fulfilled. In such a case, it is preferable to work with


a while loop. This type of loop enables us to modify our program such that all
Fibonacci numbers smaller than 1000 are computed, without knowing the required
number of iterations:
1 # initialize variables
2 F_prev = 0 # 0. number
3 n,F = 1,1 # 1. number
4
5 # compute sequence of Fibonacci numbers smaller than 1000
6 while F < 1000:
7 print("{:d}. Fibonacci number = {:d}".format(n,F))
8
9 # next number is sum of F and the previous number
10 F_next = F + F_prev
11
12 # prepare next iteration
13 F_prev = F # first reset F_prev
14 F = F_next # then assign next number to F
15 n += 1 # increment counter
The resulting numbers are:

1. Fibonacci number = 1
2. Fibonacci number = 1
3. Fibonacci number = 2
4. Fibonacci number = 3
5. Fibonacci number = 5
6. Fibonacci number = 8
7. Fibonacci number = 13
1.3 Control Structures 13

8. Fibonacci number = 21
9. Fibonacci number = 34
10. Fibonacci number = 55
11. Fibonacci number = 89
12. Fibonacci number = 144
13. Fibonacci number = 233
14. Fibonacci number = 377
15. Fibonacci number = 610
16. Fibonacci number = 987

Of course, the first ten numbers are identical to the numbers from our previous
example. If you make changes to a program, always check that you are able to
reproduce known results!
The loop header in line 6 of the above listing literally means: Perform the following
block of code while the value of F is smaller than 1000. The expression F<1000 is
an example of a Boolean (or logical) expression. The operator < compares the two
operands F and 1000 and evaluates to True if the numerical value of F is smaller
than 1000. Otherwise, the expression evaluates to False and the loop terminates.
Anything that is either True or False is said to be of Boolean type. In Python, it
is possible to define Boolean variables.
A while loop does not come with a counter. To keep track of how many Fibonacci
numbers are computed (in other words the index n of the sequence Fn ), we initialize
the counter n along with F in the multiple assignment in line 3. This is equivalent to
n = 1
F = 1
Python allows you to assign multiple values separated by commas to multiple vari-
ables (also separated by commas) in a single statement, where the ordering on the
left corresponds to the ordering on the right. We will make rarely use of this feature.
While it is useful in some cases (for example, to swap variables15 or for functions
returning multiple values), multiple assignments are rather difficult to read and prone
to errors, particularly if variables are interdependent.
While the loop counter of a for loop is automatically incremented, we need to
explicitly increase our counter in the example above at the end of each iteration. In
line 15, we use the operator += to increment n in steps of one, which is equivalent
to the assignment n=n+1 (there are similar operators -=, *=, etc. for the other basic
arithmetic operations).
Let us try to be even smarter and count how many even and odd Fibonacci numbers
below a given limit exist. This requires branching, i.e. one block of code will be
executed if some condition is met and an alternative block if not (such blocks are
also called clauses). This is exactly the meaning of the if and else statements
in the following example:

15Another application in our Fibonacci program would be the merging of lines 13 and 14 into the
multiple assignment F_prev,F = F,F_next.
14 1 Python Basics

1 # initialize variables
2 F_prev = 0 # 0. number
3 F = 1 # 1. number
4 n_even = 0
5 n_odd = 0
6
7 # compute sequence of Fibonacci numbers smaller than 1000
8 while F < 1000:
9 # next number is sum of F and the previous number
10 F_next = F + F_prev
11
12 # prepare next iteration
13 F_prev = F # first reset F_prev
14 F = F_next # then assign next number to F
15
16 # test if F is even (divisible by two) or odd
17 if F%2 == 0:
18 n_even += 1
19 else:
20 n_odd += 1
21
22 print("Found {:d} even and {:d} odd Fibonacci numbers".\
23 format(n_even,n_odd))
Instead of a single counter, we need two counters here, n_even for even Fibonacci
numbers and n_odd for the odd ones. The problem is to increment n_even if the
value of F is an even number. To that end the modulo operator % is applied to get
the remainder of division by two. If the remainder is zero, then the number is even.
This is tested with the comparison operator == in the Boolean expression following
the keyword if in line 17. If this expression evaluates to True, then the counter
for even numbers is incremented (line 18). If the condition is False, the else
branch is entered and the counter for odd numbers is incremented (line 20). You
must not confuse the operator ==, which compares variables or expressions without
changing them, with the assignment operator =, which sets the value of a variable.
The program reports (we do not bother to print the individual numbers again):

Found 5 even and 11 odd Fibonacci numbers

Altogether, there are 5 + 11 = 16 numbers. You may check that this is in agreement
with the listed numbers.

1.4 Working with Modules and Objects

Python offers a collection of useful tools in the Python Standard Library (see
docs.python.org/3/library). Functions such as print() are part of the Standard
Library. They are called built-in functions. Apart from that, many more optional
1.4 Working with Modules and Objects 15

libraries (also called packages) are available. Depending on the Python distribution
you use, you will find that some libraries are included and can be imported as shown
below, while you might need to install others.16 Python libraries have a hierarchical
modular structure. This means that you do not necessarily have to load a complete
library, but you can access some part of a library, which can be a module, a submod-
ule (i.e. a module within a module) or even individual names defined in a module.
To get started, it will be sufficient to consider a module as a collection of definitions.
By importing a module, you can use variables, functions, and classes (see below)
defined in the module.
For example, important physical constants and conversion factors are defined
in the constants module of the SciPy library (for more information, see
www.scipy.org/about.html). A module can be loaded with the import command:
1 import scipy.constants
To view an alphabetically ordered list of all names defined in this module, you can
invoke dir(scipy.constants) (this works only after a module is imported).
By scrolling through the list, you might notice the entry
’gravitational_constant’. As the name suggests, this is the gravitational
constant G. Try
2 print(scipy.constants.gravitational_constant)
which displays the value of G in SI units:

6.67408e-11

The same value is obtained via scipy.constants.G. Even so, an identifier


composed of a library name in conjunction with a module and a variable name is
rather cumbersome to use in programs. Alternatively, a module can be accessed via
an alias:
3 import scipy.constants as const
4
5 print(const.G)
also displays the value of G. Here, const is a user-defined nickname for
scipy.constants.
It is also possible to import names from a module directly into the global name-
space of Python. The variables we have defined so far all belong to the global name-
space. The syntax is as follows:
6 from scipy.constants import G
7
8 print(G)

16 See,
for example, packaging.python.org/tutorials/installing-packages
and docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-pkgs.html.
16 1 Python Basics

In this case, only G is imported, while in the examples above all names from
scipy.constants are made available. Importing names via the keyword from
should be used with care, because they can easily conflict with names used in assign-
ments elsewhere. Python does not treat this as an error. Consequently, you might
accidentally overwrite a module variable such as G with some other value.
By using constants from Python libraries, we can perform computations without
looking up physical constants on the web or in textbooks and inserting them as literals
in the code. Let us return to the example of a planet at 10 times the distance of Earth
from the Sun, i.e. r = 10 au (see Sect. 1.2). Here is an improved version of the code
for the computation of the orbital period and velocity:
1 from math import pi,sqrt
2 from astropy.constants import M_sun
3 from scipy.constants import G,au,year
4
5 print("1 au =", au, "m")
6 print("1 yr =", year, "s")
7
8 radius = 10*au
9 print("\nradial distance = {:.1f} au".format(radius/au))
10
11 # Kepler’s third law
12 period = 2*pi * sqrt(radius**3/(G*M_sun.value))
13 print("orbital period = {:.4f} yr".format(period/year))
14
15 velocity = 2*pi * radius/period # velocity in m/s
16 print("orbital velocity = {:.2f} km/s".format(1e-3*velocity))

The output of this program is

1 au = 149597870691.0 m
1 yr = 31536000.0 s

radial distance = 10.0 au


orbital period = 31.6450 yr
orbital velocity = 9.42 km/s

We utilize the value of π and the square-root function defined in the math module,
which is part of the standard library. The function sqrt() imported from math is
called in line 12 with the expression radius**3/(G*M_sun.value) as argu-
ment. This means that the number resulting from the evaluation of this expression is
passed as input to sqrt(), which executes an algorithm to compute the square root
of that number. The result returned by the function and is then multiplied with 2*pi
to obtain the orbital period. Moreover, we use constants and conversion factors from
the SciPy and Astropy libraries. For instance, au is one astronomical unit in m and
year is one year in s. The values are printed in lines 5 and 6. These conversion
factors enable us to conveniently define the radius in astronomical units (line 8) and,
after apply Kepler’s third law in SI units, to print the resulting orbital period in years
(lines 12 and 13). When printing the radius in line 9, the newline character ’\n’
at the beginning of the string inserts a blank line. Other than in Sect. 1.2, the orbital
1.4 Working with Modules and Objects 17

velocity assigned to velocity is in m/s. So we need to multiply by a factor of 10−3


to obtain the velocity in units of km/s in the final print statement.
In contrast to the gravitational constant G, which is simply a floating point number,
the mass of the Sun defined in astropy.constants is a more complex object.
In computer science, the term object has a specific meaning and refers to the object-
oriented programming (OOP) paradigm. You can go a long way in Python without
bothering about object-oriented programming. Nevertheless, you will find it helpful
if you are aware of a few basic facts:

1. Everything in Python is an object.


2. An object contains a particular kind of data.
3. Objects have methods to manipulate the object’s data in a controlled way.
4. A method can change an object or create a new object.

This implies that G is also an object, albeit a rather simple one. If you print M_sun,
you will find quite a bit more information in there, such as the uncertainty of the
value and its physical unit:

Name = Solar mass


Value = 1.9884754153381438e+30
Uncertainty = 9.236140093538353e+25
Unit = kg
Reference = IAU 2015 Resolution B 3 + CODATA 2014

Particular data items are called object attributes. For example, the value of the solar
mass is an attribute of M_sun. You can fetch an attribute by joining the names of the
object and the attribute with a dot. We refer to the attribute value in line 12 to obtain
a pure number that can be combined with other numbers in an arithmetic expression.
To list attributes belonging to an object, you can use dir(), just like for modules,
or search the documentation. Attributes and methods are defined in classes. While
objects belonging to the same class may contain different data, they have the same
attributes and methods. For example, M_earth from astropy.constants has
a value attribute just like M_sun, but the value behind this attribute is Earth’s mass
instead of the mass of the Sun. Both objects belong to the class Quantity. You can
take a glimpse behind the curtain in Appendix A, where you are briefly introduced
to writing your own classes.
Since everything in Python is an object, so is a string. Now you are able to better
understand the meaning of format() being a method. It is a method allowing you
to insert formatted numbers into a string.17 While methods are relatives of Python
functions, a method always has to be called in conjunction with a particular object.
In the print statements in lines 9, 13, and 16, the objects are string literals. The

17 Sincestrings are immutable objects, the method does not change the original string with place-
holders. It creates a new string object with the formatted numbers inserted.
18 1 Python Basics

syntax is similar to accessing object attributes, except for the arguments enclosed in
parentheses (here, the variables holding the numbers to be inserted). In general, you
can call methods on names referring to objects – in other words, Python variables.
This will be covered in more detail in the next chapter.
Chapter 2
Computing and Displaying Data

Abstract NumPy arrays are the workhorses of numerics in Python, extending it by


remarkable numerical capabilities. For example, they can be used just like simple
variables to evaluate an arithmetic expression for many different values without pro-
gramming a loop. In the first section, we combine the power of NumPy and Astropy
and compute the positions of objects on the celestial sphere. Moreover, we introduce
Matplotlib to produce plots from array data. Further applications are shown in the
context of Kepler’s laws and tidal forces, for example, printing formatted tables and
plotting vector maps.

2.1 Spherical Astronomy

In astronomy, the positions of stars are specified by directions on the sky, i.e. two
angular coordinates. The radial distance of the star from Earth would be the third
coordinate, but distances are not known for all astronomical objects. As long as
distances do not matter, all astronomical objects can be projected in radial directions
onto a sphere with Earth at its center (the size of the sphere does not matter, but you
can think of it as a distant spherical surface). This is the so-called celestial sphere.1
For an observer on Earth, the position of astronomical objects depends on geo-
graphical latitude and longitude and varies with the time of day. To specify positions
independent of the observer, angular coordinates with respect to fixed reference direc-
tions are used. In the equatorial coordinate system, one reference direction is given
by Earth’s rotation axis (or, equivalently, the orientation of the equatorial plane). The
orientation of the rotation axis is fixed because of angular momentum conservation.2
The angular distance of a star from the equatorial plane is called declination and
denoted by δ. The other reference direction is defined by the intersection between

1 In ancient and medieval times, it was thought that there is actually a physical sphere with the
stars attached to it and Earth at its center. This is known as geocentric world view. The celestial
sphere in modern astronomy is merely a useful mathematical construction with no physical meaning
whatsoever.
2 This is not exactly true since other bodies in the solar system cause perturbations, but changes are

sufficiently small over a human’s lifetime.

© Springer Nature Switzerland AG 2021 19


W. Schmidt and M. Völschow, Numerical Python in Astronomy and Astrophysics,
Undergraduate Lecture Notes in Physics,
https://doi.org/10.1007/978-3-030-70347-9_2
20 2 Computing and Displaying Data

Fig. 2.1 Celestial sphere north


with coordinates α (right celestial pole
ascension) and δ
(declination) of a stellar
object. Earth’s orbital plane
(ecliptic) intersects the
sphere along the red circle,
which is inclined by the autumnal
angle 0 (obliquity) with equinox 
respect to the celestial
equator. The celestial
equator is the outward
projection of Earth’s equator
celestia
onto the celestial sphere. The
intersection points of the
0 l equator
vernal 
ecliptic
ecliptic and the celestial
equator are the two equinox
equinoxes

s outh
c e l e s t ial p o l e

the equatorial plane and the plane of Earth’s orbital motion around the Sun. The fixed
orientation of the orbital plane, which is called ecliptic, is also a consequence of angu-
lar momentum conservation (in this case the angular momentum of orbital motion).
The second coordinate in the equatorial system, which is called right ascension α, is
the angle measured from one of the two points where the celestial sphere is pierced
by the line of intersection of the equatorial an orbital planes. The zero point for the
right ascension is known as vernal equinox, the opposite point as autumnal equinox.
If all of this sounds rather complicated, it will become clear from the illustration in
Fig. 2.1. See also [3, Sect. 2.5].

2.1.1 Declination of the Sun

While the declination of stars is constant, the position of the Sun changes in the
equatorial system over the period of a year. This is a consequence of the inclination
of Earth’s rotation axis with respect to the direction perpendicular to the ecliptic,
which is equal to 0 = 23.44◦ . The angle 0 is called obliquity of the ecliptic. The
annual variation of the declination of the Sun is approximately given by3
  
360◦
δ = − arcsin sin 0 cos (N + 10) (2.1)
365.24

3 See en.wikipedia.org/wiki/Position_of_the_Sun.
2.1 Spherical Astronomy 21

where N is the difference in days starting from 1st January. So the first day of the year
corresponds to N = 0, and the last to N = 364 (unless it is a leap year). The fraction
360◦ /365.24 equals the change in the angular position of Earth per day, assuming a
circular orbit. This is just the angular velocity ω of Earth’s orbital motion around the
Sun in units of degrees per day.4
The Sun has zero declination at the equinoxes (intersection points of celestial
equator and ecliptic) and reaches ±0 at the solstices, where the rotation axis of
the Earth is inclined towards or away from the Sun. The exact dates vary somewhat
from year to year. In 2020, for instance, equinoxes were on 20th March and 22nd
September and solstices on 20th June and 21st December (we neglect the exact times
in the following). In Exercise 2.2 you are asked to determine the corresponding values
of N . For example, the 20th of June is the 172nd day of the year 2020. Counting
from zero, we thus expect the maximum of the declination δ = 0 (first solstice) for
N = 171. Let us see if this is consistent with the approximation (2.1). The following
Python code computes the declination δ based on this formula for a given value of N :

1 import math
2
3 N = 171 # day of 1st solstice
4 omega = 2*math.pi/365.24 # angular velocity in rad/day
5 ecl = math.radians(23.44) # obliquity of the ecliptic
6
7 # approximate expression for declination of the Sun
8 delta = -math.asin(math.sin(ecl)*math.cos(omega*(N+10)))
9 print("declination = {:.2f} deg".format(math.degrees(delta)))

The result

declination = 23.43 deg

is close to the expected value of 23.44◦ . To implement Eq. (2.1), we use the sine,
cosine, and arcsine functions from the math library. The arguments of these
functions must be specified in radians. While the angular velocity is simply given
by 2π/365.24 rad/d (see line 4), 0 is converted into radians with the help of
math.radians() in line 5. Both values are assigned to variables, which allows
us to reuse them in subsequent parts of the program. Since the inverse function
math.asin() returns an angle in radians, we need to convert delta into degrees
when printing the result in line 9 (‘deg’ is short for degrees).
To calculate the declination for the second solstice and also for the equinoxes,
we need to evaluate the code in line 8 for the corresponding values of N . If you
put the code listed above into a Python script, you can change the value assigned to
the variable N and simply re-run the script. While this is certainly doable for a few
different values, it would become too tedious for many values (we will get to that
soon enough). Ideally, we would like to compute the Sun’s declination for several

4 The angular velocity in radians per unit time appears as factor 2π/P in Eq. (1.1).
22 2 Computing and Displaying Data

days at once. This can be done by using data structures know as arrays. An array is
an ordered collection of data elements of the same type. Here is as an example:
10 import numpy as np
11
12 # equinoxes and solstices in 2020
13 N = np.array([79, 171, 265, 355])
In contrast to other programming languages, arrays are not native to Python. They
are defined in the module numpy (the library name is also written as NumPy, see
www.numpy.org), which is imported under the alias np in line 10. The function
np.array() takes a list of values in brackets and, if possible, creates an array
with these values as elements. Like an array, a list is also an ordered collection
of data elements. In this book, we will rarely make use of lists (see, for example,
Sect. 5.5). They are more flexible than NumPy arrays, but flexibility comes at the
cost of efficiency. This is demonstrated in more detail in Appendix B.1. On top
of that, NumPy offers a large toolbox of numerical methods which are specifically
implemented to work with arrays.5 The array returned by np.array() is assigned
to the variable N (mark the difference between single value versus array in lines 3
and 13, respectively). Its main properties can be displayed by the following print
statements:
14 print(N)
15 print(N.size)
16 print(N.dtype)
which produces the output

[ 79 171 265 355]


4
int64

From this we see that N has four elements (the number of elements is obtained with
the .size attribute), which are the integers 79, 171, 256, and 355. The data type
can be displayed with the .dtype attribute (by default, 64-bit integers are used for
literals without decimal point).
How can we work with the values in an array? For example, N[0] refers to the
first element of the array, which is the number 79. Referring to a single element of
an array via an integer in brackets, which specifies the position of the element in the
array, is called indexing. The first element has index 0, the second element index 1
and so on (remember, this is Python’s way of counting). You can also index elements
from the end of the array. The last element has index −1, the element before the last
one has index −2, etc. So, for the array defined above,
17 print(N[1])
18 print(N[-3])

5 See also [1] for a comprehensive introduction to arrays.


2.1 Spherical Astronomy 23

outputs

171
171

Do you see why the value 171 is printed in both cases? Vary the indices and see for
yourself what you get. Before proceeding, let us summarize the defining properties
of an array:

Every element of an array must have the same data type. Each element is
identified by its index.

Having defined N as an array, we could calculate the declination of the Sun on day
171 (the first solstice) by copying the code from line 8 and replacing N by N[1]in the
expression for delta. Of course, this would not bring us any closer to calculating
the declination of the Sun for all four days at once. With NumPy, it can be done as
follows.
19 delta = -np.arcsin(math.sin(ecl) * np.cos(omega*(N+10)))
20 print(np.degrees(delta))
In short, the expression in line 19 is evaluated for each element of the array N and
the results are stored in a new array that is assigned to delta. The four elements of
delta are the values of the declination for the two equinoxes and solstices:

[ -0.9055077 23.43035419 -0.41950731 -23.43978827]

Not perfect (the declination at equinoxes should be zero), but reasonably close. We
use only an approximate formula after all.
To get a better idea of how the code in line 19 works, we expand it into several
steps and use a temporary array called tmp for intermediate results of the calculation:

21 # add 10 to each element of N


22 tmp = N+10
23 print(tmp)
24 print(tmp.dtype)
25
26 # multipy by omega
27 tmp = omega*tmp
28 print(tmp)
29 print(tmp.dtype)
30
31 # calculate the cosine of each element in the resulting array
32 # and multipy with the sine of the obliquity
33 tmp = math.sin(ecl)*np.cos(tmp)
24 2 Computing and Displaying Data

34 print(tmp)
35
36 # calculate the negative arcsine of each element
37 delta = -np.arcsin(tmp)
38 print(np.degrees(delta))

As you can see, it is possible to perform arithmetic operations on arrays. For


operators such as + and *, the operands must be (see also Fig. 2.2)
• either an array and a single number,
• or two arrays of identical shape (for arrays with only one index this amounts to
the same number of elements).
For example, we make use of the first option in line 22, where the number 10 is added
to each element of the array N. The resulting integers are assigned element-wise to
the array tmp:

[ 89 181 275 365]


int64

The next step is an element-wise multiplication with omega (Earth’s angular velocity
defined in line 4). Since the value of omega is a floating point number, the tmp array
is automatically converted from data type integer to float:

[1.53105764 3.11372396 4.73079608 6.27905661]


float64

Now we have the angular positions of Earth on its orbit, from which the vertical
distances of the Sun from the celestial equator can be computed. In line 33, the
NumPy function np.cos() is used to compute the cosine of each value in the tmp
array, while math.sin() can take only a single-valued argument, which is ecl
(the obliquity of the ecliptic). The product is

[ 0.01580343 -0.39763404 0.00732172 0.39778512]

and, after computing the arcsine of each element with np.arcsin, we finally get
the declinations:

[ -0.9055077 23.43035419 -0.41950731 -23.43978827]

While doing things step by step is helpful for beginners, combining all these steps
into the single statement shown in line 19 is extremely useful for the more experienced
programmer. Starting with the code for a single day (see line 8), the only modification
that has to be made is that the math module has to be replaced by numpy whenever
the argument of a function is an array. However, there is small pitfall. By comparing
the code examples carefully, you might notice that the identifiers for the arcsine
function read math.asin() and np.arcsin() in lines 8 and 19, respectively.
2.1 Spherical Astronomy 25

array = array + number array = array + array


a = b + c a = b + c

a[0] = b[0] + c a[0] = b[0] + c[0]


a[1] = b[1] + c a[1] = b[1] + c[1]
a[2] = b[2] + c a[2] = b[2] + c[2]
...

...

...

...

...
a[n-1] = b[n-1] + c a[n-1] = b[n-1] + c[n-1]

Fig. 2.2 Illustration of basic NumPy operations. Adding a number (variable) to an array, means
that the same number is added to each element in the array (left). If two arrays of size n are added,
the operator + is applied element-wise (right)

A likely mistake is to replace math.asin() by np.asin(), which would cause


Python to throw the following error message:

AttributeError: module ’numpy’ has no attribute ’asin’

Since math and numpy are independent modules, you cannot expect that the naming
of mathematical functions is always consistent.
Printing an array, results in all elements of the array being displayed in some
default format. Now, suppose we want to format the elements nicely as we did at the
beginning of this section before introducing arrays. Formatted printing of a particular
element of an array is of course possible by indexing the element. For example,
39 print("declination = {:.2f} deg".
40 format(math.degrees(delta[1])))
produces the same output as line 9 (where delta is a simple variable):

declination = 23.43 deg

To display all elements in a formatted table, we need to loop through the array.
Actually, we have already worked with such loops, for example, in line 19. Loops of
this type are called implicit. The following example shows an explicit for loop:
41 for val in delta:
42 print("declination = {:6.2f} deg".
43 format(math.degrees(val)))
The loop starts with the first element in the array delta, assigns its value to the
variable val, which is the loop variable (similar to the loop counter introduced in
Sect. 1.3), and then executes the loop body. The loop in the example above encom-
passes only a single print statement. After executing this statement, the loop contin-
ues with the next element and so on until the end of the array (the highest index) is
reached:
26 2 Computing and Displaying Data

declination = -0.91 deg


declination = 23.43 deg
declination = -0.42 deg
declination = -23.44 deg

However, the output is not really satisfactory yet. While repeatedly printing
declination is redundant, important information for understanding the data is
missing. In particular, the days to which these values refer are not specified. A bet-
ter way of printing related data in arrays is, of course, a table. In order to print the
days and the corresponding declinations, we need to simultaneously iterate through
the elements of N and delta. One solution is to define a counter with the help of
Python’s enumerate() function:
44 print("i day delta [deg]")
45 for i,val in enumerate(delta):
46 print("{1:d} {2:3d} {0:8.2f}".\
47 format(math.degrees(val),i,N[i]))
Compared to the for loops discussed in Sect. 1.3, the range of the counter i is
implicitly given by the size of an array: It counts through all elements of delta
and, at the same time, enables us to reference the elements of N sequentially in the
loop body. Execution of the loop produces the following table:

i day delta [deg]


0 79 -0.91
1 171 23.43
2 265 -0.42
3 355 -23.44

Here, the arguments of format() are explicitly ordered. The placeholder {1:d} in
line 46 indicates that the second argument (index 1 before the colon) is to be inserted
as integer at this position. The next placeholder refers to the third argument (index 2
before the colon) and the last one to the first argument. The format specifiers ensure
sufficient space between the columns of numbers (experiment with the settings). The
header with labels for the different columns is printed in line 44 (obviously, this has
to be done only once before the loop begins).
Surely, instead of enumerating delta, you could just as well enumerate N. Is
it possible to write a loop that simultaneously iterates both arrays without using
an explicit counter? Actually, this is the purpose of the zip() function, which
aggregates elements with the same index from two or more arrays of equal length.
In this case, the loop variable is a tuple containing one element from each array.
We will take a closer look at tuples below. All you need to know for the moment is
that the tuple row in the following code example contains one element of N and the
corresponding element of delta, forming one row of the table we want to print.
Tuple elements are indexed like array elements, so row[0] refers to the day and
row[1] to the declination for that day.
2.1 Spherical Astronomy 27

48 print("day delta [deg]")


49 for row in zip(N,delta):
50 print("{0:3d} {1:8.2f}".
51 format(row[0],math.degrees(row[1])))
Apart from the index column, we obtain the same output as above:

day delta [deg]


79 -0.91
171 23.43
265 -0.42
355 -23.44

If you replace lines 50–51 by the unformatted print statement print(row), you
will get:

(79, -0.01580409076383853)
(171, 0.40893682550286947)
(265, -0.007321783769611206)
(355, -0.4091014813515704)

While brackets are used for lists and arrays, tuples are enclosed by parentheses.
The most important difference is that tuples are immutable, i.e. it is not possible
to add, change or remove elements. For example, the tuples shown above are fixed
pairs of numbers, similar to coordinates (x, y) for points in a plane. Suppose you
want to change day 355 to 364. While it is possible to modify array N by setting
N[3] = 364, you are not allowed to assign a value to an individual element in a
tuple, such as row[0]. You can only overwrite the whole tuple by a new one (this
is what happens in the loop above).

2.1.2 Diurnal Arc

From the viewpoint of an observer on Earth, the apparent motion of an object on


the celestial sphere follows an arc above the horizon, which is called diurnal arc
(see Fig. 2.3). The time-dependent horizontal position of the object is measured by its
hour angle h. An hour angle of 24h corresponds to a full circle of 360◦ parallel to the
celestial equator (an example is the complete red circle in Fig. 2.3). For this reason,
h is can be equivalently expressed in degrees or radians. However, as we will see
below, an hour angle of 1h is not equivalent to a time difference of one solar hour. By
definition the hour angle is zero when the object reaches the highest altitude above
the horizon (see also Exercise 2.4 and Sect. 2.1.3). The hour angle corresponding to
the setting time, when the object just vanishes beneath the horizon, is given by6

6 See [3, Sect. 2.6] if you are interested in how this equation comes about.
28 2 Computing and Displaying Data

le

po

est rth
ial
cel no

ce
les
tial

mer
hrise E

r
ato

idian
qu
le
tia
N S

ls
ce
hset
W

le
po
s ti o u th
s

al
le
ce

Fig. 2.3 Diurnal arc of a star moving around the celestial sphere (thick red circle) in the horizontal
system (see Sect. 2.1.3) of an observer at latitude φ (the horizontal plane is shown in grey). Since the
equatorial plane is inclined by the angle 90◦ − φ against the horizontal plane, the upper culmination
of the star at the meridian is given by amax = 90◦ − φ + δ, where δ is the declination. In the co-
rotating system, the star rises at hour angle h rise , reaches its highest altitude when it crosses the
meridian at h = 0, and sets at the horizon at h set = −h rise

cos h set = − tan δ tan φ , (2.2)

where δ is the declination of the object (see Sect. 2.1) and φ the latitude of the
observer’s position on Earth. As a consequence, the variable T = 2h set measures the
so-called sidereal time for which the object is in principle visible on the sky (stars
are of course outshined by the Sun during daytime). It is also known as length of the
diurnal arc.
For example, let us consider the star Betelgeuse in the constellation of Orion.
It is a red giant that is among the brightest stars on the sky. Its declination can be
readily found with the help of astropy.coordinates, which offers a function
that searches the name of an object in online databases:
1 from astropy.coordinates import SkyCoord, EarthLocation
2
3 betelgeuse = SkyCoord.from_name(’Betelgeuse’)
4 print(betelgeuse)
When you are confronted with the output for the first time, it might require a little
bit of deciphering:

<SkyCoord (ICRS): (ra, dec) in deg


(88.79293899, 7.407064)>
2.1 Spherical Astronomy 29

This tells us that the right ascension (ra) and declination (dec) of the object named
Betelgeuse were found to be 88.79◦ and 7.41◦ , respectively.7 The variable
betelgeuse defined in line 3 represents not only an astronomical object; it is
a Python object, more specifically an object belonging to the class SkyCoord (see
Sect. 1.4 for objects in a nutshell). The attribute dec allows us to directly reference
the declination:
5 delta = betelgeuse.dec
6 print(delta)
The declination is conveniently printed in degrees (d), arc minutes (m) and arc sec-
onds (s), which is the preferred format to express angular coordinates in astronomy:
7d24m25.4304s

i.e. δ ≈ +07◦ 24 25 , where 1 = (1/60)◦ and 1 = (1/60) .


Suppose we want to determine the length of Betelgeuse’s diurnal arc as seen from
Hamburg Observatory (φ ≈ +53◦ 28 49 ). In addition to the star’s declination,
we need the position of the observer. The counterpart of SkyCoord for celestial
coordinates is EarthLocation (also imported in line 1), which allows us to set
the geographical latitude and longitude of a location on Earth:
7 import astropy.units as u
8
9 # geographical position of the observer
10 obs = EarthLocation(lat=53*u.deg+28*u.arcmin+49*u.arcsec,
11 lon=10*u.deg+14*u.arcmin+23*u.arcsec)
12
13 # get latitude
14 phi = obs.lat
In the expressions above, u.deg is equivalent to 1◦ , u.arcmin is 1 , and u.arcsec
is 1 . The units module from astropy implements rules to carry out computa-
tions in physical and astronomical unit systems. You will learn more about AstroPy
units in Sect. 3.1.1.
Next we compute h with the help of trigonometric functions from the math
module:
15 import math
16
17 h = math.acos(-math.tan(delta.radian) * math.tan(phi.radian))
It is necessary to convert the angles δ and φ to radians before applying the tangent
function math.tan(). With Astropy coordinates, all we need to do is to use the
radian attribute of an angle.8 To obtain T in hours, it is important to keep in mind

7 ICRS means International Celestial Reference System.


8 You could also work with the SkyCoord object defined in line 3 and use
betelgeuse.dec.radian as argument of math.tan(). betelgeuse.dec is an
Angle object. So there are objects within objects. However, the function math.radians() for
converting from degrees to radians is not compatible with Angle objects.
30 2 Computing and Displaying Data

that an angle of 360◦ (one full rotation of Earth) corresponds to a sidereal day,
which is about 4 min shorter than a solar day. As explained in [3, Sect. 2.13], this
is a consequence of the orbital motion of Earth. The conversion is made easy by the
units module (see also Exercise 2.5 for a poor man’s calculation):
18 T = (math.degrees(2*h)/360)*u.sday
19 print("T = {:.2f}".format(T.to(u.h)))
First T is defined in sidereal days (u.sday), which is equivalent to 24h or 360◦ .
Then we convert to solar hours (u.h) by applying the method to() in line 19. The
result is

T = 13.31 h

If it were not for the Sun, Betelgeuse could be seen 13 h at the Observatory. Of course,
the star will be visible only during the overlap between this period and the night,
which depends on the date. We will return to this question in the following section.
The diurnal arc of the Sun plays a central role in our daily life, as it determines the
period of daylight. In Sect. 2.1.1, we introduced an approximation for the declination
δ of the Sun. By substituting the expression (2.1) for δ into Eq. (2.2), we can
compute how the day length varies over the year. First we need to compute δ for N
ranging from 0 to 364. Using NumPy, this is very easy. In the following example, the
expression np.arange(365) fills an array with the sequence of integers starting
from 0 up to the largest number smaller than 365, which is 364.9 Apart from that, the
code works analogous to the NumPy-based computation for equinoxes and solstices
in Sect. 2.1.1. Since a new task begins here, the line numbering is reset to 1, although
we make use of previous assignments (an example is the latitude phi). In other
words, you would need to add pieces from above to make the following code work
as an autonomous program (you might want to try this).
1 import numpy as np
2
3 N = np.arange(365) # array with elements 0,1,2,...,364
4 omega = 2*math.pi/365.24 # Earth’s angular velocity in rad/day
5 ecl = math.radians(23.44) # obliquity of the ecliptic
6
7 # calculate declination of the Sun for all days of the year
8 delta = -np.arcsin(math.sin(ecl) * np.cos(omega*(N+10)))

Now we can compute the day length T for all values in the array delta using
functions from the numpy module (compare to the code example for Betelgeuse and
check which changes have been made):

9 Just
like range() in for loops, the general form is np.arange(start, stop, step),
where a start value different from 0 and a step other than 1 can be specified as optional arguments.
Another Random Scribd Document
with Unrelated Content
var en anden af Familjens Venner. Han var Droskekører og boede i
Store Brøndstræde og havde i en Aarrække ved saadanne
Lejligheder beredvillig stillet sig selv og sit Køretøj til de Gamles
Raadighed.

Paa Slaget tre holdt han ogsaa dennegang udenfor Huset med sin
nedslaaede Vogn saa fin og velpudset, som var den bestemt for et
Grossererbryllup i Vor Frue. Efter nogen Venten aabenbarede det
alderstegne Ægtepar sig for den halve Snes af Kvarterets Børn, der
havde samlet sig ved Vognen, og for de mange flere Ældre, der fra
Døre og Vinduer var Tilskuere til dette Triumftog. Madam Olufsen var
i Wienersjal og bar en stor, lysviolet Vindrueklase paa Hatten,
Højbaadsmanden var i sin stiveste Begravelsespuds med 25-Aars
Tjenestemedaljen og Sølvkorset glimtende frem bag den uknappede
Overfrakke.

Under Kørslen ind gennem Byen vakte han en Del


Opmærksomhed blandt Folk paa Grund af disse Ærestegn. Som han
sad der — hvidlokket og højtidelig — med begge Hænder urokkelig
hvilende paa Paraplyens Hornhaandtag, kunde han meget godt
vække Forestillingen om en gammel Admiral fra Aarhundredets
Begyndelse, og sikkert vilde han ogsaa have fremkaldt en hertil
svarende Ærefrygt, dersom ikke unge Didriksen — stolt over sit
Selskab — hvert Øjeblik havde vendt sig om imod det med højrøstet
og fortrolig Tiltale.

Først gjorde de en Rundtur gennem hele den gamle By, saae paa
de store, nye Bygninger, der skød op allevegne, paa Resterne af
Fæstningsvoldene, som man var i Færd med at sløjfe, og paa de
nye, overbyggede Omnibusser, der kom ind fra Frederiksberg, og
som i Østergades Menneskemylr lignede Elefanter med Ryttere paa
Ryggen. Fra Kongens Nytorv drejede de saa ned imod Kanalen,
standsede et Øjeblik udenfor Holmens Kirke, hvor de for 52 Aar
siden havde haft Bryllup, og havnede omsider paa Børsbryggen.

Per var allerede kommen. Han hilste dem fra „Karen-Sofies“


Ræling, hvor han — lidt slap — sad og lod sig bage af
Foraarssolen, mens Skipperen — en ældre Mand med graat
Fuldskæg
— gik fraborde for at tage imod.

Paa Bunden af Skibets aabne Lasterum, saa at sige i „Karen


Sofies“ Mave, hvortil en Stige førte ned fra Dækket, var der indrettet
en Slags Butik, i hvis Halvmørke Skinker, Pølser, røgede Bedelaar og
møllestensstore Oste skinnede hemmelighedsfuldt som Eventyrskatte
i en Aladdinshule. Med Pers og Skipperens Bistand blev Madam
Olufsen bugseret ned ad Stigen, bagefter fulgte Højbaadsmanden,
der her paa Søen skulde være rask paa det og vise sig som gammel
Orlogsgast og derfor afslog enhver Hjælp. Imidlertid snublede han
allerede paa det første Trin og vilde upaatvivlelig have brækket
Halsen, dersom Skipperen ikke havde fanget ham i sine Arme. Ikke
destomindre haanede han unge Didriksen, da denne som sidste
Mand krøb ned ad Stigen og forsigtig sikrede sig Fodfæste paa hvert
Trin. „Saadan kravler en Lus i en Redekam,“ tilraabte han ham med
en Talemaade, der havde lydt i den danske Marine siden fjerde
Christians Dage.

Efter en halv Times samvittighedsfuld Søgen og Smagen og Vejen


og Prutten blev Handelen afsluttet og de købte Varer bragt paa
Dækket. Og nu forefaldt der et Optrin, der Aar efter Aar gentoges
med samme Regelmæssighed som en Vittighed af Bolteslager Fuss.
Skipper Mortensen aabnede Døren til Kahytten og bad sine Gæster
ind til en lille Forfriskning; men Madam Olufsen vilde paa ingen
Maade tage mod en Indbydelse, der kom hende saa overraskende.
Ogsaa Højbaadsmanden vægrede sig paa det bestemteste ved at
opholde Tiden for deres Ven, medens unge Didriksen, altfor vel
kendt med disse Formaliteter, rolig gravede Skraaen ud af Munden
og gemte den i Vestelommen.

Snart sad man da bænket nede i det hyggelige lille Skafferum ved
et fuldt opdækket Bord, som hurtig fik Bugt med al forstilt
Beskedenhed.

Per følte sig stadig vel tilpas i saadant folkeligt Selskab. Ligesom
han aldrig spiste med friskere Appetit end ved et Bord som dette
med solide Flæskevarer og Snaps og Øl, fandt han endnu sin bedste
Underholdning i jævne Borgerfolks muntre og ligefremme Tale. Her
var han ikke — som i „Gryden“ — en tavs og kritisk Iagttager; han
kastede sig med Liv ind i Diskussionerne og snakkede med om Vejret
og Torvepriserne, om Færgevæsnet og Kommandantskabet.

Efter at man havde spist og Teen og Romflasken var kommen paa


Bordet, gled Talen hen paa Krigsaarene og den efterfølgende Dyrtid.
Per huskede fra Krigen egenlig kun Fjendens første Indrykning i
Præstegaarden, da Have og Gaardsplads pludselig var bleven
oversvømmet af Soldater og Heste, saa hele Huset maatte rømmes
med Undtagelse af Rummene ovenpaa, hvor den store Familje havde
maattet pakke sig sammen i nogle faa Værelser. Han var dengang
kun syv-otte Aar gammel og havde fundet det yderst underholdende
og ikke kunnet begribe, hvad der var at græde for. Skipper
Mortensen derimod havde som Sønderjyde været de egenlige
Krigsbegivenheder paa nærmere Hold, og han gjorde sig gerne en
Fornøjelse af med saftig Pensel at udmale de Grufuldheder, han
havde været Vidne til baade i 64 og i Treaarskrigen. Han havde da
ogsaa nu den Tilfredsstillelse, at Madam Olufsen holdt sig for Ørene
og erklærede Krig for en Afskyelighed.

Men dette vakte Højbaadsmandens Ærgerrighed; han blev let


krigerisk stemt, naar han havde drukket lidt. Han havde i 64 allerede
været pensioneret, og da han heller ikke havde deltaget i den første
Kamp, fordi han netop dengang laa paa Hospitalet for sin Benedder,
begyndte han at tale nedsættende om disse „Tyskerkrige“, hvis
Ulykker for Landet slet ikke kunde maale sig med dem fra Krigene
mod Engelskmanden, som han havde set, baade den i 1801 og 1807
og 14. Dengang maatte vi pænt af baade med Norgesland og hele
Flaaden. Se, det var noget at snakke om! For at overtrumfe
Skipperen, som havde fortalt om Dybbøl og Frederits, gav han sig til
at berette om Københavns Bombardement og om Slaget paa Reden,
som han, fem Aar gammel, havde været Øjenvidne til fra Toldboden,
hvor han havde set de Saarede blive bragt i Land i Baade, der „var
fulde af blodigt Kød ligesom et Slagtertrug.“

Men Madam Olufsen vilde nu ikke høre et Ord mere, og da det


desuden var begyndt at mørkne, forlangte hun at komme hjem. Men
nu viste det sig, at unge Didriksen var falden i Søvn under Indtrykket
af sit Fædrelands Ydmygelser. Han sad med tilbagekastet Hoved og
aaben Mund, og da man ruskede i ham, faldt Overkroppen forover,
og han sov videre med Hoved og Arme udover Bordet til Trods for, at
han i Faldet var kommen til at vælte et Ølglas, hvis Indhold flød ham
ned over Knæerne. Efterat man et Øjeblik havde betragtet dette Syn
i forundret Tavshed, løftede Per Romflasken og konstaterede, at den
i Stilhed var bleven tømt til Bunden, og man forstod da, at Manden
var stivdrukken.
Madam Olufsen blev smækfornærmet. Udenfor paa Bryggen
ventede Vognen med den krogbenede Krikke, der i al denne Tid
havde staaet taalmodig og sukket i en tom Mulepose; men det gik
hurtig op for dem alle, at der nu ikke var andet at gøre end at lade
Manden blive paa Skibet, indtil Rusen var sovet ud. Den store
Højtidsdag fik en sørgelig Afslutning. De to Gamle maatte sjokke
afsted tilfods i al deres Højtidsstads, hver med en indpakket Skinke
under Armen og med Pølser og Bedelaar stikkende frem af
Lommerne.

Per fulgte dem til Holmens Bro, hvor han fik dem anbragt i en
Sporvogn. Selv vilde han ikke hjem. Han trængte til at lufte sig lidt
ovenpaa den megen Latter og de mange stærke Drikke. Saa
spejlede han sig et Øjeblik i et Butiksvindu og gik langsmed Kanalen
op mod Højbro.

Det var i den Time, da Solskæret glider op over Tagene og gløder


paa Helligaandskirkens Spir samtidig med, at Aftenlivet allerede rører
sig livligt nede i Gaderne mellem de oplyste Butiker. Ude paa Torvet
var der endnu næsten daglyst. Her hoppede Spurvene omkring og
pillede i Gadeskarnet, og de nytændte Lygter brændte med en bleg,
aandeagtig Flamme bag Glas, hvori Solnedgangsskæret flimrede. Per
gik langsomt ind gennem Østergade, hvor der var fuldt af Folk.
Synet af de mange Mennesker gjorde ham lidt melankolsk. Trods
Aftenkulden og de røde Næser bølgede der Foraar gennem Luften.
Man kunde se det paa de Unges Øjne og høre det paa Stemmerne,
der var fyldte af Forventning. Udenfor Dameskrædernes store
Vinduesudstillinger stod Folk i Klynger for at betragte de nye
Foraarsmoder. Og alle Modeherrerne bar Violbuketter i Knaphullet.
Per var kommen til at gaa bagved et Kærestepar, der gik saa tæt
ind til hinanden og bevægede sig saa rytmisk, som var de
sammenvoksede fra Skulder til Hæl. Han betragtede den unge Piges
Øjne, der hang ved den Elskede i en egen lystig Tilbedelse; og han
tænkte paa den foregaaende Nats Glæder og blev mere og mere
forstemt. Han kunde ikke lade være med at ærgre sig over, hvad han
nu rent ud kaldte sin enfoldige Forargelse. Han mindedes navnlig
een Ting, der nu helt forsonede ham med den elskovsglade Frue;
det var den Maade, hvorpaa hun havde tildækket Barmen, da han
var ved at gaa. Det havde i Grunden været næsten rørende. Og
disse Roser paa Neergaards Kiste. — Hun maatte jo altsaa virkelig
have elsket ham. Hvad var der i Grunden at oprøres over? Livet tog
nu engang ikke smaalige Hensyn. Det krævede at røre sig, og hvor
det rejste sig i sin Vælde, sprængte det alle Vedtægter. I
Virkeligheden var der snarest noget ophøjet, noget næsten religiøst
betagende ved en saadan ubetvingelig Elskovsdrift, der overvandt
alle Hjertets Smaafornemmelser, ja selve Dødens Uhygge. En saadan
uforfærdet, altforglemmende Hengivelse til Naturen var maaske
netop Livets højeste Udtryk. De „Mørkets Magter“, han havde rystet
for, da han stod foran hendes Seng og trods sine
Samvittighedskvaler endnu følte sig mægtig hendragen til hendes
hvide Favn, — det var selve Naturgrunden i ham, det var selve hans
Væsens Urkraft, der brød op gennem Lag paa Lag af Aartusinders
Fordomme. Ja, saadan var det! Der fandtes intet andet Helvede end
det, som Menneskene selv skabte sig i deres Troldefrygt for Livets
Lyst og Kødets Almægtighed. Og Mands og Kvindes Favntag var det
Himmerige, hvor der var Glemsel for alle Sorger, Tilgivelse for alle
Synder; hvor Sjælene mødtes i skyldfri Nøgenhed som Adam og Eva
i Paradisets Have.
Der var et halvglemt Ord, en uklar Erindring, der pludselig tegnede
sig for ham som med luende Ildskrift. Det var Neergaards spottende
Ytring om hin Eventyrets Bondedreng, som drog ud i Verden for at
vinde et Kongerige men idelig saae sig tilbage og — da
Vidunderlandet virkelig aabnede sig for ham med alle Slaraffenlands
Herligheder — flygtede hjem til den hyggelige Kakkelovnskrog og sin
Mo’ers Skørter.

Han blev rød af Skam. Saa ynkelig var han kommen tilkort den
første Gang, Livet for Alvor havde prøvet hans Tro og hans Mod.
— Men lod den skete Skade sig ikke genoprette? Om han nu f.
Eks. skrev et Brev til hende, forklarede hende alt og gjorde en
Undskyldning? — —

Han var naaet hjem i Hjertensfrydgade. Skibstømrerkonen i


Stuelejligheden aabnede sin Dør og fortalte ham, at der sad en
Herre inde paa hans Værelse og ventede paa ham.

„Det er den Herre, der ogsaa var her igaar, … det er vist en
Præst. Han har siddet derinde over en Time.“

Det viste sig at være hans Broder Eberhard. Han sad i


Gyngestolen ved Bordet, Lampen var tændt, og Skyggen af hans
Hoved tegnede sig uformelig som et Troldehoved paa den nøgne
Væg. Han havde beholdt sin Overfrakke paa, og hans uldbevantede
Hænder hvilede paa en Paraply, der stod mellem hans Knæ.

„Jeg havde nær opgivet at træffe dig,“ sagde han, da de havde


hilst paa hinanden. „Du veed maaske, at jeg var her igaar?“

Per sagde ingenting. Hans Hjerte bankede. Han forstod, at


Broderen maatte have en eller anden alvorlig Meddelelse at gøre
ham, siden han saaledes søgte ham to Dage i Træk. Det var nu
heller ikke svært at se paa Eberhard, at han var sig Besøgets
Betydningsfuldhed bevidst. Hans hele Optræden var tydelig beregnet
paa at gøre Indtryk paa Per; men just derfor tog denne sig sammen
med en vældig Kraftanspændelse og gjorde sig Umage for at synes
ganske ligegyldig.

„Vil du ha’e en Cigar?“ spurgte han, mens han — helt svimmel —


tænkte: Skulde Moder være død?

„Tak, jeg skal ikke ryge,“ svarede Eberhard.

„En Bajer maaske?“

„Jeg har aldeles afvænnet mig fra spirituøse Drikke. Det


bekommer mig bedst. Og forresten nyder jeg principmæssig aldrig
noget udenfor Maaltiderne.“

Per smilte. Og skønt han i Grunden ikke selv følte nogen Trang til
at drikke, hentede han en Flaske Øl i sit Hjørneskab og trak den op.

„Ser du, jeg er nu saa barmhjertig at imødekomme Tørstens Krav


ganske uden Hensyn til Klokkeslettet,“ sagde han.

Eberhard sad lidt og drejede paa Paraplyen, mens hans store,


blege Øjne iagttog Broderen, der havde anbragt sig paa den anden
Side af Bordet og nu hurtig skyllede et Glas i sig.

„Du er vist i den Henseende mere samvittighedsfuld, end det er


nødvendigt,“ bemærkede han tilsidst.

„Er det for at sige mig det, at du er kommen her?“ begyndte Per
straks i stridbar Tone.
Eberhard gjorde en ganske lille, afvisende Bevægelse med
Haanden.

„Du veed, jeg blander mig aldrig i dine Anliggender. — Det er af


en ganske anden Grund, jeg nu har søgt dig.“

Per vilde endnu ikke spørge, — vovede det paa en Maade heller
ikke. Han var overrasket over sig selv, forstod ikke dette stærke
Indtryk, som den blotte Anelse om et Ulykkesbudskab fra Hjemmet
gjorde paa ham. Han havde troet forlængst at være kommen ud
over den Slags Fornemmelser. De derhjemme havde jo i de senere
Aar været som døde for ham allesammen, og det var langt fra, at
Broderens Nærværelse vakte nogen Hjemlængsel hos ham.
Tværtimod. Som Eberhard sad der med Hænderne over sin Paraply
og iagttog ham fra Siden med sine Gedebukkeøjne, optændte han
paany alle Fortidens uforsonlige Følelser hos ham. Denne ophøjede
Anklage i Holdning og Miner, denne tavse Tilkendegivelse af krænket
Familjeære, den hele Selvgodhedens beklumrede Atmosfære, der
slog ham imøde fra Eberhards tilknappede Skikkelse, førte Mindet
om Barndomstidens Trængsler saa levende tilbage, at det var, som
om selve den forhadte Tørverøgsfims derhjemme fra
Præstegaardens Stuer bragtes ind til ham med Broderens Person.

Og dog laa der paa Bunden af det Blik, hvormed Eberhard


betragtede ham, et Udtryk af oprigtig Sorg, af virkelig broderlig
Deltagelse. Opholdet i det lille, kælderagtige Kammer med de fattige
Udskudsmøbler, det nøgne Gulv og de tomme Vægge, dette triste
Rum, der — trods al den Omhu, hvormed den lille Trine vaagede
over sin Helligdom — var som et Billede paa selve Hjemløsheden,
havde vakt hans Medfølelse, og han ventede blot paa en Anledning
for at lade Hjertet tale.
Men Per gav ham ingen saadan Anledning, og de sad i nogen Tid
tavse begge to.

„Jeg er forresten netop kommen tilbage fra en lille Rejse,“


begyndte Eberhard ligesom prøvende. „Jeg har været hjemme paa
Besøg i nogle Dage.“

„Naa, de har det vel godt?“ henkastede Per.

„Aa nej, det kan jeg just ikke sige, Fader har skrantet ikke saa lidt
i den sidste Tid.“

„Ja saa.“

„Han er endog temmelig daarlig.“

„Af hvad?“

„Hvad jeg vilde sige … jeg havde, forinden jeg rejste tilbage, en
længere Samtale med Doktor Carlsen, og jeg fik derved bekræftet,
hvad jeg allerede i længere Tid havde haft Fornemmelsen af gennem
Brevene derhjemme fra, at Faders Tilstand giver Anledning til de
alvorligste Bekymringer. Jeg tror, kort sagt, vi maa være forberedt
paa, at han inden ret lang Tid gaar bort.“

Per, som følte Broderens Øjne hvile aarvaagent paa ham, fortrak
ikke en Mine, skønt Hjertet hamrede i hans Bryst. Det var dog ikke
Sorg, han følte ved Budskabet, ikke engang Vemod, ikke heller
Anger. Den Uro, der greb ham, udsprang væsenlig fra en ham ikke
helt bevidst Skuffelse. Aldrig var den Tanke falden ham ind, at
Faderen eller Moderen kunde dø, før han ved sit Livsværk og sin Sejr
havde retfærdiggjort sig for dem. Og nu skulde denne Efterretning
endda træffe ham i et Øjeblik, da hans store Forhaabninger var
bleven slaaet saa beskæmmende til Jorden.

„Det er efter al Sandsynlighed Kræft,“ fortsatte Eberhard. „Doktor


Carlsen brugte just ikke Ordet; men det fremgik med tilstrækkelig
Tydelighed af hans Udtalelser, at heller ikke han var i Tvivl derom.
Fader gaar dog endnu oppe og passer sin Gerning, saa vidt hans
Kræfter rækker, … du kender hans strenge Pligtfølelse. Men mange
Maaneder vil han næppe kunne blive saadan ved, og jeg tror da
ogsaa, at han selv er fuldt forberedt paa at gaa bort. Moder er
naturligvis meget nedbøjet; men — forunderlig nok — det er, som
om Bekymringen for Faders Tilstand har givet hende selv fornyet
Livskraft. Hun er endogsaa begyndt at staa lidt op for at kunne være
mere om Fader i denne Tid; men jeg tror, at denne underlige Naade,
saa taknemlig hun er for den, samtidig er hende en Bebudelse af, at
Faders Time stunder til.“

Skønt Eberhard ikke var Teolog af Fag, havde han en Forkærlighed


for at udtrykke sig i bibelske Vendinger. Han var Jurist og
betragtedes af sine Fagfæller endog som et ualmindelig klart og
skarpt juridisk Hoved. Saa ung han var, besad han allerede megen
Anseelse. Saaledes havde han nylig vakt Opmærksomhed ved en
Tidsskrift-Afhandling om Fængselsvæsenet og dettes pædagogiske
Opgaver. Selv havde han en Ansættelse i et af denne
Administrationsgrens Hovedkontorer, og da han var et Mønster paa
Flid og Pligtopfyldelse, stod han højt anskreven hos sine Foresatte.

„Jeg har nu ment, at du i Tide burde underrettes om disse


Forhold,“ vedblev han, da Per stadig ingenting sagde. „Jeg syntes,
du skulde ikke være uforberedt, ifald Katastrofen skulde indtræffe
tidligere end ventet. Vi — for jeg taler her i alle dine Søskendes Navn
og efter Samraad med dem — vi har jo ogsaa tænkt os, at du, naar
du blev bekendt med Faders Tilstand, mulig kunde føle dig opfordret
til … jeg mener, kunde føle Trang til at søge en Tilnærmelse til Fader,
inden det blev for silde.“

„Jeg forstaar ikke … Hvorledes mener du?“ spurgte Per brysk men
kunde dog ikke faa sig til at se over paa Broderen.

„Ja, jeg vil — som jeg før sagde — slet ikke blande mig i dine
Anliggender. Det skulde kun være en Henstilling til dig — du maa nu
afgøre med din egen Samvittighed, om du tror at kunne forsvare det
Forhold, hvori du saa længe har stillet dig til dine Forældre … jeg
ønsker ikke engang at udtale mig nærmere derom. Hvad jeg
derimod føler mig forpligtet til allerede nu at præcisere for dig, er, at
Faders Bortgang jo vil faa en væsenlig Indflydelse ogsaa paa de
pekuniære Forhold derhjemme. Jeg veed, at Fader hidtil — uden
iøvrig fra din Side at have mødt nogen Paaskønnelse derfor — har
ydet dig en regelmæssig Hjælp, som maaske ikke har været netop
rigelig, men med hvilken han dog — jeg kan sige det med Sikkerhed
— har strakt sig endog udover sine Kræfter. Og han har gjort det, for
at han ikke skulde kunne bebrejde sig at have vist Ligegyldighed for
dine Studier — eller hvad man nu skal kalde det — til Trods for, at
han ikke har været i Stand til at bedømme dine Evner eller, hvad
Fremskridt du har gjort.“

„Jeg veed det.“

„Denne Understøttelse vil naturligvis øjeblikkelig bortfalde, dersom


Fader skulde gaa bort. Moders Kaar vil da blive endog meget smaa,
og det vil være en Nødvendighed at udvise den største
Sparsommelighed paa alle Omraader.“
„I den Henseende skal du ingen Bekymringer gøre dig for min
Skyld,“ svarede Per, der nu fastslog for sig selv, at han vilde modtage
Neergaards Arv for at opnaa en fuldstændig Uafhængighed af
Hjemmet. „Jeg har netop selv tænkt at skrive hjem, at jeg er i Stand
til fremtidig at klare mig selv helt og holdent. Jeg trænger ikke
Hjælp mere.“

Broderen gjorde store Øjne. Men da Per ingen yderligere


Oplysning gav, blev han højtidelig indadvendt og forholdt sig en
Tid tavs.

Han kunde dog ikke længe styre sin Nysgerrighed.

„Maa jeg spørge … hvorledes har du i Sinde at —“ begyndte han.

Men Per afbrød ham.

„Jeg synes, ærlig talt, du nu skulde gøre Alvor af ikke at blande


dig i mine Affærer. Jeg har ogsaa før sagt dig, at det er mig
ubehageligt.“

Eberhard rejste sig. Han var bleg, og hans Mund med det
fremtrædende Underbid var stiv af Ophidselse.

„Ja, jeg ser, at det i det hele er ørkesløst at tale med dig.
Jeg tror det rigtigst, at vi ikke fortsætter.“

„Som du vil.“

Han tog sin Hat for at gaa. Men da han stod ved Døren, vendte
han sig endnu engang om imod Per, der var bleven siddende ved
Bordet, og sagde:
„Jeg maa dog sige dig endnu et, Peter Andreas! Skønt du — med
dine Følelser — rimeligvis vil have vanskelig ved at forstaa det, skal
du vide, at der er ingen, paa hvem Fader i denne Tid tænker mere
end paa dig. Nu, da jeg var hjemme, gik der ikke en Dag, uden at
han talte til mig om dig … og Moder for den Sags Skyld ogsaa. De
har jo for længe siden maattet opgive at forsøge at indvirke paa dig
ved Overtalelser. De har maattet haabe paa, at Livet engang vilde
bøje dit Sind og lære dig, hvad du skylder dem. Nu er Faders Tid
rimeligvis snart omme. Vogt dig, Peter Andreas, for at begaa en
Synd, som du sikkert — tidlig eller sent — bittert vilde komme til at
angre.“

Efter at Broderen var gaaet, blev Per nogen Tid siddende med
Haanden under Kinden og saae mørkt ned for sig.

„Bøje Sindet“ … „bitter Anger“ … „Synd“ … „Naade“ … Hvor han


kendte den Lektie! Den hele Spøgelsekatekismus paany repeteret!
Og hvor var det betegnende — et ægte „sideniusk“ Karaktertræk —
saadan at benytte Sygdom og Død som Anledning til et fornyet
Forsøg paa at skræmme ham tilbage til Hjemmets og Kirkens Fold …
at bruge selve Døden som Hververkorporal for den sorte
Korsdragerskare. For hvad vilde de ham andet end at bøje ham til
Lydighed under Slægtens Tugt? Hvem var det, de havde haft Bud
efter? Var det efter ham selv, saadan som Naturen i et af sine lyse,
lykkelige Øjeblikke havde skabt ham? Nej, det var hans
Underkastelse, de utaalmodig ventede paa. Det var hans Ydmygelse,
det hastede med nu, da Faderen skulde dø. Han kendte dem! For
deres egen Sjælefreds Skyld skulde hans Livsmod stækkes. Deres
Fromhed taalte ikke Synet af en rank Ryg og et løftet Hoved, naar
ikke „Naaden“ havde Part deri.
Han saae op og kom til at fryse. Der var bleven saa underlig koldt
og skummelt i hans Stue efter Broderens Bortgang. Hvorfor kunde
de ikke lade ham i Fred? Han havde jo selv begravet Fortidens
gamle, grimme Følelser og slaaet en Pæl igennem dem. Hvorfor da
komme nu og mane dem op igen? … Hans Fa’er? Nu ja, lad ham dø!
Han skyldte ham ingen Kærlighed. Han skyldte ham en Række Aar,
som han helst ikke tænkte paa. Nu havde han til Gengæld slettet
ham ud af sin Erindring. De var kvit.

Han drak ud af sit Glas. Saa rejste han sig med et Sæt, som om
han rystede en ond Drøm af sig, og gik op til de Gamle for at snakke
sit Sind i Ligevægt.

Femte Kapitel.

Eberhards Besøg og Budskabet om Faderens Sygdom fik dog den


Betydning for Per, at det gjorde en Ende paa den tankeløse
Omflakken, hvormed han de sidste Uger havde søgt at glemme sit
Nederlag hos Professor Sandrup. Endnu den samme Aften tog han
sine Tegninger og Beregninger frem af Kommodeskuffen, og hele
Natten sad han ved sit Bord med Hovedet mellem Hænderne og
stirrede grundende ned paa sine Papirer, indtil Linjer og Streger
dansede for hans Øjne og Hovedet var tungt af femsifrede Tal, der
summede derinde som sværmelystne Bier i en Kube. Og han gjorde
sig denne Nat højtideligt det Løfte ikke at helme, før han enten var
bleven fuldt overbevist om Planens Uigennemførlighed eller havde
overvundet alle Vanskeligheder og ført sin Tanke frem til Sejr.
Det varede nu ikke ret mange Dage, før det virkelig lykkedes ham
ved en Omlægning af sin Kanallinje at raade Bod paa den
Grundskade, Professor Sandrup havde paavist. For at være sikker
paa ikke igen at lade sig narre af en Regnefejl gjorde han
dennegang en omstændelig Kontraprøve paa sin
Strømhastighedsberegning, og da han saae, at Facit stemmede,
udløstes hans Spænding og Glæde i en øreskingrende Fløjtetrille.
Han følte atter fast Grund under Fødderne. Arbejdet var altsaa ikke
spildt; de tusind Nætter, det havde kostet ham, var ikke bortødslede.
— Holla! Der var maaske endnu Tid til at vinde Sejr, før Faderen
derhjemme i Præstegaarden lukkede sine Øjne.

Sit Forhold til den neergaardske Arv fik han nu hurtig ordnet uden
fornyede Skrupler. Han sagde til sig selv, at det dog ikke nyttede
med for megen Finfølelse. Man maatte gøre sig haard overfor den
Slags Fornemmelser, naar man skulde frem i Verden med et Par bare
Næver. Forresten viste det sig, at Summen ikke var saa stor som
ventet. Ved hans Besøg hos Sagføreren meddelte denne ham, at
Boet „var en Del belastet“, og med denne Erklæring lod han sig nøje
uden at tænke paa at foretage nogen nærmere Undersøgelse. Et Par
Tusinde Kroner maatte der efter Sagførerens Mening dog sikkert
blive til Rest, — det vilde altsaa sige, at han foreløbig havde sikret
sig Arbejdsro i det mindste et Aar. Et Forskud fik han straks og
meget beredvilligt udbetalt, saa han kunde afgøre sin Gæld.

Nu opgav han ogsaa sin Lærervirksomhed og den anden,


nødtvungne Bibeskæftigelse for helt at kunne ofre sig for det store
Værk. Utaalmodig som en ung Bjørn, der rejser sig af sit første
Vinterhi, rystede han den lange Lediggangs Døsighed af sig og
tumlede ud i sit Arbejde. Mens Foraaret drog henover Landet med
Solskyer og sortblaa Hagelbyger, sad han hele Dagen og den halve
Nat derinde i sit lille Kammer bøjet over sine Papirer, døv for
Stærefløjtet derude i Træerne og for den rosenrøde Sne af
Æbleblomster, der dryssede ned udenfor hans Vindu. Hver Morgen
vækkedes han af Nybodersklokkens Klemten, og han sad allerede
ved sit Arbejdsbord, naar Madam Olufsen viste sig udenfor i sin
storblomstrede Nattrøje og med Sovekammermøblet under
Forklædet for at vande Avriklerne i Haven.

Trods den forholdsvise Velstand, han nu havde opnaaet, foretog


han ingensomhelst Forandring i sin Levevis, der snarest i endnu
højere Grad blev præget af hans medfødte og tilvante
Sparsommelighed. Derimod anskaffede han sig forskellige ret
kostbare Plancheværker og andre tekniske Skrifter, som han havde
Brug for til sit Arbejde, ligesom han begyndte at holde baade et tysk
og et amerikansk Fagtidsskrift. Paa den polytekniske Skole viste han
sig aldrig mere. Han havde en Anelse om, at hans forrige
Medstuderende havde faaet Nys om Anledningen til hans Besøg hos
Professor Sandrup og hvad dette havde aabenbaret, — og forresten
ansaae han det for Tidsspilde længer at høre disse endeløse
Forelæsninger af pedantiske Stuelærde, der talte om det praktiske
Livs Krav som den Halte om en Springdans.

Fru Engelhardt saae han ikke tiere. Han tænkte vel endnu
undertiden paa Muligheden af en Forsoning; men noget Skridt dertil
havde han ikke gjort. Hvor flov han end vedblev at være over sin
Optræden hin Nat, havde Oplevelsen alligevel efterladt en lille Mistro
hos ham til det galante Eventyrs saa højt priste Glæder. Han havde
spurgt sig selv, om de nu ogsaa virkelig var de mange dermed
forbundne Besværligheder, det meget Komediespil og navnlig den
store Bekostning værd. Hvergang Fristelsen til at forny
Bekendtskabet med den forfarne Dame kom over ham, behøvede
han blot at tænke paa den syndige Hoben Penge, hun havde kostet
ham bare paa en Aften, — og det faldt ham da i Almindelighed ikke
svært at glemme hende for sine Kanalprofiler og
Vandstandsberegninger.

Naar Solen skinnede, stod hans Vinduer gerne aabne ud til det Fri.
Sommerfugle og Humlebier forvildede sig da ind til ham ude fra
Haven, uden at dette Syn dog stemte ham lyrisk. I det højeste
kunde han give sig til at fløjte under Arbejdet, og da stak
Højbaadsmanden undertiden sit kalotprydede Hoved ind ad Vinduet
for at udtrykke sin Glæde over hans gode Humør, eller Madam
Olufsen stillede en Kop rygende Kaffe ind paa Karmen og bad ham
dog „unde sig Stunder til at trække Vejret“. Havde den gode Kone en
Tid frygtet for, at hendes Logerende var kommen alvorlig paa Afveje,
saa gik hendes Bekymringer nu snarest i modsat Retning.

„Tag nu og drik den Kaffetaar, mens den er varm,“ kunde hun sige
i den kommanderende Tone, hvormed hun gerne skjulte sine
moderlige Følelser for ham.

Saa kastede Per sin Tusjpen eller Ridsefjer, tændte en lille


Shagpibe og lagde sig hen i Vinduet for at slaa en Passiar af med de
to Gamle, mens disse puslede om i den lille Stump Have, hvor
Pladsen var saa indskrænket, at de to store Mennesker daarlig
kunde bukke sig uden at støde sammen med den Del af Ryggen,
hvorom Olufsen (med en respektløs Hentydning til
Skabelseshistorien) plejede at sige, at den blev „klasket paa bagefter
af alt det, der var tilovers“.

Det varede dog sjelden længe, før han fik Uro paa sig. Og atter
sad han bøjet over sine Tegninger og saae i Aanden Hakker og
Skovle blinke i Solen, saae, hvordan Høje jævnedes og Moser og
Kær fyldtes, og hørte det dumpe Drøn af Miner, der rystede selve
Jordens Grundvold ved et Tryk af hans Finger. Han havde igen paa
forskellig Maade omformet og udvidet sit Projekt. Saaledes havde
han — i nøje Tilknytning til Kanalnettet — udkastet Grundplanen til
en stor, ny Havn paa Jyllands Vestkyst, en Verdenshavn, der skulde
kunne optage Kampen med Hamborg og Bremen. Og ikke nok
dermed. Under sin Syslen med denne Opgave var han bleven ført
ind paa den Ide at udløse Vesterhavsbølgernes Energimængder ved
Hjælp af store Bøjer af sammennittede Jernplader, der skulde
udlægges i Brændingen, og hvorfra Kraften igen førtes gennem
Ledninger ind til industrielle Anlæg paa Stranden. Ogsaa Vindens
Arbejdskraft tænkte han sig udnyttet gennem Motorer, der skulde
være i Stand til at opsamle og ligesom nedpakke Energien, hvorved
der vilde være tilvejebragt Betingelser for at omskabe hele Landet til
et Fabriksland af allerførste Rang.

Om Aftenen, naar Vejret var smukt og hans Hoved var svimmelt af


Dagens Arbejde, satte han sig ud til Højbaadsmanden paa en Bænk,
der var anbragt ved Plankeværket under et Par sammenslaaede
Lægter med en Stump gammel Sejldug over. Det var det saakaldte
„Lysthus“, hvorfra man efter de Gamles Mening havde det bedste
Overblik over det samlede Haveanlæg. Undertiden kiggede saa en,
saa en anden af Husets gamle Venner ind til dem, enten det nu var
den mosbegroede Obertømmermand Bendtz, der kom rokkende ved
sin Stok for at beklage sig over sin Lændegigt, eller det var den
immerglade Bolteslager Fuss med sit kirsebærfarvede Ansigt og
hvide Gorillaskæg. Madam Olufsen blandede da gerne en Romtoddy
til hver af dem, og Trine maatte løbe hen i Krokodillegade til
Bolteslagerens for at hente hans Guitar. Ovre i Salslejligheden i
Huset bagved boede der nemlig en ung Overkanoner, der spillede
smukt paa Humle. Hver Aften sad han ved sit aabne Vindu med det
lange, hjemmelavede Instrument foran sig, og naar nu Bolteslageren
faldt ind med sin Guitar, blev det til en hel Koncert, der vakte Glæde
i det ganske Hjertensfrydkvarter. Rundt om i Nabohusenes Vinduer
rakte Folk sig frem for at lytte; Børnene i de omliggende
Smaagaarde standsede deres Leg og kravlede op paa
Plankeværkerne for at komme til at se noget, — ja, om det saa var
Spurvene, der havde sat sig til Ro for Natten oppe i Trætoppene,
svang de sig — ugletyst — hen paa Tagryggene og sad deroppe med
Hovedet paaskæve som smaa, andægtige Tilhørere.

En saadan Musikaften fik Per Øje paa en nydelig ung Pige, der
stod bag et aabent Salsvindue i et af Nabohusene. Hun havde lagt
begge Armene paa Ryggen, tilsyneladende ganske optaget af at
høre paa Koncerten og samtidig betragte Aftenhimlens drivende
Skyer. Dog, Kindernes stadig tiltagende Rødme forraadte, at hun ikke
var helt uvidende om det Par dristige Mandfolkeøjne, der iagttog
hende ovre fra Højbaadsmandens Lysthus.
Huset derinde tjente som Embedsbolig for en af Nyboders
Rangspersoner, Mester Jacobæus, hvis Kone kaldtes Frue i hvert
Fald af Mandens Underordnede. Per fik bagefter at vide af Madam
Olufsen, at den unge Pige var denne Mands Broderdatter, og at
hun nylig var kommen her til Byen for at lære Skrædersyning.

Efter denne Aften tilbragte han mere regelmæssig


Solnedgangstimen ude paa Bænken ved Siden af Højbaadsmanden
for herfra at holde Øje med Nabohusets Vinduer; og det slog ogsaa
kun sjelden fejl, at Pigebarnet kom tilsyne i et af dem og gav sig
noget at bestille ved Blomsterne eller Fugleburet. Undertiden
lukkede hun ogsaa et Vindu op, flyttede Urtepotterne tilside og
lænede sig ud for at lade Blikket glide henover Tagryggene eller ned
i Genbogaarden eller op mod Himlen — kort sagt alle andre Steder
hen end netop ned i Højbaadsmandens Have.

Noget Blik blev der i det hele ikke vekslet imellem dem, hvor
meget Per end anstrengte sig for at aabne det stumme Sprog en
Telegrafforbindelse over Plankeværket. Saa en Morgenstund, da han
kom ud af Gadedøren, saae han hende første Gang udenfor Huset.
Hun skraaede netop over Gaden fra Bagerboden i Genbostedet —
iført grønne Plydses Hjemmesko og med en Hankekurv i Haanden.
Han kunde ikke lade være med at smile, da han saae, hvor ulykkelig,
ja næsten forbitret hun blev over, at han skulde møde hende under
saa beskæmmede Omstændigheder; denne Skamfuldhed gjorde
hende kun endnu mere indtagende i hans Øjne, og han bestemte sig
til at løfte paa Hatten. Hun lod imidlertid, som hun ikke saae ham;
og endnu samme Dags Eftermiddag skaffede hun sig en glansfuld
Oprejsning. Per vendte just hjem fra en af sine smaa raske
Spasereture paa Langelinje, da hun kom ud af Farbroderens Dør i en
fiks, lys Foraarsjaket, med en stor Silkesløjfe under Hagen og
slørombølget Hat. Et Øjeblik blev hun staaende paa Dørflisen for at
knappe den sidste Knap i et Par skinnende nye, sorte Handsker;
hvorpaa hun langsomt, med begge Hænder i Jaketlommerne, gik
ned imod Volden — uden at have saa meget som kastet et Strejfblik
til den Side, hvorfra Per kom. Men ogsaa dennegang maatte Per
smile. Han havde nemlig forinden skimtet hendes Ansigt oppe i
Mester Jacobæus’ Gadespejl, og han gissede nu, at hun havde set
ham gaa ud, og at hun havde staaet deroppe i al sin Puds for at
vente paa hans Tilbagekomst.

Men Per havde nu faaet Blod paa Tanden, og han besluttede sig til
en dristigere Tilnærmelse. Han lod Trine skaffe ham Underretning
om Beliggenheden af den Systue, hvor hun undervistes, og hvornaar
hun plejede at gaa derfra, — og en Eftermiddag ved Syvtiden
overraskede han hende ved Nørrevold, bedst som hun stod og saae
ind ad et Butiksvindu.

Han hilste hende med stor Ærbødighed og udbad sig Tilladelse til
at forestille sig for hende, og til hans Forundring viste hun sig ikke
fornærmet over hans Paatrængenhed. Det saae ud, som om hun
med provinsiel Enfoldighed fandt det ganske naturligt, at to Naboer,
der mødtes i den store By, gav sig i Samtale og gjorde hinanden
Følgeskab. Helt oprigtig var denne Troskyldighed imidlertid ikke. Hun
røbede det selv, da de nærmede sig Nyboder, idet hun pludselig
standsede og erklærede, at han nu ikke maatte følge hende
længere. Og Per, som vidste, at Mester Jacobæus var en nidkær
Mand, der var sig Ansvaret for den unge Broderdatter fuldt bevidst,
forlangte da heller ikke nogen Forklaring men tog Afsked med
Ønsket om et „snarligt Gensyn“.
I den følgende Tid mødtes de nu hyppig paa samme Maade og
fulgtes et Stykke hjemad. Ved en stiltiende Overenskomst lagde de
dog af Forsigtighedshensyn Vejen om ad Kongens Have og
Rosenborg-Gartnerierne, hvor de var mindre udsat for at møde
Nybodersfolk; og desuden forlængede Per hver Gang Vejen med et
lille Stykke, uden at hun gjorde Indsigelse derimod.

Fransisca (saadan hed den unge Pige) var af Middelhøjde, blond,


slank, nærmest mager, men meget velbygget. Mest ejendommeligt
var hendes Fodskifte, der tydede paa noget rankt og „sikkert“ i
Karakteren. Naar hun gik ned ad Gadens Fliserække med Hænderne
i sine Jaketlommer og det unge Bryst kækt fremskudt, veg Folk
uvilkaarlig tilside for hende, og Per morede sig over at se de slugne
Blikke, Herrerne sendte hende. Det røde og hvide Ansigt havde
gerne et mut Udtryk, Brynene var dystert sammentrukne, — hvad
dog slet ikke betød noget, det var bare hendes Maade at hævde sig
paa i de fremmede Omgivelser. Hun vilde med denne udfordrende
Mine lade de gode Københavnere vide, at der ogsaa fandtes Folk i
Kjerteminde.

Hendes tilsyneladende saa dristige Forhold til Per skyldtes just den
samme skjulte Frygt for at blive anset for et Guds Ord fra Landet. Og
Per mistydede ikke denne Frimodighed, dertil var den for nær
beslægtet med hans egen jyske Selvhævdelsestrang.

Overhovedet havde det, at de begge var fra Provinsen, i høj Grad


fremmet den gensidige Forstaaelse, — ja selve Pers Optagethed af
hendes Person kunde (hvad han dog ikke selv tænkte paa) føres
tilbage til Fortidsindtryk hos ham, idet hun baade ved sin Skønheds
Art, sine Manerer og sit ukøbenhavnske Sprog vakte hans Erindring
om Hjemstavnens lysblonde, skjoldmøagtige Borgerdøtre, hvortil
hans første erotiske Fornemmelser havde knyttet sig.

Det faldt nu til al Ulykke ind med en Række ualmindelig smukke


Sommeraftener, lyse, store og farvestraalende — ret som skabte til
at vække Uro i to unge, ledige Hjerter. De havde efterhaanden
forlænget deres Spasereture helt udenom Søerne, og altid gik de
hjem gennem det romantiske Anlæg bagved den endnu staaende
Rest af Byens østre Fæstningsvold, i hvis højtliggende Alle af gamle,
bredkronede Træer de tilsidst gik frem og tilbage adskillige Gange,
før de kunde overvinde sig til at skilles.

Hvad de talte om paa disse lange Vandringer? Om Vejret og om de


Folk, de mødte; om fælles Nybodersbekendte og Dagens Nyt, —
aldrig om Kærlighed. Per gjorde end ikke nogensinde Tilløb dertil. I
Begyndelsen afholdt han sig derfra for ikke at skræmme hende.
Siden undgik han Emnet for sin egen Skyld, — af Frygt for den Magt,
hun mere og mere fik over ham.

Han havde oprindelig nærmet sig hende uden nogen bestemt


Hensigt, havde rent vanemæssigt søgt Adspredelse ved at gækkes
med en ung Kvinde. Hans Arbejde havde saa fuldstændig opslugt al
hans Interesse, og hans anspændte, blodoverfyldte Hjerne havde
tæret saaledes paa hans Legemskraft, at der blev Brug ogsaa for det
Forstærkningsfond, der i Ungdommen skaber de erotiske Trængsler.
Men just dette, at han imod Sædvane intet begærede af Forholdet;
og saa denne lyse Feststemning, hvori Naturen Aften efter Aften
klædte sig, dette straalende Gyldenskær, der — netop som de
mødtes — omskabte Byen og dens Omgivelser til et Eventyrets
Land; endelig denne store Hemmelighedsfuldhed, hvori de for
Fransiscas Skyld maatte mødes, den Uro og Ængstelse, hun ikke
formaaede at skjule for ham længer, naar de skiltes, — alt dette
havde efterhaanden givet deres Forhold en ham ukendt, ja uanet
Fortryllelse, og en skøn Dag gjorde han den Opdagelse, at han aldrig
før rigtig havde forstaaet, hvad Kærlighed var.

Og han havde Ret.

Virkelig elskede han nu for første Gang. Han, som i enkelte


Retninger var saa langt forud for sin Alder, havde i Følelsernes Rige
levet som et Barn eller en Vild. Nu gik han omkring med en halvt
benauet Fornemmelse af, at der foregik en mystisk Fødsel i hans
Indre, at en helt ny Verden var i Færd med at aabenbare sig for
ham. Han, som ellers overfor Kvinder havde søgt at gøre Vejen fra
Ord til Handling saa kort som mulig, blev i Forholdet til denne unge
Pige Nænsomheden selv, saa ridderlig i sin Færd, saa angst for at
saare, at det f. Eks. varede længe, før han ved Afskeden fik Mod til
at bede hende om et Kys. Og da hun tilstod ham det og han saae
Rødmen skylle hen over hendes Ansigt, var han ikke langt fra at
fortryde sin Dristighed; og det var med en Følelse af at begaa
Helligbrøde, at han berørte hendes jomfruelige Mund og stjal
Varmen af hendes Læber.

Henpaa Eftersommeren rejste Fransisca hjem til sine Forældre paa


et længere Besøg. Trods den Regelmæssighed, hvormed de i den
sidste Tid havde mødtes, og den Uforsigtighed, de havde begaaet
ved at henlægge deres stadig ømmere Afskedsscene til Nyboders
umiddelbare Nærhed, var der endnu ingen, der kendte deres
Forhold, — ingen uden Trine. Med den næsten synske Fantasi, der
stod til dette lille svaghovedede Pigebarns Raadighed, saasnart det
galdt Per, havde hun længe vidst Besked om alt; og forresten havde
Per engang set sig nødsaget til at gøre hende til sin Fortrolige for at
faa et vigtigt Brev bragt over i Nabogaarden, — hvilket vanskelige og
slet ikke ufarlige Hverv hun havde udført, som var det en
guddommelig Sendelse. Under det selvopfundne Paaskud at skulle
hente en Klemme, der var blæst over Plankeværket, skaffede hun
sig Adgang til Mester Jacobæus’ velbefæstede Hus og overbragte
ogsaa lykkelig og vel sit hemmelige Budskab i de rette Hænder. Men
bagefter, da Per var gaaet, havde hun listet saa usædvanlig stille og
bleg omkring og havde saa hyppig maattet søge Tilflugt ovre i
Nødtørftshuset, at Madam Olufsen troede hende syg og tilsidst
kommanderede hende i Seng og lagde hende et kraftigt
Sennepsplaster paa Maven.

Efter Fransiscas Tilbagekomst i Oktober naaede hendes og Pers


Følelser for hinanden snart en saadan Inderlighedsgrad, at der
nødvendig maatte handles. Per var fuld af Uro. Den Tanke at lade
sine Følelser munde ud i Forsøget paa en Forførelse viste han
afgørende fra sig. Paa den anden Side kunde han rigtignok heller
ikke tænke sig at ophøje deres Forstaaelse til en regelret, officiel
Forlovelse; men det var uden Tvivl alene en saadan Udgang af
Sagen, Fransisca havde i Tankerne og utaalmodig gik og ventede
paa. Hun havde et Par Gange — ganske uopfordret — sat ham ind i
sine Familjeforhold, havde endog ved en enkelt Lejlighed ladet en
lille Bemærkning falde om sin Faders ganske gode
Formuesomstændigheder. Men at gifte sig med en Sadelmagerdatter
fra Kjerteminde — det stod for ham som ganske uforeneligt med det
Livsmaal, han havde sat sig. Hvergang Fristelsen kom over ham,
saae han Neergaard for sig og mindedes de Ord om
Svinedrengeprinsen, der engang før havde lyst for ham i
Flammeskrift som et spottende Mene-Tekel.
Da hændte der noget, som hidførte en uformodet og hovedkulds
Afgørelse.

Allerede i nogen Tid havde Mester Jacobæus haft Mistro til


Paalideligheden af de Fortællinger, hvormed hans Broderdatter
forklarede Grunden til sin stadig senere Hjemkomst fra Systuen, og
en Dag foresatte han sig at anstille en Efterforskning. Denne førte til
et Forhør, hvorunder han tilsidst aftvang Pigen en fuldstændig
Tilstaaelse.

Dagen efter indfandt Mester Jacobæus sig hos Per og spurgte ham
kort, endog uden først at sige, hvem han var, om det var hans
Hensigt at gifte sig med hans Broderdatter. Per prøvede i
Begyndelsen at snakke sig fra Sagen, bad ham tage Plads og lod
halvt uforstaaende. Men med et Hovedkast bad den vrede Mand sig
fritaget for Talemaader og fordrede klar Besked. Et Ja eller et Nej
vilde han have — intet andet.

Per tøvede endnu med Svaret. Han tænkte paa, at dersom han nu
sagde nej, vilde han rimeligvis aldrig se Fransisca mere — og hans
Hjerte blev tungt derved. Han saae hende for sig, saadan som hun
rimeligvis nu gik derinde i Huset ved Siden af og i Angst og
Spænding ventede paa Udfaldet. Og virkelig foer i dette Øjeblik den
Tanke ham som en Lysning gennem Sjælen at lade alle tvivlsomme
Storheds-Drømme fare, at holde fast paa denne ene, sikre lille
Lykke-Spurv, han holdt i sin Haand, og glemme Guldfuglene højt paa
Tage og Tinder. Men atter dukkede Neergaards nøgne Hoved op for
ham. Og han rettede sig i Vejret og svarede aabent Nej.

Og nu forefaldt der en Scene, som han ikke siden kunde tænke


paa uden at bide sig i Læben af Skam. Med begge Hænder i
Bukselommerne traadte Mester Jacobæus ham i to tunge Skridt saa
nær ind paa Livet, at han kunde føle Haar af hans graa Fuldskæg
kilre ham i Ansigtet. Og den fremmede Mand kaldte ham en Flab, en
Lømmel og en Gadedreng og lod ham vide, at dersom han endnu en
eneste Gang nærmede sig hans Broderdatter, skulde han blive
gennempryglet og lempet ud af Nyboder som en skabet Hund.

Per var bleven kridhvid af Raseri; men han rørte sig ikke, svarede
ikke heller. Dog var det ikke Mandens Trusler, der gjorde ham tavs.
Han havde før været ude for et Par knyttede Næver, og hans første
Tanke, da han saae Manden nærme sig, havde da ogsaa været den
at gribe ham i Kværken og sætte ham op imod Væggen og holde
ham fast der, indtil han havde faaet Galskaben sprællet af sig. Men
da han stirrede ned i dette blege, fortrukne Ansigt med den dirrende
Mund, der endnu tydeligere end hans fremstammede Tale viste, hvor
nær den hele Sag var gaaet ham, hvor alvorligt den havde græmmet
og ydmyget ham, rørte der sig i Dybet af hans Sind en Følelse af
Skyld, der holdt hans Haand nede og hans Mund lukket.

Bagefter, da Mester Jacobæus var gaaet, maatte han rigtignok


spørge sig selv, hvormed han egenlig havde forbrudt sig. Han havde
jo ikke villet Fransisca noget ondt. Dersom han fra Begyndelsen
havde anet, at der skulde udvikle sig Kærlighed imellem dem, vilde
han endda helt have holdt sig fra hende; men forresten havde han
jo ikke misbrugt hendes Tillidsfuldhed. De Kys, de i Uskyldighed
havde vekslet, kunde da for Pokker ikke kaste nogen Skygge over
hendes Fremtid. Men hvad Skade var der saa sket?

Det var altsaa igen hans „Samvittighed“, der havde overlistet ham,
— dette ubestemmelige, spøgelseagtige noget, der pludselig satte
En et Troldspejl for Øjnene, hvori man saae sig selv i hæslig
forvrænget Skikkelse. Han, som havde troet sig saa lykkelig frigjort
for alle Slags Pukler og Knyster paa Sjælen, stod atter her
beskæmmet som en Nar, — og Ærgrelsen herover var nær ved at
faa ham til at glemme baade Fransisca og Adskillelsen fra hende.

Nu viste det sig desuden, at Mester Jacobæus’ Trusler havde


været ganske overflødige. Allerede Dagen efter rejste nemlig
Fransisca efter sit eget Ønske hjem til Fyen. To Dage senere modtog
Per med Posten nogle Smaating, han nu og da havde foræret hende.
Hun tilbagesendte dem uden at ledsage dem med et eneste Ord,
endsige nogen Bebrejdelse; men hver enkelt Ting i Pakken var
omhyggelig indsvøbt i rosenrødt Silkepapir. Og som Per nu stod med
dem i Haanden, overgik der ham en ny Ydmygelse. Hans Øjne
begyndte at fugtes. Han kunde ikke afværge det. Ja, havde han ikke
skyndt sig at lukke det hele ned i sin Skuffe, kunde der let være
overgaaet ham den endnu større Skam, at han virkelig var kommen
til at græde.

Men atter var Lykken ham huld. Ikke mange Dage efter skete der
noget, der ikke alene fik ham til at glemme den bratte Udstødelse af
Kærlighedens Paradis, men næsten tog sig ud som selve
Skæbnegudens opmuntrende Vink til ham — en Belønning for hans
Standhaftighed. Havde han længe ligget og kæmpet i Dødvande og
biet paa en gunstig Vind for sin Eventyrsejlads gennem Livet, saa
rejste der sig i det hele nu en Storm af Begivenheder omkring ham,
der bar ham ud paa det aabne Hav.

***

Allerede for noget siden var han naaet saa vidt med Arbejdet paa
sit Projekt, at han havde ment igen at turde forelægge en Avtoritet
det til Bedømmelse. Han havde dennegang henvendt sig til
Formanden for Ingeniørforeningen, en pensioneret Ingeniøroberst,

You might also like