Overview¶
In electron spectroscopy matter is examined by radiating it with a bright light and measuring the kinetic energy of electrons that come off it. When the photonic energy of light and kinetic energy of the electrons are known, they can be used to derive the amount of force that was required to break off the electrons. This provides valuable information about the matter's electron structure, and its chemical and physical properties. This phenomenon where photons break off electrons is called photoionization, and the broken off electrons are called photoelectrons.
In this course project you'll learn how to read data into a program and how to perform small operations on the data, and how to plot data using Python libraries. Your task is to write a program for analyzing the photoionization spectrum of argon. For this purpose we have provided you with simulated data where argon atoms have been ionized and the kinetic energy of broken off electrons has been measured.
About Libraries¶
This project requires you to use two third party libraries: numpy and matplotlib. There are multiple ways to install them. Windows installers can be found for both, and you can also install them using pip. There are also various full stack installers available in the internet (full stack means they install Python along with a bunch of libraries, usually replacing your "generic" Python installation). Please write a comment in your code if you use any such full stack installer because they might contain different versions of the libraries than those available generally.
You'll also need our small graphical user interface library - more about it below.
Specific Requirements¶
The measurement has been performed multiple times, and each measurement session has been recorded into a different, numbered file. The file names are in the format
measurement_i.txt
. Each file contains rows of data with two floating point numbers. The first number on each line is the binding energy of electrons, derived from the measured kinetic energy (unit: electronvolt); the second number is the corresponding intensity (no specific unit; this described the amount of electrons measured with this particular binding energy). In each measurement file, the first column contains the same uniformly distributed binding energy values. Your program should add together the intensity values from each file. The purpose is to eliminate noise from the measurements. Due to the measuring equipment, the spectrum has a linear background. Aside from the obvious peaks it looks like a downward sloping line. The background signal that causes the sloping should be removed before analyzing the spectrum. This can be done by choosing two points from the spectrum and fitting a line between these points. After this, at each data point, values obtained from this line are subtracted from the measured intensity values.
When analyzing the spectrum our primary interest are the two rather obvious peaks in intensity; in particular, their relative intensity. The intensity of each peak is obtained by computing their area by obtaining its integral. This can obtained by using the trapezoidal rule to estimate the integral. According to theory the first peak should have approximately double the intensity of the second one.
Your program needs to have the following features:
- Your program has a graphical user interface with all the features available for the user.
- Load data: loads data from a user-specified location and reads it into program memory in a format that is suitable for processing. Should return one list for each column in the data. The first list should contain measured kinetic energy values (measurement points) and the second one the sums of all measurements for each row.
- Plot data: this plots the current data (the user is prompted to load the data first if it hasn't been loaded yet). You can plot the data using matplotlib, but it must be plotted inside the application window - do not use pyplot. The figure should look like the one below.
- Remove linear background: removes the linear background from the data as described above. The user selects two points from the figure, and a line is fitted between these points. The line is then subtracted from the data. If there's no data in the program memory yet, the user is given an error message about it.
- Calculate intensities: The intensity of peaks can be calculated. This is done with the trapz function from numpy. The use selects the interval by clicking on the figure. The result is printed somewhere inside the window. If there's no data in the program memory yet, the user is given an error message about it.
- Save figure: this feature allows the user to save an image of the current plot. The user uses a separate dialog for select a filename and destination for saving the figure. matplotlib provides you with the necessary features to do this.
You should name the axes in your figure with appropriate names. There are tools for doing this in matplotlib.
Graphics¶
Deployment¶
We've provided a library that is built on top of TkInter, and offers a heavily simplified interface to some of its features through functions. The library's docstrings describe how to use it. The lirary's main program also has a short example of how to make a simple interface.
User Interface Libraries 101¶
In user interface programming the main loop is usually contained inside the library being used. All of the user's actions are connected to handler functions. For instance, when the user presses a button, the handler function attached to that button is called, and it does Something. The program doesn't proceed as linearly as we've used to. User interfaces consist of components or elements that are also often called widgets. These can be simple, like buttons, or more complex like an entire file opening dialog - one you can see in many programs.
Typically an interface is created by choosing what components to put in there. While doing so, their attributes and handler functions are also defined. Rest of the implementation comes down to creating these handler functions and bunch of utility functions (that are used by the handlers).
One special characteristic is that functions are called kind of externally from the user interface library, and therefore we cannot control what arguments they are given. It's not possible to transmit the program's state in function arguments - another way to share it needs to be devised. A good choice in the context of this project is to make a dictionary that has keys for things like loaded data and data points selected by the user. If the dictionary is defined in the main program scope it can be handled in all functions, thanks to its mutability. This way any function can change the program state without having been given it as an argument.
Return Box¶
Deadline: 2025-08-31 23:59