<jupyter_start><jupyter_text>pixStem tutorialThis notebook shows how to use the `pixstem` library to analyse pixelated scanning transmission electron microscopy (STEM) data, and differential phase contrast (DPC) data.More documentation is found at http://pixstem.org Note: for Notebook to work in JupyterLab, run : `conda install pixstem hyperspy-gui-traitsui -c conda-forge` in the Anaconda prompt  Importing libraries The first step is setting the plotting toolkit<jupyter_code>%matplotlib qt5<jupyter_output><empty_output><jupyter_text>Then import the library itselfYou might get a "WARNING:hyperspy_gui_ipywidgets", this can be ignored.<jupyter_code>import pixstem.api as ps<jupyter_output><empty_output><jupyter_text>Working with fast pixelated detector STEM data  Loading data<jupyter_code>s = ps.load_ps_signal<jupyter_output><empty_output><jupyter_text>For large files, use `lazy=True`: `s = ps.load_ps_signal("data.hspy", lazy=True)`. As the file we'll be looking at is (uncompressed) 8.6 GB, we use `lazy=True`.<jupyter_code>s = ps.load_ps_signal("datasets/cross_grating_medipix3.hdf5", lazy=True)<jupyter_output><empty_output><jupyter_text>This returns a `PixelatedSTEM` class, which is inherits HyperSpy's `Signal2D`. So all functions which work in `Signal2D`, also works here:<jupyter_code>s
s.plot()<jupyter_output><empty_output><jupyter_text>Virtual detectors To make the processing go a little bit quicker, we reduce the data down from 256 x 256 probe positions, to 128 x 128.<jupyter_code>s1 = s.inav[0:128, 0:128]<jupyter_output><empty_output><jupyter_text>The `virtual_annular_dark_field` is used to construct a images from the `PixelatedSTEM` class, with the input being `(x, y, r_outer, r_inner)`<jupyter_code>s_adf = s1.virtual_annular_dark_field(128, 128, 60, 100)
s_adf.plot()<jupyter_output><empty_output><jupyter_text>This signal can now be used for navigation the `s1` signal<jupyter_code>s1.plot(navigator=s_adf)<jupyter_output><empty_output><jupyter_text>There is also a virtual bright field method. Passing no parameters to the method gives a sum of the diffraction dimensions:<jupyter_code>s_bf = s1.virtual_bright_field()
s_bf.plot()<jupyter_output><empty_output><jupyter_text>A mask can be applied in the form of (x, y, r):<jupyter_code>s_bf = s1.virtual_bright_field(128, 128, 40)
s_bf.plot()<jupyter_output><empty_output><jupyter_text>Radial integration A common task is getting the intensity as a function of scattering angle. This is done using radial integration, which firstly requires finding the center of the electron beam. Here we use the `center_of_mass` function.<jupyter_code>s_com = s1.center_of_mass(threshold=1.)<jupyter_output><empty_output><jupyter_text>This returns a `DPCSignal2D` class, which will be explored more later. What we need to know is that is it basically a HyperSpy `Signal2D` class, where the x-beam shifts are in the first navigation index (`s.inav[0]`), while the y-shifts are in the second navigation index (`s.inav[1]`).<jupyter_code>s_com.plot()<jupyter_output><empty_output><jupyter_text>To do the radial integration itself, use the `radial_integration` method, which requires the `centre_x` and `centre_y` arguments to be specified.<jupyter_code>s1_radial = s1.radial_integration(centre_x=s_com.inav[0].data, centre_y=s_com.inav[1].data)<jupyter_output><empty_output><jupyter_text>This returns a new signal, where the signal dimensions has been reduced from 2 to 1 dimensions. This is especially useful when working with large datasets, where this operation can drastically reduce the data size, making it possible to load the full data into memory.<jupyter_code>s1_radial<jupyter_output><empty_output><jupyter_text>Plotting it shows the electron scattering for each probe position:<jupyter_code>s1_radial.plot()<jupyter_output><empty_output><jupyter_text>To rather visualize the data as function of scattering angle (essentially virtual annular dark field), we can transpose the data using `s_radial.T`. This "flips" the signal and navigation axes:<jupyter_code>s1_radial.T.plot()<jupyter_output><empty_output><jupyter_text>Differential phase contrast (DPC) signals These signal classes are used for beam shift datasets, where x-shifts are stored in the first navigation index (`s_dpc.inav[0]`) and the y-shifts in the second navigation index (`s_dpc.inav[1]`).They contain many different methods for both processing and visualizing DPC data.Here, we again use `ps.dummy_data` to get a signal to work with.There types of signals can be loaded using `s = ps.load_dpc_signal`.<jupyter_code>s_dpc = ps.dummy_data.get_square_dpc_signal(add_ramp=True)
s_dpc.plot()<jupyter_output><empty_output><jupyter_text>Correcting d-scan (ramp) The `s_dpc` has a lot of d-scan, to correct it use the `correct_ramp` method. This function is fairly basic, with only the possibility to subtract a linear ramp.<jupyter_code>s_dpc = s_dpc.correct_ramp(corner_size=0.05)
s_dpc.plot()<jupyter_output><empty_output><jupyter_text>Plotting methods The class also has several methods for visualizing DPC data: `get_color_signal`, `get_magnitude_signal` and `get_color_image_with_indicator`.The two former returns a HyperSpy signal, while the latter interfaces directly with the matplotlib backend making it more customizable.<jupyter_code>s_color = s_dpc.get_color_signal()
s_color.plot()<jupyter_output><empty_output><jupyter_text>The `get_color_signal` method has a `rotation` argument, which is used to correct for mismatch between the scan direction and diffraction rotation.<jupyter_code>s_color_rot = s_dpc.get_color_signal(rotation=45)
s_color_rot.plot()<jupyter_output><empty_output><jupyter_text>`get_magnitude_signal` gives the magnitude of the beam shift vector<jupyter_code>s_magnitude = s_dpc.get_magnitude_signal()
s_magnitude.plot()<jupyter_output><empty_output><jupyter_text>The `get_color_image_with_indicator` method has a large degree of customizability, which is useful when making images for presentations, posters or articles.By default it returns a matplotlib figure object, which can be saved directly<jupyter_code>fig = s_dpc.get_color_image_with_indicator()
fig.savefig("dpc_image.jpg")<jupyter_output><empty_output><jupyter_text>It also accepts a matplotlib subplot object as an argument, which makes it easy to integrate into larger figures.An example using more of the customizability<jupyter_code>import matplotlib.pyplot as plt
fig, axarr = plt.subplots(1, 2, figsize=(8, 4))
ax_dpc = axarr[0]
ax_dif = axarr[1]
ax_dif.imshow(s.inav[0, 0].data)
s_dpc.get_color_image_with_indicator(indicator_rotation=90, scalebar_size=30, ax=ax_dpc)
fig.savefig("dpc_figure.jpg")<jupyter_output><empty_output><jupyter_text>Various rotating Rotating the scan dimensions<jupyter_code>s_dpc_rot = s_dpc.rotate_data(20)
s_dpc_rot.get_color_signal().plot()<jupyter_output><empty_output><jupyter_text>Rotating the beam shifts, to correct for mismatch between the scan direction and diffraction rotation.<jupyter_code>s_dpc_rot = s_dpc.rotate_beam_shifts(25)
s_dpc_rot.get_color_signal().plot()<jupyter_output><empty_output><jupyter_text>Blurring the beam shifts<jupyter_code>s_dpc_blur = s_dpc.gaussian_blur(1.2)
s_dpc_blur.get_color_signal().plot()<jupyter_output><empty_output><jupyter_text>Bivariate histogram<jupyter_code>s_hist = s_dpc.get_bivariate_histogram()
s_hist.plot(cmap='viridis')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08794037940379404, 'fraction_numerical': 0.012466124661246613, 'mean_word_length': 8.034271725826194, 'pattern_counts': {'":': 0, '<': 109, '<?xml version=': 0, '>': 109, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '27', 'dir': 'jupyter-structured-clean-dedup', 'id': '52070', 'license': 'MIT', 'n_tokens_mistral': 2599, 'n_tokens_neox': 2471, 'n_words': 680, 'path': 'extra/introduction_to_pixstem.ipynb', 'repo_name': 'mbercx/jlab-workshop', 'size': '7380'}