Commit f4294f5d authored by Mukherjee, Debangshu's avatar Mukherjee, Debangshu
Browse files

Fixed plotting issues in GPA and afit submodules

parent 0a246257
......@@ -8,6 +8,63 @@
"\n",
"Notebooks prepared by Debangshu Mukherjee \n",
"Email: [mukherjeed@ornl.gov](mailto:mukherjeed@ornl.gov)/[debangshu24@gmail.com](mailto:debangshu24@gmail.com)\n",
"\n",
"This notebook will go through the steps on how to analyze the data for atomic resolution DPC"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, if `stemtool` is not installed, we install it:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: stemtool in /home/qz7/anaconda3/lib/python3.7/site-packages/stemtool-0.532-py3.7.egg (0.532)\n",
"Requirement already satisfied: pyfftw>=0.10.3 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (0.12.0)\n",
"Requirement already satisfied: pywavelets>=0.5.2 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (1.1.1)\n",
"Requirement already satisfied: numpy>=1.13.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (1.19.1)\n",
"Requirement already satisfied: scipy>=1.0.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (1.5.2)\n",
"Requirement already satisfied: matplotlib>=2.2.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (3.3.1)\n",
"Requirement already satisfied: pillow>5.0.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (8.0.0)\n",
"Requirement already satisfied: numba>=0.45.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (0.51.2)\n",
"Requirement already satisfied: scikit-image>=0.13.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (0.17.2)\n",
"Requirement already satisfied: matplotlib-scalebar>=0.5.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (0.6.2)\n",
"Requirement already satisfied: ase>=3.16.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (3.19.1)\n",
"Requirement already satisfied: h5py>=2.7.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (2.10.0)\n",
"Requirement already satisfied: dask>=2.0.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from stemtool) (2.30.0)\n",
"Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.3 in /home/qz7/anaconda3/lib/python3.7/site-packages (from matplotlib>=2.2.0->stemtool) (2.4.7)\n",
"Requirement already satisfied: python-dateutil>=2.1 in /home/qz7/anaconda3/lib/python3.7/site-packages (from matplotlib>=2.2.0->stemtool) (2.8.1)\n",
"Requirement already satisfied: kiwisolver>=1.0.1 in /home/qz7/anaconda3/lib/python3.7/site-packages (from matplotlib>=2.2.0->stemtool) (1.2.0)\n",
"Requirement already satisfied: cycler>=0.10 in /home/qz7/anaconda3/lib/python3.7/site-packages (from matplotlib>=2.2.0->stemtool) (0.10.0)\n",
"Requirement already satisfied: certifi>=2020.06.20 in /home/qz7/anaconda3/lib/python3.7/site-packages (from matplotlib>=2.2.0->stemtool) (2020.6.20)\n",
"Requirement already satisfied: llvmlite<0.35,>=0.34.0.dev0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from numba>=0.45.0->stemtool) (0.34.0)\n",
"Requirement already satisfied: setuptools in /home/qz7/anaconda3/lib/python3.7/site-packages (from numba>=0.45.0->stemtool) (49.6.0.post20201009)\n",
"Requirement already satisfied: networkx>=2.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from scikit-image>=0.13.0->stemtool) (2.5)\n",
"Requirement already satisfied: imageio>=2.3.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from scikit-image>=0.13.0->stemtool) (2.9.0)\n",
"Requirement already satisfied: tifffile>=2019.7.26 in /home/qz7/anaconda3/lib/python3.7/site-packages (from scikit-image>=0.13.0->stemtool) (2020.10.1)\n",
"Requirement already satisfied: six in /home/qz7/anaconda3/lib/python3.7/site-packages (from h5py>=2.7.0->stemtool) (1.15.0)\n",
"Requirement already satisfied: pyyaml in /home/qz7/anaconda3/lib/python3.7/site-packages (from dask>=2.0.0->stemtool) (5.3.1)\n",
"Requirement already satisfied: decorator>=4.3.0 in /home/qz7/anaconda3/lib/python3.7/site-packages (from networkx>=2.0->scikit-image>=0.13.0->stemtool) (4.4.2)\n"
]
}
],
"source": [
"!pip install stemtool"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Import packages\n",
"---\n",
"First, we import the requisite packages. The `json` and `sys` packages are required for loading the data. Along with the standard *Python* packages of `numpy` and `matplotlib` we also import the **STEMTool** package as `import stemtool as st`"
......@@ -15,7 +72,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
......@@ -42,14 +99,14 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Elapsed time: 3.228466 seconds.\n",
"Elapsed time: 3.295365 seconds.\n",
"\n"
]
}
......@@ -87,13 +144,207 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"DPC = st.dpc.atomic_dpc(Data_4D, DataADF, 1000*scan_calib_vals, 60, 31)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The class function itself has a lot of the documentation built in, and this can be found out by `help(st.dpc.atomic_dpc`"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Help on class atomic_dpc in module stemtool.dpc.atomic_dpc:\n",
"\n",
"class atomic_dpc(builtins.object)\n",
" | atomic_dpc(Data_4D, Data_ADF, calib_pm, voltage, aperture)\n",
" | \n",
" | Atomic Resolution DPC estimation\n",
" | \n",
" | Parameters\n",
" | ----------\n",
" | Data_4D: ndarray\n",
" | Four-dimensional dataset where the first two\n",
" | dimensions are real space scanning dimensions,\n",
" | while the last two dimenions are the Fourier \n",
" | space electron diffraction patterns\n",
" | Data_ADF: ndarray\n",
" | Simultaneously collected two-dimensional ADF-STEM\n",
" | image\n",
" | calib_pm: float\n",
" | Real space pixel calibration in picometers\n",
" | voltage: float\n",
" | Microscope accelerating voltage in kV\n",
" | aperture: float\n",
" | The probe forming condenser aperture in milliradians\n",
" | \n",
" | Notes\n",
" | -----\n",
" | This class function takes in a 4D-STEM image, and a simultaneously\n",
" | collected atomic resolution ADF-STEM image. Based on the accelerating\n",
" | voltage and the condenser aperture this calculates the center of mass \n",
" | (C.O.M.) shifts in the central undiffracted beam. Using the idea that \n",
" | the curl of the beam shift vectors, should be minimized at the correct\n",
" | Fourier rotation angles, this class also corrects for rotation of the \n",
" | collceted 4D-STEM data with respect to the optic axis. Using these, a \n",
" | correct potential accumulation and charge accumulation maps could be \n",
" | built. To prevent errors, we convert everything to SI units first.\n",
" | \n",
" | Examples\n",
" | --------\n",
" | Run as:\n",
" | \n",
" | >>> DPC = st.dpc.atomic_dpc(Data_4D, DataADF, calibration, voltage, aper)\n",
" | \n",
" | Once the data is loaded, the ADF-STEM and the BF-STEM images could be \n",
" | visualized as:\n",
" | \n",
" | >>> DPC.show_ADF_BF()\n",
" | \n",
" | Then the following call generates the mean CBED image, and if the show_image\n",
" | call is True, shows the mean image.\n",
" | \n",
" | >>> DPC.get_cbed(show_image = True)\n",
" | \n",
" | The initial uncorrected DPC shifts are generated as:\n",
" | \n",
" | >>> DPC.initial_dpc()\n",
" | \n",
" | The corrected DPC shifts are generated:\n",
" | \n",
" | >>> DPC.correct_dpc()\n",
" | \n",
" | The charge map is generated through:\n",
" | \n",
" | >>> DPC.show_charge()\n",
" | \n",
" | While the potential map is generated though:\n",
" | \n",
" | >>> DPC.show_potential()\n",
" | \n",
" | If a section of the image needs to be observed, to visualize the beam shifts,\n",
" | call the following:\n",
" | \n",
" | >>> DPC.plot_color_dpc()\n",
" | \n",
" | References\n",
" | ----------\n",
" | .. [1] Müller, K. et al. \"Atomic electric fields revealed by a quantum mechanical \n",
" | approach to electron picodiffraction\". Nat. Commun. 5:565303 doi: 10.1038/ncomms6653 (2014)\n",
" | .. [2] Savitzky, Benjamin H., Lauren A. Hughes, Steven E. Zeltmann, Hamish G. Brown, \n",
" | Shiteng Zhao, Philipp M. Pelz, Edward S. Barnard et al. \"py4DSTEM: a software package for \n",
" | multimodal analysis of four-dimensional scanning transmission electron microscopy datasets.\" \n",
" | arXiv preprint arXiv:2003.09523 (2020).\n",
" | .. [3] Ishizuka, Akimitsu, Masaaki Oka, Takehito Seki, Naoya Shibata, \n",
" | and Kazuo Ishizuka. \"Boundary-artifact-free determination of \n",
" | potential distribution from differential phase contrast signals.\" \n",
" | Microscopy 66, no. 6 (2017): 397-405.\n",
" | \n",
" | Methods defined here:\n",
" | \n",
" | __init__(self, Data_4D, Data_ADF, calib_pm, voltage, aperture)\n",
" | Load the user defined values.\n",
" | It also calculates the wavelength based on the accelerating voltage\n",
" | This also loads several SI constants as the following attributes\n",
" | \n",
" | `planck`: The Planck's constant\n",
" | \n",
" | `epsilon0`: The dielectric permittivity of free space\n",
" | \n",
" | `e_charge`: The charge of an electron in Coulombs\n",
" | \n",
" | correct_dpc(self, imsize=(30, 17))\n",
" | This corrects for the rotation angle of the pixellated detector\n",
" | with respect to the optic axis. Some pixellated detectors flip\n",
" | the image, and if there is an image flip, it corrects it too.\n",
" | The mechanism of this, we compare the gradient of both the flipped\n",
" | and the unflipped DPC data at multiple rotation angles, and the value\n",
" | that has the highest relative contrast with the ADF-STEM image is taken\n",
" | as 90 degrees from the correct angle.\n",
" | \n",
" | get_cbed(self, imsize=(15, 15), show_image=False)\n",
" | We calculate the mean CBED pattern by averaging the Fourier data, to\n",
" | get the object attribute `cbed`. We fit this with a circle function to\n",
" | obtain the object attributes: \n",
" | \n",
" | `beam_x`: x-coordinates of the circle \n",
" | \n",
" | `beam_y`: y-coordinates of the circle \n",
" | \n",
" | `beam_r`: radius of the circle \n",
" | \n",
" | We use the calculated radius and the known aperture size to get the Fourier \n",
" | space calibration, which is stored as the `inverse` attribute\n",
" | \n",
" | initial_dpc(self, imsize=(30, 17), normalize=True)\n",
" | This calculates the initial DPC center of mass shifts by measuring\n",
" | the center of mass of each image in the 4D-STEM dataset, and then\n",
" | comparing that center of mass with the average disk center of the\n",
" | entire dataset.\n",
" | \n",
" | plot_color_dpc(self, start_frac=0, size_frac=1, skip=2, imsize=(20, 10))\n",
" | Use this to plot the corrected DPC center of mass shifts. If no variables\n",
" | are passed, the arrows are overlaid on the entire image.\n",
" | \n",
" | Parameters\n",
" | ----------\n",
" | start_frac: float, optional\n",
" | The starting fraction of the image, where you will cut from\n",
" | to show the overlaid arrows. Default is 0\n",
" | stop_frac: float, optional\n",
" | The ending fraction of the image, where you will cut from\n",
" | to show the overlaid arrows. Default is 1\n",
" | \n",
" | show_ADF_BF(self, imsize=(20, 10))\n",
" | The ADF-STEM image is already loaded, while the `data_bf`\n",
" | attribute is obtained by summing up the 4D-STEM dataset along it's \n",
" | Fourier dimensions. This is also a great checkpoint to see whether\n",
" | the ADF-STEM and the BF-STEM images are the inverse of each other.\n",
" | \n",
" | show_charge(self, imsize=(15, 17))\n",
" | We calculate the charge from the corrected DPC\n",
" | center of mass datasets. This is done through\n",
" | Poisson's equation.\n",
" | \n",
" | show_potential(self, imsize=(15, 17))\n",
" | Calculate the projected potential from the DPC measurements.\n",
" | This is accomplished by calculating the phase shift iteratively\n",
" | from the normalized center of mass shifts. Normalization means\n",
" | calculating COM shifts in inverse length units and then multiplying\n",
" | them with the electron wavelength to get an electron independent\n",
" | mrad shift, which is used to generate the phase. This phase is\n",
" | proportional to the projected potential for weak phase object\n",
" | materials (with *lots* of assumptions)\n",
" | \n",
" | ----------------------------------------------------------------------\n",
" | Data descriptors defined here:\n",
" | \n",
" | __dict__\n",
" | dictionary for instance variables (if defined)\n",
" | \n",
" | __weakref__\n",
" | list of weak references to the object (if defined)\n",
"\n"
]
}
],
"source": [
"help(st.dpc.atomic_dpc)"
]
},
{
"cell_type": "markdown",
"metadata": {},
......@@ -105,7 +356,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 5,
"metadata": {},
"outputs": [
{
......@@ -136,14 +387,14 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Elapsed time: 0.917955 seconds.\n",
"Elapsed time: 1.014183 seconds.\n",
"\n"
]
},
......@@ -166,16 +417,25 @@
"st.toc()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Calculate Initial DPC\n",
"---\n",
"We calculate the initial DPC results by measuring the center of mass of every diffraction disk, and then comparing the location of the center of mass with the disk position. This can be generated by calling the class function `DPC.initial_dpc()`"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Elapsed time: 8.966292 seconds.\n",
"Elapsed time: 9.162902 seconds.\n",
"\n"
]
},
......@@ -198,16 +458,25 @@
"st.toc()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Correct DPC rotations\n",
"---\n",
"**However!** for experimental images, we often find that the "
]
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Elapsed time: 1.374495 seconds.\n",
"Elapsed time: 1.391834 seconds.\n",
"\n"
]
},
......@@ -232,7 +501,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 9,
"metadata": {},
"outputs": [
{
......@@ -254,7 +523,7 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 10,
"metadata": {},
"outputs": [
{
......@@ -276,7 +545,16 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"If we also want to "
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
......@@ -296,6 +574,13 @@
"DPC.plot_color_dpc(start_frac=0.3, size_frac=0.4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we can also go through the list of the DPC class variables to check all the temporary variables too."
]
},
{
"cell_type": "code",
"execution_count": 11,
......@@ -105,7 +105,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Elapsed time: 23.274383 seconds.\n",
"Elapsed time: 17.717386 seconds.\n",
"\n"
]
}
......@@ -133,7 +133,7 @@
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f9e4d84ae10>"
"<matplotlib.image.AxesImage at 0x7f25b2230f60>"
]
},
"execution_count": 7,
......@@ -192,7 +192,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
......@@ -201,7 +201,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 10,
"metadata": {},
"outputs": [
{
......@@ -223,7 +223,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 11,
"metadata": {},
"outputs": [
{
......@@ -245,7 +245,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 12,
"metadata": {},
"outputs": [
{
......@@ -274,14 +274,14 @@
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Elapsed time: 2.600507 seconds.\n",
"Elapsed time: 2.070890 seconds.\n",
"\n"
]
}
......@@ -295,7 +295,7 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 14,
"metadata": {},
"outputs": [
{
......@@ -315,6 +315,13 @@
"gpa_mos2.plot_gpa_strain(imsize= (15, 15))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
......@@ -246,7 +246,7 @@ class multi_image_drift(object):
self.corr_image = np.sum(self.moved_stack, axis=0) / self.no_im
return self.corr_image
def plot_shifts(self):
def plot_shifts(self, imwidth=15):
"""
Notes
-----
......@@ -256,24 +256,37 @@ class multi_image_drift(object):
raise RuntimeError(
"Please get the images correlated first as get_shape_stack()"
)
sc_font = {"weight": "bold", "size": int(imwidth)}
imsize = (int(imwidth), int(imwidth * 0.6))
plt.figure(figsize=imsize)
vm = self.max_shift
fig = plt.figure(figsize=(20, 10))
gs = mpgs.GridSpec(1, 2)
ax1 = plt.subplot(gs[0, 0])
ax2 = plt.subplot(gs[0, 1])
gs = mpgs.GridSpec(6, 10)
ax1 = plt.subplot(gs[0:5, 0:5])
ax2 = plt.subplot(gs[0:5, 5:10])
ax3 = plt.subplot(gs[5:6, :])
im = ax1.imshow(self.row_stack, vmin=-vm, vmax=vm, cmap="RdBu_r")
ax1.set_xlabel("Stack Number")
ax1.set_ylabel("Stack Number")
ax1.set_title(label="Shift along X direction", loc="left")
im = ax2.imshow(self.col_stack, vmin=-vm, vmax=vm, cmap="RdBu_r")
ax2.imshow(self.col_stack, vmin=-vm, vmax=vm, cmap="RdBu_r")
ax2.set_xlabel("Stack Number")
ax2.set_ylabel("Stack Number")
ax2.set_title(label="Shift along Y direction", loc="left")
p1 = ax1.get_position().get_points().flatten()
p2 = ax2.get_position().get_points().flatten()
ax_cbar = fig.add_axes([p1[0], 0.25, p2[2] - 0.12, 0.02])
cbar = plt.colorbar(im, cax=ax_cbar, orientation="horizontal")
cbar.set_label("Relative Shift (pixels)")
sb = np.zeros((10, 1000), dtype=np.float)
for ii in range(10):
sb[ii, :] = np.linspace(-vm, vm, 1000)
ax3.imshow(sb, cmap="RdBu_r")
ax3.yaxis.set_visible(False)
no_labels = 9
x1 = np.linspace(0, 1000, no_labels)
ax3.set_xticks(x1)
ax3.set_xticklabels(np.round(np.linspace(-vm, vm, no_labels), 4))
for axis in ["top", "bottom", "left", "right"]:
ax3.spines[axis].set_linewidth(2)
ax3.spines[axis].set_color("black")
ax3.xaxis.set_tick_params(width=2, length=6, direction="out", pad=10)
ax3.set_title("Relative Shift (pixels)", **sc_font)
......@@ -365,7 +365,9 @@ class GPA(object):
"""
def __init__(self, image, calib, calib_units, ref_iter=20, use_blur=True):
def __init__(
self, image, calib, calib_units, ref_iter=20, use_blur=True, max_strain=0.4
):
self.image = image
self.calib = calib
self.calib_units = calib_units
......@@ -379,6 +381,7 @@ class GPA(object):
raise RuntimeError("Please ensure that the image is a square image")
self.circ_0 = 0.5 * self.imshape
self.inv_cal_units = "1/" + calib_units
self.max_strain = max_strain
self.spots_check = False
self.reference_check = False
self.refining_check = False
......@@ -714,23 +717,32 @@ class GPA(object):
self.e_dg -= np.median(self.e_dg[self.ref_reg])
self.e_th -= np.median(self.e_th[self.ref_reg])
self.e_xx -= np.median(self.e_xx[self.ref_reg])
if self.max_strain > 0:
self.e_yy[self.e_yy > self.max_strain] = self.max_strain
self.e_yy[self.e_yy < -self.max_strain] = -self.max_strain
self.e_dg[self.e_dg > self.max_strain] = self.max_strain
self.e_dg[self.e_dg < -self.max_strain] = -self.max_strain
self.e_th[self.e_th > self.max_strain] = self.max_strain
self.e_th[self.e_th < -self.max_strain] = -self.max_strain
self.e_xx[self.e_xx > self.max_strain] = self.max_strain
self.e_xx[self.e_xx < -self.max_strain] = -self.max_strain
return self.e_xx, self.e_yy, self.e_th, self.e_dg
def plot_gpa_strain(self, mval=0, imsize=(20, 20)):
def plot_gpa_strain(self, mval=0, imwidth=15):
"""
Use the calculated strain matrices to plot the strain maps
Parameters
----------
mval: float, optional
The maximum strain value that will be plotted.
Default is 0, upon which the maximum strain
percentage will be calculated, which will be used
for plotting.
imsize: tuple, optional
Size in inches of the image with the
diffraction spots marked. Default is
(20, 20)
mval: float, optional
The maximum strain value that will be plotted.
Default is 0, upon which the maximum strain
percentage will be calculated, which will be used
for plotting.
imwidth: int, optional
Size in inches of the image with the
diffraction spots marked. Default is 15
Notes
-----
......@@ -738,7 +750,7 @@ class GPA(object):
four types of strain calculated through geometric phase
analysis.
"""
fontsize = int(np.mean(np.asarray(imsize)))
fontsize = int(imwidth)
if mval == 0:
vm = 100 * np.amax(
np.abs(
......@@ -749,14 +761,16 @@ class GPA(object):
vm = mval
sc_font = {"weight": "bold", "size": fontsize}
mpl.rc("font", **sc_font)
imsize = (int(imwidth), int(imwidth * 1.1))