0% found this document useful (0 votes)
269 views

Python: Gatan, Inc. 5794 W. Las Positas Blvd. Pleasanton, CA 94588 T +1.925.463.0200

Uploaded by

Carlos Martínez
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
269 views

Python: Gatan, Inc. 5794 W. Las Positas Blvd. Pleasanton, CA 94588 T +1.925.463.0200

Uploaded by

Carlos Martínez
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 48

Python

Copyright © 2020 Gatan Inc. All rights reserved.

Gatan, Inc.
5794 W. Las Positas Blvd.
Pleasanton, CA 94588
t +1.925.463.0200
support@gatan.com
w w w .gatan.com
Copyright 2020 Gatan Inc. All Rights Reserved

All rights reserved. No parts of this work may be reproduced in any form or by any means - graphic,
electronic, or mechanical, including photocopying, recording, taping, or information storage and retrieval
systems - without the written permission of the publisher.

Products that are referred to in this document may be either trademarks and/or registered trademarks of the
respective owners. The publisher and the author make no claim to these trademarks.

While every precaution has been taken in the preparation of this document, the publisher and the author
assume no responsibility for errors or omissions, or for damages resulting from the use of information
contained in this document or from the use of programs and source code that may accompany it. In no event
shall the publisher and the author be liable for any loss of profit or any other commercial damage caused or
alleged to have been caused directly or indirectly by this document.

Publisher
Gatan, Inc.
Technical Editors
Gatan Software Team

Document revision
Rev 3.4.3.3213

www.gatan.com

Python
Table of Contents

1 Python 1
1.1 Installation .and
. . .Configuration
...................................................................1

1.1.1 Installation ................................................................2


1.1.2 Configuration ................................................................3
1.1.3 Additional pack ages
................................................................8
1.1.4 Licenses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2 Scripting in
. .Python
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

1.2.1 Running a Script


. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.2.2 Images and NumPy
. . . . Arrays
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.2.3 Hybrid Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.4 Reference. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

Index 45
Python page 1

1 Python

Python

The DigitalMicrograph scripting language has been around for many years and provides complete
access to the image processing and analysis capabilities of the application as well as enabling control
of Gatan cameras, the DigiScan and an interface to the microscope. In recent years the Python
language has grown as an all-purpose scripting language and many libraries have been created to
provide specialized image processing, data analysis and visualization capabilities that go beyond what
can be achieved in DigitalMicrograph. We have therefore added Python as a hosted language to
DigitalMicrograph. You can now access much of the capability of DigitalMicrograph, control Gatan
cameras, the DigiScan and communicate with the microscope, as well as access any Python library
from this hosted Python environment.

DigitalMicrograph adds classes to the hosted Python environment that provide access to the key
objects within DigitalMicrograph scripting, objects like the Image, ImageDocument, ImageDisplay,
LinePlotImageDisplay, Component, Window, and TagGroup, as well as Camera, DigiScan and
Microscope. The interfaces of these classes are described in the Reference chapter.

1.1 Installation and Configuration

Installation and Configuration

The Python scripting environment is installed through the Gatan Microscopy Suite (GMS) installer.
There is no specific GMS license required. The installer makes use of Miniconda from Continuum
Analytics to install the Conda package manager, Python, and NumPy, the fundamental package for
scientific computing in Python.

Python
Python page 2

1.1.1 Installation

Installation
The Python scripting environment is installed by the GMS installer.

To install the Python scripting environment

1. Select the button for "Yes, install Python support" in the GMS installer.

The GMS installer will then install Miniconda with Python and NumPy.

Python
Python page 3

1.1.2 Configuration

Configuration

There are many versions of Python and its associated libraries. The GMS installer contains a particular
version of Miniconda and it, in turn, installs a particular version of each of Python and NumPy. By
default Python in DigitalMicrograph will use these matching versions. If you have separately installed
another version of Python, using an independent installer, it may be possible to use that version in
DigitalMicrograph instead. This is only likely to work for Python versions that differ by minor version, e.
g. 3.7.5 and 3.7.6.

If you create alternate Python environments through a command line prompt using Conda they will not
be available for selection in DigitalMicrograph. You can only choose between alternate installations of
Python.

To select an alternative Python installation to use

1. Choose Global Info... on the File menu and select the Scripting entry in the list at the left

The scripting configuration page appears.

Python
Python page 4

The currently selected installation of Python is displayed. The listed versions are those
that are likely to work with DigitalMicrograph. Although installations that differ only by
minor version are listed, only the one labeled GMS_VENV_PYTHON is guaranteed to be
compatible with DigitalMicrograph.

2. Select the installation you wish to use in DigitalMicrograph and click OK

DigitalMicrograph will launch and run the Python interpreter associated with the selected
installation when running Python scripts.

Numpy configuration
The Numpy package installed by the GMS installer uses OpenBLAS as its linear algebra library. This is

Python
Python page 5

the recommended Numpy configuration in order to avoid version conflicts and system instabilities with
GMS which itself uses the MKL libraries.

When updating additional Python packages, care should be taken that this configuration is not changed
and packages use consistent dependencies on Numpy. In particular conda installs have a tendency to
default Numpy back to using the MKL libraries. It is recommended to use pip installs instead.

To verify which Numpy configuration is used

1. Open the Anaconda Prompt

The Anaconda Prompt was installed with Miniconda during GMS installation and can be
found in the Windows start menu.

You may need to start the prompt with administrative privileges.

2. Within the Anaconda Prompt, activate the environment you want to modify.

Type: activate GMS_VENV_PYTHON

Python
Python page 6

3. Start the Python interpreter.

Type: python

4. Within the Python interpreter, show the Numpy configuration:

Type: import numpy


numpy.show_config()

Python
Python page 7

To use OpenBLAS based libraries for all packages (Default option):

1. Open the Anaconda Prompt and activates the GMS_VENV_PYTHON environment as shown
above

2. Use conda to update all packages with the specified libraries:

Type: conda install conda-forge::blas=*=openblas

3. When installing additional packages, use pip install (not conda) to avoid defaulting back to
MKL.

To use MKL based libraries for all packages (NOT recommended):

1. Open the Anaconda Prompt and activates the GMS_VENV_PYTHON environment as shown
above

2. Use conda install for Numpy. The package manager will update all other affected packages:

Type: conda install numpy

To verify packages are installed correctly:

Python
Python page 8

1. Open the Anaconda Prompt and activates the GMS_VENV_PYTHON environment as shown
above

2. Use conda to list installed packages and provided additional information. Neither command
should return error messages.

Type: conda list


conda info

1.1.3 Additional packages

Additional packages

The basic installation of Python does not include any packages other than NumPy, but additional
Python packages can be installed. The selected default Python installation is the virtual environment
named GMS_VENV_PYTHON. You can use both pip and conda commands to install packages to this
environment from the Anaconda Prompt, however pip is recommended as conda may change the
Numpy configuration.

As an example, the versatile machine-learning library scikit-learn can be used from within
DigitalMicrograph directly on acquired data (see application examples).

To install the scikit-learn package for Python in Digital Micrograph

1. Ensure the computer has a working internet connection. Packages will be automatically
downloaded.

2. Open the Anaconda Prompt

The Anaconda Prompt was installed with Miniconda during GMS installation and can be
found in the Windows start menu.

You may need to start the prompt with administrative privileges.

Python
Python page 9

3. Within the Anaconda Prompt, activate the environment you want to modify.

Type: activate GMS_VENV_PYTHON

4. Install the scikit-learn package with conda

Type: pip install scikit-learn

Python
Python page 10

5. Start DigitalMicrograph and verify correct installation.

Open a script window ( CTRL + K ) and ensure the scripting language Python is
chosen.

Type and run the following example script:

import DigitalMicrograph as DM
import joblib
import scipy
import sklearn
DM.ClearResults()
print( 'joblib : ', joblib.__version__ )
print( 'SciPy : ', scipy.__version__ )
print( 'scikit-learn : ', sklearn.__version__ )

You should get an output similar to:

1.1.4 Licenses

Licenses
The Miniconda package manager, Python and the NumPy package are licensed from the following.

Miniconda, Conda

© 2017 Continuum Analytics, Inc. (dba Anaconda, Inc.). https://www.anaconda.com. All Rights
Reserved

Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:

Python
Python page 11

Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other materials provided
with the distribution.
Neither the name of Continuum Analytics, Inc. nor the names of its contributors may be used
to endorse or promote products derived from this software without specific prior written
permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS


IS†AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL CONTINUUM ANALYTICS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Python

1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual
or Organization ("Licensee") accessing and otherwise using Python 3.7.4 software in source or binary
form and its associated documentation.

2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a
nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display
publicly, prepare derivative works, distribute, and otherwise use Python 3.7.4 alone or in any derivative
version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e.,
"Copyright © 2001-2019 Python Software Foundation; All Rights Reserved" are retained in Python
3.7.4 alone or in any derivative version prepared by Licensee.

3. In the event Licensee prepares a derivative work that is based on or incorporates Python 3.7.4 or
any part thereof, and wants to make the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of the changes made to Python
3.7.4.

4. PSF is making Python 3.7.4 available to Licensee on an "AS IS" basis. PSF MAKES NO
REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT
NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF
MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
PYTHON 3.7.4 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.

Python
Python page 12

5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.7.4 FOR
ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.7.4, OR ANY DERIVATIVE
THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.

6. This License Agreement will automatically terminate upon a material breach of its terms and
conditions.

7. Nothing in this License Agreement shall be deemed to create any relationship of agency,
partnership, or joint venture between PSF and Licensee. This License Agreement does not grant
permission to use PSF trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.

8. By copying, installing or otherwise using Python 3.7.4, Licensee agrees to be bound by the terms
and conditions of this License Agreement.

NumPy

Copyright © 2005-2019, NumPy Developers. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other materials provided
with the distribution.
Neither the name of the NumPy Developers nor the names of any contributors may be used
to endorse or promote products derived from this software without specific prior written
permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Python
Python page 13

1.2 Scripting in Python

Scripting in Python
Python scripts are edited and run from the same script window that is used to edit and run a
DigitalMicrograph script. When Python support is installed the script window gains a language selector
to choose between DigitalMicrograph scripting and Python scripting.

1.2.1 Running a Script

Running a Script
A Python script can be run on the same thread as the user interface of DigitalMicrograph (the
foreground thread) or a new thread can be created (a background thread) and the script run on that.
This choice is controlled by a check-box at the bottom of the editor window.

The default is to run the script on a background thread, because scripts run on the same thread as the
user interface of DigitalMicrograph prevent all user interaction with the application during script run
time. It is not possible to interrupt the Python script in this case, and it may become necessary to kill
DigitalMicrograph to escape from a poorly written script.

Python
Python page 14

Some Python packages will not perform correctly if run on a background thread, and may even crash
DigitalMicrograph if they are not run on the foreground thread. One example of such a package is the
commonly used Matplotlib package.

Only one Python script may be run at a time. If you attempt to run a second script DigitalMicrograph
will display an error message.

To run a Python script

1. Click on the Execute button in the scripting window or hit Ctrl-Enter on the keyboard

The script in the window will be run on either the user interface (foreground thread) or a
background thread, depending on the state of the "Execute in background" check box.
Only one Python script can be executing at any time.

To interrupt a Python script running on a background thread

1. Hit the key combination Ctrl-Shift-Q

If there is a Python script running on a background thread it will be stopped. There are
times when the Python interpreter may be holding on to the Python Global Interpreter
Lock and at these times the DigitalMicrograph cannot stop the running script and will
instead present an information dialog explaining the problem.

To interrupt a Python script running on the user interface (foreground) thread

There is no way to stop a Python script that is running in the foreground. If


DigitalMicrograph is unresponsive or the script is going to take an unreasonable amount
of time to complete you will have to stop the DigitalMicrograph application through the
task manager. It can be helpful to run problem Python scripts in a stand-alone Python
interpreter to gain more insight into the problem.

To force a Python script running on the user interface (foreground) thread

Some Python scripts, in particular when using additional libraries utilizing external UI
windows, require to be run on the foreground thread and may crash DigitalMicrograph
otherwise. To prevent accidental launching of the scripts on a background thread, such
a script itself may contain the following initial code lines:

# Safety-check: Ensure this is called on the main-thread


of GMS

Python
Python page 15

if ( False == DM.IsScriptOnMainThread() ):
print( 'This script requires to be run on the main
thread.' )
exit()

1.2.2 Images and NumPy Arrays

Images and NumPy Arrays

A Python script can directly manipulate image data held in DigitalMicrograph. This is achieved by
mapping NumPy arrays onto the memory of the DigitalMicrograph images. This sharing of memory
access imposes some restrictions- see the examples on Images and NumPy arrays.

"Inversion" of dimensions

DigitalMicrograph image images store their elements with first dimension index incrementing
first, i.e consecutive values describe the next pixel in X direction until a row is completed. Only
then does the Y coordinate get incremented by one and the X coordinated reset to zero.
Similarly, only after all rows have been filled will the Z coordinate be incremented to move to the
next plane.

NumPy arrays, unfortunately, use the opposite indexing concept, incrementing the last
dimension index first. As a result, NumPy arrays mapped onto DigitalMicrograph images, and
DigitalMicrograph images created from NumPy arrays exhibit an apparent 'flip' of dimensions.

For example: A DigitalMicrograph image of size 100 x 20 is represented by a NumPy array of


shape (20, 100).
Similarly: A DigitalMicrograph stack of size 100 x 20 x 10 is represented by a NumPy array of
shape (10, 20, 100).

Memory layout

DigitalMicrograph images require continuous memory arrays with a memory-layout in 'C' order.
Numpy arrays, however, can be in either 'C' or 'F' layout, specifying the order of values in the
array. An array of 'C' layout can be created from an array in 'F' layout using the copy()
command with the parameter order='C'.

Python
Python page 16

Updating image data

NumPy arrays connected to DigitalMicrograph images directly address the same memory
space. When using a Python script to change these values, one has to be careful to only use
syntax which modifies the existing memory. Many Python commands instead create new data
arrays and subsequently assign a variable to this new array. Such commands will not update
DigitalMicrograph image data!

Updating image displays

Updating the data in a NumPy array that is connected to a DigitalMicrograph image does not
automatically trigger a display update in DigitalMicrograph. This has to be explicitly requested
by the UpdateImage() script command.

Creating an image from a NumPy array

NumPy arrays are a very flexible object and not all of them can be used as a source for a
DigitalMicrograph image. If an invalid data format is encountered, an error message will be
presented. NumPy arrays also support views on data. Here, the actual data order in memory is
unchanged, but auxiliary meta data describes how it should be addressed. This is most often
used to access non-contiguous data, which can not be used as a memory array for a
DigitalMicrograph image. For this reason, it is not possible to create a DigitalMicrograph image
directly from a NumPy array view. Instead, a contiguous copy of the view needs to be created
first.

Deleting DigitalMicrograph image variables (Py_Image)

Python scripts keep references to DigitalMicrograph images in variables of type Py_Image.


However, when the Python script ends, all such variables need to be explicitly deleted in the
script using the del command. If they are not deleted they will prevent DigitalMicrograph from
properly closing the images and they will remain in memory until the application is shut down.

1.2.3 Hybrid Scripts

Hybrid Scripts

Python
Python page 17

DigitalMicrograph hosts two different scripting languages, the Python scripts described here and it's
own scripting language known as DigitalMicrograph script (DM-script).
Each of the two script languages has commands to call scripts of the other variety, allowing for
interesting mixed 'hybrid' scripting. This can be useful as either language has its strengths and
weaknesses.
The example section on hybrid scripts shows some interesting applications.

Running a DM script from a Python script

The Python command DM.ExecuteScriptString( text ) interprets the provided


string parameter as DM script and executes it.
The text parameter needs to be a fully functional DM script, including line breaks which can
be added to a string by: \n

Running a Python script from a DM script

The DM script command void ExecutePythonScriptString( String text )


interprets the provided string parameter as Python script and executes it.
The text parameter needs to be a fully functional Python script, including line breaks and
strict indentation formatting.
The default command will execute the Python script on a background thread and continue DM
script execution immediately without awaiting the end of the Python script.

Python
Python page 18

The DM script command void ExecutePythonScriptString( String text,


Boolean onMainThread )can be used to execute the Python script on the main thread.
Now the DM script execution will wait for the Python script to complete before continuation.

Please note that other DigitalMIcrograph UI items - including the Results window - may not
update during Python execution on the main thread.
Also keep in mind that there can only be a single Python script execution at any time. If a
Python script is launched while another one is still executed, an error dialog will be shown.

1.3 Examples

Examples
This section shows some simple Python script examples for DigitalMicrograph.

Python
Python page 19

Basic input and output

Example 1: Text output examples


'''
Basic text output examples in DigitalMicrograph.
By default, the output stream is send to the Results window.
'''
import DigitalMicrograph as DM

# Clears the output results window


DM.ClearResults()

# Standard print commands


print( 'Hello World.' )

print( 'Simple value:', 123.456 )

print( 'Some items listed:', end = "\n\t" )


print( "first", "second", "third", end = "\n\t" )
print( "first", "second", "third", sep=', ', end = "\n\n" )

print( 'Using a string literal:' )


for i in range (1,5):
print( f'\tvalue:{i} squared = {i*i}')

print( '\nFormated string:\n\t second value = {1:3.1f} \n\t first value = {0:3

# The output stream can be redirected to other windows


DM.SetOutputTo(2)
print( 'Output to Debug window.' )
DM.SetOutputTo(1)
print( 'Output to Notes window.' )
DM.SetOutputTo(0)
print( 'Output to Results window.' )

# The results command will always output to the Results window


# but can only use a single, simple sring argument.
DM.SetOutputTo(1)
DM.Result( 'Always to Results window.' )
DM.SetOutputTo(0)

Example 2: Output version info


'''
Output basic information of the used Python environment.
'''
import sys
import numpy as np
import DigitalMicrograph as DM

Python
Python page 20

DM.ClearResults()
print('Python: ',sys.version)
print('Numpy : ',np.version.full_version)
print('Python path:',DM.GetPYTHONPATH())

Example 3: Output DM help


'''
Output Python commands of DigitalMicrograph.
Output command specific help.
'''
import DigitalMicrograph as DM
DM.ClearResults() # Clear Output window text

# Reflective output of directory


print( 'Content of "{0}":'.format(DM.__name__) )
for Entry in dir( DM ):
print( Entry )

# Reflective help output for a spcific command


print( '\n\n\n___\n' )
print( help(DM.ClearResults) )

Example 4: Simple dialogs


'''
The input command prompts a simple dialog and returns the entered string.
Some other simple prompted dialogs are provided by the plugin.
'''
import DigitalMicrograph as DM

str = input( 'Please enter some string:' )


print( 'You have entered: ', str )

DM.OkDialog( 'Just press OK to continue' )

bVal = DM.OkCancelDialog( 'Please select ok or cancel' )


print( 'You have pressed: ', bVal )

bVal, num = DM.GetNumber( 'Please enter a number', 123 )


print( 'You have entered: ', num )
print( 'You have pressed: ', bVal )

Images and NumPy arrays

Example 1: Creating DM images and accessing image data


'''
DM images can be created from Numpy arrays.
DM image values can be accessed as Numpy array.

Python
Python page 21

'''
import DigitalMicrograph as DM
import numpy as np

# Create a DM Image from a Numpy Array


# Note that the shape of the array lists the highest dimension first
imgArray = np.array([
[1,2,3,4,5],
[0,0,0,0,0],
[6,7,8,9,10]
])

print( 'Shape of Numpy array:',imgArray.shape )


print( imgArray )

# Create DM image with values of array.


# This creates a new memory array.
# The variable imgArray does not reference the image data array.
img = DM.CreateImage(imgArray)
img.SetName('Test image')
img.ShowImage()

DM.OkDialog('Changing values now')


# Get Numpy array referencing the image data
testImg = img.GetNumArray()

# When assigning new values to the array, care must be taken


# that values of the array are updated and not a new array is
# created and assigned to the variable!

# Invalid options are any of the following


# testImg = 5
# testImg = np.random.choice(20,size=[3,5])

# Valid options are any of the following:


testImg *= 5
testImg[:,:] = np.random.choice(20,size=[3,5])
np.copyto(testImg, np.arange(15).reshape(3,5))

# The values of the image have changed now.


# However, the image display will only change on an update
if ( DM.OkCancelDialog('Update display?') ):
img.UpdateImage()

# All DM image variables need to be explicitly deleted by the script.


# Otherwise, the referenced image can not be removed fully from memory.
del img

Example 2: Accessing and modifying DM images

Python
Python page 22

'''
Demonstration of accessing the two front-most images in GMS
'''
import DigitalMicrograph as DM

#Find the front image, and get the image data as numpy array
image1 = DM.GetFrontImage()
image1_data = image1.GetNumArray()

#Find the next image, and get its image data as numpy array
image2 = image1.FindNextImage()
image2_data = image2.GetNumArray()

# Do something with image... (i.e. invert values)


image1_data = (-1) * image1_data
image2_data = (-1) * image2_data

# Display results in 2 new images


new_image1 = DM.CreateImage(image1_data)
new_image2 = DM.CreateImage(image2_data)
new_image1.ShowImage()
new_image2.ShowImage()

# The same process as above, but all in 3 lines


# This gets us back to the original data
image3 = DM.GetFrontImage()
DM.CreateImage(image3.GetNumArray()*(-1)).ShowImage()
DM.CreateImage(image3.FindNextImage().GetNumArray()*(-1)).ShowImage()

# All DM image variables need to be explicitly deleted by the script.


# Otherwise, the referenced image can not be removed fully from memory.
del image1
del image2
del image3
del new_image1
del new_image2

Example 3: Slicing 3D images


'''
Example of how a plane slice or a spectrum slice of a DM image
is correctly addressed in Python.
This script assume a 3D image is currently front most on the workspace.
'''
import DigitalMicrograph as DM
import numpy as np

dmImg = DM.GetFrontImage() # Get reference to front most image


dmImgData = dmImg.GetNumArray() # Get NumpyArray to image data

Python
Python page 23

# Output dimensional info


nDim = dmImg.GetNumDimensions()
print( 'The front image has ', nDim, ' dimensions.' )
print( 'The Numpy array shape is:', dmImgData.shape)
print( 'DM image dimension sizes are:' )
for d in range(0,nDim) :
print( '\t Dim{} = {}'.format(d,dmImg.GetDimensionSize(d)), sep = 'x')

# Set sub-sections. (Slice in DigitalMicrograph, or View in Python)


if ( nDim == 3 ):
print( '\nSet the 2nd plane to zero.' )
dmImgData[1,:,:] = 0

print( 'Set the "spectrum" at x=1 y=2 to 10' )


dmImgData[:,2,1] = 10
dmImg.UpdateImage()

del dmImg # Always explicitly delete Py_Image variables

Example 4: Extracting a spectrum


'''
Access a single spectrum from a 3D STEM SI in DigitalMicrograph.
This script assume a 3D image is front most on the workspace.
'''
import DigitalMicrograph as DM
import numpy as np

dmImg = DM.GetFrontImage() # Get reference to front most image


dmImgData = dmImg.GetNumArray() # Get NumpyArray to image data
del dmImg # Always explicitly delete Py_Image variables when no longer needed

# Prompt the user for positions


ok, xPos = DM.GetNumber( 'Enter X coordinate to extract spectrum from.', 0 )
ok, yPos = DM.GetNumber( 'Enter Y coordinate to extract spectrum from.', 0 )

# Address spectrum data.


# View indices have to be integers, so convert
# Also note, that the numpy array is of shape (Z,Y,X)
spectrum = dmImgData[:,int(yPos),int(xPos)]

# Show as separate DM image


# We can not create images from VIEWS so we need to copy first
DM.CreateImage(spectrum.copy(order='C')).ShowImage()

Example 5: Counting negative valued pixels


'''
Count number of negative pixels in the front image
'''
import DigitalMicrograph as DM

Python
Python page 24

import numpy as np

#Get front image and image data as numpy array


img_data = DM.GetFrontImage().GetNumArray()

#Count number of negative and total pixels


num_negative = np.sum(np.where(img_data < 0, 1, 0))
num_total = np.prod(img_data.shape)

#Print result to output window after clearing its content


DM.ClearResults()
print( 'Number of Negative Pixels: %s out of %s total' %(num_negative, num_tota

Example 6: Create intensity-threshold masked image


'''
Create intensity-threshold masked version of front-most image
'''
import DigitalMicrograph as DM
import numpy as np

#Get front image and image data as numpy array


img = DM.GetFrontImage()
img_data = img.GetNumArray()

#Create mask based on image mean


mask_data = np.where(img_data > np.mean(img_data), 1, 0)
mask_img = DM.CreateImage(mask_data)

#Name and display mask image


mask_img.SetName("Binary mask for " + img.GetName())
mask_img.ShowImage()

#Create, Name, and Display masked image


img_masked = DM.CreateImage(np.where(mask_data, img_data, 0))
img_masked.SetName(img.GetName() + " masked")
img_masked.ShowImage()

#Delete Py_Images variables


del img
del mask_img
del img_masked

Example 7: Create circularly masked image


'''
Create circularly masked version of front-most image
'''
import DigitalMicrograph as DM
import numpy as np

Python
Python page 25

def create_circular_mask(h, w, center=None, radius=None):


'''
Create a circular mask of given extension with optionally defined center an
'''
if center is None: # use the middle of the image
center = [int(w/2), int(h/2)]
if radius is None: # use the smallest distance between the center and image
radius = min(center[0], center[1], w-center[0], h-center[1])

Y, X = np.ogrid[:h, :w]
dist_from_center = np.sqrt((X - center[0])**2 + (Y-center[1])**2)

mask = dist_from_center <= radius


return mask.astype('int')

#Set Radius as fraction of the image size (from center to the nearest edge)
RADIUS_FRACTION = .5

#Set the center of the circle as (x,y).


#If CENTER = None, the center of the image is used
CENTER = (300,800)
CENTER = None

#Get front image and image data as numpy array


img = DM.GetFrontImage()
img_data = img.GetNumArray()

#Get image dimensions


w = img_data.shape[1]
h = img_data.shape[0]
min_dim = min(w,h)
rad = RADIUS_FRACTION * min_dim/2

#Create mask based on image mean


mask_data = create_circular_mask(h, w, center=CENTER, radius=rad)
mask_img = DM.CreateImage(mask_data)

#Name and display mask image


mask_img.SetName("Binary mask for " + img.GetName())
mask_img.ShowImage()

#Create, Name, and Display masked image


img_masked = DM.CreateImage(np.where(mask_data, img_data, 0))
img_masked.SetName(img.GetName() + " masked")
img_masked.ShowImage()

#Delete Py_Images variables


del img
del mask_img

Python
Python page 26

del img_masked

Example 8: Find image by ID - chronological search


'''
Example use of FindImage by ID. This script gets the chronologically last image
It works, because image IDs are incremented whenever new memory is allocated.
'''
import DigitalMicrograph as DM

maxID = 10000 # Start with ID value exceeding current maximum


img = None

# Get an image and check if it exists.


# Otherwise reduce ID
while ( maxID > 0 and ( img is None )) :
img = DM.FindImageByID( maxID )
maxID = maxID - 1

if ( img is None ):
print( 'No image was found' )
else:
img.ShowImage()
img.SetName( 'Found image!' )

del img # Always explicitly delete Py_Image variables

Example 9: Find image by name


'''
Example use of FindImage by name.
'''
import DigitalMicrograph as DM

searchName = 'untitled' # Use any exact name here


img = DM.FindImageByName( searchName )

if ( img is None ):
print( 'No image "', searchName, '" was found' )
else:
img.ShowImage()
img.SetName( 'Found image!' )

del img # Always explicitly delete Py_Image variables

Example 10: Find image by label (image-letter)


'''
Example use of FindImage by label. The label is the image letter shown in the w
'''

Python
Python page 27

import DigitalMicrograph as DM

searchStr = 'B' # the label is not case-sensitive


img = DM.FindImageByLabel( searchStr )

if ( img is None ):
print( 'No image [', searchStr, '] was found' )
else:
img.ShowImage()
img.SetName( 'Found image!' )

del img # Always explicitly delete Py_Image variables

ImageDisplays
Example 1: Adding annotations to an imageDisplay
'''
Example of adding annotation components to an ImageDisplay.
The script uses the front-most displayed image. If none is
found, it creates and displays one.
'''
import DigitalMicrograph as DM
import numpy as np

testImg = 0
if ( 0<DM.CountImageDocuments() ):
testImg = DM.GetFrontImage()
else:
testImg = DM.CreateImage( np.arange(120000).reshape(300, 400).copy() )
testImg.ShowImage()

sx = testImg.GetDimensionSize(0)
sy = testImg.GetDimensionSize(1)
img_disp = testImg.GetImageDisplay(0)

img_disp.AddNewComponent( 2, sy*3/9, sx*1/5, sy*3/9, sx*4/5) # line


img_disp.AddNewComponent( 3, sy*4/9, sx*1/5, sy*5/9, sx*4/5) # arrow
img_disp.AddNewComponent( 4, sy*6/9, sx*1/5, sy*6/9, sx*4/5) # double arrow
img_disp.AddNewComponent( 5, sy*1/9, sx*1/9, sy*8/9, sx*8/9) # box
img_disp.AddNewComponent( 6, sy*1/9, sx*1/9, sy*8/9, sx*8/9) # oval
img_disp.AddNewComponent(33, sy*1/9, sx*8/9, sy*9/9, sx*9/9) # intensity bar

# Cleanup
del img_disp
del testImg

Example 2: Set all annotations to one color

Python
Python page 28

'''
This script sets the drawing properties of all annotations
on the front-most displayed image.
'''
import DigitalMicrograph as DM

if ( 0 == DM.CountImageDocuments() ):
exit()

testImg = DM.GetFrontImage()
img_disp = testImg.GetImageDisplay(0)

nSubComp = img_disp.CountChildren()
for index in range(nSubComp):
comp = img_disp.GetChild(index)
comp.SetForegroundColor(0,1,0) # green
comp.SetBackgroundColor(0.2,0.2,0.5)# dark blue
comp.SetFillMode(2) # not filled
comp.SetDrawingMode(1) # with outline

# Cleanup
del img_disp
del testImg

TagGroups (Meta Data)

Example 1: Reading image tags


'''
Example of reading tags from images.
'''
import DigitalMicrograph as DM

tagPath = 'Meta Data:Format'


frontImageTags = DM.GetFrontImage().GetTagGroup()
success, val = frontImageTags.GetTagAsString(tagPath)
if ( success ):
print( 'The tag [',tagPath,'] has the value: ', val, sep="" )
else:
print( 'The tag [',tagPath,'] was not found or not of valid type.', sep="

Example 2: Writing image tags


'''
Example of writing tags to images.
Here tags are created, but the set commands can also be used
to overwrite already existing tags.
'''
import DigitalMicrograph as DM
import numpy as np

Python
Python page 29

# Create a simple 16 x 16 image, then name and show it


testImg = DM.CreateImage( np.arange( 256 ).reshape( 16, 16 ).copy() )
testImg.SetName( 'Tagging test' )
testImg.ShowImage()

# Get the images taggroup (root level)


imgTG = testImg.GetTagGroup()

# Write various meta data (tags) of different types


imgTG.SetTagAsString( 'Python Tags:String','Some Text' )
imgTG.SetTagAsBoolean( 'Python Tags:Bool', True )
imgTG.SetTagAsShort( 'Python Tags:Numbers:Short', 235 )
imgTG.SetTagAsLong( 'Python Tags:Numbers:Long', 12 )
imgTG.SetTagAsFloat( 'Python Tags:Numbers:Float', 1.2 )
imgTG.SetTagAsDouble( 'Python Tags:Numbers:Double', 1.3 )
imgTG.SetTagAsUInt16( 'Python Tags:Numbers:UInt16', 13 )
imgTG.SetTagAsUInt32( 'Python Tags:Numbers:UInt16', 15 )

# Creating a new TagGroup and adding it


groupTG = DM.NewTagGroup()
groupTG.SetTagAsString( 'Some string', 'Hello' )
groupTG.SetTagAsLong( 'Some number', 100 )
imgTG.SetTagAsTagGroup( 'Python Tags:TagGroup', groupTG )

# Creating a new TagList and adding it


listTG = DM.NewTagList()
for i in range(0,5) :
entryTG = DM.NewTagGroup()
entryTG.SetTagAsBoolean( 'Check flag', True )
entryTG.SetTagAsLong( 'index squared', i*i )
listTG.AddTagGroupAtEnd( entryTG )

imgTG.SetTagAsTagGroup( 'Python Tags:TagList', listTG )

print( 'Tags have been added to the image as can be seen in the image display'

# Always remove image variables explicitly


del testImg

Example 3: Reading global preferences tags


'''
Example of reading tags from the global preferences.
Here we read the setting for the currently chosen GMS Python.
'''
import DigitalMicrograph as DM

tagPath = 'Private:Python:Python Path'


globalTags = DM.GetPersistentTagGroup()

Python
Python page 30

success, val = globalTags.GetTagAsString(tagPath)


if ( success ):
print( 'The tag [',tagPath,'] has the value: ', val, sep="" )
else:
print( 'The tag [',tagPath,'] was not found or not of valid type.', sep="

Example 4: Copying image tags and calibrations


'''
Copy image calibrations and tags from one image to another
'''
import DigitalMicrograph as DM

def Calibration_Copy(image_source, image_dest):


'''
Copy dimension and intensity calibration between source and destination.
On mismatch of number of dimension, prompt user and return.
'''
#Count and check that number of dimensions match
num_dim_s = image_source.GetNumDimensions()
num_dim_d = image_dest.GetNumDimensions()
if num_dim_d != num_dim_s:
DM.OkDialog('Images do not have same number of dimensions!')
return

#Copy Dimension Calibrations


origin = [0 for _ in range(num_dim_s)]
scale = origin
power = origin
unit = ["" for _ in range(num_dim_s)]
unit2 = unit
for i in range(num_dim_s):
origin[i], scale[i], unit[i] = image_source.GetDimensionCalibratio
image_dest.SetDimensionCalibration(i,origin[i],scale[i],unit[i],0)
unit2[i], power[i] = image_source.GetDimensionUnitInfo(i)
image_dest.SetDimensionUnitInfo(i,unit2[i],power[i])

#Copy Intensity Calibrations


i_scale = image_source.GetIntensityScale()
i_unit = image_source.GetIntensityUnitString()
i_origin = image_source.GetIntensityOrigin()
image_dest.SetIntensityScale(i_scale)
image_dest.SetIntensityUnitString(i_unit)
image_dest.SetIntensityOrigin(i_origin)

def Tag_Copy(image_source, image_dest, subPath = None ):


'''
Copy all tags between source and destination.

Python
Python page 31

If no destination subPath is provided, the destination tags will be repla


'''
#Copy Tags
tg_source = image_source.GetTagGroup()
tg_dest = image_dest.GetTagGroup()
if ( subPath != None ):
tg_dest.SetTagAsTagGroup(subPath,tg_source.Clone())
else:
tg_dest.DeleteAllTags()
tg_dest.CopyTagsFrom(tg_source.Clone())

#Get Front 2 Images


image_source = DM.GetFrontImage()
image_dest = image_source.FindNextImage()

#Call the function to copy everything


Calibration_Copy(image_source, image_dest)
Tag_Copy(image_source, image_dest )#, 'Copied over' )
print("Calibrations and Tags Copied")

#Delete Py_Image variables to avoid memory leakage


del image_source
del image_dest

Hardware access

Example 1: DigiScan acquisition


'''
Example script staring a simple DigiScan acquisition via a parameter set.
Fore more details on DigiScan access via scripting also refer to the
DM-scripting documentation.
'''
import DigitalMicrograph as DM
import numpy as np

# Create Acquisition Parameter set


rotation = 0
size = 512
pixelTime = 10
lineSync = False
paramID = DM.DS_CreateParameters( size, size, rotation, pixelTime, lineSync )

# Add to be acquired signals


# Variant 1: Let DM create the destination image
signalIndex = 0 # 1st assigned STEM Detector. Usually HAADF
selectSignal = True
dataByte = 4

Python
Python page 32

useImgID = 0

DM.DS_SetParametersSignal( paramID, signalIndex, dataByte, selectSignal, useImg

# Variant 2: Provide a suitable data container (size and type must match)
signalIndex = 1 # 2nd assigned STEM Detector
selectSignal = True
dataByte = 4
array = np.zeros(shape=(size,size),dtype='uint32')
dmImg = DM.CreateImage( array )
dmImg.ShowImage()
useImgID = dmImg.GetID()
dmImg.SetName( "Provided image" )
del dmImg # Always delete image variables again when no longer needed

DM.DS_SetParametersSignal( paramID, signalIndex, dataByte, selectSignal, useImg

# Run acquisition, temporarily disable UI


continuous = False
synchronous = True

DM.DS_DialogEnabled( False )
DM.DS_StartAcquisition_2( paramID, continuous, synchronous )
DM.DS_DialogEnabled( True )

# Remove Parameter set from memory again


DM.DS_DeleteParameters( paramID )

Example 2: Camera acquisitions


'''
Example script showing different types of camara acquisition.
'''
import DigitalMicrograph as DM
import numpy as np
# Get the current camera and ensure it is ready for acquisition
cam = DM.GetActiveCamera()
cam.PrepareForAcquire()

# Simpe single read-out acquisition


DM.OkDialog( 'Showing simple single acquire.' )
exposure = 0.1
bin = 1
kUnproc = DM.GetCameraUnprocessedEnum()
cam.AcquireImage( exposure, bin, bin, kUnproc ).ShowImage()

# In-place single read-out acquisition


DM.OkDialog( 'Showing single in-place acquire.' )
preImg = cam.CreateImageForAcquire( bin, bin, kUnproc )
preImg.SetName( "Pre-created image container" )

Python
Python page 33

preImg.ShowImage()
DM.OkDialog( 'Image created, now acquire...' )
cam.AcquireInPlace( preImg, exposure, bin, bin, kUnproc )
del preImg # Always delete Py_Image variables again

# Continuous acquistion example


DM.OkDialog( 'Showing continuous acquisition. 20 frames' )
dstImage = cam.CreateImageForAcquire( bin, bin, kUnproc )
dstImage.SetName( "Container" )
dstImage.ShowImage()
cam.StartContinuousAcquisition( exposure, bin, bin, kUnproc )

nFrames = 20 # Number of readouts until script stops


max_wait_s = 5 # time out after 5 sec.
for i in range(0,nFrames):
if ( cam.GetFrameInContinuousMode( dstImage, max_wait_s ) ):
print( 'Got frame #', i )
dstImage.UpdateImage() # Force display update
else:
print( 'Time-out' )

cam.StopContinuousAcquisition( )
del dstImage # Always delete Py_Image variables again

print( 'All done now.' )

Example 3: Microscope control


'''
Example script basic microscope access.
For further info please also refer to the DM-scripting documentation
on Microscope access.
'''
import DigitalMicrograph as DM

mic = DM.Py_Microscope()

# Ouptut some microscope parameters


print( 'Brightness:', mic.GetBrightness() )
print( 'Focus:', mic.GetFocus() )
print( 'Condenser aperture:', mic.GetCondenserAperture() )

# Set microscope focus


mic.SetFocus( 30 )
print( 'Focus (changed):', mic.GetFocus() )

Application examples

Example 1: NMF decomposition of STEM SI data using scikit-learn

Python
Python page 34

'''
This example requires the scikit-learn packages to be installed.
The script assumes a STEM SI image is front most on the workspace.
This is a 3D image which contains spectral data along the z-dimension
for individual points of the xy-array. Typically, this will be an
EELS or EDS data set.
The example performs NMF decomposition on the data, trying to find a
set of non-negative components which can represent the data by linear
combination.
'''
import DigitalMicrograph as DM
import numpy as np
import sys
import joblib
import scipy
import sklearn

# Output some version info for verification


# of a suitable package installation.
DM.ClearResults()
print( 'Python : ', sys.version )
print( 'Numpy : ', np.version.full_version )
print( 'joblib : ', joblib.__version__ )
print( 'SciPy : ', scipy.__version__ )
print( 'scikit-learn : ', sklearn.__version__ )

# Get data array of front most image


SIdata = DM.GetFrontImage().GetNumArray()
nChannels = SIdata.shape[0]
nPoints = SIdata.shape[1] * SIdata.shape[2]

# NMF can only deal with non-negative data.


# If needed, offset data to positive values
if ( SIdata.min() < 0 ):
print( 'Shifting data values to be non-negative.(Copy data)' )
SIdata = SIdata.copy() - SIdata.min()

# Reshape the array for apropriate format


# data to be decomposed has to be of shape (n_components, n_features)
data = SIdata.reshape( nChannels, nPoints ).transpose()

# Ask for how many components should be found (Integer value)


OK, wanted_components = DM.GetNumber( 'How many componnets?', 2 )
wanted_components = int( wanted_components )

# Do the NMF
from sklearn.decomposition import NMF
estimator = NMF(n_components=wanted_components, init='nndsvd', tol=5e-3)
estimator.fit( data )

Python
Python page 35

# Put the result into a DM image "stack"


cArr = estimator.components_
asStack = ( cArr.shape[0], 1, cArr.shape[1] )
resultStack = DM.CreateImage( cArr.reshape( asStack ).copy() )
resultStack.SetName("NMF components")
resultStack.ShowImage()

# Always remove image variables


del resultStack

Example 2: Using Matplotlib examples


'''
Examples of using the matplotlib library from within DigitalMicrograph.
Note that any such script MUST NOT be run on the background thread.
The sys-argv extension line is also essential.
This examples implements some example code from https://matplotlib.org/gallery
The script rquires the matplotlib package to be installed.
'''
import numpy as np
import sys
sys.argv.extend(['-a', ' '])
import matplotlib.pyplot as plt

# Safety-check: Ensure this is called on the main-thread of GMS


if ( False == DM.IsScriptOnMainThread() ):
print( ' MatplotLib scripts require to be run on the main thread.' )
exit()

def SharedAxisDemo():
"""
Shared Axis Demo
https://matplotlib.org/gallery/subplots_axes_and_figures/shared_axis_demo
"""

t = np.arange(0.01, 5.0, 0.01)


s1 = np.sin(2 * np.pi * t)
s2 = np.exp(-t)
s3 = np.sin(4 * np.pi * t)

ax1 = plt.subplot(311)
plt.plot(t, s1)
plt.setp(ax1.get_xticklabels(), fontsize=6)

# share x only
ax2 = plt.subplot(312, sharex=ax1)
plt.plot(t, s2)

# make these tick labels invisible

Python
Python page 36

plt.setp(ax2.get_xticklabels(), visible=False)

# share x and y
ax3 = plt.subplot(313, sharex=ax1, sharey=ax1)
plt.plot(t, s3)
plt.xlim(0.01, 5.0)
plt.show()

def ScatterPlotWithHistogramDemo():
"""
Scatter plot with histograms
https://matplotlib.org/gallery/lines_bars_and_markers/scatter_hist.html
"""
# the random data
x = np.random.randn(1000)
y = np.random.randn(1000)

# definitions for the axes


left, width = 0.1, 0.65
bottom, height = 0.1, 0.65
spacing = 0.005

rect_scatter = [left, bottom, width, height]


rect_histx = [left, bottom + height + spacing, width, 0.2]
rect_histy = [left + width + spacing, bottom, 0.2, height]

# start with a rectangular Figure


plt.figure(figsize=(8, 8))

ax_scatter = plt.axes(rect_scatter)
ax_scatter.tick_params(direction='in', top=True, right=True)
ax_histx = plt.axes(rect_histx)
ax_histx.tick_params(direction='in', labelbottom=False)
ax_histy = plt.axes(rect_histy)
ax_histy.tick_params(direction='in', labelleft=False)

# the scatter plot:


ax_scatter.scatter(x, y)

# now determine nice limits by hand:


binwidth = 0.25
lim = np.ceil(np.abs([x, y]).max() / binwidth) * binwidth
ax_scatter.set_xlim((-lim, lim))
ax_scatter.set_ylim((-lim, lim))

bins = np.arange(-lim, lim + binwidth, binwidth)


ax_histx.hist(x, bins=bins)
ax_histy.hist(y, bins=bins, orientation='horizontal')

Python
Python page 37

ax_histx.set_xlim(ax_scatter.get_xlim())
ax_histy.set_ylim(ax_scatter.get_ylim())

plt.show()

def ContourDemo():
"""
Contour Demo
https://matplotlib.org/gallery/images_contours_and_fields/contour_demo.ht
"""
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
fig, ax = plt.subplots()
CS = ax.contour(X, Y, Z)
ax.clabel(CS, inline=1, fontsize=10)
ax.set_title('Simplest default with labels')

plt.show()

SharedAxisDemo()
ScatterPlotWithHistogramDemo()
ContourDemo()

Example 3: Matplotlib plot as DM image


'''
Examples of using the matplotlib library from within DigitalMicrograph
and display created figures as greyscale DigitalMicrograph image.
Note that any such script MUST NOT be run on the background thread.
The script requires the matplotlib package to be installed.
To get plots as RGB color images in DigitalMicrograph, see the extended
example in the Hybrid Scripting examples section
'''
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.argv.extend(['-a', ' ']) # Required for Matplotlib to work

# Safety-check: Ensure this is called on the main-thread of GMS


if ( False == DM.IsScriptOnMainThread() ):
print( ' MatplotLib scripts require to be run on the main thread.' )
exit()

# Create any plot image

Python
Python page 38

fig1, ax1 = plt.subplots(figsize=(4, 4))


labels = 'Apple', 'Banana', 'Cherries'
values = [10.0, 20.0, 15.2]
ax1.pie(values, labels=labels, startangle=90)
ax1.axis('equal')
fig1.tight_layout()
ax1.grid(True)

# Don't show it, but render the canvas


# Then get the rendering as numpy array
fig1.canvas.draw()
X = np.array(fig1.canvas.renderer._renderer)

# The array is (Y,X,C) with C being the color channel


# Get individual colors
R = X[:,:,0]
G = X[:,:,1]
B = X[:,:,2]

# DM Python does not support RGB image creation yet


# Convert this to a greyscale image simple array
Mono = 0.2989*R + 0.5870*G + 0.1140*B

# Show as DM image
DM.CreateImage( Mono ).ShowImage()

Example 4: Creating a Spiral Galaxy image (uses SciPy)


'''
Demonstarte creation of a new image in GMS with script-generated data.
The script requires the SciPy package to be additionally installed.
Creates an image of a Spiral Galaxy.
'''
import DigitalMicrograph as DM
import numpy as np
from scipy import signal

#Specify User-Set Parameters (500, 1024, 4) are recommended for first try
#Larger values for any of these parameters will increase the time required
NUM_STARS_PER_ARM = 500
IMAGE_SIZE = 1024
KERN_SIZE = 4

#Calculate all star positions


n = NUM_STARS_PER_ARM
b = 0.6
th = np.random.randn(n)
x = np.exp(b*th)*np.cos(th)
y = np.exp(b*th)*np.sin(th)
x1 = np.exp(b*(th))*np.cos(th+np.pi)

Python
Python page 39

y1 = np.exp(b*(th))*np.sin(th+np.pi)
sx = np.random.normal(0, 0.25, n)
sy = np.random.normal(0, 0.25, n)
xc = np.concatenate(((x+sy),(x1+sx)))
yc = np.concatenate(((y+sx),(y1+sy)))
dmax = 1.01*max(max(np.abs(xc)),max(np.abs(yc)))

#Create an exponential kernal used to produce intensity gradient around each st


def create_exp_kernel(size):
x = np.arange(-size, size)
y = np.arange(-size, size)
xx, yy = np.meshgrid(x, y)
r = np.sqrt(xx**2+yy**2)
return(np.exp(-2*r))

#Initialize images before starting for-loop


sx = IMAGE_SIZE
kern = create_exp_kernel(KERN_SIZE)
blank_image = np.zeros((sx,sx))
image_data = np.copy(blank_image)
pointimage = np.copy(blank_image)

#Loop over each star


for star in range(len(xc)):
#add star position as single pixel
px = int(np.fix(xc[star]/dmax*sx/2)+sx//2)
py = int(np.fix(yc[star]/dmax*sx/2)+sx//2)
pointimage[px,py] = 1
#once every 50 stars, convolve the single-pixel image with the kernel
#to generate a single image frame and add this to the final image_data ar
if star % 50 == 0:
image_data += signal.convolve2d(pointimage, kern, mode='same')
#reset the single-pixel image so it is blank again
pointimage = np.copy(blank_image)
#print progress to the Output Window in GMS
print('Processed %s points' %star)

DM.CreateImage(image_data).ShowImage()

Hybrid scripts (Mixed Python and DM-scripts)

Example 1: Hybrid Test - Python calls DM ShowAlert


'''
Hybrid script example. This Python script builds and runs
a DigitalMicrograph script.
'''
import DigitalMicrograph as DM

Python
Python page 40

# We need to build the DM script as a string including line breaks


# DM scripts uses only " to denote strings. Python can use either " or '.
# We can utilize this to the advantage by strictly using ' for Python.
dmScript = '// This is a DM script' + '\n'
dmScript += 'ShowAlert( "This is an error", 0 )' + '\n'
dmScript += 'ShowAlert( "This is a warning", 1 )' + '\n'
dmScript += 'ShowAlert( "This is information", 2 )' + '\n'
dmScript += 'ShowAlert( "This is a question", 3 )' + '\n'

# We output the script for info


DM.ClearResults()
print( 'We are calling the following DM script:' )
print( dmScript )

# Execute DM script
DM.ExecuteScriptString( dmScript )

# Continue Python script once DM script finishes


print( 'We are done with the DM script. Python resumes.' )

Example 2: Create and show RGB images


'''
This script creates 3 images in Python and utilizes a DM-script
to create and show a color-overlay image. It is an example for
how Hybrid scripts can be used to access functionality not (yet)
available in the Python language directly. The script shows how
image-labels can be used to address images across the two scripts.
'''
import DigitalMicrograph as DM
import numpy as np

# Create 3D DM-Images from Python Numpy arrays


DMImg1 = DM.CreateImage( np.arange(50,150).reshape(10,10).copy() )
DMImg2 = DM.CreateImage( np.arange(150,50,-1).reshape(10,10).copy() )
DMImg3 = DM.CreateImage( np.random.choice(150,size=(10,10)).copy() )

# Optionally display the sub-images


show = False
if ( show ):
DMImg1.ShowImage()
DMImg2.ShowImage()
DMImg3.ShowImage()

# Build DM-script to create RGB image from these


# We can use the image-labels as reference.
DMScript = '// This is a DM script' + '\n'
DMScript += 'RGBImage col := RGB('
DMScript += DMImg1.GetLabel() + ','
DMScript += DMImg2.GetLabel() + ','

Python
Python page 41

DMScript += DMImg3.GetLabel() + ')' + '\n'


DMScript += 'col.ShowImage()'

# Optionally show DM script in new window


showScript = False
if ( showScript ):
DM.ClearResults()
print( 'The following DM script will be executed:\n\n' )
print( DMScript, '\n\n' )

# Run the DM script


DM.ExecuteScriptString( DMScript )

# Always delete DMImage variables when no longer needed


# Note that they are needed during DM script execution
# as they ensure the images are kept in memory even if
# not displayed on the workspace.
del DMImg1
del DMImg2
del DMImg3

Example 3: DM SCRIPT - Performing NMF via Python and Scikit-learn


// THIS IS A DM-SCRIPT NOT A PYTHON SCRIPT!!
// ///////////////////////////////////////////////////
// It requires the Python plugin to be installed
// as well as the scikit-learn package being added.
// The script perform NMF decomposition on a provided
// 3D image (STEM SI) data.
// ///////////////////////////////////////////////////
Image PerformNMFonSI( image StemSI, number nComp )
{
if ( 3 != StemSI.ImageGetNumDimensions() )
Throw( "The front image is not a 3D STEM SI." )

if ( min( StemSI ) < 0 )


Throw( "The SI data contains negative values. Non-negative factoriz

number id = StemSI.ImageGetID()
number nCh = StemSI.ImageGetDimensionSize(2)
number nPts = StemSI.ImageGetDimensionSize(0) * StemSI.ImageGetDimensionS

if ( nComp > nCh )


Throw( "Can not have more components than spectral channels." )

// Build Python-script
string pyScript = "# This is a Python script"
pyScript += "import numpy as np" + "\n"
pyScript += "import sklearn" + "\n"
pyScript += "from sklearn.decomposition import NMF" + "\n"

Python
Python page 42

pyScript += "data = DM.FindImageByID(" + id + ").GetNumArray().reshape("


pyScript += "nComp = " + nComp + "\n"
pyScript += "estimator = NMF( n_components=nComp, init='nndsvda', tol=5e-
pyScript += "estimator.fit( data )" + "\n"
pyScript += "cArr = estimator.components_" + "\n"
pyScript += "asStack = ( cArr.shape[0], 1, cArr.shape[1] )" + "\n"
pyScript += "resultStack = DM.CreateImage( cArr.reshape( asStack ).copy()
pyScript += "resultStack.ShowImage()" + "\n"
pyScript += "del resultStack " + "\n"

// Run PythonScript ( on main thread, synchronous )


ExecutePythonScriptString( pyScript, 1 )

// Continue with DM-script after results have been created and shown by P
image compStack := GetFrontImage()
compStack.SetName( "NMF components of '" + StemSI.ImageGetName() + "'" )

return compStack
}

Image front := GetFrontImage()


Number nComp
if ( !GetNumber( "How many componnets?", 2, nComp ) ) Exit( 0 )
PerformNMFonSI( front, nComp )

Example 3: Matplotlib plot as color DM image


'''
Examples of using the matplotlib library from within DigitalMicrograph
and display created figures as DigitalMicrograph image.
Note that any such script MUST NOT be run on the background thread.
The script requires the matplotlib package to be installed.
'''
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.argv.extend(['-a', ' ']) # Required for Matplotlib to work

# Safety-check: Ensure this is called on the main-thread of GMS


if ( False == DM.IsScriptOnMainThread() ):
print( ' MatplotLib scripts require to be run on the main thread.' )
exit()

# Create any plot image


fig1, ax1 = plt.subplots(figsize=(4, 4))
labels = 'Apple', 'Banana', 'Cherries'
values = [10.0, 20.0, 15.2]
ax1.pie(values, labels=labels, startangle=90)
ax1.axis('equal')
fig1.tight_layout()

Python
Python page 43

ax1.grid(True)

# Don't show it, but render the canvas


# Then get the rendering as numpy array
fig1.canvas.draw()
X = np.array(fig1.canvas.renderer._renderer)

# The array is (Y,X,C) with C being the color channel


# DM Python does not support RGB image creation, so use
# a DM-script for this functionality

# Create DM images for each color


r_ = DM.CreateImage(X[:,:,0].copy())
g_ = DM.CreateImage(X[:,:,1].copy())
b_ = DM.CreateImage(X[:,:,2].copy())

# Build one-liner DM-script to show RGB image


dms = 'rgb(' + r_.GetLabel() + ',' + g_.GetLabel() + ',' + b_.GetLabel() + ').S
DM.ExecuteScriptString(dms)

# Always delete Py_Image references in the script


del r_
del g_
del b_

1.4 Reference

Reference
From Python scripting you can access the major classes of objects in DigitalMicrograph and control
the Camera or a DigiScan. You can also communicate with the microscope.

The DigitalMicrograph namespace contains general functions as well as functions that create and
provide access to instances of the classes. The individual classes provide access to the properties
and behavior of the objects they represent.

namespace DigitalMicrograph

class Py_Window
class Py_ImageDocument
class Py_Image

Python
Python page 44

class Py_Component
class Py_ImageDisplay
class Py_LinePlotImageDisplay
class Py_ROI

class Py_ScriptObject
class Py_TagGroup

class Py_Camera
class Py_Microscope

Python
Index page 45

Index
I
ImageDisplays 27

Python

You might also like