SEM automation guidelines for small script development: simulation and reporting

By Wouter Arts - October 18, 2018

Scripts are small automated software tools that can help a scanning electron microscope (SEM) user work more efficiently. In my previous blogs, I have explained how we can use the Phenom SEM with the Phenom programmable interface (PPI) to automate the process of acquiring, analyzing and evaluating images. In this blog, I will add the Phenom PPI simulator to that and explain how you can generate and export reports using PPI. 

First, I’ll explain how to create a Phenom SEM Simulator in PPI and how to use it to acquire images. The Simulator mimics the behavior of the Phenom and is a great tool to develop code without needing to have to access to a Phenom SEM.

After that, I will demonstrate how you can analyze these images using an external module and how you can generate a report using PPI.

The Phenom PPI Simulator

The Simulator can be created by calling the Phenom class in PPI and passing empty strings for the Phenom ID, username, and password. In code it looks like this:


Acquiring images works in exactly the same way as I explained in my first blog on guidelines for script making.

We create a class of ScanParams and fill it with the desired settings. In this case, we want to acquire an image with a resolution of 1024x1024, using the BSD detector, 16 frames to average, 8-bit image depth, and a scale of 1. The image is then obtained using phenom.SemAcquireImage(). The image is displayed in a matplotlib figure. The code for this is:


The resulting image from the Simulator are repeating diagonal gradients, which is shown in Figure 1.


Fig 1: Phenom Simulator image

Analyze using an external module 

In my previous blogs on script development and automated image analysis, I have shown how an image can be analyzed and evaluated using external libraries. In this blog, we will use an external module and determine the peak to peak distance on a circular cross section of the image. To determine this distance we will import a great little module called detect_peaks (for more information see link).

Using the detect_peaks module we can determine local peaks based on its characteristics. Importing an external module is as easy as downloading the .py file and putting it in the root directory of your script and then adding the following line to your import statements:


We extract a circular path because it is a little more exciting than using just a straight line, where all the peaks would be equidistant, and the results would be rather dull. To create a circle with points spread by 1 degree, a radius of 300 pixels, and positioned in the middle of the acquired image:


In this script we force the numbers to remain integers, otherwise, we cannot use them to extract a cross-section. This is done with astype(np.uint16), the numbers are now unsigned integers with a bit-range of 16 bits (i.e. from 0 to 65,535).

Extracting the circle and peaks can now be easily done by:


The mpd parameter in detect peaks is the minimum spread between the peaks and the mph is the minimum peak height.

To plot the results, we create a new image. In the left-hand plot, we will show the acquired image with a circle indicating where we took the cross section and red crosses to show where the peaks were found. In the right-hand image, we will plot the value of the cross section with red crosses where the peaks were found. We will add titles and labels to the plot and save it to a jpeg file in order to be able to use it in the report later on.


The resulting image will be displayed in the report we will generate in the next section.

PPI reporting

To powerfully report the results to a user of a script, PPI has its own PDF-reporting tool. It is based on libHaru. Creating a pdf is fairly easy, once you know which steps to take. The first step is to create a document in Python:


In the document, we need to create a page. This is done by:


All positioning of text and objects is done with reference to the bottom left corner of the page. The positions are given in points and the default resolution is 72 dpi, thus the default size for A4 is: 595x842 pixels. The size of the paper is saved into the height and width variables.

In this document, I will show how you can make headings, write large sections of text, make tables, and include figures. We start by adding text. I added three different types of text, first a big and bold header, then a smaller italic header, and a section with a large string that runs over multiple lines.


To create text we begin with page.BeginText(). After that, we set the font with page.SetFontAndSize(). Then we position the text to the top left of the document with a margin of 50 pixels (about 2 cm in the document) with page.MoveTextPos(). To insert text we add a line with page.ShowText(). To move to the next line we only have to set the relative movement over the page with page.MoveTextPos().

The first time you call page.MoveTextPos() the starting point is the bottom left corner of the document, and the second time it is a relative change to the new position. Typically, if you have a long text it is a hassle to find where every line break should be. To automatically find where a line break should be a text box can be made. This text box automatically does the line breaks and alignments of the text for you.

It can be called with page.TextRect(), and the following attributes are passed: a PPI rectangle giving the absolute position of the text box, the string with the text that should be printed in the report, and the alignment. You can also see that I have changed the font three times to be able to distinguish between headers and sub-headers and normal text.

To make a table, normal text is used but is displayed in a structured manner. First a header is made using text spaced in a regular horizontal pattern. Below this header we want a single line. However, drawing is not allowed between page.BeginText() and page.EndText() parts, so we have to close the text part to draw and then reopen it again.

To draw the line we move the position to the start location and use the page.LineTo() to define the line. The real drawing is done by page.Stroke(). After that we iterate over the items we want to put in the table and put them all in the right column, with the same spacing. The table ends with a double underlining. The code to do this is:


To save the pdf pdf.SaveToFile() is used. To open the pdf the subprocess library can be used:


The resulting PDF is:

Schermafbeelding 2018-10-08 om 14.42.25

This blog concludes my series of blogs with guidelines for small script development, I hope you have enjoyed it. If you would like to learn more about PPI and automation you can download the PPI specification sheet below:

New call-to-action

About the author

Wouter Arts is an application software engineer at for the Thermo Scientific Phenom Desktop SEM product range at Thermo Fisher Scientific. He is interested in finding new smart methods to convert images to physical properties using the Phenom Desktop SEM. In addition, he develops scripts to help companies in using the Phenom Desktop SEM for automated processes.

Press Room | Privacy Policy | Terms of Use | Sitemap |