{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Band Excitation data procesing using pycroscopy\n", "#### Suhas Somnath, Chris R. Smith, Stephen Jesse\n", "The Center for Nanophase Materials Science and The Institute for Functional Imaging for Materials
\n", "Oak Ridge National Laboratory
\n", "2/10/2017\n", "\n", "\n", "## cKPFM analysis\n", "#### Sabine Neumayer\n", "University College Dublin
\n", "7/4/2017" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![notebook_rules.png](notebook_rules.png)\n", "\n", "Image courtesy of Jean Bilheux from the [neutron imaging](https://github.com/neutronimaging/python_notebooks) GitHub repository." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Configure the notebook" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Collecting package metadata (current_repodata.json): ...working... done\n", "Solving environment: ...working... done\n", "\n", "# All requested packages already installed.\n", "\n", "Requirement already satisfied: sidpy in c:\\users\\yla\\anaconda3\\lib\\site-packages (0.0.5)\n", "Requirement already satisfied: bglib in c:\\users\\yla\\anaconda3\\lib\\site-packages (0.0.3)\n" ] } ], "source": [ "# Make sure needed packages are installed and up-to-date\n", "import sys\n", "!conda install --yes --prefix {sys.prefix} numpy scipy matplotlib scikit-learn Ipython ipywidgets h5py\n", "!{sys.executable} -m pip install -U --no-deps sidpy bglib" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Ensure python 3 compatibility\n", "from __future__ import division, print_function, absolute_import\n", "\n", "# Import necessary libraries:\n", "# General utilities:\n", "import sys\n", "import os\n", "import math\n", "\n", "# Computation:\n", "import numpy as np\n", "import h5py\n", "\n", "# Visualization:\n", "import matplotlib.pyplot as plt\n", "import matplotlib.colors as colors\n", "import ipywidgets as widgets\n", "\n", "from IPython.display import display, HTML\n", "\n", "# Finally, BGlib itself\n", "sys.path.append('..')\n", "\n", "from BGlib import be as belib\n", "import pyUSID as usid\n", "import sidpy\n", "\n", "# Make Notebook take up most of page width\n", "display(HTML(data=\"\"\"\n", "\n", "\"\"\"))" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# set up notebook to show plots within the notebook\n", "%matplotlib notebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set some basic parameters for computation\n", "This notebook performs some functional fitting whose duration can be substantially decreased by using more memory and CPU cores. We have provided default values below but you may choose to change them if necessary." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "max_mem = 1024*8 # Maximum memory to use, in Mbs. Default = 1024\n", "max_cores = None # Number of logical cores to use in fitting. None uses all but 2 available cores." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Make the data pycroscopy compatible\n", "Converting the raw data into a pycroscopy compatible hierarchical data format (HDF or .h5) file gives you access to the fast fitting algorithms and powerful analysis functions within pycroscopy\n", "\n", "#### H5 files:\n", "* are like smart containers that can store matrices with data, folders to organize these datasets, images, metadata like experimental parameters, links or shortcuts to datasets, etc.\n", "* are readily compatible with high-performance computing facilities\n", "* scale very efficiently from few kilobytes to several terabytes\n", "* can be read and modified using any language including Python, Matlab, C/C++, Java, Fortran, Igor Pro, etc.\n", "\n", "#### You can load either of the following:\n", "* Any .mat or .txt parameter file from the original experiment\n", "* A .h5 file generated from the raw data using pycroscopy - skips translation\n", "\n", "You can select desired file type by choosing the second option in the pull down menu on the bottom right of the file window" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "File is already Pycroscopy ready.\n", "Working on:\n", "C:/Users/yla/Google Drive/PD time files/User Work/SimonFraser_ZuoGuangYe/sample2/BEcKPFM_2um_0012.h5\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\yla\\Anaconda3\\lib\\site-packages\\sidpy\\sid\\translator.py:42: FutureWarning: Consider using sidpy.Reader instead of sidpy.Translator if possible and contribute your reader to ScopeReaders\n", " warn('Consider using sidpy.Reader instead of sidpy.Translator if '\n" ] } ], "source": [ "input_file_path = r'C:/Users/yla/Google Drive/PD time files/User Work/SimonFraser_ZuoGuangYe/sample2/BEcKPFM_2um_0012.h5'\n", "\n", "(data_dir, filename) = os.path.split(input_file_path)\n", "\n", "if input_file_path.endswith('.h5'):\n", " # No translation here\n", " h5_path = input_file_path\n", " force = False # Set this to true to force patching of the datafile.\n", " tl = belib.translators.LabViewH5Patcher()\n", " tl.translate(h5_path, force_patch=force)\n", "else:\n", " # Set the data to be translated\n", " data_path = input_file_path\n", "\n", " (junk, base_name) = os.path.split(data_dir)\n", "\n", " # Check if the data is in the new or old format. Initialize the correct translator for the format.\n", " if base_name == 'newdataformat':\n", " (junk, base_name) = os.path.split(junk)\n", " translator = belib.translators.BEPSndfTranslator(max_mem_mb=max_mem)\n", " else:\n", " translator = belib.translators.BEodfTranslator(max_mem_mb=max_mem)\n", " if base_name.endswith('_d'):\n", " base_name = base_name[:-2]\n", " # Translate the data\n", " h5_path = translator.translate(data_path, show_plots=True, save_plots=False)\n", "\n", "h5_file = h5py.File(h5_path, 'r+')\n", "print('Working on:\\n' + h5_path)\n", "\n", "h5_main = usid.hdf_utils.find_dataset(h5_file, 'Raw_Data')[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Inspect the contents of this h5 data file\n", "The file contents are stored in a tree structure, just like files on a conventional computer.\n", "The data is stored as a 2D matrix (position, spectroscopic value) regardless of the dimensionality of the data. Thus, the positions will be arranged as row0-col0, row0-col1.... row0-colN, row1-col0.... and the data for each position is stored as it was chronologically collected \n", "\n", "The main dataset is always accompanied by four ancillary datasets that explain the position and spectroscopic value of any given element in the dataset." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Datasets and datagroups within the file:\n", "------------------------------------\n", "/\n", "├ Measurement_000\n", " ---------------\n", " ├ Channel_000\n", " -----------\n", " ├ Bin_FFT\n", " ├ Bin_Frequencies\n", " ├ Bin_Indices\n", " ├ Bin_Step\n", " ├ Excitation_Waveform\n", " ├ Noise_Floor\n", " ├ Position_Indices\n", " ├ Position_Values\n", " ├ Raw_Data\n", " ├ Raw_Data-SHO_Fit_000\n", " --------------------\n", " ├ Guess\n", " ├ Spectroscopic_Indices\n", " ├ Spectroscopic_Values\n", " ├ Raw_Data-SHO_Fit_001\n", " --------------------\n", " ├ Fit\n", " ├ Guess\n", " ├ Spectroscopic_Indices\n", " ├ Spectroscopic_Values\n", " ├ completed_fit_positions\n", " ├ completed_guess_positions\n", " ├ Spatially_Averaged_Plot_Group_000\n", " ---------------------------------\n", " ├ Bin_Frequencies\n", " ├ Mean_Spectrogram\n", " ├ Spectroscopic_Parameter\n", " ├ Step_Averaged_Response\n", " ├ Spectroscopic_Indices\n", " ├ Spectroscopic_Values\n", " ├ Channel_001\n", " -----------\n", " ├ Position_Indices\n", " ├ Position_Values\n", " ├ Raw_Data\n", " ├ Spectroscopic_Indices\n", " ├ Spectroscopic_Values\n", "\n", "The main dataset:\n", "------------------------------------\n", "\n", "located at: \n", "\t/Measurement_000/Channel_000/Raw_Data \n", "Data contains: \n", "\tquantity (a.u.) \n", "Data dimensions and original shape: \n", "Position Dimensions: \n", "\tX - size: 10 \n", "\tY - size: 10 \n", "Spectroscopic Dimensions: \n", "\tFrequency - size: 124 \n", "\tField - size: 2 \n", "\twrite_bias - size: 20 \n", "\tread_bias - size: 11\n", "Data Type:\n", "\tcomplex64\n", "\n", "The ancillary datasets:\n", "------------------------------------\n", "\n", "\n", "\n", "\n", "\n", "Metadata or attributes in a datagroup\n", "------------------------------------\n", "AFM_InvOLS : 1e-07\n", "AFM_XLVDT_sensor : 3.7947347683133456e-06\n", "AFM_XPiezo_sensitivity : -1.605988e-07\n", "AFM_YLVDT_sensor : 3.968488902834937e-06\n", "AFM_YPiezo_sensitivity : 1.8273e-07\n", "AFM_ZLVDT_sensor : 2.4883e-06\n", "AFM_ZPiezo_sensitivity : 2.8128e-08\n", "AR_ : 31.0\n", "AR_Frequency_Setpoint : 100.0\n", "AR_Gain_for_PFM_Dart_mode : 0.0\n", "AR_Inverted_Optical_Lever_Sensitivity : 1e-07\n", "AR_Lockin_0_ : 1500.0\n", "AR_Number_of_frames_when_IMS_scanning : 0.0\n", "AR_The_Deflection_Setpoint_in_meters : 0.0\n", "AR_The_Integral_Gain_(the_one_that_matters) : 10.0\n", "AR_The_Offset_that_is_applied_to_the_user_channels : 0.0\n", "AR_The_Proportional_Gain_(what_is_it_good_for?) : 0.0\n", "AR_The_Set_Point_if_we_are_feeding_back_on_amplitude : 0.8\n", "AR_The_amount_of_rounding_on_the_scans : 0.04\n", "AR_The_amount_of_secret_gain_in_X : 7.02\n", "AR_The_amount_of_secret_gain_in_Y : 7.09\n", "AR_The_amount_of_secret_gain_in_Z : 0.0\n", "AR_The_amount_that_the_X_LVDT_is_not_centered : 0.0\n", "AR_The_amount_the_size_of_the_scan_is_reduced_by_the_scan_angle : 0.0\n", "AR_The_amplitude_of_the_drive_to_the_tip_piezo : 0.1\n", "AR_The_amplitude_set_point_in_meters : 8.72e-08\n", "AR_The_angle_of_the_scan_in_degrees_going_clockwise : 90.0\n", "AR_The_current_distance_moved_by_force_curves : 4e-07\n", "AR_The_deflection_Setpoint_in_newtons : 5e-09\n", "AR_The_displayed_Setpoint : 0.0008\n", "AR_The_frequency_of_the_drive_to_the_piezo : 0.0\n", "AR_The_frequency_width_during_a_tune : 5000.0\n", "AR_The_gain_on_the_fast_ADC_in_dB : 0.0\n", "AR_The_gains_that_are_applied_to_the_user_channels : 1.0\n", "AR_The_integral_gain_of_the_X_axis : 4.72\n", "AR_The_integral_gain_of_the_Y_axis : 4.74\n", "AR_The_maximum_physical_scan_size : 9e-05\n", "AR_The_number_of_lines_per_scan : 256.0\n", "AR_The_number_of_points_in_cantilever_tune : 480.0\n", "AR_The_number_of_points_per_line : 0.0\n", "AR_The_offset_of_the_X_LVDT_sensor : -0.09\n", "AR_The_offset_of_the_Y_LVDT_sensor : -0.1\n", "AR_The_offset_of_the_Z_LVDT_sensor : 0.55\n", "AR_The_offset_of_the_scan_in_meters_from_the_center_in_X : 1.2502379e-06\n", "AR_The_offset_of_the_scan_in_meters_from_the_center_in_Y : 7.339670100000001e-06\n", "AR_The_offset_required_to_center_the_phase : 0.0\n", "AR_The_proportional_gain_of_the_X_axis : -inf\n", "AR_The_proportional_gain_of_the_Y_axis : -inf\n", "AR_The_rate_of_the_scan_in_hertz : 1.0\n", "AR_The_sensitivity_of_the_X_LVDT_sensor : 3.7947347683133456e-06\n", "AR_The_sensitivity_of_the_X_piezo : -1.605988e-07\n", "AR_The_sensitivity_of_the_Y_LVDT_sensor : 3.968488902834937e-06\n", "AR_The_sensitivity_of_the_Y_piezo : 1.8273e-07\n", "AR_The_sensitivity_of_the_Z_LVDT_sensor : 2.4883e-06\n", "AR_The_sensitivity_of_the_Z_piezo : 3.6124e-08\n", "AR_The_setpoint_if_we_are_feeding_back_on_deflection : 1.0\n", "AR_The_size_of_the_scan_in_meters : 2e-06\n", "AR_The_size_of_the_scan_in_the_fast_direction_in_meters : 2e-06\n", "AR_The_size_of_the_scan_in_the_slow_direction_in_meters : 2e-06\n", "AR_The_speed_of_the_scan_in_meters_per_second : 5.0080128205128205e-06\n", "AR_The_spring_constant_of_the_cantilever : 1.0\n", "AR_The_spring_constant_of_the_secondary_mode_of_the_cantilever : 100.0\n", "AR_The_suffix_applied_to_saved_images : 1.0\n", "AR_The_voltage_bias_on_the_User_0_BNC : 0.0\n", "AR_The_voltage_bias_on_the_User_1_BNC : 0.0\n", "AR_The_voltage_bias_on_the_sample : 0.0\n", "AR_The_voltage_bias_on_the_tip : 0.0\n", "AR_This_is_1e-9_of_the_secondary_mode_spring_constant,_for_display_versus_nm : 1.0000000000000001e-07\n", "AR_This_is_1e-9_of_the_spring_constant,_for_display_versus_nm : 1e-09\n", "AR_What_imaging_mode_are_we_in : 0.0\n", "AR_What_the_gain_was_before_it_was_changed : 12.0\n", "AR_Whether_or_not_the_slow_scan_is_enabled : 0.0\n", "AR_Whether_the_image_has_been_changed_during_this_scan : 0.0\n", "AR_Whether_the_parameters_have_changed : 0.0\n", "AR_Whether_this_is_the_last_scan_or_not : 2.0\n", "AR_Whether_to_save_images_or_not : 2.0\n", "AR_Which_Way_the_scan_is_heading : 1.0\n", "AR_variable_that_attempts_to_line_up_trace_with_retrace : 0.0\n", "BE_amplitude_[V] : 2.0\n", "BE_auto_smooth_cond : 1.0\n", "BE_band_width_[Hz] : 100000.0\n", "BE_center_frequency_[Hz] : 390000.0\n", "BE_phase_content : b'chirp-sinc hybrid'\n", "BE_phase_variation : 1.0\n", "BE_pulse_duration_[s] : 0.008\n", "BE_repeats : 4.0\n", "BE_signal_type_ring : 1.0\n", "BE_smoothing : 3208.717049919559\n", "BE_window_adjustment : 0.215625\n", "File_file_name : BEcKPFM_2um_0012\n", "IO_AFM_platform : b'1 Cypher AR16'\n", "IO_AI_range : 10.0\n", "IO_AO_range : 10.0\n", "IO_Analog_output_routing : 0.0\n", "IO_Channel_001_type : b'topography'\n", "IO_Channel_002_type : b'none'\n", "IO_Channel_003_type : b'none'\n", "IO_analog_output_amplifier_ring : 1.0\n", "IO_card : b'6124'\n", "IO_deflection_detector_ring : 0\n", "IO_rate : 4000000.0\n", "IO_sensitivity : 1.0\n", "VS_delay_time_after_step_[s] : 0.0\n", "VS_max_read_bias_[V] : 1.0\n", "VS_max_write_bias_[V] : 6.0\n", "VS_min_read_bias_[V] : -1.0\n", "VS_min_write_bias_[V] : -6.0\n", "VS_mode : b'cKPFM'\n", "VS_num_DC_write_steps : 20\n", "VS_num_read_steps : 11\n", "VS_step_transition_time_[s] : 0.001\n", "data_type : b'cKPFMData'\n", "grid_current_col : 9\n", "grid_current_row : 9\n", "grid_num_cols : 10\n", "grid_num_rows : 10\n", "grid_set_point_[V] : 1.0\n", "grid_settle_time_[s] : 1.0\n", "grid_transit_time_[s] : 1.0\n", "num_H5_col : 54560\n", "num_UDVS_steps : 440\n", "num_pix : 100\n", "num_steps : 440\n" ] } ], "source": [ "print('Datasets and datagroups within the file:\\n------------------------------------')\n", "usid.hdf_utils.print_tree(h5_file)\n", " \n", "print('\\nThe main dataset:\\n------------------------------------')\n", "print(h5_main)\n", "print('\\nThe ancillary datasets:\\n------------------------------------')\n", "print(h5_file['/Measurement_000/Channel_000/Position_Indices'])\n", "print(h5_file['/Measurement_000/Channel_000/Position_Values'])\n", "print(h5_file['/Measurement_000/Channel_000/Spectroscopic_Indices'])\n", "print(h5_file['/Measurement_000/Channel_000/Spectroscopic_Values'])\n", "\n", "print('\\nMetadata or attributes in a datagroup\\n------------------------------------')\n", "for key in h5_file['/Measurement_000'].attrs:\n", " print('{} : {}'.format(key, h5_file['/Measurement_000'].attrs[key]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get some basic parameters from the H5 file\n", "This information will be vital for futher analysis and visualization of the data" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['X', 'Y'] [10, 10]\n" ] } ], "source": [ "h5_pos_inds = h5_main.h5_pos_inds\n", "pos_dims = h5_main.pos_dim_sizes\n", "pos_labels = h5_main.pos_dim_labels\n", "print(pos_labels, pos_dims)\n", "\n", "parm_dict = h5_file['/Measurement_000'].attrs\n", "is_ckpfm = True\n", "\n", "num_write_steps = parm_dict['VS_num_DC_write_steps']\n", "num_read_steps = parm_dict['VS_num_read_steps']\n", "num_fields = 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Visualize the raw data\n", "Use the sliders below to visualize spatial maps (2D only for now), and spectrograms.\n", "For simplicity, all the spectroscopic dimensions such as frequency, excitation bias, cycle, field, etc. have been collapsed to a single slider." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "No position datasets found as attributes of /Measurement_000/Channel_000/Spectroscopic_Values\n" ] }, { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "/* global mpl */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function () {\n", " if (typeof WebSocket !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof MozWebSocket !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert(\n", " 'Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.'\n", " );\n", " }\n", "};\n", "\n", "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = this.ws.binaryType !== undefined;\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById('mpl-warnings');\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent =\n", " 'This browser does not support binary websocket messages. ' +\n", " 'Performance may be slow.';\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = document.createElement('div');\n", " this.root.setAttribute('style', 'display: inline-block');\n", " this._root_extra_style(this.root);\n", "\n", " parent_element.appendChild(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message('supports_binary', { value: fig.supports_binary });\n", " fig.send_message('send_image_mode', {});\n", " if (fig.ratio !== 1) {\n", " fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n", " }\n", " fig.send_message('refresh', {});\n", " };\n", "\n", " this.imageObj.onload = function () {\n", " if (fig.image_mode === 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function () {\n", " fig.ws.close();\n", " };\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "};\n", "\n", "mpl.figure.prototype._init_header = function () {\n", " var titlebar = document.createElement('div');\n", " titlebar.classList =\n", " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", " var titletext = document.createElement('div');\n", " titletext.classList = 'ui-dialog-title';\n", " titletext.setAttribute(\n", " 'style',\n", " 'width: 100%; text-align: center; padding: 3px;'\n", " );\n", " titlebar.appendChild(titletext);\n", " this.root.appendChild(titlebar);\n", " this.header = titletext;\n", "};\n", "\n", "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", "\n", "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", "\n", "mpl.figure.prototype._init_canvas = function () {\n", " var fig = this;\n", "\n", " var canvas_div = (this.canvas_div = document.createElement('div'));\n", " canvas_div.setAttribute(\n", " 'style',\n", " 'border: 1px solid #ddd;' +\n", " 'box-sizing: content-box;' +\n", " 'clear: both;' +\n", " 'min-height: 1px;' +\n", " 'min-width: 1px;' +\n", " 'outline: 0;' +\n", " 'overflow: hidden;' +\n", " 'position: relative;' +\n", " 'resize: both;'\n", " );\n", "\n", " function on_keyboard_event_closure(name) {\n", " return function (event) {\n", " return fig.key_event(event, name);\n", " };\n", " }\n", "\n", " canvas_div.addEventListener(\n", " 'keydown',\n", " on_keyboard_event_closure('key_press')\n", " );\n", " canvas_div.addEventListener(\n", " 'keyup',\n", " on_keyboard_event_closure('key_release')\n", " );\n", "\n", " this._canvas_extra_style(canvas_div);\n", " this.root.appendChild(canvas_div);\n", "\n", " var canvas = (this.canvas = document.createElement('canvas'));\n", " canvas.classList.add('mpl-canvas');\n", " canvas.setAttribute('style', 'box-sizing: content-box;');\n", "\n", " this.context = canvas.getContext('2d');\n", "\n", " var backingStore =\n", " this.context.backingStorePixelRatio ||\n", " this.context.webkitBackingStorePixelRatio ||\n", " this.context.mozBackingStorePixelRatio ||\n", " this.context.msBackingStorePixelRatio ||\n", " this.context.oBackingStorePixelRatio ||\n", " this.context.backingStorePixelRatio ||\n", " 1;\n", "\n", " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", " 'canvas'\n", " ));\n", " rubberband_canvas.setAttribute(\n", " 'style',\n", " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", " );\n", "\n", " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", " if (this.ResizeObserver === undefined) {\n", " if (window.ResizeObserver !== undefined) {\n", " this.ResizeObserver = window.ResizeObserver;\n", " } else {\n", " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n", " this.ResizeObserver = obs.ResizeObserver;\n", " }\n", " }\n", "\n", " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n", " var nentries = entries.length;\n", " for (var i = 0; i < nentries; i++) {\n", " var entry = entries[i];\n", " var width, height;\n", " if (entry.contentBoxSize) {\n", " if (entry.contentBoxSize instanceof Array) {\n", " // Chrome 84 implements new version of spec.\n", " width = entry.contentBoxSize[0].inlineSize;\n", " height = entry.contentBoxSize[0].blockSize;\n", " } else {\n", " // Firefox implements old version of spec.\n", " width = entry.contentBoxSize.inlineSize;\n", " height = entry.contentBoxSize.blockSize;\n", " }\n", " } else {\n", " // Chrome <84 implements even older version of spec.\n", " width = entry.contentRect.width;\n", " height = entry.contentRect.height;\n", " }\n", "\n", " // Keep the size of the canvas and rubber band canvas in sync with\n", " // the canvas container.\n", " if (entry.devicePixelContentBoxSize) {\n", " // Chrome 84 implements new version of spec.\n", " canvas.setAttribute(\n", " 'width',\n", " entry.devicePixelContentBoxSize[0].inlineSize\n", " );\n", " canvas.setAttribute(\n", " 'height',\n", " entry.devicePixelContentBoxSize[0].blockSize\n", " );\n", " } else {\n", " canvas.setAttribute('width', width * fig.ratio);\n", " canvas.setAttribute('height', height * fig.ratio);\n", " }\n", " canvas.setAttribute(\n", " 'style',\n", " 'width: ' + width + 'px; height: ' + height + 'px;'\n", " );\n", "\n", " rubberband_canvas.setAttribute('width', width);\n", " rubberband_canvas.setAttribute('height', height);\n", "\n", " // And update the size in Python. We ignore the initial 0/0 size\n", " // that occurs as the element is placed into the DOM, which should\n", " // otherwise not happen due to the minimum size styling.\n", " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n", " fig.request_resize(width, height);\n", " }\n", " }\n", " });\n", " this.resizeObserverInstance.observe(canvas_div);\n", "\n", " function on_mouse_event_closure(name) {\n", " return function (event) {\n", " return fig.mouse_event(event, name);\n", " };\n", " }\n", "\n", " rubberband_canvas.addEventListener(\n", " 'mousedown',\n", " on_mouse_event_closure('button_press')\n", " );\n", " rubberband_canvas.addEventListener(\n", " 'mouseup',\n", " on_mouse_event_closure('button_release')\n", " );\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband_canvas.addEventListener(\n", " 'mousemove',\n", " on_mouse_event_closure('motion_notify')\n", " );\n", "\n", " rubberband_canvas.addEventListener(\n", " 'mouseenter',\n", " on_mouse_event_closure('figure_enter')\n", " );\n", " rubberband_canvas.addEventListener(\n", " 'mouseleave',\n", " on_mouse_event_closure('figure_leave')\n", " );\n", "\n", " canvas_div.addEventListener('wheel', function (event) {\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " on_mouse_event_closure('scroll')(event);\n", " });\n", "\n", " canvas_div.appendChild(canvas);\n", " canvas_div.appendChild(rubberband_canvas);\n", "\n", " this.rubberband_context = rubberband_canvas.getContext('2d');\n", " this.rubberband_context.strokeStyle = '#000000';\n", "\n", " this._resize_canvas = function (width, height, forward) {\n", " if (forward) {\n", " canvas_div.style.width = width + 'px';\n", " canvas_div.style.height = height + 'px';\n", " }\n", " };\n", "\n", " // Disable right mouse context menu.\n", " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", " event.preventDefault();\n", " return false;\n", " });\n", "\n", " function set_focus() {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "};\n", "\n", "mpl.figure.prototype._init_toolbar = function () {\n", " var fig = this;\n", "\n", " var toolbar = document.createElement('div');\n", " toolbar.classList = 'mpl-toolbar';\n", " this.root.appendChild(toolbar);\n", "\n", " function on_click_closure(name) {\n", " return function (_event) {\n", " return fig.toolbar_button_onclick(name);\n", " };\n", " }\n", "\n", " function on_mouseover_closure(tooltip) {\n", " return function (event) {\n", " if (!event.currentTarget.disabled) {\n", " return fig.toolbar_button_onmouseover(tooltip);\n", " }\n", " };\n", " }\n", "\n", " fig.buttons = {};\n", " var buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'mpl-button-group';\n", " for (var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " /* Instead of a spacer, we start a new button group. */\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", " buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'mpl-button-group';\n", " continue;\n", " }\n", "\n", " var button = (fig.buttons[name] = document.createElement('button'));\n", " button.classList = 'mpl-widget';\n", " button.setAttribute('role', 'button');\n", " button.setAttribute('aria-disabled', 'false');\n", " button.addEventListener('click', on_click_closure(method_name));\n", " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", "\n", " var icon_img = document.createElement('img');\n", " icon_img.src = '_images/' + image + '.png';\n", " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", " icon_img.alt = tooltip;\n", " button.appendChild(icon_img);\n", "\n", " buttonGroup.appendChild(button);\n", " }\n", "\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", "\n", " var fmt_picker = document.createElement('select');\n", " fmt_picker.classList = 'mpl-widget';\n", " toolbar.appendChild(fmt_picker);\n", " this.format_dropdown = fmt_picker;\n", "\n", " for (var ind in mpl.extensions) {\n", " var fmt = mpl.extensions[ind];\n", " var option = document.createElement('option');\n", " option.selected = fmt === mpl.default_extension;\n", " option.innerHTML = fmt;\n", " fmt_picker.appendChild(option);\n", " }\n", "\n", " var status_bar = document.createElement('span');\n", " status_bar.classList = 'mpl-message';\n", " toolbar.appendChild(status_bar);\n", " this.message = status_bar;\n", "};\n", "\n", "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", " // which will in turn request a refresh of the image.\n", " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", "};\n", "\n", "mpl.figure.prototype.send_message = function (type, properties) {\n", " properties['type'] = type;\n", " properties['figure_id'] = this.id;\n", " this.ws.send(JSON.stringify(properties));\n", "};\n", "\n", "mpl.figure.prototype.send_draw_message = function () {\n", " if (!this.waiting) {\n", " this.waiting = true;\n", " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", " var format_dropdown = fig.format_dropdown;\n", " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", " fig.ondownload(fig, format);\n", "};\n", "\n", "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", " var size = msg['size'];\n", " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", " fig._resize_canvas(size[0], size[1], msg['forward']);\n", " fig.send_message('refresh', {});\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", " var x0 = msg['x0'] / fig.ratio;\n", " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n", " var x1 = msg['x1'] / fig.ratio;\n", " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", " y1 = Math.floor(y1) + 0.5;\n", " var min_x = Math.min(x0, x1);\n", " var min_y = Math.min(y0, y1);\n", " var width = Math.abs(x1 - x0);\n", " var height = Math.abs(y1 - y0);\n", "\n", " fig.rubberband_context.clearRect(\n", " 0,\n", " 0,\n", " fig.canvas.width / fig.ratio,\n", " fig.canvas.height / fig.ratio\n", " );\n", "\n", " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", "};\n", "\n", "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", " // Updates the figure title.\n", " fig.header.textContent = msg['label'];\n", "};\n", "\n", "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", " var cursor = msg['cursor'];\n", " switch (cursor) {\n", " case 0:\n", " cursor = 'pointer';\n", " break;\n", " case 1:\n", " cursor = 'default';\n", " break;\n", " case 2:\n", " cursor = 'crosshair';\n", " break;\n", " case 3:\n", " cursor = 'move';\n", " break;\n", " }\n", " fig.rubberband_canvas.style.cursor = cursor;\n", "};\n", "\n", "mpl.figure.prototype.handle_message = function (fig, msg) {\n", " fig.message.textContent = msg['message'];\n", "};\n", "\n", "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", " // Request the server to send over a new figure.\n", " fig.send_draw_message();\n", "};\n", "\n", "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", " fig.image_mode = msg['mode'];\n", "};\n", "\n", "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", " for (var key in msg) {\n", " if (!(key in fig.buttons)) {\n", " continue;\n", " }\n", " fig.buttons[key].disabled = !msg[key];\n", " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", " if (msg['mode'] === 'PAN') {\n", " fig.buttons['Pan'].classList.add('active');\n", " fig.buttons['Zoom'].classList.remove('active');\n", " } else if (msg['mode'] === 'ZOOM') {\n", " fig.buttons['Pan'].classList.remove('active');\n", " fig.buttons['Zoom'].classList.add('active');\n", " } else {\n", " fig.buttons['Pan'].classList.remove('active');\n", " fig.buttons['Zoom'].classList.remove('active');\n", " }\n", "};\n", "\n", "mpl.figure.prototype.updated_canvas_event = function () {\n", " // Called whenever the canvas gets updated.\n", " this.send_message('ack', {});\n", "};\n", "\n", "// A function to construct a web socket function for onmessage handling.\n", "// Called in the figure constructor.\n", "mpl.figure.prototype._make_on_message_function = function (fig) {\n", " return function socket_on_message(evt) {\n", " if (evt.data instanceof Blob) {\n", " /* FIXME: We get \"Resource interpreted as Image but\n", " * transferred with MIME type text/plain:\" errors on\n", " * Chrome. But how to set the MIME type? It doesn't seem\n", " * to be part of the websocket stream */\n", " evt.data.type = 'image/png';\n", "\n", " /* Free the memory for the previous frames */\n", " if (fig.imageObj.src) {\n", " (window.URL || window.webkitURL).revokeObjectURL(\n", " fig.imageObj.src\n", " );\n", " }\n", "\n", " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", " evt.data\n", " );\n", " fig.updated_canvas_event();\n", " fig.waiting = false;\n", " return;\n", " } else if (\n", " typeof evt.data === 'string' &&\n", " evt.data.slice(0, 21) === 'data:image/png;base64'\n", " ) {\n", " fig.imageObj.src = evt.data;\n", " fig.updated_canvas_event();\n", " fig.waiting = false;\n", " return;\n", " }\n", "\n", " var msg = JSON.parse(evt.data);\n", " var msg_type = msg['type'];\n", "\n", " // Call the \"handle_{type}\" callback, which takes\n", " // the figure and JSON message as its only arguments.\n", " try {\n", " var callback = fig['handle_' + msg_type];\n", " } catch (e) {\n", " console.log(\n", " \"No handler for the '\" + msg_type + \"' message type: \",\n", " msg\n", " );\n", " return;\n", " }\n", "\n", " if (callback) {\n", " try {\n", " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", " callback(fig, msg);\n", " } catch (e) {\n", " console.log(\n", " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", " e,\n", " e.stack,\n", " msg\n", " );\n", " }\n", " }\n", " };\n", "};\n", "\n", "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", "mpl.findpos = function (e) {\n", " //this section is from http://www.quirksmode.org/js/events_properties.html\n", " var targ;\n", " if (!e) {\n", " e = window.event;\n", " }\n", " if (e.target) {\n", " targ = e.target;\n", " } else if (e.srcElement) {\n", " targ = e.srcElement;\n", " }\n", " if (targ.nodeType === 3) {\n", " // defeat Safari bug\n", " targ = targ.parentNode;\n", " }\n", "\n", " // pageX,Y are the mouse positions relative to the document\n", " var boundingRect = targ.getBoundingClientRect();\n", " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", "\n", " return { x: x, y: y };\n", "};\n", "\n", "/*\n", " * return a copy of an object with only non-object keys\n", " * we need this to avoid circular references\n", " * http://stackoverflow.com/a/24161582/3208463\n", " */\n", "function simpleKeys(original) {\n", " return Object.keys(original).reduce(function (obj, key) {\n", " if (typeof original[key] !== 'object') {\n", " obj[key] = original[key];\n", " }\n", " return obj;\n", " }, {});\n", "}\n", "\n", "mpl.figure.prototype.mouse_event = function (event, name) {\n", " var canvas_pos = mpl.findpos(event);\n", "\n", " if (name === 'button_press') {\n", " this.canvas.focus();\n", " this.canvas_div.focus();\n", " }\n", "\n", " var x = canvas_pos.x * this.ratio;\n", " var y = canvas_pos.y * this.ratio;\n", "\n", " this.send_message(name, {\n", " x: x,\n", " y: y,\n", " button: event.button,\n", " step: event.step,\n", " guiEvent: simpleKeys(event),\n", " });\n", "\n", " /* This prevents the web browser from automatically changing to\n", " * the text insertion cursor when the button is pressed. We want\n", " * to control all of the cursor setting manually through the\n", " * 'cursor' event from matplotlib */\n", " event.preventDefault();\n", " return false;\n", "};\n", "\n", "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", " // Handle any extra behaviour associated with a key event\n", "};\n", "\n", "mpl.figure.prototype.key_event = function (event, name) {\n", " // Prevent repeat events\n", " if (name === 'key_press') {\n", " if (event.which === this._key) {\n", " return;\n", " } else {\n", " this._key = event.which;\n", " }\n", " }\n", " if (name === 'key_release') {\n", " this._key = null;\n", " }\n", "\n", " var value = '';\n", " if (event.ctrlKey && event.which !== 17) {\n", " value += 'ctrl+';\n", " }\n", " if (event.altKey && event.which !== 18) {\n", " value += 'alt+';\n", " }\n", " if (event.shiftKey && event.which !== 16) {\n", " value += 'shift+';\n", " }\n", "\n", " value += 'k';\n", " value += event.which.toString();\n", "\n", " this._key_event_extra(event, name);\n", "\n", " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", " return false;\n", "};\n", "\n", "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", " if (name === 'download') {\n", " this.handle_save(this, null);\n", " } else {\n", " this.send_message('toolbar_button', { name: name });\n", " }\n", "};\n", "\n", "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", "\n", "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", "// prettier-ignore\n", "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n", "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", "\n", "mpl.default_extension = \"png\";/* global mpl */\n", "\n", "var comm_websocket_adapter = function (comm) {\n", " // Create a \"websocket\"-like object which calls the given IPython comm\n", " // object with the appropriate methods. Currently this is a non binary\n", " // socket, so there is still some room for performance tuning.\n", " var ws = {};\n", "\n", " ws.close = function () {\n", " comm.close();\n", " };\n", " ws.send = function (m) {\n", " //console.log('sending', m);\n", " comm.send(m);\n", " };\n", " // Register the callback with on_msg.\n", " comm.on_msg(function (msg) {\n", " //console.log('receiving', msg['content']['data'], msg);\n", " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", " ws.onmessage(msg['content']['data']);\n", " });\n", " return ws;\n", "};\n", "\n", "mpl.mpl_figure_comm = function (comm, msg) {\n", " // This is the function which gets called when the mpl process\n", " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", "\n", " var id = msg.content.data.id;\n", " // Get hold of the div created by the display call when the Comm\n", " // socket was opened in Python.\n", " var element = document.getElementById(id);\n", " var ws_proxy = comm_websocket_adapter(comm);\n", "\n", " function ondownload(figure, _format) {\n", " window.open(figure.canvas.toDataURL());\n", " }\n", "\n", " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", "\n", " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", " // web socket which is closed, not our websocket->open comm proxy.\n", " ws_proxy.onopen();\n", "\n", " fig.parent_element = element;\n", " fig.cell_info = mpl.find_output_cell(\"
\");\n", " if (!fig.cell_info) {\n", " console.error('Failed to find cell for figure', id, fig);\n", " return;\n", " }\n", " fig.cell_info[0].output_area.element.on(\n", " 'cleared',\n", " { fig: fig },\n", " fig._remove_fig_handler\n", " );\n", "};\n", "\n", "mpl.figure.prototype.handle_close = function (fig, msg) {\n", " var width = fig.canvas.width / fig.ratio;\n", " fig.cell_info[0].output_area.element.off(\n", " 'cleared',\n", " fig._remove_fig_handler\n", " );\n", " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n", "\n", " // Update the output cell to use the data from the current canvas.\n", " fig.push_to_output();\n", " var dataURL = fig.canvas.toDataURL();\n", " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable();\n", " fig.parent_element.innerHTML =\n", " '';\n", " fig.close_ws(fig, msg);\n", "};\n", "\n", "mpl.figure.prototype.close_ws = function (fig, msg) {\n", " fig.send_message('closing', msg);\n", " // fig.ws.close()\n", "};\n", "\n", "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", " var width = this.canvas.width / this.ratio;\n", " var dataURL = this.canvas.toDataURL();\n", " this.cell_info[1]['text/html'] =\n", " '';\n", "};\n", "\n", "mpl.figure.prototype.updated_canvas_event = function () {\n", " // Tell IPython that the notebook contents must change.\n", " IPython.notebook.set_dirty(true);\n", " this.send_message('ack', {});\n", " var fig = this;\n", " // Wait a second, then push the new image to the DOM so\n", " // that it is saved nicely (might be nice to debounce this).\n", " setTimeout(function () {\n", " fig.push_to_output();\n", " }, 1000);\n", "};\n", "\n", "mpl.figure.prototype._init_toolbar = function () {\n", " var fig = this;\n", "\n", " var toolbar = document.createElement('div');\n", " toolbar.classList = 'btn-toolbar';\n", " this.root.appendChild(toolbar);\n", "\n", " function on_click_closure(name) {\n", " return function (_event) {\n", " return fig.toolbar_button_onclick(name);\n", " };\n", " }\n", "\n", " function on_mouseover_closure(tooltip) {\n", " return function (event) {\n", " if (!event.currentTarget.disabled) {\n", " return fig.toolbar_button_onmouseover(tooltip);\n", " }\n", " };\n", " }\n", "\n", " fig.buttons = {};\n", " var buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'btn-group';\n", " var button;\n", " for (var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " /* Instead of a spacer, we start a new button group. */\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", " buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'btn-group';\n", " continue;\n", " }\n", "\n", " button = fig.buttons[name] = document.createElement('button');\n", " button.classList = 'btn btn-default';\n", " button.href = '#';\n", " button.title = name;\n", " button.innerHTML = '';\n", " button.addEventListener('click', on_click_closure(method_name));\n", " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", " buttonGroup.appendChild(button);\n", " }\n", "\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = document.createElement('span');\n", " status_bar.classList = 'mpl-message pull-right';\n", " toolbar.appendChild(status_bar);\n", " this.message = status_bar;\n", "\n", " // Add the close button to the window.\n", " var buttongrp = document.createElement('div');\n", " buttongrp.classList = 'btn-group inline pull-right';\n", " button = document.createElement('button');\n", " button.classList = 'btn btn-mini btn-primary';\n", " button.href = '#';\n", " button.title = 'Stop Interaction';\n", " button.innerHTML = '';\n", " button.addEventListener('click', function (_evt) {\n", " fig.handle_close(fig, {});\n", " });\n", " button.addEventListener(\n", " 'mouseover',\n", " on_mouseover_closure('Stop Interaction')\n", " );\n", " buttongrp.appendChild(button);\n", " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", "};\n", "\n", "mpl.figure.prototype._remove_fig_handler = function (event) {\n", " var fig = event.data.fig;\n", " if (event.target !== this) {\n", " // Ignore bubbled events from children.\n", " return;\n", " }\n", " fig.close_ws(fig, {});\n", "};\n", "\n", "mpl.figure.prototype._root_extra_style = function (el) {\n", " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", "};\n", "\n", "mpl.figure.prototype._canvas_extra_style = function (el) {\n", " // this is important to make the div 'focusable\n", " el.setAttribute('tabindex', 0);\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " } else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "};\n", "\n", "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager) {\n", " manager = IPython.keyboard_manager;\n", " }\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which === 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", " fig.ondownload(fig, null);\n", "};\n", "\n", "mpl.find_output_cell = function (html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i = 0; i < ncells; i++) {\n", " var cell = cells[i];\n", " if (cell.cell_type === 'code') {\n", " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", " var data = cell.output_area.outputs[j];\n", " if (data.data) {\n", " // IPython >= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] === html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "};\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel !== null) {\n", " IPython.notebook.kernel.comm_manager.register_target(\n", " 'matplotlib',\n", " mpl.mpl_figure_comm\n", " );\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "152651dae5074d6098961e4df188b710", "version_major": 2, "version_minor": 0 }, "text/plain": [ "HBox(children=(Text(value='BEcKPFM_2um_0012.png', description='Output Filename:', layout=Layout(width='50%'), …" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "aff983a27acf4e14aed0fdb5a41b2e4e", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(IntSlider(value=0, description='Step', max=54560), Output()), _dom_classes=('widget-inte…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = belib.viz.be_viz_utils.jupyter_visualize_be_spectrograms(h5_main)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\n", "located at: \n", "\t/Measurement_000/Channel_000/Raw_Data \n", "Data contains: \n", "\tquantity (a.u.) \n", "Data dimensions and original shape: \n", "Position Dimensions: \n", "\tX - size: 10 \n", "\tY - size: 10 \n", "Spectroscopic Dimensions: \n", "\tFrequency - size: 124 \n", "\tField - size: 2 \n", "\twrite_bias - size: 20 \n", "\tread_bias - size: 11\n", "Data Type:\n", "\tcomplex64" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h5_main" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Fit the Band Excitation (BE) spectra\n", "Fit each of the acquired spectra to a simple harmonic oscillator (SHO) model to extract the following information regarding the response:\n", "* Oscillation amplitude\n", "* Phase\n", "* Resonance frequency\n", "* Quality factor\n", "\n", "By default, the cell below will take any previous result instead of re-computing the SHO fit" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Consider calling test() to check results before calling compute() which computes on the entire dataset and writes results to the HDF5 file\n", "Group: had neither the status HDF5 dataset or the legacy attribute: \"last_pixel\".\n", "\n", "Note: SHO_Fit has already been performed with the same parameters before. These results will be returned by compute() by default. Set override to True to force fresh computation\n", "\n", "[]\n", "\n", "Note: SHO_Fit has already been performed with the same parameters before. These results will be returned by compute() by default. Set override to True to force fresh computation\n", "\n", "[]\n", "Returned previously computed results at /Measurement_000/Channel_000/Raw_Data-SHO_Fit_001\n", "\n", "Note: SHO_Fit has already been performed with the same parameters before. These results will be returned by compute() by default. Set override to True to force fresh computation\n", "\n", "[]\n", "Returned previously computed results at /Measurement_000/Channel_000/Raw_Data-SHO_Fit_001\n" ] } ], "source": [ "sho_fit_points = 5 # The number of data points at each step to use when fitting\n", "sho_override = False # Force recompute if True\n", "results_to_new_file = False\n", "\n", "h5_sho_targ_grp = None\n", "if results_to_new_file:\n", " h5_sho_file_path = os.path.join(folder_path, \n", " h5_raw_file_name.replace('.h5', '_sho_fit.h5'))\n", " print('\\n\\nSHO Fits will be written to:\\n' + h5_sho_file_path + '\\n\\n')\n", " f_open_mode = 'w'\n", " if os.path.exists(h5_sho_file_path):\n", " f_open_mode = 'r+'\n", " h5_sho_file = h5py.File(h5_sho_file_path, mode=f_open_mode)\n", " h5_sho_targ_grp = h5_sho_file\n", " \n", "sho_fitter = belib.analysis.BESHOfitter(h5_main, cores=max_cores, verbose=False, h5_target_group=h5_sho_targ_grp)\n", "sho_fitter.set_up_guess(guess_func=belib.analysis.be_sho_fitter.SHOGuessFunc.complex_gaussian,\n", " num_points=sho_fit_points)\n", "h5_sho_guess = sho_fitter.do_guess(override=sho_override)\n", "sho_fitter.set_up_fit()\n", "h5_sho_fit = sho_fitter.do_fit(override=sho_override)\n", "h5_sho_grp = h5_sho_fit.parent" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# cKPFM data analysis\n", "\n", "- Specify the output file path where the figures should be saved to.\n", "- Set high_voltage_amplf to 10 if a high voltage amplifier was used, otherwise set to 1" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# Specify output file path, default is the same directory as the data\n", "output_file_path = data_dir\n", "\n", "# If HV amplifier was used set high_voltage_amplf to 10, else to 1\n", "high_voltage_amplf = 1\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Remove phase offset\n", "\n", "If removing the instrumental phase offset is not desired, set phase_offset = 0" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Nd_mat shape = (10, 10, 2, 20, 11)\n", "Phase offset [rad] = -0.3490023\n" ] } ], "source": [ "Nd_mat = h5_sho_fit.get_n_dim_form()\n", "print('Nd_mat shape = ', Nd_mat.shape)\n", "\n", "phase_offset = Nd_mat[0, 0, 1, 0, 0]['Phase [rad]']\n", "\n", "print('Phase offset [rad] = ', phase_offset)\n", "\n", "Nd_mat[:,:,:,:,:]['Phase [rad]'] = Nd_mat[:,:,:,:,:]['Phase [rad]'] - phase_offset\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Display cKPFM data\n", "The figure shows:\n", "\n", "- Read and write voltage steps with the selected step marked as a red dot\n", "- Response map at read and write voltage steps selected with sliders\n", "- Real component of the response at selected read and write steps and x/y coordinates -> select option\n", "- Response at each write step (x-axis) after each write pulse (color coded)\n", "\n", "The 'Save figure' button saves the displayed figure in the above specified output file path as tiff, png and eps file. Alternatively, figures can be copy pasted into other programs like Powerpoint or Word.\n", "\n", "#### Select display option by setting 'option = 1' or 'option = 2' in the second line of the code\n", "- Option 1: display response curves from the maximum write step to the minimum write step\n", "- Option 2: display response curves from all write voltages" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "def plot_line_family(axis, x_vec, line_family, line_names=None, label_prefix='', label_suffix='',\n", " y_offset=0, show_cbar=False, **kwargs):\n", " \"\"\"\n", " Plots a family of lines with a sequence of colors\n", "\n", " Parameters\n", " ----------\n", " axis : matplotlib.axes.Axes object\n", " Axis to plot the curve\n", " x_vec : array-like\n", " Values to plot against\n", " line_family : 2D numpy array\n", " family of curves arranged as [curve_index, features]\n", " line_names : array-like\n", " array of string or numbers that represent the identity of each curve in the family\n", " label_prefix : string / unicode\n", " prefix for the legend (before the index of the curve)\n", " label_suffix : string / unicode\n", " suffix for the legend (after the index of the curve)\n", " y_offset : (optional) number\n", " quantity by which the lines are offset from each other vertically (useful for spectra)\n", " show_cbar : (optional) bool\n", " Whether or not to show a colorbar (instead of a legend)\n", "\n", " \"\"\"\n", " \n", " x_vec = np.array(x_vec)\n", " #assert x_vec.ndim == 1, 'x_vec must be a 1D array'\n", " if not isinstance(line_family, list):\n", " line_family = np.array(line_family)\n", " \n", " assert line_family.ndim == 2, 'line_family must be a 2D array'\n", " # assert x_vec.shape[1] == line_family.shape[1], \\\n", " # 'The size of the 2nd dimension of line_family must match with of x_vec, but line fam has shape {} whereas xvec has shape {}'.format(line_family.shape, x_vec.shape)\n", " num_lines = line_family.shape[0]\n", "\n", "\n", " if line_names is None:\n", " # label_prefix = 'Line '\n", " line_names = [str(line_ind) for line_ind in range(num_lines)]\n", "\n", " line_names = ['{} {} {}'.format(label_prefix, cur_name, label_suffix) for cur_name in line_names]\n", " \n", " print(\"Line family shape is {}\".format(line_family.shape))\n", " \n", " for line_ind in range(num_lines):\n", " colors = plt.cm.get_cmap('jet', line_family.shape[-1])\n", " axis.plot(x_vec, line_family[line_ind] + line_ind * y_offset,\n", " color = colors(line_ind),\n", " )\n", "\n", " if show_cbar:\n", " # put back the cmap parameter:\n", " kwargs.update({'cmap': cmap})\n", " _ = cbar_for_line_plot(axis, num_lines, **kwargs)\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "No position datasets found as attributes of /Measurement_000/Channel_000/Raw_Data-SHO_Fit_001/Spectroscopic_Values\n", "These are the labels ['Field', 'write_bias', 'read_bias']\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "50c885d737f94ec0b43c9208e378df00", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(IntSlider(value=4, continuous_update=False, description='Read step', max=10), IntSlider(…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "96f2b5e49bb74f20a02a1666ef959ed8", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Button(description='Save figure', style=ButtonStyle())" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "global option, save_figure \n", "# Option 1: only show curves from maximum to minimum write voltage\n", "# Option 2: Show all curves from the whole write voltage waveform\n", "option = 1 \n", "save_figure = False # Save the figure after being generated if True\n", "\n", "h5_sho_spec_inds = h5_sho_fit.h5_spec_inds\n", "h5_sho_spec_vals = h5_sho_fit.h5_spec_vals\n", "\n", "sho_spec_labels = h5_sho_fit.spec_dim_labels\n", "pos_labels = h5_sho_fit.pos_dim_labels\n", "\n", "num_fields = h5_sho_fit.spec_dim_sizes[h5_sho_fit.spec_dim_labels.index('Field')]\n", "num_write_steps = h5_sho_fit.spec_dim_sizes[h5_sho_fit.spec_dim_labels.index('write_bias')]\n", "num_read_steps = h5_sho_fit.spec_dim_sizes[h5_sho_fit.spec_dim_labels.index('read_bias')]\n", "\n", "# It turns out that the read voltage index starts from 1 instead of 0\n", "# Also the VDC indices are NOT repeating. They are just rising monotonically\n", "write_volt_index = sho_spec_labels.index('write_bias')\n", "read_volt_index = sho_spec_labels.index('read_bias')\n", "h5_sho_spec_inds[read_volt_index, :] -= np.min(h5_sho_spec_inds[read_volt_index, :])\n", "h5_sho_spec_inds[write_volt_index, :] = np.tile(np.repeat(np.arange(num_write_steps), num_fields), num_read_steps)\n", "\n", "# Get the bias matrix:\n", "bias_mat, _ = usid.hdf_utils.reshape_to_n_dims(h5_sho_spec_vals, h5_spec=h5_sho_spec_inds)\n", "bias_vec_r_all = bias_mat[read_volt_index]*high_voltage_amplf\n", "bias_vec_w_all = bias_mat[write_volt_index]*high_voltage_amplf\n", "bias_vec_w = bias_vec_w_all.reshape(h5_sho_fit.spec_dim_sizes)[1, :, 1]\n", "bias_vec_r = bias_vec_r_all.reshape(h5_sho_fit.spec_dim_sizes)[1, :, :]\n", "\n", "# Option 1: only show curves from maximum to minimum write voltage:\n", "if option == 1:\n", " write_step_start = np.argmax(bias_vec_w)\n", " write_step_end = np.argmin(bias_vec_w)\n", "\n", "# ption 2: show all curves from the whole write voltage waveform\n", "if option == 2:\n", " write_step_start = 0\n", " write_step_end = num_write_steps-1\n", "\n", "bias_vec_r_display = np.transpose(bias_vec_r[write_step_start:write_step_end+1,:])\n", "\n", "print('These are the labels', sho_spec_labels)\n", "\n", "nd_labels = h5_sho_fit.n_dim_labels\n", "\n", "num_read_steps = Nd_mat.shape[nd_labels.index('read_bias')]\n", "num_write_steps = Nd_mat.shape[nd_labels.index('write_bias')]\n", "num_row = Nd_mat.shape[nd_labels.index('Y')]\n", "num_col = Nd_mat.shape[nd_labels.index('X')]\n", "\n", "# Indices of initial data points to plot\n", "row = 0\n", "col = 0\n", "field = 1\n", "dc_step_read = 0\n", "dc_step_write = 0\n", "\n", "# Select color scale range for map here\n", "cmin = -0.0001\n", "cmax = 0.0001\n", "\n", "# Get the read and write data to plot\n", "resp_vec_w = Nd_mat[row,col,field,:,dc_step_read]['Amplitude [V]'] * np.cos(Nd_mat[row,col,field,:,dc_step_read]['Phase [rad]'])*1000\n", "\n", "resp_mat_r = Nd_mat[:,:,1,dc_step_write,dc_step_read]['Amplitude [V]'] * np.cos(Nd_mat[:,:,1,dc_step_write,dc_step_read]['Phase [rad]'])*1000\n", "\n", "resp_vec_r = np.squeeze(Nd_mat[:,:,1,write_step_start:write_step_end+1,:]['Amplitude [V]'] \n", " * np.cos(Nd_mat[:,:,1,write_step_start:write_step_end+1,:]['Phase [rad]'])*1000)\n", "\n", "\n", "def make_figure(resp_mat_r, resp_vec_r, resp_vec_w, dc_step_read, dc_step_write, col, row):\n", " global save_figure\n", " plt.clf();\n", " fig = plt.figure(figsize=(13, 9))\n", " fig.set_facecolor('white')\n", " \n", " ax_bias_w = plt.subplot2grid((20, 2), (0, 0), colspan=1, rowspan=3)\n", " ax_bias_r = plt.subplot2grid((20, 2), (5, 0), colspan=1, rowspan=3)\n", " ax_loop_w = plt.subplot2grid((20, 2), (0, 1), colspan=1, rowspan=7)\n", " ax_loop_r = plt.subplot2grid((20, 2), (9, 1), colspan=1, rowspan=8)\n", " ax_colorbar = plt.subplot2grid((20, 2), (19, 1), colspan=1, rowspan=1)\n", " ax_map = plt.subplot2grid((20, 2), (10, 0), colspan=1, rowspan=11)\n", " \n", " \n", " \n", " ax_bias_w.set_xlabel('Step', fontsize = 12)\n", " ax_bias_w.set_ylabel('Write voltage [V]', fontsize = 12)\n", " ax_bias_r.set_xlabel('Step', fontsize = 12)\n", " ax_bias_r.set_ylabel('Read voltage [V]', fontsize = 12)\n", " ax_loop_w.set_ylabel('Response [a.u.]', fontsize = 12)\n", " ax_loop_w.set_xlabel('Write voltage [V]', fontsize = 12)\n", " ax_loop_r.set_ylabel('Response [a.u.]', fontsize = 12)\n", " ax_loop_r.set_xlabel('Read voltage [V]', fontsize = 12)\n", "\n", " # Title saying read and write voltages\n", " fig.suptitle('Read voltage = '+str(bias_vec_r[1,dc_step_read])+' V, Write voltage = ' +str(bias_vec_w[dc_step_write])+' V'\n", " ', x = '+str(col)+', y = '+str(row), fontsize = 14);\n", " \n", " co_b = ax_map.imshow(resp_mat_r, cmap = sidpy.plot_utils.cmap_jet_white_center(), origin='upper', \n", " interpolation='none');\n", " cb = fig.colorbar(co_b)\n", " \n", " #Graph of DC write voltage\n", " ax_bias_w.plot(bias_vec_w,'b.');\n", " ax_bias_w.plot(dc_step_write,bias_vec_w[dc_step_write],'r.');\n", " ax_bias_w.set_ylim([np.min(bias_vec_w)-0.5, np.max(bias_vec_w)+0.5])\n", " \n", " #Graph of DC read voltage\n", " ax_bias_r.plot(np.transpose(bias_vec_r[1]),'b.');\n", " ax_bias_r.plot(dc_step_read,np.transpose(bias_vec_r[1,dc_step_read]),'r.');\n", " ax_bias_r.set_ylim([np.min(bias_vec_r)-0.5, np.max(bias_vec_r)+0.5])\n", " \n", " #Graph of response loop (amplitude * cos(phase)) vs write voltage at selected x, y and read step\n", " ax_loop_w.plot(bias_vec_w, resp_vec_w,'.-');\n", " \n", " #Response loops (amplitude * cos(phase)) of all write voltage steps (color coded) vs read voltage at selected x, y\n", " plot_line_family(ax_loop_r, bias_vec_r_display[:, :], \n", " resp_vec_r, line_names='None',\n", " label_prefix='Line', label_suffix='')\n", " \n", " if option == 1:\n", " colorbar_mat = np.column_stack((range(write_step_start,write_step_end+1),range(write_step_start,write_step_end+1)))\n", " ax_colorbar.imshow(np.transpose(colorbar_mat[:,:]), cmap=plt.cm.jet, origin='lower', interpolation='none')\n", " ax_colorbar.set_yticklabels('')\n", " ax_colorbar.tick_params(axis = 'y', left = 'off', right = 'off')\n", " plt.sca(ax_colorbar)\n", " plt.xticks([0,write_step_end-write_step_start],[bias_vec_w[write_step_start],bias_vec_w[write_step_end]])\n", " ax_colorbar.set_xlabel('Write voltage [V]', fontsize = 12)\n", " \n", " if option == 2:\n", " colorbar_mat = np.column_stack((range(0,num_write_steps-1),range(0,num_write_steps-1)))\n", " ax_colorbar.imshow(np.transpose(colorbar_mat[:,:]), cmap=plt.cm.jet, origin='lower', interpolation='none')\n", " ax_colorbar.set_yticklabels('')\n", " ax_colorbar.tick_params(axis = 'y', left = 'off', right = 'off')\n", " ax_colorbar.set_xlabel('Write voltage step', fontsize = 12)\n", " \n", " \n", " if save_figure == True:\n", " fig.savefig(output_file_path+'\\cb_cKPFM_Vr'+str(dc_step_read)+'_Vw'+str(dc_step_write)+'_x='+str(col)+'_y='+str(row)+'.png', format='png')\n", " fig.savefig(output_file_path+'\\cb_cKPFM_Vr'+str(dc_step_read)+'_Vw'+str(dc_step_write)+'_x='+str(col)+'_y='+str(row)+'.eps', format='eps')\n", " fig.savefig(output_file_path+'\\cb_cKPFM_Vr'+str(dc_step_read)+'_Vw'+str(dc_step_write)+'_x='+str(col)+'_y='+str(row)+'.tif', format='tiff')\n", " save_figure = False\n", "\n", " \n", "def update_sho_plots(dc_step_read, dc_step_write, col, row, **kwargs):\n", " resp_vec_w = Nd_mat[row,col,field,:,dc_step_read]['Amplitude [V]'] * np.cos(Nd_mat[row,col,field,:,dc_step_read]['Phase [rad]'])*1000\n", " resp_vec_w = Nd_mat[row,col,field,:,dc_step_read]['Amplitude [V]'] * np.cos(Nd_mat[row,col,field,:,dc_step_read]['Phase [rad]'])*1000\n", " resp_mat_r = Nd_mat[:,:,1,dc_step_write,dc_step_read]['Amplitude [V]'] * np.cos(Nd_mat[:,:,1,dc_step_write,dc_step_read]['Phase [rad]'])*1000\n", " resp_vec_r = (Nd_mat[row,col,field,write_step_start:write_step_end+1,:]['Amplitude [V]'] \n", " * np.cos(Nd_mat[row,col,field,write_step_start:write_step_end+1,:]['Phase [rad]'])*1000)\n", "\n", " make_figure(resp_mat_r, resp_vec_r, resp_vec_w, dc_step_read, dc_step_write, col, row)\n", " \n", " \n", "def on_save_button_clicked(b):\n", " global save_figure \n", " save_figure = True\n", " dc_step_read = dc_step_read_slider.value\n", " dc_step_write = dc_step_write_slider.value\n", " col = x_slider.value\n", " row = y_slider.value\n", " \n", " update_sho_plots(dc_step_read,dc_step_write, col, row)\n", " \n", "\n", "slider_dict = dict() \n", "\n", "dc_step_read_slider = widgets.IntSlider(min = 0, max = num_read_steps-1, step = 1,value = 4,\n", " description = 'Read step',continuous_update = False);\n", "dc_step_write_slider = widgets.IntSlider(min = 0, max = num_write_steps-1, step = 1,value = 0,\n", " description = 'Write step', continuous_update = False);\n", "x_slider = widgets.IntSlider(min = 0, max = num_col-1,step = 1,value = 0,\n", " description='x',continuous_update = False);\n", "y_slider = widgets.IntSlider(min = 0,max = num_row-1,step = 1,value = 0,\n", " description = 'y',continuous_update = False);\n", "\n", "widgets.interact(update_sho_plots,dc_step_read=dc_step_read_slider,dc_step_write=dc_step_write_slider, col = x_slider, row = y_slider, **slider_dict); \n", "\n", "button = widgets.Button(description = 'Save figure')\n", "display(button)\n", "button.on_click(on_save_button_clicked)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Display averaged cKPFM data\n", "\n", "Figures show response at each write step (x-axis) after each write pulse (color coded) averaged over the whole map (left) and averaged over the area selected with x- and y-range sliders (right).\n", "\n", "#### Select display option by setting 'option = 1' or 'option = 2' in the first line of the code\n", "- Option 1: display response curves from the maximum write step to the minimum write step\n", "- Option 2: display response curves from all write voltages" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "scrolled": false }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "495b331624074b93b84c2da7489b6ad6", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(IntRangeSlider(value=(2, 6), continuous_update=False, description='x-range', max=9), Int…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "a1d6353a5d2246c2ba5599da2c36d24d", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Button(description='Save figure', style=ButtonStyle())" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "option = 1\n", "\n", "# Option 1: only show curves from maximum to minimum write voltage:\n", "if option == 1:\n", " write_step_start = np.argmax(bias_vec_w)\n", " write_step_end = np.argmin(bias_vec_w)\n", "\n", "# Option 2: show all curves from the whole write voltage waveform\n", "if option == 2:\n", " write_step_start = 0\n", " write_step_end = num_write_steps-1\n", "\n", " \n", "bias_vec_r_display = np.transpose(bias_vec_r[write_step_start:write_step_end+1,:])\n", "\n", "num_display_steps = bias_vec_r_display.shape[1]\n", "\n", "\n", "global save_figure_vsr\n", "\n", "save_figure_vsr = False\n", "\n", "\n", "resp_mat_vsr = np.squeeze(Nd_mat[:,:,1,write_step_start:write_step_end+1,:]['Amplitude [V]'] \n", " * np.cos(Nd_mat[:,:,1,write_step_start:write_step_end+1,:]['Phase [rad]'])*1000)\n", "\n", "# Calculate response at 0 V read voltage averaged over all pixels\n", "resp_vsr_mean1 = np.nanmean(resp_mat_vsr,axis = 0)\n", "resp_vsr_std1 = np.nanstd(resp_mat_vsr,axis = 0)\n", "resp_vsr_mean = np.nanmean(resp_vsr_mean1,axis = 0)\n", "resp_vsr_std = np.nanstd(resp_vsr_std1,axis = 0)\n", "\n", "\n", "def make_figure_respvsr(resp_vsr_mean_range, resp_vsr_std_range, x_range, y_range):\n", " global save_figure_vsr\n", " \n", " fig_vsr = plt.figure(figsize=(12,5)) \n", " fig_vsr.clf()\n", " fig_vsr.set_facecolor('white')\n", " ax_plot = plt.subplot2grid((5, 2), (0, 0), colspan=1, rowspan=4)\n", " ax_plot_range = plt.subplot2grid((5, 2), (0, 1), colspan=1, rowspan=4)\n", " ax_colorbar = plt.subplot2grid((5, 2), (4, 0), colspan=1, rowspan=1)\n", " ax_colorbar2 = plt.subplot2grid((5, 2), (4, 1), colspan=1, rowspan=1)\n", "\n", " plot_line_family(ax_plot, bias_vec_r_display[:, :], \n", " resp_vsr_mean[:, :], line_names='None',label_prefix='Line', \n", " label_suffix='', cmap=plt.cm.jet)\n", " plot_line_family(ax_plot_range, bias_vec_r_display[:, :], \n", " resp_vsr_mean_range[:, :], line_names='None',\n", " label_prefix='Line', label_suffix='', cmap=plt.cm.jet)\n", " \n", " ax_plot.set_xlabel('Read voltage [V]', fontsize = 12)\n", " ax_plot.set_ylabel('Response [a.u.]', fontsize = 12)\n", " ax_plot.set_title('Averaged over whole map', fontsize = 12)\n", " \n", " ax_plot_range.set_xlabel('Read voltage [V]', fontsize = 12)\n", " ax_plot_range.set_ylabel('Response [a.u.]', fontsize = 12)\n", " ax_plot_range.set_title('Averaged x = '+str(x_range[0])+' - '+str(x_range[1])\n", " +', y = '+str(y_range[0])+' - '+str(y_range[1]), fontsize = 12)\n", " if option == 1:\n", " colorbar_mat = np.column_stack((range(write_step_start,write_step_end+1),range(write_step_start,write_step_end+1)))\n", " ax_colorbar.imshow(np.transpose(colorbar_mat[:,:]), cmap=plt.cm.jet, origin='lower', interpolation='none')\n", " ax_colorbar.set_yticklabels('')\n", " ax_colorbar.tick_params(axis = 'y', left = 'off', right = 'off')\n", " plt.sca(ax_colorbar)\n", " plt.xticks([0,write_step_end-write_step_start],[bias_vec_w[write_step_start],bias_vec_w[write_step_end]])\n", " ax_colorbar.set_xlabel('Write voltage [V]', fontsize = 12)\n", " \n", " ax_colorbar2.imshow(np.transpose(colorbar_mat[:,:]), cmap=plt.cm.jet, origin='lower', interpolation='none')\n", " ax_colorbar2.set_yticklabels('')\n", " ax_colorbar2.tick_params(axis = 'y', left = 'off', right = 'off')\n", " plt.sca(ax_colorbar2)\n", " plt.xticks([0,write_step_end-write_step_start],[bias_vec_w[write_step_start],bias_vec_w[write_step_end]])\n", " ax_colorbar2.set_xlabel('Write voltage [V]', fontsize = 12)\n", "\n", " \n", " \n", " if option == 2:\n", " colorbar_mat = np.column_stack((range(0,num_write_steps-1),range(0,num_write_steps-1)))\n", " ax_colorbar.imshow(np.transpose(colorbar_mat[:,:]), cmap=plt.cm.jet, origin='lower', interpolation='none')\n", " ax_colorbar.set_yticklabels('')\n", " ax_colorbar.tick_params(axis = 'y', left = 'off', right = 'off')\n", " ax_colorbar.set_xlabel('Write voltage step', fontsize = 12)\n", " \n", " ax_colorbar2.imshow(np.transpose(colorbar_mat[:,:]), cmap=plt.cm.jet, origin='lower', interpolation='none')\n", " ax_colorbar2.set_yticklabels('')\n", " ax_colorbar2.tick_params(axis = 'y', left = 'off', right = 'off')\n", " ax_colorbar2.set_xlabel('Write voltage step', fontsize = 12)\n", " \n", " \n", " \n", " fig_vsr.tight_layout();\n", " \n", " if save_figure_vsr == True:\n", " fig_vsr.savefig(output_file_path+'\\cbColor_Response_vsReadVoltage_x'+str(x_range)+'_y'+str(y_range)+'.png', format='png')\n", " fig_vsr.savefig(output_file_path+'\\cbColor_Response_vsReadVoltage_x'+str(x_range)+'_y'+str(y_range)+'.eps', format='eps')\n", " fig_vsr.savefig(output_file_path+'\\cbColor_Response_vsReadVoltage_x'+str(x_range)+'_y'+str(y_range)+'.tif', format='tiff')\n", " save_figure_vsr = False\n", " \n", " \n", " \n", "\n", "def update_xyrange(x_range, y_range):\n", "\n", "# Calculate response averaged over selected pixels\n", " \n", " resp_mat_vsr_range = np.squeeze(Nd_mat[y_range[0]:y_range[1], x_range[0]:x_range[1],1,write_step_start:write_step_end+1,:]['Amplitude [V]']\n", " *np.cos(Nd_mat[y_range[0]:y_range[1], x_range[0]:x_range[1],1,write_step_start:write_step_end+1,:]['Phase [rad]'])*1000)\n", " \n", " resp_vsr_mean1_range = np.nanmean(resp_mat_vsr_range,axis = 0)\n", " resp_vsr_std1_range = np.nanstd(resp_mat_vsr_range,axis = 0)\n", " resp_vsr_mean_range = np.nanmean(resp_vsr_mean1_range,axis = 0)\n", " resp_vsr_std_range = np.nanstd(resp_vsr_std1_range,axis = 0)\n", "\n", " make_figure_respvsr(resp_vsr_mean_range, resp_vsr_std_range, x_range, y_range)\n", " \n", " \n", "x_range = widgets.IntRangeSlider(min = 0,max = num_col-1,step = 1,value = 0,\n", " description = 'x-range',continuous_update = False)\n", "\n", "y_range = widgets.IntRangeSlider(min = 0,max = num_col-1,step = 1,value = 0,\n", " description = 'y-range',continuous_update = False)\n", "\n", "widgets.interact(update_xyrange,x_range = x_range, y_range = y_range);\n", "\n", "\n", "\n", "def on_save_button_clicked_vsr(b):\n", " global save_figure_vsr \n", " save_figure_vsr = True\n", " \n", " update_xyrange(x_range.value, y_range.value)\n", "\n", "button_vsr = widgets.Button(description = 'Save figure')\n", "display(button_vsr)\n", "button_vsr.on_click(on_save_button_clicked_vsr)\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Export response after all write steps for all pixels\n", "\n", "Response data (\\= amplitude * cos(phase)) is exported into separate tab delimited text files for each read voltage (see file names). The columns in the text file represent write voltage steps, the rows represent individual pixels. " ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "#Export response of all write steps (columns) for all pixels (rows) to one delimited text file for each read step\n", "\n", "for dc_step_read in range(0,num_read_steps-1):\n", " resp_mat = np.squeeze(Nd_mat[:,:,1,:,dc_step_read]['Amplitude [V]'] \n", " * np.cos(Nd_mat[:,:,1,:,dc_step_read]['Phase [rad]'])*1000)\n", "\n", " resp_vec = np.reshape(resp_mat, (num_row*num_col, num_write_steps))\n", " np.savetxt(os.path.join(output_file_path,'Response_at_Vread_'+str(bias_vec_r[0,dc_step_read])+'V.txt'),resp_vec, fmt='%f', delimiter='\\t')\n", "\n", "np.savetxt(os.path.join(output_file_path,'Read_voltage_vec.txt'), np.squeeze(bias_vec_r[0,:]), fmt='%f', delimiter='\\t')\n", "np.savetxt(os.path.join(output_file_path,'Write_voltage_vec.txt'), np.squeeze(bias_vec_w[:]), fmt='%f', delimiter='\\t')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Display averaged response at 0 V read voltage\n", "\n", "The left figure shows response at 0 V read voltage averaged over the whole grid, the right figure shows response at 0 V read voltage averaged over the x- and y- range specified with sliders." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "scrolled": false }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e522589f9f2e400c9c380a8127d5ac24", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(IntRangeSlider(value=(2, 6), continuous_update=False, description='x-range', max=9, step…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "647f5142aceb43a5b2aeb5b1778f4728", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Button(description='Save figure', style=ButtonStyle())" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Plot response at 0 V read voltage averaged over all pixels\n", "global save_figure_0V\n", "\n", "save_figure_0V = False\n", "dc_step_read = np.argwhere(np.isclose(bias_vec_r[0,:], 0)).squeeze()\n", "\n", "resp_mat_0Vr = np.squeeze(Nd_mat[:,:,1,:,dc_step_read]['Amplitude [V]'] \n", " * np.cos(Nd_mat[:,:,1,:,dc_step_read]['Phase [rad]'])*1000)\n", "\n", "# Calculate response at 0 V read voltage averaged over all pixels\n", "resp_0V_mean1 = np.nanmean(resp_mat_0Vr,axis = 0)\n", "resp_0V_std1 = np.nanstd(resp_mat_0Vr,axis = 0)\n", "resp_0V_mean = np.nanmean(resp_0V_mean1,axis = 0)\n", "resp_0V_std = np.nanstd(resp_0V_std1,axis = 0)\n", "\n", "\n", "def make_figure_resp0V(resp_0V_mean_range, resp_0V_std_range, x_range, y_range):\n", " global save_figure_0V\n", " \n", " fig_r0V = plt.figure(figsize=(10,4)) \n", " fig_r0V.clf()\n", " fig_r0V.set_facecolor('white')\n", " ax_plot = plt.subplot2grid((1, 2), (0, 0), colspan=1, rowspan=1)\n", " ax_plot_range = plt.subplot2grid((1, 2), (0, 1), colspan=1, rowspan=1)\n", " \n", " ax_plot.plot(bias_vec_w[:], resp_0V_mean\n", " , '.-')\n", " ax_plot.errorbar(bias_vec_w[:], resp_0V_mean, yerr = resp_0V_std, fmt = '.-')\n", " \n", " ax_plot.set_xlabel('Write voltage [V]', fontsize = 12)\n", " ax_plot.set_ylabel('Response [a.u.]', fontsize = 12)\n", " ax_plot.set_title('Averaged over whole map', fontsize = 12)\n", " \n", " ax_plot_range.errorbar(bias_vec_w[:], resp_0V_mean_range, yerr = resp_0V_std_range, fmt = '.-')\n", " ax_plot_range.set_xlabel('Write voltage [V]', fontsize = 12)\n", " ax_plot_range.set_ylabel('Response [a.u.]', fontsize = 12)\n", " ax_plot_range.set_title('Averaged from x = '+str(x_range[0])+'-'+str(x_range[1])\n", " +', y = '+str(y_range[0])+'-'+str(y_range[1]), fontsize = 12)\n", " \n", " fig_r0V.tight_layout();\n", " fig_r0V.suptitle('Spatially averaged response at read voltage = 0 V', y = 1.05, x=0.55, fontsize = 12)\n", " \n", " #save_figure_0V = True \n", " if save_figure_0V == True:\n", " fig_r0V.savefig(output_file_path+'\\Response_0V_x'+str(x_range)+'_y'+str(y_range)+'.png', format='png')\n", " fig_r0V.savefig(output_file_path+'\\Response_0V_x'+str(x_range)+'_y'+str(y_range)+'.eps', format='eps')\n", " fig_r0V.savefig(output_file_path+'\\Response_0V_x'+str(x_range)+'_y'+str(y_range)+'.tif', format='tiff')\n", " save_figure_0V = False\n", " \n", " \n", " \n", "\n", "def update_xyrange(x_range, y_range):\n", "\n", "# Calculate response at 0 V read voltage averaged over selected pixels\n", "# a=Nd_mat[x_range[0]:x_range[1], y_range[0]:y_range[1],1,:,dc_step_read]['Amplitude [V]']\n", " \n", " resp_mat_0Vr_range = np.squeeze(Nd_mat[y_range[0]:y_range[1], x_range[0]:x_range[1],1,:,dc_step_read]['Amplitude [V]']\n", " *np.cos(Nd_mat[y_range[0]:y_range[1], x_range[0]:x_range[1],1,:,dc_step_read]['Phase [rad]'])*1000)\n", " \n", " resp_0V_mean1_range = np.nanmean(resp_mat_0Vr_range,axis = 0)\n", " resp_0V_std1_range = np.nanstd(resp_mat_0Vr_range,axis = 0)\n", " resp_0V_mean_range = np.nanmean(resp_0V_mean1_range,axis = 0)\n", " resp_0V_std_range = np.nanstd(resp_0V_std1_range,axis = 0)\n", " \n", " print(resp_0V_mean_range, resp_0V_std_range, x_range, y_range)\n", " \n", " make_figure_resp0V(resp_0V_mean_range, resp_0V_std_range, x_range, y_range)\n", " \n", " \n", "x_range = widgets.IntRangeSlider(min = 0,max = num_col-1,step = 0.1,value = 0,\n", " description = 'x-range',continuous_update = False)\n", "\n", "y_range = widgets.IntRangeSlider(min = 0,max = num_col-1,step = 0.1,value = 0,\n", " description = 'y-range',continuous_update = False)\n", "\n", "widgets.interact(update_xyrange,x_range = x_range, y_range = y_range);\n", "\n", "\n", "\n", "def on_save_button_clicked_0V(b):\n", " global save_figure_0V \n", " save_figure_0V = True\n", "\n", " \n", " update_xyrange(x_range.value, y_range.value)\n", "\n", "button_0V = widgets.Button(description = 'Save figure')\n", "display(button_0V)\n", "button_0V.on_click(on_save_button_clicked_0V)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Display response, amplitude and phase data at 0 V read voltage for a single pixel\n", "\n", "Select the pixel of interest below by setting x_select and y_select to the desired coordinates." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "/* global mpl */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function () {\n", " if (typeof WebSocket !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof MozWebSocket !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert(\n", " 'Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.'\n", " );\n", " }\n", "};\n", "\n", "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = this.ws.binaryType !== undefined;\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById('mpl-warnings');\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent =\n", " 'This browser does not support binary websocket messages. ' +\n", " 'Performance may be slow.';\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = document.createElement('div');\n", " this.root.setAttribute('style', 'display: inline-block');\n", " this._root_extra_style(this.root);\n", "\n", " parent_element.appendChild(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message('supports_binary', { value: fig.supports_binary });\n", " fig.send_message('send_image_mode', {});\n", " if (fig.ratio !== 1) {\n", " fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n", " }\n", " fig.send_message('refresh', {});\n", " };\n", "\n", " this.imageObj.onload = function () {\n", " if (fig.image_mode === 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function () {\n", " fig.ws.close();\n", " };\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "};\n", "\n", "mpl.figure.prototype._init_header = function () {\n", " var titlebar = document.createElement('div');\n", " titlebar.classList =\n", " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", " var titletext = document.createElement('div');\n", " titletext.classList = 'ui-dialog-title';\n", " titletext.setAttribute(\n", " 'style',\n", " 'width: 100%; text-align: center; padding: 3px;'\n", " );\n", " titlebar.appendChild(titletext);\n", " this.root.appendChild(titlebar);\n", " this.header = titletext;\n", "};\n", "\n", "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", "\n", "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", "\n", "mpl.figure.prototype._init_canvas = function () {\n", " var fig = this;\n", "\n", " var canvas_div = (this.canvas_div = document.createElement('div'));\n", " canvas_div.setAttribute(\n", " 'style',\n", " 'border: 1px solid #ddd;' +\n", " 'box-sizing: content-box;' +\n", " 'clear: both;' +\n", " 'min-height: 1px;' +\n", " 'min-width: 1px;' +\n", " 'outline: 0;' +\n", " 'overflow: hidden;' +\n", " 'position: relative;' +\n", " 'resize: both;'\n", " );\n", "\n", " function on_keyboard_event_closure(name) {\n", " return function (event) {\n", " return fig.key_event(event, name);\n", " };\n", " }\n", "\n", " canvas_div.addEventListener(\n", " 'keydown',\n", " on_keyboard_event_closure('key_press')\n", " );\n", " canvas_div.addEventListener(\n", " 'keyup',\n", " on_keyboard_event_closure('key_release')\n", " );\n", "\n", " this._canvas_extra_style(canvas_div);\n", " this.root.appendChild(canvas_div);\n", "\n", " var canvas = (this.canvas = document.createElement('canvas'));\n", " canvas.classList.add('mpl-canvas');\n", " canvas.setAttribute('style', 'box-sizing: content-box;');\n", "\n", " this.context = canvas.getContext('2d');\n", "\n", " var backingStore =\n", " this.context.backingStorePixelRatio ||\n", " this.context.webkitBackingStorePixelRatio ||\n", " this.context.mozBackingStorePixelRatio ||\n", " this.context.msBackingStorePixelRatio ||\n", " this.context.oBackingStorePixelRatio ||\n", " this.context.backingStorePixelRatio ||\n", " 1;\n", "\n", " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", " 'canvas'\n", " ));\n", " rubberband_canvas.setAttribute(\n", " 'style',\n", " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", " );\n", "\n", " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", " if (this.ResizeObserver === undefined) {\n", " if (window.ResizeObserver !== undefined) {\n", " this.ResizeObserver = window.ResizeObserver;\n", " } else {\n", " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n", " this.ResizeObserver = obs.ResizeObserver;\n", " }\n", " }\n", "\n", " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n", " var nentries = entries.length;\n", " for (var i = 0; i < nentries; i++) {\n", " var entry = entries[i];\n", " var width, height;\n", " if (entry.contentBoxSize) {\n", " if (entry.contentBoxSize instanceof Array) {\n", " // Chrome 84 implements new version of spec.\n", " width = entry.contentBoxSize[0].inlineSize;\n", " height = entry.contentBoxSize[0].blockSize;\n", " } else {\n", " // Firefox implements old version of spec.\n", " width = entry.contentBoxSize.inlineSize;\n", " height = entry.contentBoxSize.blockSize;\n", " }\n", " } else {\n", " // Chrome <84 implements even older version of spec.\n", " width = entry.contentRect.width;\n", " height = entry.contentRect.height;\n", " }\n", "\n", " // Keep the size of the canvas and rubber band canvas in sync with\n", " // the canvas container.\n", " if (entry.devicePixelContentBoxSize) {\n", " // Chrome 84 implements new version of spec.\n", " canvas.setAttribute(\n", " 'width',\n", " entry.devicePixelContentBoxSize[0].inlineSize\n", " );\n", " canvas.setAttribute(\n", " 'height',\n", " entry.devicePixelContentBoxSize[0].blockSize\n", " );\n", " } else {\n", " canvas.setAttribute('width', width * fig.ratio);\n", " canvas.setAttribute('height', height * fig.ratio);\n", " }\n", " canvas.setAttribute(\n", " 'style',\n", " 'width: ' + width + 'px; height: ' + height + 'px;'\n", " );\n", "\n", " rubberband_canvas.setAttribute('width', width);\n", " rubberband_canvas.setAttribute('height', height);\n", "\n", " // And update the size in Python. We ignore the initial 0/0 size\n", " // that occurs as the element is placed into the DOM, which should\n", " // otherwise not happen due to the minimum size styling.\n", " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n", " fig.request_resize(width, height);\n", " }\n", " }\n", " });\n", " this.resizeObserverInstance.observe(canvas_div);\n", "\n", " function on_mouse_event_closure(name) {\n", " return function (event) {\n", " return fig.mouse_event(event, name);\n", " };\n", " }\n", "\n", " rubberband_canvas.addEventListener(\n", " 'mousedown',\n", " on_mouse_event_closure('button_press')\n", " );\n", " rubberband_canvas.addEventListener(\n", " 'mouseup',\n", " on_mouse_event_closure('button_release')\n", " );\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband_canvas.addEventListener(\n", " 'mousemove',\n", " on_mouse_event_closure('motion_notify')\n", " );\n", "\n", " rubberband_canvas.addEventListener(\n", " 'mouseenter',\n", " on_mouse_event_closure('figure_enter')\n", " );\n", " rubberband_canvas.addEventListener(\n", " 'mouseleave',\n", " on_mouse_event_closure('figure_leave')\n", " );\n", "\n", " canvas_div.addEventListener('wheel', function (event) {\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " on_mouse_event_closure('scroll')(event);\n", " });\n", "\n", " canvas_div.appendChild(canvas);\n", " canvas_div.appendChild(rubberband_canvas);\n", "\n", " this.rubberband_context = rubberband_canvas.getContext('2d');\n", " this.rubberband_context.strokeStyle = '#000000';\n", "\n", " this._resize_canvas = function (width, height, forward) {\n", " if (forward) {\n", " canvas_div.style.width = width + 'px';\n", " canvas_div.style.height = height + 'px';\n", " }\n", " };\n", "\n", " // Disable right mouse context menu.\n", " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", " event.preventDefault();\n", " return false;\n", " });\n", "\n", " function set_focus() {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "};\n", "\n", "mpl.figure.prototype._init_toolbar = function () {\n", " var fig = this;\n", "\n", " var toolbar = document.createElement('div');\n", " toolbar.classList = 'mpl-toolbar';\n", " this.root.appendChild(toolbar);\n", "\n", " function on_click_closure(name) {\n", " return function (_event) {\n", " return fig.toolbar_button_onclick(name);\n", " };\n", " }\n", "\n", " function on_mouseover_closure(tooltip) {\n", " return function (event) {\n", " if (!event.currentTarget.disabled) {\n", " return fig.toolbar_button_onmouseover(tooltip);\n", " }\n", " };\n", " }\n", "\n", " fig.buttons = {};\n", " var buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'mpl-button-group';\n", " for (var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " /* Instead of a spacer, we start a new button group. */\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", " buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'mpl-button-group';\n", " continue;\n", " }\n", "\n", " var button = (fig.buttons[name] = document.createElement('button'));\n", " button.classList = 'mpl-widget';\n", " button.setAttribute('role', 'button');\n", " button.setAttribute('aria-disabled', 'false');\n", " button.addEventListener('click', on_click_closure(method_name));\n", " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", "\n", " var icon_img = document.createElement('img');\n", " icon_img.src = '_images/' + image + '.png';\n", " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", " icon_img.alt = tooltip;\n", " button.appendChild(icon_img);\n", "\n", " buttonGroup.appendChild(button);\n", " }\n", "\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", "\n", " var fmt_picker = document.createElement('select');\n", " fmt_picker.classList = 'mpl-widget';\n", " toolbar.appendChild(fmt_picker);\n", " this.format_dropdown = fmt_picker;\n", "\n", " for (var ind in mpl.extensions) {\n", " var fmt = mpl.extensions[ind];\n", " var option = document.createElement('option');\n", " option.selected = fmt === mpl.default_extension;\n", " option.innerHTML = fmt;\n", " fmt_picker.appendChild(option);\n", " }\n", "\n", " var status_bar = document.createElement('span');\n", " status_bar.classList = 'mpl-message';\n", " toolbar.appendChild(status_bar);\n", " this.message = status_bar;\n", "};\n", "\n", "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", " // which will in turn request a refresh of the image.\n", " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", "};\n", "\n", "mpl.figure.prototype.send_message = function (type, properties) {\n", " properties['type'] = type;\n", " properties['figure_id'] = this.id;\n", " this.ws.send(JSON.stringify(properties));\n", "};\n", "\n", "mpl.figure.prototype.send_draw_message = function () {\n", " if (!this.waiting) {\n", " this.waiting = true;\n", " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", " var format_dropdown = fig.format_dropdown;\n", " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", " fig.ondownload(fig, format);\n", "};\n", "\n", "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", " var size = msg['size'];\n", " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", " fig._resize_canvas(size[0], size[1], msg['forward']);\n", " fig.send_message('refresh', {});\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", " var x0 = msg['x0'] / fig.ratio;\n", " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n", " var x1 = msg['x1'] / fig.ratio;\n", " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", " y1 = Math.floor(y1) + 0.5;\n", " var min_x = Math.min(x0, x1);\n", " var min_y = Math.min(y0, y1);\n", " var width = Math.abs(x1 - x0);\n", " var height = Math.abs(y1 - y0);\n", "\n", " fig.rubberband_context.clearRect(\n", " 0,\n", " 0,\n", " fig.canvas.width / fig.ratio,\n", " fig.canvas.height / fig.ratio\n", " );\n", "\n", " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", "};\n", "\n", "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", " // Updates the figure title.\n", " fig.header.textContent = msg['label'];\n", "};\n", "\n", "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", " var cursor = msg['cursor'];\n", " switch (cursor) {\n", " case 0:\n", " cursor = 'pointer';\n", " break;\n", " case 1:\n", " cursor = 'default';\n", " break;\n", " case 2:\n", " cursor = 'crosshair';\n", " break;\n", " case 3:\n", " cursor = 'move';\n", " break;\n", " }\n", " fig.rubberband_canvas.style.cursor = cursor;\n", "};\n", "\n", "mpl.figure.prototype.handle_message = function (fig, msg) {\n", " fig.message.textContent = msg['message'];\n", "};\n", "\n", "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", " // Request the server to send over a new figure.\n", " fig.send_draw_message();\n", "};\n", "\n", "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", " fig.image_mode = msg['mode'];\n", "};\n", "\n", "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", " for (var key in msg) {\n", " if (!(key in fig.buttons)) {\n", " continue;\n", " }\n", " fig.buttons[key].disabled = !msg[key];\n", " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", " if (msg['mode'] === 'PAN') {\n", " fig.buttons['Pan'].classList.add('active');\n", " fig.buttons['Zoom'].classList.remove('active');\n", " } else if (msg['mode'] === 'ZOOM') {\n", " fig.buttons['Pan'].classList.remove('active');\n", " fig.buttons['Zoom'].classList.add('active');\n", " } else {\n", " fig.buttons['Pan'].classList.remove('active');\n", " fig.buttons['Zoom'].classList.remove('active');\n", " }\n", "};\n", "\n", "mpl.figure.prototype.updated_canvas_event = function () {\n", " // Called whenever the canvas gets updated.\n", " this.send_message('ack', {});\n", "};\n", "\n", "// A function to construct a web socket function for onmessage handling.\n", "// Called in the figure constructor.\n", "mpl.figure.prototype._make_on_message_function = function (fig) {\n", " return function socket_on_message(evt) {\n", " if (evt.data instanceof Blob) {\n", " /* FIXME: We get \"Resource interpreted as Image but\n", " * transferred with MIME type text/plain:\" errors on\n", " * Chrome. But how to set the MIME type? It doesn't seem\n", " * to be part of the websocket stream */\n", " evt.data.type = 'image/png';\n", "\n", " /* Free the memory for the previous frames */\n", " if (fig.imageObj.src) {\n", " (window.URL || window.webkitURL).revokeObjectURL(\n", " fig.imageObj.src\n", " );\n", " }\n", "\n", " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", " evt.data\n", " );\n", " fig.updated_canvas_event();\n", " fig.waiting = false;\n", " return;\n", " } else if (\n", " typeof evt.data === 'string' &&\n", " evt.data.slice(0, 21) === 'data:image/png;base64'\n", " ) {\n", " fig.imageObj.src = evt.data;\n", " fig.updated_canvas_event();\n", " fig.waiting = false;\n", " return;\n", " }\n", "\n", " var msg = JSON.parse(evt.data);\n", " var msg_type = msg['type'];\n", "\n", " // Call the \"handle_{type}\" callback, which takes\n", " // the figure and JSON message as its only arguments.\n", " try {\n", " var callback = fig['handle_' + msg_type];\n", " } catch (e) {\n", " console.log(\n", " \"No handler for the '\" + msg_type + \"' message type: \",\n", " msg\n", " );\n", " return;\n", " }\n", "\n", " if (callback) {\n", " try {\n", " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", " callback(fig, msg);\n", " } catch (e) {\n", " console.log(\n", " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", " e,\n", " e.stack,\n", " msg\n", " );\n", " }\n", " }\n", " };\n", "};\n", "\n", "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", "mpl.findpos = function (e) {\n", " //this section is from http://www.quirksmode.org/js/events_properties.html\n", " var targ;\n", " if (!e) {\n", " e = window.event;\n", " }\n", " if (e.target) {\n", " targ = e.target;\n", " } else if (e.srcElement) {\n", " targ = e.srcElement;\n", " }\n", " if (targ.nodeType === 3) {\n", " // defeat Safari bug\n", " targ = targ.parentNode;\n", " }\n", "\n", " // pageX,Y are the mouse positions relative to the document\n", " var boundingRect = targ.getBoundingClientRect();\n", " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", "\n", " return { x: x, y: y };\n", "};\n", "\n", "/*\n", " * return a copy of an object with only non-object keys\n", " * we need this to avoid circular references\n", " * http://stackoverflow.com/a/24161582/3208463\n", " */\n", "function simpleKeys(original) {\n", " return Object.keys(original).reduce(function (obj, key) {\n", " if (typeof original[key] !== 'object') {\n", " obj[key] = original[key];\n", " }\n", " return obj;\n", " }, {});\n", "}\n", "\n", "mpl.figure.prototype.mouse_event = function (event, name) {\n", " var canvas_pos = mpl.findpos(event);\n", "\n", " if (name === 'button_press') {\n", " this.canvas.focus();\n", " this.canvas_div.focus();\n", " }\n", "\n", " var x = canvas_pos.x * this.ratio;\n", " var y = canvas_pos.y * this.ratio;\n", "\n", " this.send_message(name, {\n", " x: x,\n", " y: y,\n", " button: event.button,\n", " step: event.step,\n", " guiEvent: simpleKeys(event),\n", " });\n", "\n", " /* This prevents the web browser from automatically changing to\n", " * the text insertion cursor when the button is pressed. We want\n", " * to control all of the cursor setting manually through the\n", " * 'cursor' event from matplotlib */\n", " event.preventDefault();\n", " return false;\n", "};\n", "\n", "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", " // Handle any extra behaviour associated with a key event\n", "};\n", "\n", "mpl.figure.prototype.key_event = function (event, name) {\n", " // Prevent repeat events\n", " if (name === 'key_press') {\n", " if (event.which === this._key) {\n", " return;\n", " } else {\n", " this._key = event.which;\n", " }\n", " }\n", " if (name === 'key_release') {\n", " this._key = null;\n", " }\n", "\n", " var value = '';\n", " if (event.ctrlKey && event.which !== 17) {\n", " value += 'ctrl+';\n", " }\n", " if (event.altKey && event.which !== 18) {\n", " value += 'alt+';\n", " }\n", " if (event.shiftKey && event.which !== 16) {\n", " value += 'shift+';\n", " }\n", "\n", " value += 'k';\n", " value += event.which.toString();\n", "\n", " this._key_event_extra(event, name);\n", "\n", " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", " return false;\n", "};\n", "\n", "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", " if (name === 'download') {\n", " this.handle_save(this, null);\n", " } else {\n", " this.send_message('toolbar_button', { name: name });\n", " }\n", "};\n", "\n", "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", "\n", "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", "// prettier-ignore\n", "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n", "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", "\n", "mpl.default_extension = \"png\";/* global mpl */\n", "\n", "var comm_websocket_adapter = function (comm) {\n", " // Create a \"websocket\"-like object which calls the given IPython comm\n", " // object with the appropriate methods. Currently this is a non binary\n", " // socket, so there is still some room for performance tuning.\n", " var ws = {};\n", "\n", " ws.close = function () {\n", " comm.close();\n", " };\n", " ws.send = function (m) {\n", " //console.log('sending', m);\n", " comm.send(m);\n", " };\n", " // Register the callback with on_msg.\n", " comm.on_msg(function (msg) {\n", " //console.log('receiving', msg['content']['data'], msg);\n", " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", " ws.onmessage(msg['content']['data']);\n", " });\n", " return ws;\n", "};\n", "\n", "mpl.mpl_figure_comm = function (comm, msg) {\n", " // This is the function which gets called when the mpl process\n", " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", "\n", " var id = msg.content.data.id;\n", " // Get hold of the div created by the display call when the Comm\n", " // socket was opened in Python.\n", " var element = document.getElementById(id);\n", " var ws_proxy = comm_websocket_adapter(comm);\n", "\n", " function ondownload(figure, _format) {\n", " window.open(figure.canvas.toDataURL());\n", " }\n", "\n", " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", "\n", " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", " // web socket which is closed, not our websocket->open comm proxy.\n", " ws_proxy.onopen();\n", "\n", " fig.parent_element = element;\n", " fig.cell_info = mpl.find_output_cell(\"
\");\n", " if (!fig.cell_info) {\n", " console.error('Failed to find cell for figure', id, fig);\n", " return;\n", " }\n", " fig.cell_info[0].output_area.element.on(\n", " 'cleared',\n", " { fig: fig },\n", " fig._remove_fig_handler\n", " );\n", "};\n", "\n", "mpl.figure.prototype.handle_close = function (fig, msg) {\n", " var width = fig.canvas.width / fig.ratio;\n", " fig.cell_info[0].output_area.element.off(\n", " 'cleared',\n", " fig._remove_fig_handler\n", " );\n", " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n", "\n", " // Update the output cell to use the data from the current canvas.\n", " fig.push_to_output();\n", " var dataURL = fig.canvas.toDataURL();\n", " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable();\n", " fig.parent_element.innerHTML =\n", " '';\n", " fig.close_ws(fig, msg);\n", "};\n", "\n", "mpl.figure.prototype.close_ws = function (fig, msg) {\n", " fig.send_message('closing', msg);\n", " // fig.ws.close()\n", "};\n", "\n", "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", " var width = this.canvas.width / this.ratio;\n", " var dataURL = this.canvas.toDataURL();\n", " this.cell_info[1]['text/html'] =\n", " '';\n", "};\n", "\n", "mpl.figure.prototype.updated_canvas_event = function () {\n", " // Tell IPython that the notebook contents must change.\n", " IPython.notebook.set_dirty(true);\n", " this.send_message('ack', {});\n", " var fig = this;\n", " // Wait a second, then push the new image to the DOM so\n", " // that it is saved nicely (might be nice to debounce this).\n", " setTimeout(function () {\n", " fig.push_to_output();\n", " }, 1000);\n", "};\n", "\n", "mpl.figure.prototype._init_toolbar = function () {\n", " var fig = this;\n", "\n", " var toolbar = document.createElement('div');\n", " toolbar.classList = 'btn-toolbar';\n", " this.root.appendChild(toolbar);\n", "\n", " function on_click_closure(name) {\n", " return function (_event) {\n", " return fig.toolbar_button_onclick(name);\n", " };\n", " }\n", "\n", " function on_mouseover_closure(tooltip) {\n", " return function (event) {\n", " if (!event.currentTarget.disabled) {\n", " return fig.toolbar_button_onmouseover(tooltip);\n", " }\n", " };\n", " }\n", "\n", " fig.buttons = {};\n", " var buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'btn-group';\n", " var button;\n", " for (var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " /* Instead of a spacer, we start a new button group. */\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", " buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'btn-group';\n", " continue;\n", " }\n", "\n", " button = fig.buttons[name] = document.createElement('button');\n", " button.classList = 'btn btn-default';\n", " button.href = '#';\n", " button.title = name;\n", " button.innerHTML = '';\n", " button.addEventListener('click', on_click_closure(method_name));\n", " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", " buttonGroup.appendChild(button);\n", " }\n", "\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = document.createElement('span');\n", " status_bar.classList = 'mpl-message pull-right';\n", " toolbar.appendChild(status_bar);\n", " this.message = status_bar;\n", "\n", " // Add the close button to the window.\n", " var buttongrp = document.createElement('div');\n", " buttongrp.classList = 'btn-group inline pull-right';\n", " button = document.createElement('button');\n", " button.classList = 'btn btn-mini btn-primary';\n", " button.href = '#';\n", " button.title = 'Stop Interaction';\n", " button.innerHTML = '';\n", " button.addEventListener('click', function (_evt) {\n", " fig.handle_close(fig, {});\n", " });\n", " button.addEventListener(\n", " 'mouseover',\n", " on_mouseover_closure('Stop Interaction')\n", " );\n", " buttongrp.appendChild(button);\n", " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", "};\n", "\n", "mpl.figure.prototype._remove_fig_handler = function (event) {\n", " var fig = event.data.fig;\n", " if (event.target !== this) {\n", " // Ignore bubbled events from children.\n", " return;\n", " }\n", " fig.close_ws(fig, {});\n", "};\n", "\n", "mpl.figure.prototype._root_extra_style = function (el) {\n", " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", "};\n", "\n", "mpl.figure.prototype._canvas_extra_style = function (el) {\n", " // this is important to make the div 'focusable\n", " el.setAttribute('tabindex', 0);\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " } else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "};\n", "\n", "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager) {\n", " manager = IPython.keyboard_manager;\n", " }\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which === 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", " fig.ondownload(fig, null);\n", "};\n", "\n", "mpl.find_output_cell = function (html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i = 0; i < ncells; i++) {\n", " var cell = cells[i];\n", " if (cell.cell_type === 'code') {\n", " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", " var data = cell.output_area.outputs[j];\n", " if (data.data) {\n", " // IPython >= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] === html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "};\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel !== null) {\n", " IPython.notebook.kernel.comm_manager.register_target(\n", " 'matplotlib',\n", " mpl.mpl_figure_comm\n", " );\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "x_select = 3\n", "y_select = 2\n", "\n", "resp_mat_0Vr = np.squeeze(Nd_mat[:,:,1,:,dc_step_read]['Amplitude [V]'] \n", " * np.cos(Nd_mat[:,:,1,:,dc_step_read]['Phase [rad]'])*1000)\n", "amp_mat_0Vr = np.squeeze(Nd_mat[:,:,1,:,dc_step_read]['Amplitude [V]'])*1000\n", "phase_mat_0Vr = np.squeeze(Nd_mat[:,:,1,:,dc_step_read]['Phase [rad]'])\n", "\n", "\n", "fig_r0V = plt.figure(figsize=(12,4)) \n", "fig_r0V.clf()\n", "fig_r0V.set_facecolor('white')\n", "ax_resp = plt.subplot2grid((1, 3), (0, 0), colspan=1, rowspan=1)\n", "ax_amp = plt.subplot2grid((1, 3), (0, 1), colspan=1, rowspan=1)\n", "ax_phase = plt.subplot2grid((1, 3), (0, 2), colspan=1, rowspan=1)\n", "\n", "ax_resp.plot(bias_vec_w[:], resp_mat_0Vr[y_select, x_select, :],'.-')\n", "ax_resp.set_xlabel('Write voltage [V]', fontsize = 12)\n", "ax_resp.set_ylabel('Response [a.u.]', fontsize = 12)\n", "\n", "ax_amp.plot(bias_vec_w[:], amp_mat_0Vr[y_select, x_select, :],'.-')\n", "ax_amp.set_xlabel('Write voltage [V]', fontsize = 12)\n", "ax_amp.set_ylabel('Amplitude [a.u.]', fontsize = 12)\n", "\n", "ax_phase.plot(bias_vec_w[:], phase_mat_0Vr[y_select, x_select, :],'.-')\n", "ax_phase.set_xlabel('Write voltage [V]', fontsize = 12)\n", "ax_phase.set_ylabel('Phase [rad]', fontsize = 12)\n", "ax_phase.set_ylim([-4, 4])\n", "\n", "fig_r0V.tight_layout()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Display on-field loops for all read steps\n", "\n", "The figure shows on-field response vs. write voltage for all read voltages (color coded) averaged over the whole map." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "ename": "AttributeError", "evalue": "module 'numpy' has no attribute 'matlib'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 8\u001b[0m \u001b[0mresp_IF_std\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnanstd\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mresp_IF_std1\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0maxis\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 10\u001b[1;33m \u001b[0mbias_vec_w_graph\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmatlib\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrepmat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mbias_vec_w\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnum_read_steps\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 11\u001b[0m \u001b[1;31m# print(resp_IF_mean.shape, resp_IF_std.shape, bias_vec_w_graph.shape)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32m~\\Anaconda3\\lib\\site-packages\\numpy\\__init__.py\u001b[0m in \u001b[0;36m__getattr__\u001b[1;34m(attr)\u001b[0m\n\u001b[0;32m 301\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mTester\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 302\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 303\u001b[1;33m raise AttributeError(\"module {!r} has no attribute \"\n\u001b[0m\u001b[0;32m 304\u001b[0m \"{!r}\".format(__name__, attr))\n\u001b[0;32m 305\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mAttributeError\u001b[0m: module 'numpy' has no attribute 'matlib'" ] } ], "source": [ "resp_mat_IF = np.squeeze(Nd_mat[:,:,0,:,:]['Amplitude [V]'] \n", " * np.cos(Nd_mat[:,:,0,:,:]['Phase [rad]'])*1000)\n", "\n", "# Calculate response at 0 V read voltage averaged over all pixels\n", "resp_IF_mean1 = np.nanmean(resp_mat_IF,axis = 0)\n", "resp_IF_std1 = np.nanstd(resp_mat_IF,axis = 0)\n", "resp_IF_mean = np.nanmean(resp_IF_mean1,axis = 0)\n", "resp_IF_std = np.nanstd(resp_IF_std1,axis = 0)\n", "\n", "bias_vec_w_graph = np.matlib.repmat(bias_vec_w,num_read_steps, 1)\n", "# print(resp_IF_mean.shape, resp_IF_std.shape, bias_vec_w_graph.shape)\n", "\n", "fig_IF = plt.figure(figsize=(6,6)) \n", "fig_IF.clf()\n", "fig_IF.set_facecolor('white')\n", "ax_plot = plt.subplot2grid((15, 5), (0, 0), colspan=5, rowspan=12)\n", "ax_colorbar = plt.subplot2grid((15, 5), (14, 0), colspan=5, rowspan=1)\n", "\n", "px.plot_utils.plot_line_family(ax_plot, np.transpose(bias_vec_w_graph), np.transpose(resp_IF_mean), line_names='None',label_prefix='Line', label_suffix='', cmap=plt.cm.jet)\n", "# ax_plot.plot(bias_vec_w[:], resp_IF_mean, '.-')\n", "# ax_plot.errorbar(bias_vec_w[:], resp_IF_mean, yerr = resp_IF_std, fmt = '.-')\n", "colorbar_mat = np.column_stack((range(0,num_read_steps),range(0,num_read_steps)))\n", "ax_colorbar.imshow(np.transpose(colorbar_mat[:,:]), cmap=plt.cm.jet, origin='lower', interpolation='none', aspect = 0.25)\n", "ax_colorbar.set_yticklabels('')\n", "\n", "\n", "ax_colorbar.tick_params(axis = 'y', left = 'off', right = 'off')\n", "\n", "\n", "# ax_colorbar.set_xlabel('Read step')\n", " \n", "\n", "ax_plot.set_xlabel('Write voltage [V]', fontsize = 12)\n", "ax_plot.set_ylabel('In field response [a.u.]', fontsize = 12)\n", "ax_plot.set_title('Averaged over whole map', fontsize = 12)\n", "\n", "labels = list(range(num_read_steps))\n", "\n", "for i in range(0, num_read_steps-0, 1):\n", " labels[i] = str(bias_vec_r[0,i])\n", "\n", "ax_colorbar.set_xticks(np.arange(num_read_steps))\n", "ax_colorbar.set_xticklabels(labels, fontsize = 10)\n", "\n", "ax_colorbar.set_xlabel('Read voltage [V]', fontsize = 12)\n", "# fig_IF.tight_layout();\n", "\n", "def on_save_button4_clicked(b):\n", " \n", " fig_IF.savefig(output_file_path+'\\IFresponse.png', format='png')\n", " fig_IF.savefig(output_file_path+'\\IFresponse.eps', format='eps')\n", " fig_IF.savefig(output_file_path+'\\IFresponse.tif', format='tiff')\n", "\n", " \n", " \n", "button4 = widgets.Button(description = 'Save figure')\n", "display(button4)\n", "button4.on_click(on_save_button4_clicked)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculate the jCPD\n", "\n", "The junction contact potential difference (jCPD) is extracted for each dc write voltage step by linear fitting of the response vs. read bias and calculating the x-intercept.\n", "\n", "If only a certain (linear) regime of the cKPFM curves should be fitted, set v_read_start_index and v_read_end_index to the first and last index of the data that should be considered for the fit." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "v_read_start_index = 0 , v_read_end_index = 10\n", "[-1. -0.8 -0.6 -0.4 -0.2 0. 0.2 0.4 0.6 0.8 1. ]\n" ] } ], "source": [ "#Calculate x intercept -> jCPD\n", "\n", "v_read_start_index = 0\n", "v_read_end_index = num_read_steps-1\n", "\n", "print('v_read_start_index = ', v_read_start_index, ', v_read_end_index = ', v_read_end_index)\n", "# resp_mat_r_all_all = Nd_mat[:,:,1,:,:]['Amplitude [V]'] * np.cos(Nd_mat[:,:,1,:,:]['Phase [rad]'])*1000\n", "resp_mat_r_all = Nd_mat[:,:,1,:,v_read_start_index : v_read_end_index+1]['Amplitude [V]'] * np.cos(Nd_mat[:,:,1,:,v_read_start_index : v_read_end_index+1]['Phase [rad]'])*1000\n", "\n", "\n", "# print(num_read_steps)\n", "# print(resp_mat_r_all.shape)\n", "# print('resp_mat_r_all', resp_mat_r_all[0,0,0,:])\n", "# print('resp_mat_r_all_all', resp_mat_r_all_all[0,0,0,:])\n", "\n", "fit_slope = np.zeros((num_col, num_row, num_write_steps))\n", "fit_yintercept = np.zeros((num_col, num_row, num_write_steps))\n", "jCPD_mat = np.zeros((num_col, num_row, num_write_steps))\n", " \n", "print(bias_vec_r[1,v_read_start_index : v_read_end_index+1])\n", "# print(bias_vec_r[1,:])\n", "\n", "for row in range(num_row):\n", " for col in range(num_col):\n", " for vw in range(0,num_write_steps-1):\n", " fit_coeff = np.polyfit(bias_vec_r[1,v_read_start_index : v_read_end_index+1], resp_mat_r_all[col, row, vw,:],1)\n", " fit_slope[col, row, vw] = fit_coeff[0]\n", " fit_yintercept[col, row, vw] = fit_coeff[1]\n", " jCPD_mat[col, row, vw] = -fit_coeff[1]/ fit_coeff[0]\n", " \n", "\n", "# fit_y = fit_coeff[0] * bias_vec_r[1,:] + fit_coeff[1]\n", "\n", "# row = 1\n", "# col = 1\n", "# vw = 10 \n", "# print(fit_slope[col, row, vw])\n", "# print(fit_yintercept[col, row, vw])\n", "# print(jCPD_mat[col ,row, vw])\n", "\n", "\n", "# plt.figure(1)\n", "# plt.plot(bias_vec_r[1,:],resp_mat_r_all[col, row, vw,:],'.-')\n", "# plt.plot(bias_vec_r[1,:],fit_y)\n", "# print(fit_coeff[0],fit_coeff[1],jCPD_mat[col, row, vw])\n", "#Filter outliers from jCPD matrix, (-> improve code)\n", "# for r in range(1, num_row):\n", "# for c in range(1, num_col):\n", "# for s in range(1, num_write_steps):\n", "# if jCPD_mat[r-1, c-1, s-1] > 20 or jCPD_mat[r-1, c-1, s-1] < -20:\n", "# # jCPD_mat[r-1, c-1, s-1] = np.nan\n", "# jCPD_mat[r-1, c-1, s-1] = 0\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Display jCPD data\n", "Figure shows\n", "\n", "- The jCPD map for the write voltage step selected with the slider\n", "- Graphs of jCPD cross sections along the selected x- and y- axes for the selected write voltage step" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "dcf03ab3bfce469388eee0592df282e5", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(IntSlider(value=0, description='Write Step', max=19), IntSlider(value=0, description='x'…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "eded5cd06e7d499c9a3f761f35cea1ef", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Button(description='Save figure', style=ButtonStyle())" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "global save_figure\n", "\n", "save_figure = False\n", "\n", "#Color scale minimum and maximum\n", "cmin = -0.2\n", "cmax = 0.02\n", " \n", "def make_jCPD_figure(dc_step_write, x_select, y_select): \n", " global save_figure \n", "\n", " fig2 = plt.figure(figsize=(14,8)) \n", " fig2.set_facecolor('white') \n", " ax_jCPD_xcross_section = plt.subplot2grid((10, 10), (0, 7), colspan=4, rowspan=3)\n", " plt.title('jCPD cross section at x ='+str(x_select), fontsize = 12)\n", " \n", " ax_jCPD_ycross_section = plt.subplot2grid((10, 10), (4, 7), colspan=4, rowspan=3)\n", " plt.title('jCPD cross section at y ='+str(y_select), fontsize = 12)\n", " \n", " ax_jCPD_plot = plt.subplot2grid((10, 10), (0, 0), colspan=6, rowspan=7)\n", " plt.title('jCPD [V] at write voltage = '+str(bias_vec_w[dc_step_write])+' V', fontsize = 12)\n", " \n", "\n", " \n", " ax_jCPD_xcross_section.plot(range(num_col),jCPD_mat[:,x_select,dc_step_write],'.-')\n", " ax_jCPD_xcross_section.set_xlabel('Pixel #', fontsize = 12)\n", " ax_jCPD_xcross_section.set_ylabel('jCPD [V]', fontsize = 12)\n", " \n", " ax_jCPD_ycross_section.plot(range(num_row),jCPD_mat[y_select,:,dc_step_write],'.-')\n", " ax_jCPD_ycross_section.set_xlabel('Pixel #', fontsize = 12)\n", " ax_jCPD_ycross_section.set_ylabel('jCPD [V]', fontsize = 12)\n", " \n", "# co_b2 = ax_jCPD_plot.imshow(jCPD_mat[:,:,dc_step_write], \n", "# cmap=px.plot_utils.cmap_jet_white_center(), \n", "# origin='lower', interpolation='none', clim=(cmin, cmax));\n", " co_b2 = ax_jCPD_plot.imshow(jCPD_mat[:,:,dc_step_write], \n", " cmap=usid.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " cb2 = fig2.colorbar(co_b2)\n", " \n", " \n", " if save_figure == True:\n", " fig2.savefig(output_file_path+'jCPD_map_WriteStep'+str(dc_step_write)+'y'+str(row)+'.png', format='png')\n", " fig2.savefig(output_file_path+'jCPD_map_WriteStep'+str(dc_step_write)+'y'+str(row)+'.eps', format='eps')\n", " save_figure = False;\n", "\n", " \n", "\n", "slider_dict = dict() \n", "dc_step_write_slider = widgets.IntSlider(min = 0, max = num_write_steps-1, step = 1,value = 0,description='Write Step');\n", "x_slider = widgets.IntSlider(min = 0, max = num_col, step = 1, value = 0, description = 'x')\n", "y_slider = widgets.IntSlider(min = 0, max = num_row, step = 1, value = 0, description = 'y')\n", "\n", "widgets.interact(make_jCPD_figure, dc_step_write = dc_step_write_slider, x_select = x_slider, y_select = y_slider, **slider_dict); \n", "\n", "\n", "def on_save_button2_clicked(b):\n", " global save_figure\n", " save_figure = True \n", " \n", " dc_step_write = dc_step_write_slider.value\n", " x_select = x_slider.value\n", " y_select = y_slider.value\n", " \n", " make_jCPD_figure(dc_step_write, x_select, y_select)\n", " \n", " \n", "button2 = widgets.Button(description = 'Save figure')\n", "display(button2)\n", "button2.on_click(on_save_button2_clicked)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Display jCPD and fitting parameters\n", "\n", "Figure shows maps of\n", "- jCPD\n", "- slope\n", "- y-intercept\n", "\n", "for the write voltage step selected with slider." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "2fd22b8a497543e7b416ae3134a04553", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(IntSlider(value=0, description='Write Step', max=19), Output()), _dom_classes=('widget-i…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "2d01b19f41a7451b8d931eb8f36b13fa", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Button(description='Save figure', style=ButtonStyle())" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "global save_figure\n", "\n", "save_figure = False\n", " \n", "cmin = -3\n", "cmax = 3\n", " \n", "def make_fitting_figure(dc_step_write): \n", " global save_figure \n", " fig3 = plt.figure(figsize=(10,3)) \n", " fig3.set_facecolor('white') \n", " ax_jCPD_plot = plt.subplot(131)\n", " ax_slope_plot = plt.subplot(132)\n", " ax_yintercept_plot = plt.subplot(133)\n", " ax_slope_plot.set_title('Slope [a.u.]', fontsize = 12)\n", " \n", " im3 = ax_jCPD_plot.imshow(jCPD_mat[:,:,dc_step_write], \n", " cmap=usid.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " \n", "# im3 = ax_jCPD_plot.imshow(jCPD_mat[:,:,dc_step_write], \n", "# cmap=px.plot_utils.cmap_jet_white_center(), \n", "# origin='upper', interpolation='none', clim=(cmin, cmax)); \n", " \n", " fig3.colorbar(im3, ax = ax_jCPD_plot)\n", " ax_jCPD_plot.set_title('jCPD [V]', fontsize = 12)\n", " \n", " im = ax_slope_plot.imshow(fit_slope[:,:,dc_step_write], \n", " cmap=usid.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " \n", " fig3.colorbar(im, ax = ax_slope_plot)\n", " \n", " im2 = ax_yintercept_plot.imshow(fit_yintercept[:,:,dc_step_write], \n", " cmap=usid.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " ax_yintercept_plot.set_title('y-intercept [a.u.]', fontsize = 12)\n", " \n", " fig3.colorbar(im2, ax = ax_yintercept_plot)\n", " \n", " #fig3.suptitle('Write voltage = '+str(bias_vec_w[dc_step_write])+' V', fontsize = 14, y = 1.06)\n", " \n", " fig3.suptitle('Write voltage = '+str(bias_vec_w[dc_step_write])+' V', fontsize = 14)\n", " \n", " \n", "# fig3.add_subplot(132).text(2,11,'Write voltage = '+str(bias_vec_w[dc_step_write])+' V', fontsize = 14, orientation='vertical')\n", " plt.tight_layout()\n", " plt.subplots_adjust(top=0.8)\n", " if save_figure == True:\n", " fig3.savefig(output_file_path+'\\jCPD_map_WriteStep'+str(dc_step_write)+'.png', format='png')\n", " fig3.savefig(output_file_path+'\\jCPD_map_WriteStep'+str(dc_step_write)+'.eps', format='eps')\n", " fig3.savefig(output_file_path+'\\jCPD_map_WriteStep'+str(dc_step_write)+'.tif', format='tif')\n", " save_figure = False;\n", "\n", " \n", "slider_dict = dict() \n", "dc_step_write_slider = widgets.IntSlider(min = 0, max = num_write_steps-1, step = 1, value = 0, description='Write Step');\n", "\n", "widgets.interact(make_fitting_figure, dc_step_write = dc_step_write_slider, **slider_dict); \n", "\n", "\n", "def on_save_button3_clicked(b):\n", " global save_figure\n", " save_figure = True \n", " \n", " dc_step_write = dc_step_write_slider.value\n", "# x_select = x_slider.value\n", "# y_select = y_slider.value\n", " \n", " make_fitting_figure(dc_step_write)\n", " \n", " \n", "button3 = widgets.Button(description = 'Save figure')\n", "display(button3)\n", "button3.on_click(on_save_button3_clicked)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## jCPD plots\n", "\n", "- Left graph depicts the jCPD averaged over all pixels as a function of write voltage\n", "- Specify a pixel that jCPD data should be displayed from in graph on the right by setting x_select and y_select." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "/* global mpl */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function () {\n", " if (typeof WebSocket !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof MozWebSocket !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert(\n", " 'Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.'\n", " );\n", " }\n", "};\n", "\n", "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = this.ws.binaryType !== undefined;\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById('mpl-warnings');\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent =\n", " 'This browser does not support binary websocket messages. ' +\n", " 'Performance may be slow.';\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = document.createElement('div');\n", " this.root.setAttribute('style', 'display: inline-block');\n", " this._root_extra_style(this.root);\n", "\n", " parent_element.appendChild(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message('supports_binary', { value: fig.supports_binary });\n", " fig.send_message('send_image_mode', {});\n", " if (fig.ratio !== 1) {\n", " fig.send_message('set_dpi_ratio', { dpi_ratio: fig.ratio });\n", " }\n", " fig.send_message('refresh', {});\n", " };\n", "\n", " this.imageObj.onload = function () {\n", " if (fig.image_mode === 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function () {\n", " fig.ws.close();\n", " };\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "};\n", "\n", "mpl.figure.prototype._init_header = function () {\n", " var titlebar = document.createElement('div');\n", " titlebar.classList =\n", " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", " var titletext = document.createElement('div');\n", " titletext.classList = 'ui-dialog-title';\n", " titletext.setAttribute(\n", " 'style',\n", " 'width: 100%; text-align: center; padding: 3px;'\n", " );\n", " titlebar.appendChild(titletext);\n", " this.root.appendChild(titlebar);\n", " this.header = titletext;\n", "};\n", "\n", "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", "\n", "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", "\n", "mpl.figure.prototype._init_canvas = function () {\n", " var fig = this;\n", "\n", " var canvas_div = (this.canvas_div = document.createElement('div'));\n", " canvas_div.setAttribute(\n", " 'style',\n", " 'border: 1px solid #ddd;' +\n", " 'box-sizing: content-box;' +\n", " 'clear: both;' +\n", " 'min-height: 1px;' +\n", " 'min-width: 1px;' +\n", " 'outline: 0;' +\n", " 'overflow: hidden;' +\n", " 'position: relative;' +\n", " 'resize: both;'\n", " );\n", "\n", " function on_keyboard_event_closure(name) {\n", " return function (event) {\n", " return fig.key_event(event, name);\n", " };\n", " }\n", "\n", " canvas_div.addEventListener(\n", " 'keydown',\n", " on_keyboard_event_closure('key_press')\n", " );\n", " canvas_div.addEventListener(\n", " 'keyup',\n", " on_keyboard_event_closure('key_release')\n", " );\n", "\n", " this._canvas_extra_style(canvas_div);\n", " this.root.appendChild(canvas_div);\n", "\n", " var canvas = (this.canvas = document.createElement('canvas'));\n", " canvas.classList.add('mpl-canvas');\n", " canvas.setAttribute('style', 'box-sizing: content-box;');\n", "\n", " this.context = canvas.getContext('2d');\n", "\n", " var backingStore =\n", " this.context.backingStorePixelRatio ||\n", " this.context.webkitBackingStorePixelRatio ||\n", " this.context.mozBackingStorePixelRatio ||\n", " this.context.msBackingStorePixelRatio ||\n", " this.context.oBackingStorePixelRatio ||\n", " this.context.backingStorePixelRatio ||\n", " 1;\n", "\n", " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", " 'canvas'\n", " ));\n", " rubberband_canvas.setAttribute(\n", " 'style',\n", " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", " );\n", "\n", " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", " if (this.ResizeObserver === undefined) {\n", " if (window.ResizeObserver !== undefined) {\n", " this.ResizeObserver = window.ResizeObserver;\n", " } else {\n", " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n", " this.ResizeObserver = obs.ResizeObserver;\n", " }\n", " }\n", "\n", " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n", " var nentries = entries.length;\n", " for (var i = 0; i < nentries; i++) {\n", " var entry = entries[i];\n", " var width, height;\n", " if (entry.contentBoxSize) {\n", " if (entry.contentBoxSize instanceof Array) {\n", " // Chrome 84 implements new version of spec.\n", " width = entry.contentBoxSize[0].inlineSize;\n", " height = entry.contentBoxSize[0].blockSize;\n", " } else {\n", " // Firefox implements old version of spec.\n", " width = entry.contentBoxSize.inlineSize;\n", " height = entry.contentBoxSize.blockSize;\n", " }\n", " } else {\n", " // Chrome <84 implements even older version of spec.\n", " width = entry.contentRect.width;\n", " height = entry.contentRect.height;\n", " }\n", "\n", " // Keep the size of the canvas and rubber band canvas in sync with\n", " // the canvas container.\n", " if (entry.devicePixelContentBoxSize) {\n", " // Chrome 84 implements new version of spec.\n", " canvas.setAttribute(\n", " 'width',\n", " entry.devicePixelContentBoxSize[0].inlineSize\n", " );\n", " canvas.setAttribute(\n", " 'height',\n", " entry.devicePixelContentBoxSize[0].blockSize\n", " );\n", " } else {\n", " canvas.setAttribute('width', width * fig.ratio);\n", " canvas.setAttribute('height', height * fig.ratio);\n", " }\n", " canvas.setAttribute(\n", " 'style',\n", " 'width: ' + width + 'px; height: ' + height + 'px;'\n", " );\n", "\n", " rubberband_canvas.setAttribute('width', width);\n", " rubberband_canvas.setAttribute('height', height);\n", "\n", " // And update the size in Python. We ignore the initial 0/0 size\n", " // that occurs as the element is placed into the DOM, which should\n", " // otherwise not happen due to the minimum size styling.\n", " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n", " fig.request_resize(width, height);\n", " }\n", " }\n", " });\n", " this.resizeObserverInstance.observe(canvas_div);\n", "\n", " function on_mouse_event_closure(name) {\n", " return function (event) {\n", " return fig.mouse_event(event, name);\n", " };\n", " }\n", "\n", " rubberband_canvas.addEventListener(\n", " 'mousedown',\n", " on_mouse_event_closure('button_press')\n", " );\n", " rubberband_canvas.addEventListener(\n", " 'mouseup',\n", " on_mouse_event_closure('button_release')\n", " );\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband_canvas.addEventListener(\n", " 'mousemove',\n", " on_mouse_event_closure('motion_notify')\n", " );\n", "\n", " rubberband_canvas.addEventListener(\n", " 'mouseenter',\n", " on_mouse_event_closure('figure_enter')\n", " );\n", " rubberband_canvas.addEventListener(\n", " 'mouseleave',\n", " on_mouse_event_closure('figure_leave')\n", " );\n", "\n", " canvas_div.addEventListener('wheel', function (event) {\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " on_mouse_event_closure('scroll')(event);\n", " });\n", "\n", " canvas_div.appendChild(canvas);\n", " canvas_div.appendChild(rubberband_canvas);\n", "\n", " this.rubberband_context = rubberband_canvas.getContext('2d');\n", " this.rubberband_context.strokeStyle = '#000000';\n", "\n", " this._resize_canvas = function (width, height, forward) {\n", " if (forward) {\n", " canvas_div.style.width = width + 'px';\n", " canvas_div.style.height = height + 'px';\n", " }\n", " };\n", "\n", " // Disable right mouse context menu.\n", " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", " event.preventDefault();\n", " return false;\n", " });\n", "\n", " function set_focus() {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "};\n", "\n", "mpl.figure.prototype._init_toolbar = function () {\n", " var fig = this;\n", "\n", " var toolbar = document.createElement('div');\n", " toolbar.classList = 'mpl-toolbar';\n", " this.root.appendChild(toolbar);\n", "\n", " function on_click_closure(name) {\n", " return function (_event) {\n", " return fig.toolbar_button_onclick(name);\n", " };\n", " }\n", "\n", " function on_mouseover_closure(tooltip) {\n", " return function (event) {\n", " if (!event.currentTarget.disabled) {\n", " return fig.toolbar_button_onmouseover(tooltip);\n", " }\n", " };\n", " }\n", "\n", " fig.buttons = {};\n", " var buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'mpl-button-group';\n", " for (var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " /* Instead of a spacer, we start a new button group. */\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", " buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'mpl-button-group';\n", " continue;\n", " }\n", "\n", " var button = (fig.buttons[name] = document.createElement('button'));\n", " button.classList = 'mpl-widget';\n", " button.setAttribute('role', 'button');\n", " button.setAttribute('aria-disabled', 'false');\n", " button.addEventListener('click', on_click_closure(method_name));\n", " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", "\n", " var icon_img = document.createElement('img');\n", " icon_img.src = '_images/' + image + '.png';\n", " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", " icon_img.alt = tooltip;\n", " button.appendChild(icon_img);\n", "\n", " buttonGroup.appendChild(button);\n", " }\n", "\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", "\n", " var fmt_picker = document.createElement('select');\n", " fmt_picker.classList = 'mpl-widget';\n", " toolbar.appendChild(fmt_picker);\n", " this.format_dropdown = fmt_picker;\n", "\n", " for (var ind in mpl.extensions) {\n", " var fmt = mpl.extensions[ind];\n", " var option = document.createElement('option');\n", " option.selected = fmt === mpl.default_extension;\n", " option.innerHTML = fmt;\n", " fmt_picker.appendChild(option);\n", " }\n", "\n", " var status_bar = document.createElement('span');\n", " status_bar.classList = 'mpl-message';\n", " toolbar.appendChild(status_bar);\n", " this.message = status_bar;\n", "};\n", "\n", "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", " // which will in turn request a refresh of the image.\n", " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", "};\n", "\n", "mpl.figure.prototype.send_message = function (type, properties) {\n", " properties['type'] = type;\n", " properties['figure_id'] = this.id;\n", " this.ws.send(JSON.stringify(properties));\n", "};\n", "\n", "mpl.figure.prototype.send_draw_message = function () {\n", " if (!this.waiting) {\n", " this.waiting = true;\n", " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", " var format_dropdown = fig.format_dropdown;\n", " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", " fig.ondownload(fig, format);\n", "};\n", "\n", "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", " var size = msg['size'];\n", " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", " fig._resize_canvas(size[0], size[1], msg['forward']);\n", " fig.send_message('refresh', {});\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", " var x0 = msg['x0'] / fig.ratio;\n", " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n", " var x1 = msg['x1'] / fig.ratio;\n", " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", " y1 = Math.floor(y1) + 0.5;\n", " var min_x = Math.min(x0, x1);\n", " var min_y = Math.min(y0, y1);\n", " var width = Math.abs(x1 - x0);\n", " var height = Math.abs(y1 - y0);\n", "\n", " fig.rubberband_context.clearRect(\n", " 0,\n", " 0,\n", " fig.canvas.width / fig.ratio,\n", " fig.canvas.height / fig.ratio\n", " );\n", "\n", " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", "};\n", "\n", "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", " // Updates the figure title.\n", " fig.header.textContent = msg['label'];\n", "};\n", "\n", "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", " var cursor = msg['cursor'];\n", " switch (cursor) {\n", " case 0:\n", " cursor = 'pointer';\n", " break;\n", " case 1:\n", " cursor = 'default';\n", " break;\n", " case 2:\n", " cursor = 'crosshair';\n", " break;\n", " case 3:\n", " cursor = 'move';\n", " break;\n", " }\n", " fig.rubberband_canvas.style.cursor = cursor;\n", "};\n", "\n", "mpl.figure.prototype.handle_message = function (fig, msg) {\n", " fig.message.textContent = msg['message'];\n", "};\n", "\n", "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", " // Request the server to send over a new figure.\n", " fig.send_draw_message();\n", "};\n", "\n", "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", " fig.image_mode = msg['mode'];\n", "};\n", "\n", "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", " for (var key in msg) {\n", " if (!(key in fig.buttons)) {\n", " continue;\n", " }\n", " fig.buttons[key].disabled = !msg[key];\n", " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", " if (msg['mode'] === 'PAN') {\n", " fig.buttons['Pan'].classList.add('active');\n", " fig.buttons['Zoom'].classList.remove('active');\n", " } else if (msg['mode'] === 'ZOOM') {\n", " fig.buttons['Pan'].classList.remove('active');\n", " fig.buttons['Zoom'].classList.add('active');\n", " } else {\n", " fig.buttons['Pan'].classList.remove('active');\n", " fig.buttons['Zoom'].classList.remove('active');\n", " }\n", "};\n", "\n", "mpl.figure.prototype.updated_canvas_event = function () {\n", " // Called whenever the canvas gets updated.\n", " this.send_message('ack', {});\n", "};\n", "\n", "// A function to construct a web socket function for onmessage handling.\n", "// Called in the figure constructor.\n", "mpl.figure.prototype._make_on_message_function = function (fig) {\n", " return function socket_on_message(evt) {\n", " if (evt.data instanceof Blob) {\n", " /* FIXME: We get \"Resource interpreted as Image but\n", " * transferred with MIME type text/plain:\" errors on\n", " * Chrome. But how to set the MIME type? It doesn't seem\n", " * to be part of the websocket stream */\n", " evt.data.type = 'image/png';\n", "\n", " /* Free the memory for the previous frames */\n", " if (fig.imageObj.src) {\n", " (window.URL || window.webkitURL).revokeObjectURL(\n", " fig.imageObj.src\n", " );\n", " }\n", "\n", " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", " evt.data\n", " );\n", " fig.updated_canvas_event();\n", " fig.waiting = false;\n", " return;\n", " } else if (\n", " typeof evt.data === 'string' &&\n", " evt.data.slice(0, 21) === 'data:image/png;base64'\n", " ) {\n", " fig.imageObj.src = evt.data;\n", " fig.updated_canvas_event();\n", " fig.waiting = false;\n", " return;\n", " }\n", "\n", " var msg = JSON.parse(evt.data);\n", " var msg_type = msg['type'];\n", "\n", " // Call the \"handle_{type}\" callback, which takes\n", " // the figure and JSON message as its only arguments.\n", " try {\n", " var callback = fig['handle_' + msg_type];\n", " } catch (e) {\n", " console.log(\n", " \"No handler for the '\" + msg_type + \"' message type: \",\n", " msg\n", " );\n", " return;\n", " }\n", "\n", " if (callback) {\n", " try {\n", " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", " callback(fig, msg);\n", " } catch (e) {\n", " console.log(\n", " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", " e,\n", " e.stack,\n", " msg\n", " );\n", " }\n", " }\n", " };\n", "};\n", "\n", "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", "mpl.findpos = function (e) {\n", " //this section is from http://www.quirksmode.org/js/events_properties.html\n", " var targ;\n", " if (!e) {\n", " e = window.event;\n", " }\n", " if (e.target) {\n", " targ = e.target;\n", " } else if (e.srcElement) {\n", " targ = e.srcElement;\n", " }\n", " if (targ.nodeType === 3) {\n", " // defeat Safari bug\n", " targ = targ.parentNode;\n", " }\n", "\n", " // pageX,Y are the mouse positions relative to the document\n", " var boundingRect = targ.getBoundingClientRect();\n", " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", "\n", " return { x: x, y: y };\n", "};\n", "\n", "/*\n", " * return a copy of an object with only non-object keys\n", " * we need this to avoid circular references\n", " * http://stackoverflow.com/a/24161582/3208463\n", " */\n", "function simpleKeys(original) {\n", " return Object.keys(original).reduce(function (obj, key) {\n", " if (typeof original[key] !== 'object') {\n", " obj[key] = original[key];\n", " }\n", " return obj;\n", " }, {});\n", "}\n", "\n", "mpl.figure.prototype.mouse_event = function (event, name) {\n", " var canvas_pos = mpl.findpos(event);\n", "\n", " if (name === 'button_press') {\n", " this.canvas.focus();\n", " this.canvas_div.focus();\n", " }\n", "\n", " var x = canvas_pos.x * this.ratio;\n", " var y = canvas_pos.y * this.ratio;\n", "\n", " this.send_message(name, {\n", " x: x,\n", " y: y,\n", " button: event.button,\n", " step: event.step,\n", " guiEvent: simpleKeys(event),\n", " });\n", "\n", " /* This prevents the web browser from automatically changing to\n", " * the text insertion cursor when the button is pressed. We want\n", " * to control all of the cursor setting manually through the\n", " * 'cursor' event from matplotlib */\n", " event.preventDefault();\n", " return false;\n", "};\n", "\n", "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", " // Handle any extra behaviour associated with a key event\n", "};\n", "\n", "mpl.figure.prototype.key_event = function (event, name) {\n", " // Prevent repeat events\n", " if (name === 'key_press') {\n", " if (event.which === this._key) {\n", " return;\n", " } else {\n", " this._key = event.which;\n", " }\n", " }\n", " if (name === 'key_release') {\n", " this._key = null;\n", " }\n", "\n", " var value = '';\n", " if (event.ctrlKey && event.which !== 17) {\n", " value += 'ctrl+';\n", " }\n", " if (event.altKey && event.which !== 18) {\n", " value += 'alt+';\n", " }\n", " if (event.shiftKey && event.which !== 16) {\n", " value += 'shift+';\n", " }\n", "\n", " value += 'k';\n", " value += event.which.toString();\n", "\n", " this._key_event_extra(event, name);\n", "\n", " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", " return false;\n", "};\n", "\n", "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", " if (name === 'download') {\n", " this.handle_save(this, null);\n", " } else {\n", " this.send_message('toolbar_button', { name: name });\n", " }\n", "};\n", "\n", "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", "\n", "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", "// prettier-ignore\n", "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n", "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", "\n", "mpl.default_extension = \"png\";/* global mpl */\n", "\n", "var comm_websocket_adapter = function (comm) {\n", " // Create a \"websocket\"-like object which calls the given IPython comm\n", " // object with the appropriate methods. Currently this is a non binary\n", " // socket, so there is still some room for performance tuning.\n", " var ws = {};\n", "\n", " ws.close = function () {\n", " comm.close();\n", " };\n", " ws.send = function (m) {\n", " //console.log('sending', m);\n", " comm.send(m);\n", " };\n", " // Register the callback with on_msg.\n", " comm.on_msg(function (msg) {\n", " //console.log('receiving', msg['content']['data'], msg);\n", " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", " ws.onmessage(msg['content']['data']);\n", " });\n", " return ws;\n", "};\n", "\n", "mpl.mpl_figure_comm = function (comm, msg) {\n", " // This is the function which gets called when the mpl process\n", " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", "\n", " var id = msg.content.data.id;\n", " // Get hold of the div created by the display call when the Comm\n", " // socket was opened in Python.\n", " var element = document.getElementById(id);\n", " var ws_proxy = comm_websocket_adapter(comm);\n", "\n", " function ondownload(figure, _format) {\n", " window.open(figure.canvas.toDataURL());\n", " }\n", "\n", " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", "\n", " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", " // web socket which is closed, not our websocket->open comm proxy.\n", " ws_proxy.onopen();\n", "\n", " fig.parent_element = element;\n", " fig.cell_info = mpl.find_output_cell(\"
\");\n", " if (!fig.cell_info) {\n", " console.error('Failed to find cell for figure', id, fig);\n", " return;\n", " }\n", " fig.cell_info[0].output_area.element.on(\n", " 'cleared',\n", " { fig: fig },\n", " fig._remove_fig_handler\n", " );\n", "};\n", "\n", "mpl.figure.prototype.handle_close = function (fig, msg) {\n", " var width = fig.canvas.width / fig.ratio;\n", " fig.cell_info[0].output_area.element.off(\n", " 'cleared',\n", " fig._remove_fig_handler\n", " );\n", " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n", "\n", " // Update the output cell to use the data from the current canvas.\n", " fig.push_to_output();\n", " var dataURL = fig.canvas.toDataURL();\n", " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable();\n", " fig.parent_element.innerHTML =\n", " '';\n", " fig.close_ws(fig, msg);\n", "};\n", "\n", "mpl.figure.prototype.close_ws = function (fig, msg) {\n", " fig.send_message('closing', msg);\n", " // fig.ws.close()\n", "};\n", "\n", "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", " var width = this.canvas.width / this.ratio;\n", " var dataURL = this.canvas.toDataURL();\n", " this.cell_info[1]['text/html'] =\n", " '';\n", "};\n", "\n", "mpl.figure.prototype.updated_canvas_event = function () {\n", " // Tell IPython that the notebook contents must change.\n", " IPython.notebook.set_dirty(true);\n", " this.send_message('ack', {});\n", " var fig = this;\n", " // Wait a second, then push the new image to the DOM so\n", " // that it is saved nicely (might be nice to debounce this).\n", " setTimeout(function () {\n", " fig.push_to_output();\n", " }, 1000);\n", "};\n", "\n", "mpl.figure.prototype._init_toolbar = function () {\n", " var fig = this;\n", "\n", " var toolbar = document.createElement('div');\n", " toolbar.classList = 'btn-toolbar';\n", " this.root.appendChild(toolbar);\n", "\n", " function on_click_closure(name) {\n", " return function (_event) {\n", " return fig.toolbar_button_onclick(name);\n", " };\n", " }\n", "\n", " function on_mouseover_closure(tooltip) {\n", " return function (event) {\n", " if (!event.currentTarget.disabled) {\n", " return fig.toolbar_button_onmouseover(tooltip);\n", " }\n", " };\n", " }\n", "\n", " fig.buttons = {};\n", " var buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'btn-group';\n", " var button;\n", " for (var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " /* Instead of a spacer, we start a new button group. */\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", " buttonGroup = document.createElement('div');\n", " buttonGroup.classList = 'btn-group';\n", " continue;\n", " }\n", "\n", " button = fig.buttons[name] = document.createElement('button');\n", " button.classList = 'btn btn-default';\n", " button.href = '#';\n", " button.title = name;\n", " button.innerHTML = '';\n", " button.addEventListener('click', on_click_closure(method_name));\n", " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", " buttonGroup.appendChild(button);\n", " }\n", "\n", " if (buttonGroup.hasChildNodes()) {\n", " toolbar.appendChild(buttonGroup);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = document.createElement('span');\n", " status_bar.classList = 'mpl-message pull-right';\n", " toolbar.appendChild(status_bar);\n", " this.message = status_bar;\n", "\n", " // Add the close button to the window.\n", " var buttongrp = document.createElement('div');\n", " buttongrp.classList = 'btn-group inline pull-right';\n", " button = document.createElement('button');\n", " button.classList = 'btn btn-mini btn-primary';\n", " button.href = '#';\n", " button.title = 'Stop Interaction';\n", " button.innerHTML = '';\n", " button.addEventListener('click', function (_evt) {\n", " fig.handle_close(fig, {});\n", " });\n", " button.addEventListener(\n", " 'mouseover',\n", " on_mouseover_closure('Stop Interaction')\n", " );\n", " buttongrp.appendChild(button);\n", " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", "};\n", "\n", "mpl.figure.prototype._remove_fig_handler = function (event) {\n", " var fig = event.data.fig;\n", " if (event.target !== this) {\n", " // Ignore bubbled events from children.\n", " return;\n", " }\n", " fig.close_ws(fig, {});\n", "};\n", "\n", "mpl.figure.prototype._root_extra_style = function (el) {\n", " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", "};\n", "\n", "mpl.figure.prototype._canvas_extra_style = function (el) {\n", " // this is important to make the div 'focusable\n", " el.setAttribute('tabindex', 0);\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " } else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "};\n", "\n", "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager) {\n", " manager = IPython.keyboard_manager;\n", " }\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which === 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "};\n", "\n", "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", " fig.ondownload(fig, null);\n", "};\n", "\n", "mpl.find_output_cell = function (html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i = 0; i < ncells; i++) {\n", " var cell = cells[i];\n", " if (cell.cell_type === 'code') {\n", " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", " var data = cell.output_area.outputs[j];\n", " if (data.data) {\n", " // IPython >= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] === html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "};\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel !== null) {\n", " IPython.notebook.kernel.comm_manager.register_target(\n", " 'matplotlib',\n", " mpl.mpl_figure_comm\n", " );\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "jCPD averaged over all pixels and write voltage steps = -0.5591658004864636 +/- 13.630228163902892 V\n" ] } ], "source": [ "# specify x select and y select\n", "\n", "x_select = 3\n", "y_select = 2\n", "\n", "x_range2 = [0, num_col-1]\n", "y_range2 = [0, num_row-1]\n", "# x_range2[0] = 0\n", "# x_range2[1] = num_col-1\n", "# y_range2[0] = 0\n", "# y_range2[1] = num_row-1\n", "\n", "jCPD_mean1 = np.nanmean(jCPD_mat[y_range2[0]:y_range2[1], x_range2[0]:x_range2[1],:],axis = 0)\n", "jCPD_std1 = np.nanstd(jCPD_mat[y_range2[0]:y_range2[1], x_range2[0]:x_range2[1],:],axis = 0)\n", "jCPD_mean_w = np.nanmean(jCPD_mean1,axis = 0)\n", "jCPD_std_w = np.nanstd(jCPD_mean1,axis = 0)\n", "\n", "\n", "\n", "#jCPD_mean_w[2] = np.nan\n", "\n", "\n", "jCPD_mean_all = np.nanmean(jCPD_mean_w,axis = 0)\n", "jCPD_std_all = np.nanstd(jCPD_std_w,axis = 0)\n", "\n", "\n", "fig3 = plt.figure(figsize=(12,7)) \n", "fig3.set_facecolor('white')\n", "ax_jCPD_mean = plt.subplot2grid((10, 10), (0, 0), colspan=4, rowspan=5)\n", "ax_jCPD_xy = plt.subplot2grid((10, 10), (0, 5), colspan=4, rowspan=5)\n", "\n", "plt.title('Mean jCPD vs write voltage', fontsize = 12)\n", "# ax_jCPD_mean.errorbar(bias_vec_w, jCPD_mean_w, yerr = jCPD_std_w, fmt = '.-')\n", "ax_jCPD_mean.plot(bias_vec_w, jCPD_mean_w, '.-')\n", "ax_jCPD_mean.set_xlabel('Write voltage [V]', fontsize = 12)\n", "ax_jCPD_mean.set_ylabel('Mean jCPD [V]', fontsize = 12)\n", "# ax_jCPD_mean.set_ylim([-10,10])\n", "\n", "ax_jCPD_xy.plot(bias_vec_w, jCPD_mat[y_select,x_select, : ], '.-')\n", "ax_jCPD_xy.set_xlabel('Write voltage [V]', fontsize = 12)\n", "ax_jCPD_xy.set_ylabel('jCPD [V]', fontsize = 12)\n", "# ax_jCPD_xy.set_ylim([-10,15])\n", "plt.title('jCPD at x = '+str(x_select)+' y = '+str(y_select))\n", "\n", "print('jCPD averaged over all pixels and write voltage steps = '+ str(jCPD_mean_all)+' +/- '+str(jCPD_std_all)+' V')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## PCA analysis\n", "\n", "### Singular value decomposition performed on raw data:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(100, 54560)\n" ] }, { "ename": "AttributeError", "evalue": "module 'pyUSID' has no attribute 'svd_utils'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m# Do SVD on raw data\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mh5_main\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mdo_svd\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0musid\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msvd_utils\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mSVD\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mh5_main\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnum_components\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m40\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 4\u001b[0m \u001b[0mSVD_data\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdo_svd\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcompute\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mAttributeError\u001b[0m: module 'pyUSID' has no attribute 'svd_utils'" ] } ], "source": [ "# Do SVD on raw data\n", "print(h5_main.shape)\n", "do_svd = px.svd_utils.SVD(h5_main, num_components=40)\n", "SVD_data = do_svd.compute()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### SVD on jCPD, slope, y-intercept data and response at 0 V read voltage:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Do SVD on jCPD, slope and y-intercept data\n", "\n", "from sklearn.utils.extmath import randomized_svd\n", "\n", "num_components = 20;\n", "\n", "# # #Filter outliers from jCPD matrix, (-> improve code)\n", "# # for r in range(1, num_row):\n", "# # for c in range(1, num_col):\n", "# # for s in range(1, num_write_steps):\n", "# # if jCPD_mat[r-1, c-1, s-1] > 5 or jCPD_mat[r-1, c-1, s-1] < -5:\n", "# # jCPD_mat[r-1, c-1, s-1] = np.nan\n", "# # # jCPD_mat[r-1, c-1, s-1] = 0\n", "\n", "\n", "x_delete = np.array([])\n", "y_delete = np.array([])\n", "\n", "\n", "index_delete = (num_col)*y_delete+x_delete\n", "\n", "\n", "jCPD_mat_SVD = np.reshape(jCPD_mat,(num_row*num_col, num_write_steps))\n", "\n", "nan_pos = np.squeeze((np.argwhere(np.isnan(jCPD_mat_SVD).any(axis=1))))\n", "index_delete = np.insert(index_delete, index_delete.shape[0], nan_pos, axis = 0)\n", "\n", "index_delete = -np.sort(-index_delete)\n", "\n", "\n", "jCPD_mat_SVD_clean = jCPD_mat_SVD\n", "\n", "for i in range(0,index_delete.shape[0]):\n", " jCPD_mat_SVD_clean = np.delete(jCPD_mat_SVD_clean, index_delete[i], axis = 0)\n", "\n", "U_SVD_jCPD, S_SVD_jCPD, V_SVD_jCPD = randomized_svd(jCPD_mat_SVD_clean, n_components = num_components)\n", "\n", "\n", "index_delete = np.sort(index_delete)\n", "\n", "for i in range(0,index_delete.shape[0]):\n", " U_SVD_jCPD = np.insert(U_SVD_jCPD, index_delete[i], np.nan ,axis = 0)\n", " print(i,index_delete[i])\n", " \n", "print(U_SVD_jCPD.shape)\n", "\n", "\n", "slope_mat_SVD = np.reshape(fit_slope,(num_row*num_col, num_write_steps))\n", "U_SVD_slope, S_SVD_slope, V_SVD_slope = randomized_svd(slope_mat_SVD, n_components = num_components)\n", "\n", "yintercept_mat_SVD = np.reshape(fit_yintercept,(num_row*num_col, num_write_steps))\n", "U_SVD_yintercept, S_SVD_yintercept, V_SVD_yintercept = randomized_svd(yintercept_mat_SVD, n_components = num_components)\n", "\n", "\n", "# Do SVD on cKPFM signal at 0 V read voltage (= PFM)\n", "dc_step_read = np.argwhere(np.isclose(bias_vec_r[0,:], 0)).squeeze()\n", "\n", "resp_mat_0Vr = np.squeeze(Nd_mat[:,:,1,:,dc_step_read]['Amplitude [V]'] * \n", " np.cos(Nd_mat[:,:,1,:,dc_step_read]['Phase [rad]'])*1000)\n", "\n", "resp_mat_0Vr = np.reshape(resp_mat_0Vr,(num_row*num_col, num_write_steps))\n", "U_SVD_resp0Vr, S_SVD_resp0Vr, V_SVD_resp0Vr = randomized_svd(resp_mat_0Vr, n_components = num_components)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Display SVD score maps and eigenvectors of jCPD data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Visualize PCA of jCPD data\n", "\n", "U_SVD_jCPD = np.reshape(U_SVD_jCPD,(num_row, num_col, num_components))\n", "\n", "fig5 = plt.figure(figsize=(12,12))\n", "fig5.clf()\n", "fig5.set_facecolor('white') \n", "\n", "n_components = 20\n", "\n", "for component in range(1, n_components+1):\n", " \n", "\n", " ax_SVD_plot = plt.subplot(5, 4, component)\n", " image = ax_SVD_plot.imshow(U_SVD_jCPD[:,:,component-1], cmap=px.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " ax_SVD_plot.set_title('#'+str(component), fontsize = 10)\n", " \n", " fig5.colorbar(image, ax = ax_SVD_plot)\n", " \n", "fig5.suptitle('PCA scores of jCPD data', weight = 'bold', fontsize = 12, y=1)\n", "fig5.tight_layout()\n", "\n", "\n", "\n", "fig55 = plt.figure(figsize=(12,12))\n", "fig55.clf()\n", "fig55.set_facecolor('white')\n", "\n", "for component in range(1, n_components+1):\n", " ax_SVD_plot = plt.subplot(5, 4, component)\n", " image = ax_SVD_plot.plot(bias_vec_w, V_SVD_jCPD[component-1,:],'.-');\n", " ax_SVD_plot.set_title('#'+str(component), fontsize = 10)\n", " ax_SVD_plot.set_xlabel('Write voltage [V]')\n", "\n", "\n", "fig55.suptitle('PCA eigenvectors of jCPD data', weight = 'bold', fontsize = 12, y=1);\n", "\n", "fig55.tight_layout()\n", "\n", "\n", "def on_save_button4_clicked(b):\n", " \n", " fig5.savefig(output_file_path+'\\PCA_jCPD_scores.png', format='png')\n", " fig5.savefig(output_file_path+'\\PCA_jCPD_scores.eps', format='eps')\n", " fig5.savefig(output_file_path+'\\PCA_jCPD_scores.tif', format='tif')\n", " fig55.savefig(output_file_path+'\\PCA_jCPD_ev.png', format='png')\n", " fig55.savefig(output_file_path+'\\PCA_jCPD_ev.eps', format='eps')\n", " fig55.savefig(output_file_path+'\\PCA_jCPD_ev.tif', format='tif')\n", "\n", " \n", "button4 = widgets.Button(description = 'Save figure')\n", "display(button4)\n", "button4.on_click(on_save_button4_clicked)\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Display SVD score maps and eigenvectors of slope data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Visualize PCA of slope data\n", "U_SVD_slope = np.reshape(U_SVD_slope,(num_row, num_col, num_components))\n", "\n", "fig6 = plt.figure(figsize=(12,12))\n", "fig6.clf()\n", "fig6.set_facecolor('white') \n", "\n", "n_components = 20\n", "\n", "for component in range(1, n_components+1):\n", " \n", "\n", " ax_SVD_plot = plt.subplot(5, 4, component)\n", " image = ax_SVD_plot.imshow(U_SVD_slope[:,:,component-1], cmap=px.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " ax_SVD_plot.set_title('#'+str(component), fontsize = 10)\n", " fig6.colorbar(image, ax = ax_SVD_plot)\n", " \n", "fig6.tight_layout()\n", "fig6.suptitle('PCA scores of slope data', weight = 'bold', fontsize = 12, y = 1);\n", "\n", "\n", "fig66 = plt.figure(figsize=(12,12))\n", "fig66.clf()\n", "fig66.set_facecolor('white')\n", "\n", "for component in range(1, n_components+1):\n", " ax_SVD_plot = plt.subplot(5, 4, component)\n", " image = ax_SVD_plot.plot(bias_vec_w, V_SVD_slope[component-1,:],'.-');\n", " ax_SVD_plot.set_title('#'+str(component), fontsize = 10)\n", " ax_SVD_plot.set_xlabel('Write voltage [V]')\n", "fig66.tight_layout()\n", "\n", "fig66.suptitle('PCA eigenvectors of slope data', weight = 'bold', fontsize = 12, y = 1);\n", "\n", "def on_save_button5_clicked(b):\n", " \n", " fig6.savefig(output_file_path+'\\PCA_slope_scores.png', format='png')\n", " fig6.savefig(output_file_path+'\\PCA_slope_scores.eps', format='eps')\n", " fig6.savefig(output_file_path+'\\PCA_slope_scores.tif', format='tif')\n", " fig66.savefig(output_file_path+'\\PCA_slope_ev.png', format='png')\n", " fig66.savefig(output_file_path+'\\PCA_slope_ev.eps', format='eps')\n", " fig66.savefig(output_file_path+'\\PCA_slope_ev.tif', format='tif')\n", "\n", " \n", "button5 = widgets.Button(description = 'Save figure')\n", "display(button5)\n", "button5.on_click(on_save_button5_clicked)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Display SVD score maps and eigenvectors of y-intercept data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Visualize PCA of y-intercept data\n", "U_SVD_yintercept = np.reshape(U_SVD_yintercept,(num_row, num_col, num_components))\n", "\n", "fig7 = plt.figure(figsize=(12,12))\n", "fig7.clf()\n", "fig7.set_facecolor('white') \n", "\n", "n_components = 20\n", "\n", "for component in range(1, n_components+1):\n", " \n", "\n", " ax_SVD_plot = plt.subplot(5, 4, component)\n", " image = ax_SVD_plot.imshow(U_SVD_yintercept[:,:,component-1], cmap=px.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " ax_SVD_plot.set_title('#'+str(component), fontsize = 10)\n", " \n", " fig7.colorbar(image, ax = ax_SVD_plot)\n", " \n", "\n", "fig7.tight_layout()\n", "\n", "fig7.suptitle('PCA scores of y-intercept data', weight = 'bold', fontsize = 12, y = 1);\n", "\n", "fig77 = plt.figure(figsize=(12,12))\n", "fig77.clf()\n", "fig77.set_facecolor('white')\n", "\n", "for component in range(1, n_components+1):\n", " ax_SVD_plot = plt.subplot(5, 4, component)\n", " image = ax_SVD_plot.plot(bias_vec_w, V_SVD_yintercept[component-1,:],'.-');\n", " ax_SVD_plot.set_title('#'+str(component), fontsize = 10)\n", " ax_SVD_plot.set_xlabel('Write voltage [V]')\n", "fig77.tight_layout()\n", "\n", "fig77.suptitle('PCA eigenvectors of y-intercept data', weight = 'bold', fontsize = 12, y = 1);\n", "\n", "def on_save_button6_clicked(b):\n", " \n", " fig7.savefig(output_file_path+'\\PCA_yintercept_scores.png', format='png')\n", " fig7.savefig(output_file_path+'\\PCA_yintercept_scores.eps', format='eps')\n", " fig7.savefig(output_file_path+'\\PCA_yintercept_scores.tif', format='tif')\n", " fig77.savefig(output_file_path+'\\PCA_yintercept_ev.png', format='png')\n", " fig77.savefig(output_file_path+'\\PCA_yintercept_ev.eps', format='eps')\n", " fig77.savefig(output_file_path+'\\PCA_yintercept_ev.tif', format='tif')\n", "\n", " \n", "button6 = widgets.Button(description = 'Save figure')\n", "display(button6)\n", "button6.on_click(on_save_button6_clicked)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Display SVD score maps and eigenvectors of response at 0 V read voltage:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Visualize PCA of response at 0 V read voltage\n", "U_SVD_resp0Vr = np.reshape(U_SVD_resp0Vr,(num_row, num_col, num_components))\n", "\n", "fig8 = plt.figure(figsize=(12,12))\n", "fig8.clf()\n", "fig8.set_facecolor('white') \n", "\n", "n_components = 20\n", "\n", "\n", "for component in range(1, n_components+1):\n", " \n", "\n", " ax_SVD_plot = plt.subplot(5, 4, component)\n", " image = ax_SVD_plot.imshow(U_SVD_resp0Vr[:,:,component-1], cmap=px.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " ax_SVD_plot.set_title('#'+str(component), fontsize = 10)\n", " fig8.colorbar(image, ax = ax_SVD_plot)\n", " \n", "\n", "fig8.tight_layout()\n", "\n", "fig8.suptitle('PCA scores of response at V$_{read}$ = 0 V', weight = 'bold', fontsize = 12, y = 1);\n", "\n", "fig88 = plt.figure(figsize=(12,12))\n", "fig88.clf()\n", "fig88.set_facecolor('white')\n", "\n", "for component in range(1, n_components+1):\n", " ax_SVD_plot = plt.subplot(5, 4, component)\n", " image = ax_SVD_plot.plot(bias_vec_w, V_SVD_resp0Vr[component-1,:],'.-');\n", " ax_SVD_plot.set_xlabel('Write voltage [V]')\n", " ax_SVD_plot.set_title('#'+str(component), fontsize = 10)\n", "fig88.tight_layout()\n", "\n", "fig88.suptitle('PCA eigenvectors of response at V$_{read}$ = 0 V', weight = 'bold', fontsize = 12, y = 1);\n", "\n", "def on_save_button7_clicked(b):\n", " \n", " fig8.savefig(output_file_path+'\\PCA_resp0V_scores.png', format='png')\n", " fig8.savefig(output_file_path+'\\PCA_resp0V_scores.eps', format='eps')\n", " fig8.savefig(output_file_path+'\\PCA_resp0V_scores.tif', format='tif')\n", " fig88.savefig(output_file_path+'\\PCA_resp0V_ev.png', format='png')\n", " fig88.savefig(output_file_path+'\\PCA_resp0V_ev.eps', format='eps')\n", " fig88.savefig(output_file_path+'\\PCA_resp0V_ev.tif', format='tif')\n", "\n", " \n", "button7 = widgets.Button(description = 'Save figure')\n", "display(button7)\n", "button7.on_click(on_save_button7_clicked)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Display SVD score maps and eigenvectors of raw data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# Visualize PCA of raw data\n", "S_mat = SVD_data['S'][:]\n", "U_mat = SVD_data['U'][:]\n", "V_mat = SVD_data['V'][:]\n", "\n", "n_components = min(40, S_mat.size)\n", "\n", "U_mat = np.reshape(U_mat,(num_row, num_col, n_components))\n", "\n", "fig4 = plt.figure(figsize=(12,20))\n", "fig4.clf()\n", "fig4.set_facecolor('white') \n", "\n", "for component in range(1, n_components+1):\n", " ax_SVD_plot = plt.subplot(10, 4, component)\n", " \n", " image = ax_SVD_plot.imshow(U_mat[:,:,component-1], \n", " cmap=px.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " ax_SVD_plot.set_title('#'+str(component), fontsize = 10)\n", " fig4.colorbar(image, ax = ax_SVD_plot)\n", " \n", "fig4.tight_layout()\n", "\n", "\n", "fig4.suptitle('PCA scores of raw data', weight = 'bold', fontsize = 12, y = 1);\n", "\n", "\n", "fig44 = plt.figure(figsize=(12,20))\n", "fig44.clf()\n", "fig44.set_facecolor('white')\n", "\n", "for component in range(1, n_components+1):\n", " ax_SVD_plot = plt.subplot(10, 4, component)\n", " image = ax_SVD_plot.plot(V_mat[component-1,:],'.-');\n", " ax_SVD_plot.set_title('#'+str(component), fontsize = 10)\n", "fig44.tight_layout()\n", "\n", "fig44.suptitle('PCA eigenvectors of of raw data', weight = 'bold', fontsize = 12, y = 1);\n", "\n", "def on_save_button8_clicked(b):\n", " \n", " fig4.savefig(output_file_path+'\\PCA_rawdata_scores.png', format='png')\n", " fig4.savefig(output_file_path+'\\PCA_rawdata_scores.eps', format='eps')\n", " fig4.savefig(output_file_path+'\\PCA_rawdata_scores.tif', format='tif')\n", " fig44.savefig(output_file_path+'\\PCA_rawdata_ev.png', format='png')\n", " fig44.savefig(output_file_path+'\\PCA_rawdata_ev.eps', format='eps')\n", " fig44.savefig(output_file_path+'\\PCA_rawdata_ev.tif', format='tif')\n", "\n", " \n", "button8 = widgets.Button(description = 'Save figure')\n", "display(button8)\n", "button8.on_click(on_save_button8_clicked)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# BEPS/ FORC viewer" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "global count\n", "count = 0\n", "cycle = 0\n", "row = 0\n", "col = 0\n", "dc_step_write = 0\n", "step_chan = b'read_bias'\n", "\n", "guess_3d_data, success = px.hdf_utils.reshape_to_Ndims(h5_sho_fit)\n", "h5_sho_spec_inds = px.hdf_utils.getAuxData(h5_sho_fit, auxDataName='Spectroscopic_Indices')[0]\n", "h5_sho_spec_vals = px.hdf_utils.getAuxData(h5_sho_fit, auxDataName='Spectroscopic_Values')[0]\n", "\n", "spec_nd, _ = px.hdf_utils.reshape_to_Ndims(h5_sho_spec_inds, h5_spec=h5_sho_spec_inds)\n", "\n", "spec_nd, _ = px.hdf_utils.reshape_to_Ndims(h5_sho_spec_inds, h5_spec=h5_sho_spec_inds)\n", "# sho_spec_sort = get_sort_order(h5_sho_spec_inds)\n", "sho_spec_dims = np.array(spec_nd.shape[1:])\n", "sho_spec_labels = h5_sho_spec_inds.attrs['labels']\n", "\n", "h5_pos_inds = px.hdf_utils.getAuxData(h5_sho_fit, auxDataName='Position_Indices')[-1];\n", "pos_nd, _ = px.hdf_utils.reshape_to_Ndims(h5_pos_inds, h5_pos=h5_pos_inds)\n", "pos_dims = list(pos_nd.shape[:h5_pos_inds.shape[1]])\n", "pos_labels = h5_pos_inds.attrs['labels']\n", "\n", "# reshape to X, Y, step, all others\n", "spec_step_dim_ind = np.where(sho_spec_labels == step_chan)[0]\n", "step_dim_ind = len(pos_dims) + spec_step_dim_ind\n", "\n", "# move the step dimension to be the first after all position dimensions\n", "rest_sho_dim_order = list(range(len(pos_dims), len(guess_3d_data.shape)))\n", "rest_sho_dim_order.remove(step_dim_ind)\n", "new_order = list(range(len(pos_dims))) + step_dim_ind.tolist() + rest_sho_dim_order\n", "\n", "# Transpose the 3D dataset to this shape:\n", "sho_guess_Nd_1 = np.transpose(guess_3d_data, new_order)\n", "\n", "# Now move the step dimension to the front for the spec labels as well\n", "new_spec_order = list(range(len(sho_spec_labels)))\n", "new_spec_order.remove(spec_step_dim_ind)\n", "new_spec_order = spec_step_dim_ind.tolist() + new_spec_order\n", "\n", "# new_spec_labels = sho_spec_labels[new_spec_order]\n", "new_spec_dims = np.array(sho_spec_dims)[new_spec_order]\n", "\n", "# Now collapse all additional dimensions\n", "final_guess_shape = pos_dims + [new_spec_dims[0]] + [-1]\n", "sho_dset_collapsed = np.reshape(sho_guess_Nd_1, final_guess_shape)\n", "\n", "# Get the bias matrix:\n", "bias_mat, _ = px.hdf_utils.reshape_to_Ndims(h5_sho_spec_vals, h5_spec=h5_sho_spec_inds)\n", "bias_mat = np.transpose(bias_mat[spec_step_dim_ind].squeeze(), new_spec_order).reshape(sho_dset_collapsed.\n", " shape[len(pos_dims):])\n", "bias_mat = bias_mat*high_voltage_amplf\n", "\n", "num_read_steps = sho_dset_collapsed.shape[1]\n", "num_write_steps = sho_dset_collapsed.shape[2]\n", "num_row = sho_dset_collapsed.shape[1]\n", "num_col = sho_dset_collapsed.shape[0]\n", "\n", "print(sho_dset_collapsed.shape)\n", "print('bias mat shape', bias_mat.shape)\n", "\n", "num_loops = bias_mat.shape[1]\n", "num_loops_h = int(num_loops/2)\n", "# plt.figure()\n", "# plt.plot(bias_mat[:,:]);\n", "\n", "\n", "\n", "# print(sho_dset_collapsed.attrs)\n", "# print(getattr(obj))\n", "\n", "amp_map = sho_dset_collapsed[:, :, dc_step_write, cycle]['Amplitude [V]']*1000\n", "phase_map = sho_dset_collapsed[:, :, dc_step_write, cycle]['Phase [rad]']\n", "frequency_map = sho_dset_collapsed[:, :, dc_step_write, cycle]['Frequency [Hz]']/1000\n", "Q_map = sho_dset_collapsed[:, :, dc_step_write, cycle]['Quality Factor']\n", "\n", "mixed_map = amp_map*np.cos(phase_map)\n", "mixed_mat_h = sho_dset_collapsed[:, :, :, :]['Amplitude [V]'] * np.cos(sho_dset_collapsed[:, :, :, :]['Phase [rad]'])*1000\n", "\n", "print('mixed shape = ', mixed_mat_h.shape)\n", "\n", "def make_figure_beps_forc(amp_map, phase_map, mixed_map, Q_map, frequency_map, mixed_mat_h, col, row, cycle, dc_step_write):\n", " global fig_bf\n", " fig_bf = plt.figure(figsize=(12,6))\n", " fig_bf.clf()\n", " fig_bf.set_facecolor('white') \n", " \n", " \n", " \n", " ax_amp = plt.subplot(2, 3, 1)\n", " img_a = ax_amp.imshow(amp_map, cmap=px.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " ax_amp.set_title('Amplitude [a.u.]', fontsize = 10)\n", " fig_bf.colorbar(img_a, ax = ax_amp)\n", "\n", " ax_phase = plt.subplot(2, 3, 2)\n", " img_p = ax_phase.imshow(phase_map, cmap=px.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none', clim = [-3.5, 3.5]);\n", " ax_phase.set_title('Phase [rad]', fontsize = 10)\n", " fig_bf.colorbar(img_p, ax = ax_phase)\n", "\n", " ax_m = plt.subplot(2, 3, 3)\n", " img_m = ax_m.imshow(mixed_map, cmap=px.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " ax_m.set_title('Real component [a.u.]', fontsize = 10)\n", " fig_bf.colorbar(img_m, ax = ax_m)\n", "\n", " ax_q = plt.subplot(2, 3, 4)\n", " img_q = ax_q.imshow(Q_map, cmap=px.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " ax_q.set_title('Quality factor', fontsize = 10)\n", " fig_bf.colorbar(img_q, ax = ax_q) \n", "\n", " ax_f = plt.subplot(2, 3, 5)\n", " img_f = ax_f.imshow(frequency_map, cmap=px.plot_utils.cmap_jet_white_center(), \n", " origin='upper', interpolation='none');\n", " ax_f.set_title('Resonance frequency [kHz]', fontsize = 10)\n", " fig_bf.colorbar(img_f, ax = ax_f) \n", "\n", " ax_h = plt.subplot(2, 3, 6)\n", " ax_h.plot(bias_mat[:,0:num_loops//2], mixed_mat_h[row, col, :, 0:num_loops//2],'-.', marker ='*')\n", " ax_h.plot(bias_mat[:,num_loops_h:num_loops], mixed_mat_h[row, col, :, num_loops_h:num_loops],'.-')\n", " ax_h.set_ylabel('Response [a.u.]')\n", " ax_h.set_xlabel('Write voltage [V]')\n", " ax_h.set_title('x = '+str(col)+' y = '+str(row), fontsize = 10)\n", " \n", " \n", " fig_bf.suptitle('Step# = '+str(dc_step_write)+', cycle# = '+str(cycle)\n", " +', V$_{write}$ = '+str(bias_mat[dc_step_write, 0]) +' V'\n", " , fontsize = 12);\n", " \n", "\n", " fig_bf.tight_layout()\n", " \n", " plt.subplots_adjust(top = 0.9)\n", "\n", "make_figure_beps_forc(amp_map, phase_map, mixed_map, Q_map, frequency_map, mixed_mat_h, col, row, cycle, dc_step_write)\n", " \n", "def update_beps_forc_plot(dc_step_write, cycle, col, row):\n", " \n", " amp_map = sho_dset_collapsed[:, :, dc_step_write, cycle]['Amplitude [V]']*1000\n", " phase_map = sho_dset_collapsed[:, :, dc_step_write, cycle]['Phase [rad]']\n", " frequency_map = sho_dset_collapsed[:, :, dc_step_write, cycle]['Frequency [Hz]']/1000\n", " Q_map = sho_dset_collapsed[:, :, dc_step_write, cycle]['Quality Factor']\n", " mixed_map = amp_map*np.cos(phase_map)\n", " mixed_mat_h = sho_dset_collapsed[:, :, :, :]['Amplitude [V]'] * np.cos(sho_dset_collapsed[:, :, :, :]['Phase [rad]'])*1000\n", "\n", " make_figure_beps_forc(amp_map, phase_map, mixed_map, Q_map, frequency_map, mixed_mat_h, col, row, cycle, dc_step_write)\n", "\n", "num_loops_h =num_loops//2-1\n", "\n", "dc_step_write_slider_bf = widgets.IntSlider(min = 0, max = num_write_steps-1, step = 1,value = 0,\n", " description = 'Write step',continuous_update = False)\n", "cycle_slider = widgets.IntSlider(min = 2, max = num_loops-1, step = 1,value = 2,\n", " description = 'Cycle', continuous_update = False)\n", "x_slider_bf = widgets.IntSlider(min = 0, max = num_col-1,step = 1,value = 0,\n", " description='x',continuous_update = False)\n", "y_slider_bf = widgets.IntSlider(min = 0,max = num_row-1,step = 1,value = 0, description = 'y',continuous_update = False)\n", "\n", "widgets.interact(update_beps_forc_plot, dc_step_write = dc_step_write_slider_bf, cycle = cycle_slider, \n", " col = x_slider_bf, row = y_slider_bf, **slider_dict); \n", "\n", "\n", "def on_save_button9_clicked(b):\n", " global count\n", " \n", " fig_bf.savefig(output_file_path+'\\SHO_parms'+str(count)+'.png', format='png')\n", " fig_bf.savefig(output_file_path+'\\SHO_parms'+str(count)+'.eps', format='eps')\n", " fig_bf.savefig(output_file_path+'\\SHO_parms'+str(count)+'.tif', format='tif')\n", " count+=1\n", " \n", "button9 = widgets.Button(description = 'Save figure')\n", "display(button9)\n", "button9.on_click(on_save_button9_clicked)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "amp_data = sho_dset_collapsed[:, :, :, :]['Amplitude [V]']*1000\n", "phase_data = sho_dset_collapsed[:, :, :, :]['Phase [rad]']\n", "\n", "amp_mean1 = np.nanmean(amp_data, axis = 0)\n", "amp_mean = np.nanmean(amp_mean1, axis = 0)\n", "\n", "phase_mean1 = np.nanmean(phase_data, axis = 0)\n", "phase_mean = np.nanmean(phase_mean1, axis = 0)\n", "\n", "mixed_mat_mean1 = np.nanmean(mixed_mat_h, axis = 0)\n", "mixed_mat_mean = np.nanmean(mixed_mat_mean1, axis = 0)\n", "\n", "fig_loops = plt.figure(figsize=(16,4))\n", "fig_loops.clf()\n", "fig_loops.set_facecolor('white') \n", "\n", "ax_mixed = plt.subplot(1, 3, 1)\n", "img_a = ax_mixed.plot(bias_mat[:, 2:4], mixed_mat_mean[:, 2:4],'.-');\n", "ax_mixed.set_xlabel('DC voltage [V]', fontsize = 12)\n", "ax_mixed.set_ylabel('Mixed response [a.u.]', fontsize = 12)\n", "\n", "ax_phase = plt.subplot(1, 3, 2)\n", "img_c = ax_phase.plot(bias_mat[:,2:4], phase_mean[:, 2:4],'.-');\n", "ax_phase.set_xlabel('DC voltage [V]', fontsize = 12)\n", "ax_phase.set_ylabel('Phase [rad]', fontsize = 12)\n", "\n", "ax_amp = plt.subplot(1, 3, 3)\n", "img_b = ax_amp.plot(bias_mat[:,2:4], amp_mean[:,2:4],'.-');\n", "ax_amp.set_xlabel('DC voltage [V]', fontsize = 12)\n", "ax_amp.set_ylabel('Amplitude [a.u.]', fontsize = 12)\n", "\n", "def on_save_button10_clicked(b):\n", " fig_loops.savefig(output_file_path+'\\Loops.png', format='png')\n", " fig_loops.savefig(output_file_path+'\\Loops.eps', format='eps')\n", " fig_loops.savefig(output_file_path+'\\Loops.tif', format='tif')\n", " \n", " \n", "button10 = widgets.Button(description = 'Save figure')\n", "display(button10)\n", "button10.on_click(on_save_button10_clicked)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# PCA on real component\n", "\n", "from sklearn.utils.extmath import randomized_svd\n", "\n", "\n", "mixed_mat_h[:, :, :, num_loops_h:num_loops]\n", "\n", "# resp_mat_0Vr = np.reshape(resp_mat_0Vr,(num_row*num_col, num_write_steps))\n", "# U_SVD_resp0Vr, S_SVD_resp0Vr, V_SVD_resp0Vr = randomized_svd(resp_mat_0Vr, n_components = num_components)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from matplotlib.widgets import Cursor\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "\n", "fig = plt.figure(figsize=(8, 6))\n", "ax = fig.add_subplot(111)\n", "\n", "x, y = 4*(np.random.rand(2, 100) - .5)\n", "ax.plot(x, y, 'o')\n", "ax.set_xlim(-2, 2)\n", "ax.set_ylim(-2, 2)\n", "\n", "# set useblit = True on gtkagg for enhanced performance\n", "cursor = Cursor(ax, useblit=True, color='red', linewidth=2)\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Visualize the SHO results of BEline, BEPS and FORC data\n", "Here, we visualize the parameters for the SHO fits. BE-line (3D) data is visualized via simple spatial maps of the SHO parameters while more complex BEPS datasets (4+ dimensions) can be visualized using a simple interactive visualizer below. \n", "\n", "You can choose to visualize the guesses for SHO function or the final fit values from the first line of the cell below.\n", "\n", "Use the sliders below to inspect the BE response at any given location. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "use_sho_guess = False\n", "use_static_viz_func = False\n", "\n", "if use_sho_guess:\n", " sho_dset = h5_sho_guess\n", "else:\n", " sho_dset = h5_sho_fit\n", "\n", "if hdf.file.attrs['data_type'] == 'BELineData' or len(pos_dims) != 2:\n", " use_static_viz_func = True\n", " step_chan = None\n", "else:\n", " if h5_main.parent.parent.attrs['VS_mode'] not in ['AC modulation mode with time reversal', \n", " 'DC modulation mode']:\n", " use_static_viz_func = True\n", " else:\n", " if h5_main.parent.parent.attrs['VS_mode'] == 'DC modulation mode':\n", " step_chan = 'DC_Offset'\n", " else:\n", " step_chan = 'AC_Amplitude'\n", "if not use_static_viz_func:\n", " try:\n", " # use interactive visualization\n", " px.be_viz_utils.jupyter_visualize_beps_sho(sho_dset, step_chan)\n", " except:\n", " print('There was a problem with the interactive visualizer')\n", " use_static_viz_func = True\n", "if use_static_viz_func:\n", " # show plots of SHO results vs. applied bias\n", " px.be_viz_utils.visualize_sho_results(sho_dset, show_plots=True, \n", " save_plots=False)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "h5_sho_dset = sho_dset\n", "resp_func = None\n", "guess_3d_data, success = px.io.hdf_utils.reshape_to_Ndims(h5_sho_dset)\n", "\n", "h5_sho_spec_inds = px.io.hdf_utils.getAuxData(h5_sho_dset, 'Spectroscopic_Indices')[0]\n", "h5_sho_spec_vals = px.io.hdf_utils.getAuxData(h5_sho_dset, 'Spectroscopic_Values')[0]\n", "spec_nd, _ = px.io.hdf_utils.reshape_to_Ndims(h5_sho_spec_inds, h5_spec=h5_sho_spec_inds)\n", "# sho_spec_sort = get_sort_order(h5_sho_spec_inds)\n", "sho_spec_dims = np.array(spec_nd.shape[1:])\n", "sho_spec_labels = h5_sho_spec_inds.attrs['labels']\n", "\n", "h5_pos_inds = px.io.hdf_utils.getAuxData(h5_sho_dset, auxDataName='Position_Indices')[-1]\n", "pos_nd, _ = px.io.hdf_utils.reshape_to_Ndims(h5_pos_inds, h5_pos=h5_pos_inds)\n", "print(pos_nd.shape)\n", "pos_dims = list(pos_nd.shape[:h5_pos_inds.shape[1]])\n", "print(pos_dims)\n", "pos_labels = h5_pos_inds.attrs['labels']\n", "print(pos_labels)\n", "\n", "# reshape to X, Y, step, all others\n", "spec_step_dim_ind = np.argwhere(sho_spec_labels == step_chan)[0][0]\n", "step_dim_ind = len(pos_dims) + spec_step_dim_ind\n", "\n", "# move the step dimension to be the first after all position dimensions\n", "rest_sho_dim_order = list(range(len(pos_dims), len(guess_3d_data.shape)))\n", "rest_sho_dim_order.remove(step_dim_ind)\n", "new_order = list(range(len(pos_dims))) + [step_dim_ind] + rest_sho_dim_order\n", "\n", "# Transpose the 3D dataset to this shape:\n", "sho_guess_Nd_1 = np.transpose(guess_3d_data, new_order)\n", "\n", "# Now move the step dimension to the front for the spec labels as well\n", "new_spec_order = list(range(len(sho_spec_labels)))\n", "new_spec_order.remove(spec_step_dim_ind)\n", "new_spec_order = [spec_step_dim_ind] + new_spec_order\n", "\n", "# new_spec_labels = sho_spec_labels[new_spec_order]\n", "new_spec_dims = np.array(sho_spec_dims)[new_spec_order]\n", "\n", "# Now collapse all additional dimensions\n", "final_guess_shape = pos_dims + [new_spec_dims[0]] + [-1]\n", "sho_dset_collapsed = np.reshape(sho_guess_Nd_1, final_guess_shape)\n", "\n", "# Get the bias matrix:\n", "bias_mat, _ = px.io.hdf_utils.reshape_to_Ndims(h5_sho_spec_vals, h5_spec=h5_sho_spec_inds)\n", "bias_mat = np.transpose(bias_mat[spec_step_dim_ind], new_spec_order).reshape(sho_dset_collapsed.shape[len(pos_dims):])\n", "\n", "# This is just the visualizer:\n", "sho_quantity = 'Amplitude [V]'\n", "step_ind = 0\n", "row_ind = 1\n", "col_ind = 1\n", "\n", "def dc_spectroscopy_func(resp_vec):\n", " return resp_vec['Amplitude [V]'] * np.cos(resp_vec['Phase [rad]']) * 1E+3\n", "\n", "def ac_spectroscopy_func(resp_vec):\n", " return resp_vec['Amplitude [V]']\n", "\n", "if resp_func is None:\n", " if step_chan == 'DC_Offset':\n", " resp_func = dc_spectroscopy_func\n", " resp_label = 'A cos($\\phi$) (a. u.)'\n", " else:\n", " resp_func = ac_spectroscopy_func\n", " resp_label = 'Amplitude (a. u.)'\n", "\n", "spatial_map = sho_dset_collapsed[:, :, step_ind, 0][sho_quantity]\n", "resp_vec = sho_dset_collapsed[row_ind, col_ind, :, :]\n", "resp_vec = resp_func(resp_vec)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Fit loops to a function\n", "This is applicable only to DC voltage spectroscopy datasets from BEPS. The PFM hysteresis loops in this dataset will be projected to maximize the loop area and then fitted to a function.\n", "\n", "Note: This computation generally takes a while for reasonably sized datasets." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Do the Loop Fitting on the SHO Fit dataset\n", "loop_success = False\n", "h5_loop_group = px.hdf_utils.findH5group(h5_sho_fit, 'Loop_Fit')\n", "if len(h5_loop_group) == 0:\n", " try:\n", " loop_fitter = px.BELoopModel(h5_sho_fit, variables=['read_bias'], parallel=True)\n", " print('No loop fits found. Fitting now....')\n", " h5_loop_guess = loop_fitter.do_guess(processors=max_cores, max_mem=max_mem)\n", " h5_loop_fit = loop_fitter.do_fit(processors=max_cores, max_mem=max_mem)\n", " loop_success = True\n", " except ValueError:\n", " print('Loop fitting is applicable only to DC spectroscopy datasets!')\n", " raise\n", "else:\n", " loop_success = True\n", " print('Taking previously computed loop fits')\n", " h5_loop_guess = h5_loop_group[-1]['Guess']\n", " h5_loop_fit = h5_loop_group[-1]['Fit']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prepare datasets for visualization" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Prepare some variables for plotting loops fits and guesses\n", "# Plot the Loop Guess and Fit Results\n", "if loop_success:\n", " h5_projected_loops = h5_loop_guess.parent['Projected_Loops']\n", " h5_proj_spec_inds = px.hdf_utils.getAuxData(h5_projected_loops, \n", " auxDataName='Spectroscopic_Indices')[-1]\n", " h5_proj_spec_vals = px.hdf_utils.getAuxData(h5_projected_loops, \n", " auxDataName='Spectroscopic_Values')[-1]\n", "\n", " # reshape the vdc_vec into DC_step by Loop\n", " sort_order = px.hdf_utils.get_sort_order(h5_proj_spec_inds)\n", " dims = px.hdf_utils.get_dimensionality(h5_proj_spec_inds[()], \n", " sort_order[::-1])\n", " vdc_vec = np.reshape(h5_proj_spec_vals[h5_proj_spec_vals.attrs['read_bias']], dims).T\n", "\n", " #Also reshape the projected loops to Positions-DC_Step-Loop\n", " # Also reshape the projected loops to Positions-DC_Step-Loop\n", " proj_nd, _ = px.hdf_utils.reshape_to_Ndims(h5_projected_loops)\n", " proj_3d = np.reshape(proj_nd, [h5_projected_loops.shape[0], \n", " proj_nd.shape[2], -1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Visualize Loop fits" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "use_static_plots = False\n", "if loop_success:\n", " if not use_static_plots:\n", " try:\n", " px.be_viz_utils.jupyter_visualize_beps_loops(h5_projected_loops, h5_loop_guess, h5_loop_fit)\n", " except:\n", " print('There was a problem with the interactive visualizer')\n", " use_static_plots = True\n", " if use_static_plots:\n", " for iloop in range(h5_loop_guess.shape[1]):\n", " fig, ax = px.be_viz_utils.plot_loop_guess_fit(vdc_vec[:, iloop], proj_3d[:, :, iloop], \n", " h5_loop_guess[:, iloop], h5_loop_fit[:, iloop],\n", " title='Loop {} - All Positions'.format(iloop))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Save and close\n", "* Save the .h5 file that we are working on by closing it.
\n", "* Also, consider exporting this notebook as a notebook or an html file.
To do this, go to File >> Download as >> HTML\n", "* Finally consider saving this notebook if necessary" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hdf.close()" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" }, "widgets": { "state": { "004b75b3c0a9453ca262e88bcffe6320": { "views": [ { "cell_index": 32 } ] }, "013ef43338834ac39d1f55e0551f215f": { "views": [ { "cell_index": 20 } ] }, "03731bbe4e7d465c87b35c0b214a490b": { "views": [ { "cell_index": 20 } ] }, "0c2522aad7044463a20d86643b11210c": { "views": [ { "cell_index": 22 } ] }, "0da6103db52140148c92ce3ec3c92ea7": { "views": [ { "cell_index": 34 } ] }, "0df0b276e40145aeab5e3202f50e2b9a": { "views": [ { "cell_index": 22 } ] }, "0f2d2083cd374bd7b06ffd7cf3dc7c79": { "views": [ { "cell_index": 22 } ] }, "0fba4a2efa3f4c0cacd61f7949b828d0": { "views": [ { "cell_index": 48 } ] }, "106ba6b9a2894013ad1ff2fa2aa47685": { "views": [ { "cell_index": 20 } ] }, "1091c7898b69459f82d77f44c0dbe692": { "views": [ { "cell_index": 27 } ] }, "1245a5ae807749d8affe00b6e8a06815": { "views": [ { "cell_index": 22 } ] }, "16c05b12e4384404a5bff00c8f070e82": { "views": [ { "cell_index": 22 } ] }, "18390a7af99d4e4490908f7f8e2ccb64": { "views": [ { "cell_index": 22 } ] }, "1887b799056c41ddb614014b0b6b3052": { "views": [ { "cell_index": 20 } ] }, "1b168bdf1dfc4e029a7bcdfaf5287d9e": { "views": [ { "cell_index": 26 } ] }, "1c8b17397e97460a912c240618cce55b": { "views": [ { "cell_index": 22 } ] }, "1e3a3abddfd44d44b3d8b35f614e4f6d": { "views": [ { "cell_index": 22 } ] }, "1eff84f3a0644385a260536c132b5350": { "views": [ { "cell_index": 20 } ] }, "1f3b6953cd83422ba4536fda5217fb0f": { "views": [ { "cell_index": 22 } ] }, "1f57be14625349f88520479895455a09": { "views": [ { "cell_index": 20 } ] }, "1fb9b7b1b1fe435aa6cd66e8ce7fc873": { "views": [ { "cell_index": 22 } ] }, "200ee1d6a3604138b8ab81673c6d2437": { "views": [ { "cell_index": 20 } ] }, "229081689cac459288eb97c2402e4647": { "views": [ { "cell_index": 22 } ] }, "2333ee6e2b3041c1b14c4839f213a35f": { "views": [ { "cell_index": 34 } ] }, "24683f19881944aa9e159aa3cd212b26": { "views": [ { "cell_index": 22 } ] }, "252296babdb140b9822e152a621d3c6f": { "views": [ { "cell_index": 20 } ] }, "253c6da489d24de9b9e9c3f57c834f8e": { "views": [ { "cell_index": 22 } ] }, "27cec2a4bcf1481ab5fa76546685d313": { "views": [ { "cell_index": 22 } ] }, "27ea4625d1264657abf1335f10309d48": { "views": [ { "cell_index": 22 } ] }, "2a5f6a0c370e491f805769f82b16f1f5": { "views": [ { "cell_index": 22 } ] }, "2c326a8d9c014475bb08a96f2d48ec6b": { "views": [ { "cell_index": 20 } ] }, "2d978ede735d4a008c6d6939e7af0d34": { "views": [ { "cell_index": 20 } ] }, "2eba2773d5a3439bab45d7c75633b80a": { "views": [ { "cell_index": 22 } ] }, "2f08fd75283d4c9bbbb2f585c18c2b84": { "views": [ { "cell_index": 22 } ] }, "2f5edd3f8d164672b6253acd481bab5c": { "views": [ { "cell_index": 22 } ] }, "2fd188ee4d81451797c14a58f6d70013": { "views": [ { "cell_index": 22 } ] }, "3226cf4e6c214735a3319a94b62452d9": { "views": [ { "cell_index": 20 } ] }, "32c72b404c3540c3b9ee8321eb549227": { "views": [ { "cell_index": 22 } ] }, "334527a619684c94ac23c0bb3927e7e2": { "views": [ { "cell_index": 20 } ] }, "33c2a2056b4a48a2b4caf5416d6c15de": { "views": [ { "cell_index": 22 } ] }, "3a11fd566d1243f88c7a1d9f9568346e": { "views": [ { "cell_index": 22 } ] }, "3c2e566d0c5047c9bbb376a386566811": { "views": [ { "cell_index": 20 } ] }, "3c6531bf8739465b9e278aa147b8bce0": { "views": [ { "cell_index": 22 } ] }, "3c6b79158906476ba2ae69eb3626ef29": { "views": [ { "cell_index": 20 } ] }, "3cd3856d1bec4cbca42bfdb385eac13b": { "views": [ { "cell_index": 22 } ] }, "3ea78f55d0c24b39a8604fc5ae7fc470": { "views": [ { "cell_index": 22 } ] }, "3fa3e0756a0a4858a044c50eb96655a4": { "views": [ { "cell_index": 22 } ] }, "3fd4c31c30104f54bd0e36b599f1b0d7": { "views": [ { "cell_index": 20 } ] }, "426f6d47a8b84e7ca4babb28232f785c": { "views": [ { "cell_index": 27 } ] }, "441862466c3542d9b8614d285acc2d89": { "views": [ { "cell_index": 33 } ] }, "4440c4795e124ebbbc97d48d20082a4b": { "views": [ { "cell_index": 22 } ] }, "45d76a9ccb5341f58a4e940b81d72ad6": { "views": [ { "cell_index": 22 } ] }, "466cf44264604b1ca750ddf1212e2ee8": { "views": [ { "cell_index": 34 } ] }, "47667b6638864a2387eab723e4872a8b": { "views": [ { "cell_index": 50 } ] }, "48db59f08e0e47859b0ee0edebed06b5": { "views": [ { "cell_index": 22 } ] }, "49e68a65d3c34a8aa0858798e5116098": { "views": [ { "cell_index": 22 } ] }, "4a08b03856224646ae6fc06386762f7d": { "views": [ { "cell_index": 20 } ] }, "4b0eeeae2b384f59b72c7ec06f9c471a": { "views": [ { "cell_index": 20 } ] }, "4c80135c71cf499fbc2be1eb7b3039ca": { "views": [ { "cell_index": 22 } ] }, "4e34b568636f48ca8da39e6023d7b946": { "views": [ { "cell_index": 20 } ] }, "50a8632de0c94ca981418a62c43b229d": { "views": [ { "cell_index": 22 } ] }, "518ad177ac774c97b1bf788dfa362e87": { "views": [ { "cell_index": 22 } ] }, "52e1cd22d4cc46f78b1bdb199b30b32e": { "views": [ { "cell_index": 22 } ] }, "55545d47ba384198aad1cd7808448c7f": { "views": [ { "cell_index": 22 } ] }, "57516f91b20b4797a77235b67e315d07": { "views": [ { "cell_index": 22 } ] }, "5759b7e6994a44219ce213e406eb7982": { "views": [ { "cell_index": 22 } ] }, "58548d5bb6e041da91fc1e34d67497c8": { "views": [ { "cell_index": 24 } ] }, "59b02714a16e4aea94a8831867dff71e": { "views": [ { "cell_index": 22 } ] }, "5a2a9080cd404793a247ef01c74a890a": { "views": [ { "cell_index": 22 } ] }, "5a5f2318950d49978dec3511cb4b00dc": { "views": [ { "cell_index": 22 } ] }, "5adc30a3eb994a6493a249a223ee3eaa": { "views": [ { "cell_index": 28 } ] }, "5da98c3f88a9498d9bb77f208323c6fa": { "views": [ { "cell_index": 33 } ] }, "5f140d874f0a4c7f86ccbb9d8f181f87": { "views": [ { "cell_index": 22 } ] }, "5fcdc1b98d9a46b3b3698348ff309f76": { "views": [ { "cell_index": 20 } ] }, "601a1d573ef54f3da0207940088436fc": { "views": [ { "cell_index": 22 } ] }, "61923f2aa2014259ae563b97a8f030ba": { "views": [ { "cell_index": 22 } ] }, "6215fec2288b4f8d908226db6f432b9f": { "views": [ { "cell_index": 22 } ] }, "62705169cbc74b3eab7f8c50ea8c52fe": { "views": [ { "cell_index": 20 } ] }, "640653936f65487988404f6d426da533": { "views": [ { "cell_index": 20 } ] }, "6479f5cb4cf04daca716b0df1e643186": { "views": [ { "cell_index": 22 } ] }, "6781d0b6a8e84ab691cd021175acefb3": { "views": [ { "cell_index": 22 } ] }, "6820c0bb148c4cf9b2b3e2babf9d4876": { "views": [ { "cell_index": 22 } ] }, "6a30ab4b402849a19a5ab69a0425d99f": { "views": [ { "cell_index": 22 } ] }, "6a829084d30c43a990cf429ef467c5f5": { "views": [ { "cell_index": 20 } ] }, "6aedfc25a0194d0ba4aa69bef246298c": { "views": [ { "cell_index": 36 } ] }, "6b977337480340bea29cb7393cc86adf": { "views": [ { "cell_index": 26 } ] }, "6f1267616b1442808bc8e28eaf990b9a": { "views": [ { "cell_index": 22 } ] }, "745d38ec65f444e08b73f49bb4d5f19d": { "views": [ { "cell_index": 12 } ] }, "75db983b508b44608fec25c6217f85f8": { "views": [ { "cell_index": 22 } ] }, "76f8e33e84b24376891f86fce56e610b": { "views": [ { "cell_index": 27 } ] }, "772c140a0c2040b4a21bde7f61617789": { "views": [ { "cell_index": 22 } ] }, "78860c1ca5ba4daf8c1f8aa9cdf9886d": { "views": [ { "cell_index": 22 } ] }, "78955f0364994a3c971afd1863a05b3a": { "views": [ { "cell_index": 22 } ] }, "7cc6aa3950504a1abb7bb1fdaed4e8b4": { "views": [ { "cell_index": 20 } ] }, "7dd37cbc0bb34505b9b8997ac8602da9": { "views": [ { "cell_index": 34 } ] }, "81ea2b5c960741218ce783af9cc518b9": { "views": [ { "cell_index": 22 } ] }, "8285c6714ca041f1a2294d40f8a744b5": { "views": [ { "cell_index": 22 } ] }, "83148171a8254f2bba18f2825784d5cb": { "views": [ { "cell_index": 30 } ] }, "835480b7080f4c739c41cf4d5ed2fc2c": { "views": [ { "cell_index": 22 } ] }, "84f40717e9c649e5bbabaa85cf0ae263": { "views": [ { "cell_index": 22 } ] }, "84f62ae372fd4442b5b1f43807e1f31c": { "views": [ { "cell_index": 20 } ] }, "870b7b8a3fa24a4ba6d94d618fa3f3e3": { "views": [ { "cell_index": 22 } ] }, "8719d35335554d098f37003a3e4d7266": { "views": [ { "cell_index": 22 } ] }, "87f7c00bc4e24d46aa9e7d168574f79e": { "views": [ { "cell_index": 20 } ] }, "8b0ef9eac4e24702b6f2fd4a94810f56": { "views": [ { "cell_index": 27 } ] }, "8c0f848a076a41d89ccb59d04113fde2": { "views": [ { "cell_index": 22 } ] }, "8cbe81dbfe0042aab68990f5f727e57f": { "views": [ { "cell_index": 32 } ] }, "8ea4ba4cfd1c44c085b929fda24c9b3c": { "views": [ { "cell_index": 22 } ] }, "8f637079f4eb44ed93e69a76ad7c8446": { "views": [ { "cell_index": 22 } ] }, "8fd6b3062f27485d85b170e5dc493bd1": { "views": [ { "cell_index": 20 } ] }, "90fc2cd4bc5a4bc9933eefe6eade6d73": { "views": [ { "cell_index": 20 } ] }, "936a08daf35148fb9fd86dad1e54ad70": { "views": [ { "cell_index": 20 } ] }, "943beb03286741f4ada739f7d3bfbf8f": { "views": [ { "cell_index": 27 } ] }, "96323125acc0426281e0a3d62847dd46": { "views": [ { "cell_index": 20 } ] }, "9710a09cec7c42ad89a94d5eb3458949": { "views": [ { "cell_index": 22 } ] }, "9985eed09f37449fa1f1c8f245f4085f": { "views": [ { "cell_index": 22 } ] }, "9a77a5c0079d42c5b2ccde0034423cad": { "views": [ { "cell_index": 22 } ] }, "9abef5c8b2d54b7cbe1f7a6b71949bd9": { "views": [ { "cell_index": 22 } ] }, "9b35d7483a93479da1b9f36593b7d564": { "views": [ { "cell_index": 34 } ] }, "9f98b4f217ca4e68b9629b09bb30709d": { "views": [ { "cell_index": 22 } ] }, "a319db55898f48c98a1a41f056b214aa": { "views": [ { "cell_index": 22 } ] }, "a4132c170ec7479c8e19f0001aee322c": { "views": [ { "cell_index": 22 } ] }, "a6000ebbbd6f42b2821a8e928102e349": { "views": [ { "cell_index": 20 } ] }, "a85c126a09884a349ca65e98fdb6a175": { "views": [ { "cell_index": 22 } ] }, "a8b860980e2f4c539fe2ecf6609de434": { "views": [ { "cell_index": 20 } ] }, "aa32b3e3313e494899ce0e0d6d64c161": { "views": [ { "cell_index": 22 } ] }, "ab22b74afdb246b5bf31c5d0d2c24eae": { "views": [ { "cell_index": 22 } ] }, "ad5a9688818140fcb5d11d72e8448197": { "views": [ { "cell_index": 20 } ] }, "ad888acb36d849bd9cecf53e7af0b263": { "views": [ { "cell_index": 22 } ] }, "afbd23209f284c1e9f47a9925617b1e4": { "views": [ { "cell_index": 22 } ] }, "b018aeb25f774f3e84edd16671e7448d": { "views": [ { "cell_index": 19 } ] }, "b1dd9ef912ab40e4939dbbc8296d99df": { "views": [ { "cell_index": 22 } ] }, "b2e873efb17d456b9e88099444f8c49d": { "views": [ { "cell_index": 22 } ] }, "b3a3132aa5904950953e77668be69239": { "views": [ { "cell_index": 20 } ] }, "b587b62ed2674093ac7547c28322dade": { "views": [ { "cell_index": 22 } ] }, "b7aff4785f1a48919c6202e28194cd8a": { "views": [ { "cell_index": 22 } ] }, "b7b4e90ac1c946f0b2a0a1a3944e3a72": { "views": [ { "cell_index": 20 } ] }, "bae378b5ee894a82b3d0a01cd6226292": { "views": [ { "cell_index": 26 } ] }, "c0818ccd1f224489b76a8e384050e05d": { "views": [ { "cell_index": 22 } ] }, "c140980fff33438295f215f4a14bf1a0": { "views": [ { "cell_index": 33 } ] }, "c1ae6f91f28a4979adc60164ae3c23a9": { "views": [ { "cell_index": 20 } ] }, "c4bf1a0b9f5c4ae385c4f29ca2500930": { "views": [ { "cell_index": 20 } ] }, "c53ed2724b494dd49705edd102548e1e": { "views": [ { "cell_index": 32 } ] }, "ca651c48b785444db4843482c5c0128f": { "views": [ { "cell_index": 20 } ] }, "cc8a22026fe94604ab8edf7bfc9d8ea4": { "views": [ { "cell_index": 22 } ] }, "ceabcdc115244af88db6b71fb5541653": { "views": [ { "cell_index": 36 } ] }, "cf01b46ee4eb47deab9fe18393b056bb": { "views": [ { "cell_index": 22 } ] }, "d5624ebebcee48cdadabb67c904e06bb": { "views": [ { "cell_index": 22 } ] }, "da7c461ef7014ae2bbf2027f8e096974": { "views": [ { "cell_index": 22 } ] }, "daa28c65a80f43c8a73415376bdb4c0f": { "views": [ { "cell_index": 22 } ] }, "db4ec01f773e4aafa9cb6f218273d987": { "views": [ { "cell_index": 20 } ] }, "ddab1ab606344b008646a203ae843dad": { "views": [ { "cell_index": 22 } ] }, "e13e4e9f39184699bb11f8c1cd3cdae4": { "views": [ { "cell_index": 52 } ] }, "e1597335a1d44d8eb26e983ac939deeb": { "views": [ { "cell_index": 22 } ] }, "e5e52ee5548c4aaf9ba824c4c82916e8": { "views": [ { "cell_index": 34 } ] }, "e655206f0ed04bc9aeafb7fef58a3405": { "views": [ { "cell_index": 46 } ] }, "e95b6a5beb194275979b5e71c9982243": { "views": [ { "cell_index": 33 } ] }, "e9fb83d24e1b4b24b32022998a54c3d7": { "views": [ { "cell_index": 22 } ] }, "ec619dc0e5a64620b425b3c7ec149c40": { "views": [ { "cell_index": 27 } ] }, "ed220ad67e454d999b2da008a9df9771": { "views": [ { "cell_index": 22 } ] }, "ed2ebc25e05246568c1477da2b97bc7a": { "views": [ { "cell_index": 22 } ] }, "f0bd4c54c7a34f8fadf2443e6503e908": { "views": [ { "cell_index": 22 } ] }, "f11b353d940642c49c91cc64e7b8b87c": { "views": [ { "cell_index": 22 } ] }, "f139fa25257b4f0a8f780339d87b8ab3": { "views": [ { "cell_index": 33 } ] }, "f1d46b6184c242eb8776b7848f59a233": { "views": [ { "cell_index": 20 } ] }, "f776056026424da39823d5d1a90c6c73": { "views": [ { "cell_index": 22 } ] }, "f886e32db5a848c680e24bffebf5a248": { "views": [ { "cell_index": 20 } ] }, "f8eb0f63bc52416792d963d341e92cac": { "views": [ { "cell_index": 22 } ] }, "f93549d3234d437991e3e8ccee7e2aef": { "views": [ { "cell_index": 22 } ] }, "fb128ad83d604626b40e13b454e0cb91": { "views": [ { "cell_index": 24 } ] }, "fd5503410927484f8e3a79f91701820e": { "views": [ { "cell_index": 20 } ] }, "fd7a314013ae4b67b3051732b774dcf6": { "views": [ { "cell_index": 44 } ] }, "fe12f66437d94adc95c058e7ab155a6b": { "views": [ { "cell_index": 22 } ] } }, "version": "1.2.0" } }, "nbformat": 4, "nbformat_minor": 1 }