Getting Started

Here we will discuss how to use the package and how to get started with it. We will lateron also discuss additional features ant tricks to get the most out of the package.

Installation:

The package can be installed via pip:

pip install snom-analysis

Alternatively, you can clone the repository and install the package manually from github https://github.com/Hajo376/SNOM_AFM_analysis/. If you install via pip all dependencies will be installed automatically. I recommend to use a virtual environment.

How to use:

First of all install the package either from PyPi or by using a wheel from the dist folder from the github page. You can also clone the repository and use it as is or create your own wheel by running pyhton -m build. I would always recommend to use a virtual environment to install the package and use the wheel.

Then try out the example script which should be somewhere in the repository. (#todo) You can also just use the script as a loader and do whatever you want in between. The data is just stored as a list of np.array in the instance.all_data variable, the channel names are in a correlated list instance.channels. Additional information is in the two dictionaries instance.measurement_tag_dict and instance.channels_tag_dict. These are just dictionaries containing the parameters from the parameters.txt file (measurement_tag_dict) and the individual headers from the .gsf files (channels_tag_dict). Note that the channels_tag_dict is also a list correlated with instance.channels. This gives you a lot of freedome to implement your own functionality.

Anyways, here are a few short examples of how to use the package.

Simple usage example using the SnomMeasurement class:

This is a very simple example using just some base functions without any extra parameters.

 1# Load the main functionality from the package, in this case the SnomMeasurement class.
 2from snom_analysis.main import SnomMeasurement
 3
 4# Create an instance of the SnomMeasurement class by providing the path to the measurement folder.
 5measurement = SnomMeasurement('path/to/your/measurement/folder')
 6
 7# Now you can access the data and the functions of the measurement instance.
 8# For example you can plot the data by calling the plot function.
 9# If you don't specify any arguments all channels will be plotted.
10measurement.display_channels()
11
12# You can also apply some modifications to the data, for example you can crop the data.
13# If you don't specify any arguments you will be asked to provide the cropping range using
14# some default channel and the crop will be applied to all channels.
15measurement.cut_channels()
16
17# You can also blurr the data using a gaussian filter.
18# If you want to blurr phase data you will need to have
19# the phase and amplitude channels of the same demodulation in memory.
20measurement.gauss_filter_channels_complex()
21
22# You can use a simple 3 point correction to level the height data.
23# For better leveling you can always use some other software
24# like Gwyddion and import already leveled data.
25measurement.level_height_channels_3point()
26
27# I always like to set the minimum of the height channel to zero.
28# This should be applied after the leveling. Otherwise the leveling will also change the minimum.
29measurement.set_min_to_zero(['Z C'])
30
31# Now you can plot the data again to see the modifications.
32measurement.display_channels()
33
34# You can also compare the data before and after the modifications.
35measurement.display_all_subplots()
36
37# If you are happy with the modifications you can save the data.
38# This will save the data to a new .gsf file in the measurement folder.
39measurement.save_to_gsf()
40# Per default the '_manipulated' suffix will be added to the filename,
41# to ensure you don't overwrite the original data.

More advanced usage example using the SnomMeasurement class:

This is an example using the tkinter filedialog and some more advanced fuctions.

 1# Import filedialog to open a file dialog to select the measurement folder.
 2from tkinter import filedialog
 3
 4# Load the main functionality from the package, in this case the SnomMeasurement class.
 5from snom_analysis.main import SnomMeasurement
 6
 7# Open a file dialog to select the measurement folder.
 8directory = filedialog.askdirectory()
 9
10# It is always a good idea to select the channels you want to use before loading the data.
11channels = ['O2P', 'O2A', 'Z C']
12
13# Create an instance of the SnomMeasurement class by providing the path to the measurement folder.
14measurement = SnomMeasurement(directory, channels)
15
16# Plot the data without any modifications.
17measurement.display_channels()
18
19# You can also add a scalebar, which will be saved to the plot memory.
20measurement.scalebar(['Z C'])
21
22# for phase data the level_data_columnwise function is not yet working properly,
23# if the phase data is not in the range of 0 to 2pi (drifts more than 2pi)
24# but we can correct a linear drift in the phase data before.
25measurement.correct_phase_drift_nonlinear()
26
27# You can also aplly corrections such as a linear 2 point based y-phase drift correction.
28# measurement.correct_phase_drift()
29# or a nonlinear dift correction, wich takes into account each line and also applies
30# a linear correction in x-direction if both sides are specified
31measurement.level_data_columnwise()
32
33# I always like to set the minimum of the height channel to zero.
34# This should be applied after the drift correction.
35# Otherwise the drift correction will also change the minimum.
36measurement.set_min_to_zero(['Z C'])
37
38# You can shift the phase-offset of the phase channel.
39# Some functions will take additional parameters, if given they will apply directly.
40# If not they will promt the user with a popup window to select the parameters manually.
41measurement.shift_phase()
42# or you can specify the shift directly.
43# measurement.shift_phase(shift=0.3)
44
45# Now you can plot the data.
46measurement.display_channels()
47
48# You can also compare the data before and after the modifications.
49measurement.display_all_subplots()

Example showing how to do a synccorrection of transmission mode measurements:

This is an example using the tkinter filedialog and some more advanced fuctions.

 1# Import filedialog to open a file dialog to select the measurement folder.
 2from tkinter import filedialog
 3
 4# Load the main functionality from the package, in this case the SnomMeasurement class.
 5from snom_analysis.main import SnomMeasurement, PlotDefinitions
 6PlotDefinitions.colorbar_width = 2 # colorbar width for long thin measurements looks too big
 7
 8# Open a file dialog to select the measurement folder.
 9directory = filedialog.askdirectory()
10
11# It is always a good idea to select the channels you want to use before loading the data.
12channels = ['O2P', 'O2A', 'Z C']
13
14# Create an instance of the SnomMeasurement class by providing the path to the measurement folder.
15# If we want to apply the synccorrection we need to set autoscale to False.
16measurement = SnomMeasurement(directory, channels, autoscale=False)
17
18# Plot the data without any modifications.
19measurement.display_channels()
20
21# Apply the synccorrection to the data. But we don't know the direction yet.
22# The interferometer sometimes goes in the wron direction.
23# This will create corrected channels and save them as .gsf with the appendix '_corrected'.
24measurement.synccorrection(1.6)
25
26# We want to display the corrected channels, so we reinitialize the channels with the corrected channels.
27measurement.initialize_channels(['O2P_corrected', 'O2A', 'Z C'])
28
29# Plot the corrected data.
30measurement.display_channels()
31
32# You can also compare the data before and after the modifications.
33measurement.display_all_subplots()

Example showing how to create a gif from the realpart data, useful to visualize traveling waves:

This is a very simple example using just some base functions without any extra parameters.

 1# Import filedialog to open a file dialog to select the measurement folder.
 2from tkinter import filedialog
 3
 4# Load the main functionality from the package, in this case the SnomMeasurement class.
 5from snom_analysis.main import SnomMeasurement, PlotDefinitions
 6PlotDefinitions.colorbar_width = 4 # colorbar width for long thin measurements looks too big
 7
 8# Open a file dialog to select the measurement folder.
 9directory_name = filedialog.askdirectory()
10
11# Create an instance of the SnomMeasurement class by providing the path to the measurement folder.
12# If we want to apply the synccorrection we need to set autoscale to False.
13measurement = SnomMeasurement(directory_name, autoscale=False)
14
15# Plot the data without any modifications.
16measurement.display_channels()
17
18# Apply the synccorrection to the data. But we don't know the direction yet. The interferometer sometimes goes in the wrong direction.
19# This will create corrected channels and save them as .gsf with the appendix '_corrected'.
20# measurement.synccorrection(1.6) # for chiral coupler
21measurement.synccorrection(0.97)
22
23# We want to use the corrected channels, so we reinitialize the channels with the corrected channels.
24measurement.autoscale = True
25measurement.initialize_channels(['O2A', 'O2P_corrected'])
26
27# create a gif of the realpart of the O2A channel and the O2P_corrected channel.
28measurement.create_gif('O2A', 'O2P_corrected', frames=20, fps=10, dpi=100)

Simple usage example using the ApproachCurve class:

This is a very simple example using just some base functions without any extra parameters.

 1# Import filedialog to open a file dialog to select the measurement folder.
 2from tkinter import filedialog
 3
 4# Load the main functionality from the package, in this case the SnomMeasurement class.
 5from snom_analysis.main import ApproachCurve
 6
 7# Open a file dialog to select the measurement folder.
 8directory_name = filedialog.askdirectory()
 9
10# It is always a good idea to select the channels you want to use before loading the data.
11channels = ['M1A', 'O2P', 'O2A']
12
13# Create an instance of the ApproachCurve class by providing the path to the measurement folder.
14measurement = ApproachCurve(directory_name, channels)
15
16# Set the minimum value of the data to zero.
17measurement.set_min_to_zero()
18
19# Display the channels in a plot. And scale each data set to the whole image size.
20measurement.display_channels_v2()
21
22# Alternatively you can use the display_channels() function, which will display the channels in a plot without rescaling.
23measurement.display_channels()

Simple usage example using the Scan3D class:

This is a very simple example using just some base functions to display x-z-cutplanes from the 3D scans.

 1# Import filedialog to open a file dialog to select the measurement folder.
 2from tkinter import filedialog
 3
 4# Load the main functionality from the package, in this case the SnomMeasurement class.
 5from snom_analysis.main import Scan3D
 6
 7# Open a file dialog to select the measurement folder.
 8directory = filedialog.askdirectory()
 9
10# It is always a good idea to select the channels you want to use before loading the data.
11channels = ['O2A', 'O2P', 'O3A', 'O3P', 'Z']
12
13# Create an instance of the Scan3D class by providing the path to the measurement folder.
14measurement = Scan3D(directory, channels)
15
16# Set the minimum value of the data to zero.
17measurement.set_min_to_zero()
18
19# Change the colorbar width to 3 on the fly will apply to all following plots.
20PlotDefinitions.colorbar_width = 3
21
22# Generate all cutplane data for the channels.
23measurement.generate_all_cutplane_data()
24
25# Match the phase offset of the channels O2P and O3P to the reference channel O2P.
26measurement.match_phase_offset(channels=['O2P', 'O3P'], reference_channel='O2P', reference_area='manual', manual_width=3)
27
28# For example display just the first cutplane of the O2P channel. Then display the first cutplane of the O3P channel.
29measurement.display_cutplane_v3(axis='x', line=0, channel='O2P')
30measurement.display_cutplane_v3(axis='x', line=0, channel='O3P')
31
32# Shift the phase of the channels O2P and O3P by an arbitrary amount to make it visually clearer what you want to see.
33measurement.shift_phase()
34
35# Display the first cutplane again with all the changes applied.
36measurement.display_cutplane_v3(axis='x', line=0, channel='O2P')
37measurement.display_cutplane_v3(axis='x', line=0, channel='O3P')
38
39# Display the real part of the first cutplane of the O2 channel and the O3 channel.
40measurement.display_cutplane_v3_realpart(axis='x', line=0, demodulation=2)
41measurement.display_cutplane_v3_realpart(axis='x', line=0, demodulation=3)

Simple usage example using the Scan3D class and averaging the data:

This is an example using just some base functions and using the multiple y lines to average each x-z-cutplane.

 1# Import filedialog to open a file dialog to select the measurement folder.
 2from tkinter import filedialog
 3
 4# Load the main functionality from the package, in this case the SnomMeasurement class.
 5from snom_analysis.main import Scan3D
 6
 7# Open a file dialog to select the measurement folder.
 8directory = filedialog.askdirectory()
 9
10# It is always a good idea to select the channels you want to use before loading the data.
11channels = ['O2A', 'O2P', 'O3A', 'O3P', 'Z']
12
13# Create an instance of the Scan3D class by providing the path to the measurement folder.
14measurement = Scan3D(directory, channels)
15
16# Set the minimum value of the data to zero.
17measurement.set_min_to_zero()
18
19# Change the colorbar width to 3 on the fly will apply to all following plots.
20PlotDefinitions.colorbar_width = 3
21
22# Average all individual cutplanes of the channels O2P and O3P.
23# This is an alternative approach to generating individual cutplanes.
24# All other functions will work with the averaged data, just make shure to use the 'line=0' parameter.
25measurement.average_data()
26
27# Match the phase offset of the channels O2P and O3P to the reference channel O2P.
28measurement.match_phase_offset(channels=['O2P', 'O3P'], reference_channel='O2P', reference_area='manual', manual_width=3)
29
30# For example display just the first cutplane of the O2P channel. Then display the first cutplane of the O3P channel.
31measurement.display_cutplane_v3(axis='x', line=0, channel='O2P')
32measurement.display_cutplane_v3(axis='x', line=0, channel='O3P')

How to use: