From 70946b6335d8e2204d764f883c7e3f29e632380d Mon Sep 17 00:00:00 2001 From: Jawad Chowdhury Date: Fri, 1 May 2026 19:28:37 -0400 Subject: [PATCH 1/4] refactor (SidpyFitterRefactor): replaced old fitter model on BE_Processing_sidpy.ipynb --- notebooks/be/BE_Processing_sidpy.ipynb | 443 +++++++++++-------------- 1 file changed, 203 insertions(+), 240 deletions(-) diff --git a/notebooks/be/BE_Processing_sidpy.ipynb b/notebooks/be/BE_Processing_sidpy.ipynb index b48518a6..7c328294 100644 --- a/notebooks/be/BE_Processing_sidpy.ipynb +++ b/notebooks/be/BE_Processing_sidpy.ipynb @@ -6,7 +6,9 @@ "metadata": {}, "outputs": [], "source": [ - "%matplotlib widget\n" + "# !pip install dask-ml\n", + "# !pip install git+https://github.com/pycroscopy/sidpy.git@main\n", + "# !pip install \"dask==2025.1.0\" \"distributed==2025.1.0\"" ] }, { @@ -15,38 +17,16 @@ "metadata": {}, "outputs": [], "source": [ + "import os\n", "import sys\n", - "sys.path.insert(0, r'/Users/rvv/Github/BGlib/')\n", - "sys.path.insert(0, r'/Users/rvv/Github/sidpy/')\n", - "\n", - "import BGlib.be as belib\n", "import numpy as np\n", - "import os\n", "import matplotlib.pyplot as plt\n", "import h5py\n", "import sidpy\n", "import SciFiReaders as sr\n", - "from BGlib.be.analysis.utils.sidpy_sho_fitter import SHOestimateGuess, SHOestimateGuess, SHO_fit_flattened\n", - "\n", - "\n", - "def load_data(file_path):\n", - " \"\"\"\n", - " \n", - " Given the path to a .h5 dataset, reads, patches and returns the BEPS dataset, \n", - " the frequency vector, and the index of the independent dimensions\n", - " \n", - " \"\"\"\n", - " \n", - " patcher = belib.translators.LabViewH5Patcher()\n", - " patcher.translate(file_path)\n", - " reader = sr.Usid_reader(file_path)\n", - " beps_raw = reader.read() \n", - " freq_axis = beps_raw.labels.index('Frequency (Hz)')\n", - " freq_vec = beps_raw._axes[freq_axis].values\n", - " all_dims = np.arange(len(data.shape))\n", - " ind_dims = np.delete(all_dims, freq_axis)\n", - " \n", - " return beps_raw, freq_vec, ind_dims\n" + "import BGlib.be as belib\n", + "from BGlib.be.analysis.utils.sidpy_sho_fitter import SHOestimateGuess, SHO_fit_flattened\n", + "from sidpy.proc.fitter_refactor import SidpyFitterRefactor" ] }, { @@ -55,65 +35,37 @@ "metadata": {}, "outputs": [], "source": [ - "folder_path = r'/Users/rvv/Dropbox (ORNL)/PTO LSMO JCY/031822'\n", - "file_name = r'60x60_0deg_0004.h5'\n", - "path_to_file = os.path.join(folder_path, file_name)" + "%matplotlib widget" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, - "outputs": [], - "source": [ - "#path_gwy = r'/Users/rvv/Dropbox (ORNL)/AE Related Stuff/RL for Walls/Paper/Resubmission/12202023/PTO_110_Virgin0001.gwy'\n", - "#gwy_reader = sr.GwyddionReader(path_gwy)\n", - "#data = gwy_reader.read()" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "#fig = data[0].plot()\n", - "\n", - "#threadpoolctl version. We need to insist on version 3.2.0 \n" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "/Users/rvv/Github/sidpy/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" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "File is already Pycroscopy ready.\n" + "C:\\jawad_pc\\2_code\\20250912_code_pyc_bglib\\env_pb2\\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", + "2026-05-01 19:25:15,928 - BGlib.be.translators.labview_h5_patcher - INFO - File is already Pycroscopy ready.\n" ] } ], "source": [ + "folder_path = r'../../../inputs/'\n", + "file_name = r'60x60_0deg_0004.h5'\n", + "path_to_file = os.path.join(folder_path, file_name)\n", "patcher = belib.translators.LabViewH5Patcher()\n", "patcher.translate(path_to_file)\n", - "\n", "reader = sr.Usid_reader(path_to_file)\n", "data = reader.read()" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -261,7 +213,7 @@ "Cycle: Cycle (generic) of size (2,)" ] }, - "execution_count": 7, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -272,7 +224,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -285,161 +237,149 @@ ], "source": [ "beps_raw = data\n", - "\n", "freq_axis = beps_raw.labels.index('Frequency (Hz)')\n", "freq_vec = beps_raw._axes[freq_axis].values\n", "all_dims = np.arange(len(data.shape))\n", "ind_dims = np.delete(all_dims, freq_axis)\n", - "print(ind_dims, freq_vec.shape)\n" + "print(ind_dims, freq_vec.shape)" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Setting Ind_dims from given values from user\n" + "Setup Complete. Params: 4 | Spatial Dims: [0, 1, 3, 4, 5]\n" ] } ], "source": [ "lb = [1E-6, freq_vec.min(), 50, -2*np.pi]\n", "ub = [1E-3, freq_vec.max(), 500, 2*np.pi]\n", - "beps_small = beps_raw[:5, :5, :]\n", - "\n", - "fitter = sidpy.proc.fitter.SidFitter(beps_small, SHO_fit_flattened,num_workers=16,\n", - " guess_fn = SHOestimateGuess,ind_dims=ind_dims,\n", - " threads=1, return_cov=False, return_fit=True, return_std=False,\n", - " km_guess=True,num_fit_parms = 4, n_clus = 5)\n" + "beps_small = beps_raw[:2, :2, :, :, :1, :1]\n", + "fitter = SidpyFitterRefactor(beps_small, SHO_fit_flattened, SHOestimateGuess, ind_dims=(freq_axis,), num_params=4, lower_bounds=lb, upper_bounds=ub)\n", + "fitter.setup_calc()" ] }, { "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "fitter.do_guess()\n", - "#fit_dset = fitter.do_fit(bounds = (lb,ub))" - ] - }, - { - "cell_type": "code", - "execution_count": 11, + "execution_count": 8, "metadata": {}, "outputs": [ { - "name": "stdout", + "name": "stderr", "output_type": "stream", "text": [ - "Warning: complex dataset detected. For Kmeans priors, we will treat real part only\n" + "C:\\jawad_pc\\2_code\\20250912_code_pyc_bglib\\env_pb2\\lib\\site-packages\\sidpy\\sid\\dataset.py:1517: UserWarning: Dimensional information will be lost. Please use fold, unfold to combine dimensions\n", + " warnings.warn('Dimensional information will be lost.\\\n", + "2026-05-01 19:25:21,876 - root - INFO - Starting _check_array\n", + "2026-05-01 19:25:21,896 - root - INFO - Finished _check_array in 0:00:00.020675\n", + "2026-05-01 19:25:21,899 - root - INFO - Starting init_scalable\n", + "2026-05-01 19:25:21,902 - dask_ml.cluster.k_means - INFO - Initializing with k-means||\n", + "2026-05-01 19:25:21,928 - dask_ml.cluster.k_means - INFO - Starting init iteration 1/ 8 , 1 centers\n", + "2026-05-01 19:25:21,953 - dask_ml.cluster.k_means - INFO - Finished init iteration 1/ 8 , 1 centers in 0:00:00.023995\n", + "2026-05-01 19:25:21,963 - dask_ml.cluster.k_means - INFO - Starting init iteration 2/ 8 , 3 centers\n", + "2026-05-01 19:25:21,986 - dask_ml.cluster.k_means - INFO - Finished init iteration 2/ 8 , 3 centers in 0:00:00.023730\n" ] }, { - "name": "stderr", + "name": "stdout", "output_type": "stream", "text": [ - "/Users/rvv/pycroscopy_env/lib/python3.12/site-packages/distributed/client.py:3371: UserWarning: Sending large graph of size 864.85 MiB.\n", - "This may cause some slowdown.\n", - "Consider loading the data with Dask directly\n", - " or using futures or delayed objects to embed the data into the graph without repetition.\n", - "See also https://docs.dask.org/en/stable/best-practices.html#load-data-with-dask for more information.\n", - " warnings.warn(\n", - "/Users/rvv/pycroscopy_env/lib/python3.12/site-packages/distributed/client.py:3371: UserWarning: Sending large graph of size 864.85 MiB.\n", - "This may cause some slowdown.\n", - "Consider loading the data with Dask directly\n", - " or using futures or delayed objects to embed the data into the graph without repetition.\n", - "See also https://docs.dask.org/en/stable/best-practices.html#load-data-with-dask for more information.\n", - " warnings.warn(\n" + "Starting Dask K-Means Guess with 5 clusters...\n" ] }, { - "name": "stdout", + "name": "stderr", "output_type": "stream", "text": [ - "---Finished KMeans, onto fiting each KM Center---\n", - "Fitting center 0\n", - "Fitting center 1\n", - "Fitting center 2\n", - "Fitting center 3\n", - "Fitting center 4\n", - "Shapes of output of fitting function is 246 and original data is 123 Reshaping output dataset. You are responsible for reshaping\n", - "using generic parameters for dimension 0\n", - "using generic parameters for dimension 1\n" + "2026-05-01 19:25:21,998 - dask_ml.cluster.k_means - INFO - Starting init iteration 3/ 8 , 4 centers\n", + "2026-05-01 19:25:22,023 - dask_ml.cluster.k_means - INFO - Finished init iteration 3/ 8 , 4 centers in 0:00:00.025654\n", + "2026-05-01 19:25:22,034 - dask_ml.cluster.k_means - INFO - Starting init iteration 4/ 8 , 7 centers\n", + "2026-05-01 19:25:22,057 - dask_ml.cluster.k_means - INFO - Finished init iteration 4/ 8 , 7 centers in 0:00:00.023276\n", + "2026-05-01 19:25:22,068 - dask_ml.cluster.k_means - INFO - Starting init iteration 5/ 8 , 8 centers\n", + "2026-05-01 19:25:22,093 - dask_ml.cluster.k_means - INFO - Finished init iteration 5/ 8 , 8 centers in 0:00:00.024689\n", + "2026-05-01 19:25:22,105 - dask_ml.cluster.k_means - INFO - Starting init iteration 6/ 8 , 9 centers\n", + "2026-05-01 19:25:22,128 - dask_ml.cluster.k_means - INFO - Finished init iteration 6/ 8 , 9 centers in 0:00:00.022756\n", + "2026-05-01 19:25:22,137 - dask_ml.cluster.k_means - INFO - Starting init iteration 7/ 8 , 12 centers\n", + "2026-05-01 19:25:22,161 - dask_ml.cluster.k_means - INFO - Finished init iteration 7/ 8 , 12 centers in 0:00:00.024653\n", + "2026-05-01 19:25:22,172 - dask_ml.cluster.k_means - INFO - Starting init iteration 8/ 8 , 14 centers\n", + "2026-05-01 19:25:22,196 - dask_ml.cluster.k_means - INFO - Finished init iteration 8/ 8 , 14 centers in 0:00:00.024030\n", + "2026-05-01 19:25:23,927 - root - INFO - Finished init_scalable in 0:00:02.027677\n", + "2026-05-01 19:25:23,929 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 0.\n", + "2026-05-01 19:25:24,774 - dask_ml.cluster.k_means - INFO - Shift: 0.4728\n", + "2026-05-01 19:25:24,775 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 0. in 0:00:00.846585\n", + "2026-05-01 19:25:24,776 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 1.\n", + "2026-05-01 19:25:24,803 - dask_ml.cluster.k_means - INFO - Shift: 0.0062\n", + "2026-05-01 19:25:24,805 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 1. in 0:00:00.028397\n", + "2026-05-01 19:25:24,806 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 2.\n", + "2026-05-01 19:25:24,830 - dask_ml.cluster.k_means - INFO - Shift: 0.0117\n", + "2026-05-01 19:25:24,831 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 2. in 0:00:00.024633\n", + "2026-05-01 19:25:24,831 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 3.\n", + "2026-05-01 19:25:24,851 - dask_ml.cluster.k_means - INFO - Shift: 0.0069\n", + "2026-05-01 19:25:24,852 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 3. in 0:00:00.021325\n", + "2026-05-01 19:25:24,854 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 4.\n", + "2026-05-01 19:25:24,878 - dask_ml.cluster.k_means - INFO - Shift: 0.0039\n", + "2026-05-01 19:25:24,880 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 4. in 0:00:00.025909\n", + "2026-05-01 19:25:24,880 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 5.\n", + "2026-05-01 19:25:24,904 - dask_ml.cluster.k_means - INFO - Shift: 0.0007\n", + "2026-05-01 19:25:24,906 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 5. in 0:00:00.025330\n", + "2026-05-01 19:25:24,907 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 6.\n", + "2026-05-01 19:25:24,931 - dask_ml.cluster.k_means - INFO - Shift: 0.0000\n", + "2026-05-01 19:25:24,932 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 6. in 0:00:00.026369\n" ] }, { - "name": "stderr", + "name": "stdout", "output_type": "stream", "text": [ - "/Users/rvv/Github/sidpy/sidpy/base/num_utils.py:54: RuntimeWarning: invalid value encountered in divide\n", - " if var / step_avg < tol:\n" + "Calculating cluster means and fitting priors...\n" ] } ], "source": [ - "output = fitter.do_fit(bounds = (lb,ub))" + "output = fitter.do_fit(use_kmeans=True, n_clusters=5, fit_parameter_labels=['Amplitude', 'Resonant Frequency', 'Quality Factor', 'Phase'])" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{0: X: X (nm) of size (5,),\n", - " 1: Y: Y (nm) of size (5,),\n", + "{0: X: X (nm) of size (2,),\n", + " 1: Y: Y (nm) of size (2,),\n", " 2: DC_Offset: DC_Offset (V) of size (64,),\n", - " 3: Field: Field (generic) of size (2,),\n", - " 4: Cycle: Cycle (generic) of size (2,),\n", - " 5: fit_parms: fit_parameters (a.u.) of size (4,)}" + " 3: Field: Field (generic) of size (1,),\n", + " 4: Cycle: Cycle (generic) of size (1,),\n", + " 5: fit_parameters: Label (generic) of size (4,)}" ] }, - "execution_count": 12, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "#Let's check the fitted dataset.\n", - "output[0].data_type = 'spectral_image'\n", - "\n", - "output[0]._axes" + "output.data_type = 'spectral_image'\n", + "output._axes" ] }, { "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "http://127.0.0.1:8787/status\n" - ] - } - ], - "source": [ - "address = fitter.client.dashboard_link\n", - "print(address)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "2d2efed20806492db2bb444defb0b723", + "model_id": "850f0181d6b849e093f705979a0f45c0", "version_major": 2, "version_minor": 0 }, @@ -461,14 +401,14 @@ "# Example synthetic dataset\n", "# ==============================================\n", "\n", - "data = output[0]\n", + "data = output\n", "\n", "# Axes\n", - "X_vals = output[0]._axes[0].values\n", - "Y_vals = output[0]._axes[1].values\n", - "DC_vals = output[0]._axes[2].values\n", - "field_vals = output[0]._axes[3].values\n", - "cycle_vals = output[0]._axes[4].values\n", + "X_vals = output._axes[0].values\n", + "Y_vals = output._axes[1].values\n", + "DC_vals = output._axes[2].values\n", + "field_vals = output._axes[3].values\n", + "cycle_vals = output._axes[4].values\n", "fit_labels = ['Amplitude', 'Resonant Frequency', 'Quality Factor', 'Phase'] #need to add into the fit labels\n", "\n", "# ==============================================\n", @@ -592,54 +532,54 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(5, 5, 64, 2, 2, 4)" + "(2, 2, 64, 1, 1, 4)" ] }, - "execution_count": 15, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "output[0].shape" + "output.shape" ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[]" + "[]" ] }, - "execution_count": 15, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "803243fd92da42b7bc59ad46653be3a4", + "model_id": "c36f9f9f981041a9b9075cd3e1d6d1d3", "version_major": 2, "version_minor": 0 }, - "image/png": "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S0pKir46unjxYrn77rv1PVtWl5ubK3/961/1vaNqoRnOdttttzWM1b2RKhC2a9dOFi5cqBc1WJn6x6a6Ajh79mz9sboCqH72qPv91N8vOBauANqRsLAwcXNz+8mKMvVxRESEsbrs0enzYfVz9dBDD8nKlStl3bp1euHDaeocqFsKCgsLLXt+1JWaTp06yTXXXKOvdKkFRS+99JLlz42axlSLyq6++mpxd3fXhwrG6sZ9NVZXa6x8fn5MXe2Li4uTPXv2WP57R63sVVfRz9S1a9eGKXJ+LjsWAqCdvWGpN6u1a9ee9S8u9bG6dwn/p0OHDvoHypnnqri4WK86s8K5UutiVPhT05qff/65Ph9nUt9HaqXemedHbROjflBb4fyci/q7VFlZaflzc8stt+jpcXV19PShruqoe91Oj618fn6stLRUsrOzdfix+veOus3kx9tN7d69W18hVaz+c9nhmF6FgrO99957esXUO++8Y8vIyLDdd999tuDgYFteXp7NatQqxe+//14f6lt1wYIFerx//379+LPPPqvPzYcffmhLS0uzDRs2zNahQwfbqVOnbM7u/vvvtwUFBdm++OIL25EjRxqO8vLyhuf8+c9/tkVHR9s+//xz29atW229evXShxU89thjekX03r179feG+tjFxcX22Wef2ax+bs7lzFXAVj8/48eP13+v1PfO119/bevfv78tLCxMr7S3+rnZsmWLzd3d3TZr1ixbVlaW7d///rfN19fX9q9//avhOVb+uexoCIB26G9/+5v+AePp6am3hdm8ebPNitatW6eD34+Pu+++u2HLgaeeesoWHh6uQ/Mtt9xi27Vrl80KznVe1PH22283PEf9wH3ggQf09ifqh/SIESN0SLSCe+65x9auXTv9d6hly5b6e+N0+LP6ubmYAGjl8/PLX/7S1rp1a/2906ZNG/3xnj17Gh638rlRVqxYYUtISNA/c7t06WJ78803z3rcyj+XHY2L+o/pq5AAAABoPtwDCAAAYDEEQAAAAIshAAIAAFgMARAAAMBiCIAAAAAWQwAEAACwGAIgAACAxRAAAQAALIYACAAAYDEEQAAAAIshAAIAAFgMARAAAMBiCIAAAAAWQwAEAACwGAIgAACAxRAAAQAALIYACAAAYDEEQAAAAIshAAIAAFgMARAAAMBiCIAAAAAWQwAEAACwGAIgAACAxRAAAQAALIYACAAAYDEEQAAAAIshAAIAAFgMARAAAMBiCIAAAAAWQwAEAACwGAIgAACAWMv/B8ze10AwkqEHAAAAAElFTkSuQmCC", + "image/png": "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", "text/html": [ "\n", "
\n", "
\n", " Figure\n", "
\n", - " \n", + " \n", "
\n", " " ], @@ -653,12 +593,12 @@ ], "source": [ "plt.figure()\n", - "plt.plot(output[0]._axes[2])" + "plt.plot(output._axes[2])" ] }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -670,7 +610,7 @@ " ('Phase', 3)]" ] }, - "execution_count": 60, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -683,113 +623,136 @@ "cell_type": "code", "execution_count": 14, "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'beline_sidpy' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[31m---------------------------------------------------------------------------\u001b[39m", - "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", - "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[14]\u001b[39m\u001b[32m, line 88\u001b[39m\n\u001b[32m 85\u001b[39m \u001b[38;5;28mself\u001b[39m.fig.tight_layout()\n\u001b[32m 86\u001b[39m \u001b[38;5;66;03m# Example usage\u001b[39;00m\n\u001b[32m 87\u001b[39m \u001b[38;5;66;03m# Assume raw_data and fit_data are your input matrices\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m88\u001b[39m raw_data = np.array(\u001b[43mbeline_sidpy\u001b[49m) \u001b[38;5;66;03m# Replace this with your actual raw data\u001b[39;00m\n\u001b[32m 89\u001b[39m fit_data = np.array(fit_results[\u001b[32m0\u001b[39m]) \u001b[38;5;66;03m# Replace this with your actual fit data\u001b[39;00m\n\u001b[32m 91\u001b[39m \u001b[38;5;66;03m# Instantiate the visualizer\u001b[39;00m\n", - "\u001b[31mNameError\u001b[39m: name 'beline_sidpy' is not defined" - ] - } - ], + "outputs": [], "source": [ "\"\"\"\n", - "THis visualizer works for BELIne data. Just input a BEline sidpy dataset and an SHO fit dataset from sidpy fitter\n", - "Some things need work\n", - "Get X,Y units from sidpy dataset\n", - "Plot a scale bar and add a checkbox for whether you want it\n", - "Add export plot button\n", - "Make a simple viz for the plot parameters only, and enable figures to be output.\n", - "Get the frequency vector from the sidpy dataset\n", - "Then, start work on a BEPS visualizer.\n", + "Interactive per-pixel SHO fit-quality visualizer for BE-line / BEPS-slice data.\n", + "Shows: raw 2D heatmap at one frequency | raw vs fitted amplitude | raw vs fitted phase.\n", + "Click on the heatmap to pick a pixel; move the slider to change the frequency slice.\n", "\"\"\"\n", "\n", - "%matplotlib notebook\n", "import matplotlib.pyplot as plt\n", - "from mpl_toolkits.mplot3d import Axes3D\n", "import numpy as np\n", - "from ipywidgets import interact, widgets\n", + "from ipywidgets import widgets, VBox\n", + "from matplotlib.patches import Rectangle\n", + "from IPython.display import display\n", "\n", "\n", "class InteractiveVisualizer:\n", " def __init__(self, raw_data, fit_data, freq_vec):\n", - " self.raw_data = raw_data\n", - " self.fit_data = fit_data\n", - " self.freq_vec = freq_vec\n", - " self.fig, (self.ax1, self.ax2, self.ax3) = plt.subplots(1, 3, figsize=(12, 4))\n", - " \n", + " self.raw_data = raw_data # (X, Y, freq) complex\n", + " self.fit_data = fit_data # (X, Y, 4) real (Amp, w_0, Q, phi)\n", + " self.freq_vec = freq_vec # (freq,) real\n", + "\n", " self.x = 0\n", " self.y = 0\n", " self.freq_slice = 0\n", "\n", - " # Connect the button press event handler to the 2D image plot\n", + " # Build figure with ipympl-friendly pattern: ioff() so plt.subplots\n", + " # doesn't auto-display in a separate output area.\n", + " plt.ioff()\n", + " self.fig, (self.ax1, self.ax2, self.ax3) = plt.subplots(1, 3, figsize=(12, 4))\n", + " self.fig.canvas.header_visible = False\n", + " plt.ion()\n", + "\n", + " # Click handler on the heatmap\n", " self.fig.canvas.mpl_connect('button_press_event', self.on_click)\n", "\n", - " self.freq_slice_slider = widgets.IntSlider(min=0, max=len(freq_vec), value=0, description='Freq Slice:')\n", - " interact(self.update_plots, freq_slice=self.freq_slice_slider, x=widgets.fixed(0), y=widgets.fixed(0))\n", + " # Slider (max is INCLUSIVE in IntSlider, so last valid index = len - 1)\n", + " self.freq_slice_slider = widgets.IntSlider(\n", + " min=0, max=len(freq_vec) - 1, value=0, description='Freq Slice:'\n", + " )\n", + " self.freq_slice_slider.observe(self._on_slider_change, names='value')\n", + "\n", + " # First draw, then display slider + figure together\n", + " self.update_plots(self.freq_slice, self.x, self.y)\n", + " display(VBox([self.freq_slice_slider, self.fig.canvas]))\n", + "\n", + " def _on_slider_change(self, change):\n", + " self.update_plots(change['new'], self.x, self.y)\n", "\n", - " self.update_plots(self.freq_slice, self.x,self.y)\n", - " \n", " def on_click(self, event):\n", - " if event.inaxes == self.ax1:\n", - " self.x, self.y = int(event.xdata + 0.5), int(event.ydata + 0.5)\n", + " if event.inaxes == self.ax1 and event.xdata is not None and event.ydata is not None:\n", + " nx, ny = self.raw_data.shape[0], self.raw_data.shape[1]\n", + " self.x = int(np.clip(round(event.xdata), 0, nx - 1))\n", + " self.y = int(np.clip(round(event.ydata), 0, ny - 1))\n", " self.update_plots(self.freq_slice, self.x, self.y)\n", "\n", " def update_plots(self, freq_slice, x, y):\n", " self.freq_slice = freq_slice\n", - " # Plot the slice of the raw data\n", + "\n", + " # --- Raw 2D heatmap at this frequency slice ---\n", " self.ax1.clear()\n", - " self.ax1.imshow(np.abs(self.raw_data[:, :, freq_slice]))\n", - " self.ax1.set_title('Raw Data')\n", + " self.ax1.imshow(np.abs(self.raw_data[:, :, freq_slice]), origin='lower')\n", + " self.ax1.set_title(f'Raw |amp| @ freq idx {freq_slice}')\n", " self.ax1.set_xlabel('X')\n", " self.ax1.set_ylabel('Y')\n", - " self.ax1.add_patch(Rectangle((self.x-0.5, self.y-0.5), 1, 1, linewidth=2, edgecolor='red', facecolor='none'))\n", - "\n", - " \n", - " amp_data = np.abs(self.raw_data[x,y,:])\n", - " phase_data = np.angle(self.raw_data[x,y,:])\n", - " \n", - " fit_parms = self.fit_data[x,y,:]\n", - " \n", - " sho_fit = SHO_fit_flattened(freq_vec, *fit_parms)\n", - " \n", - " sho_fit_complex = sho_fit[:len(sho_fit)//2] + 1j*sho_fit[len(sho_fit)//2 :]\n", + " self.ax1.add_patch(Rectangle(\n", + " (x - 0.5, y - 0.5), 1, 1, linewidth=2, edgecolor='red', facecolor='none'\n", + " ))\n", + "\n", + " # --- Raw vs fitted amplitude/phase at selected pixel ---\n", + " amp_data = np.abs(self.raw_data[x, y, :])\n", + " phase_data = np.angle(self.raw_data[x, y, :])\n", + "\n", + " fit_parms = self.fit_data[x, y, :]\n", + " sho_fit = SHO_fit_flattened(self.freq_vec, *fit_parms)\n", + " n = len(sho_fit) // 2\n", + " sho_fit_complex = sho_fit[:n] + 1j * sho_fit[n:]\n", " amp_fit = np.abs(sho_fit_complex)\n", " phase_fit = np.angle(sho_fit_complex)\n", - " \n", - " # Plot the spectrum at the selected X, Y position from raw data and fit data\n", - " #Plot amplitude\n", - " \n", + "\n", " self.ax2.clear()\n", - " self.ax2.plot(self.freq_vec, amp_data,'ro', label = 'Raw Data')\n", - " self.ax2.plot(self.freq_vec, amp_fit,'r-', label = 'Fit')\n", - " self.ax2.set_title('Amplitude')\n", - " self.ax2.set_xlabel('Frequency')\n", + " self.ax2.plot(self.freq_vec, amp_data, 'ro', label='Raw')\n", + " self.ax2.plot(self.freq_vec, amp_fit, 'r-', label='Fit')\n", + " self.ax2.set_title(f'Amplitude @ ({x},{y})')\n", + " self.ax2.set_xlabel('Frequency (Hz)')\n", " self.ax2.set_ylabel('Amplitude (a.u.)')\n", - " \n", - " #Plot phase\n", + " self.ax2.legend()\n", + "\n", " self.ax3.clear()\n", - " self.ax3.plot(self.freq_vec, phase_data,'ro', label = 'Raw Data')\n", - " self.ax3.plot(self.freq_vec, phase_fit,'r-', label = 'Fit')\n", - " self.ax3.set_title('Phase')\n", - " self.ax3.set_xlabel('Frequency')\n", - " self.ax3.set_ylabel('Amplitude (a.u.)')\n", - "\n", - " # Update the figure\n", - " self.fig.canvas.draw()\n", - " self.fig.tight_layout()\n", + " self.ax3.plot(self.freq_vec, phase_data, 'ro', label='Raw')\n", + " self.ax3.plot(self.freq_vec, phase_fit, 'r-', label='Fit')\n", + " self.ax3.set_title(f'Phase @ ({x},{y})')\n", + " self.ax3.set_xlabel('Frequency (Hz)')\n", + " self.ax3.set_ylabel('Phase (rad)')\n", + " self.ax3.legend()\n", + "\n", + " try:\n", + " self.fig.canvas.draw_idle()\n", + " except AttributeError:\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c3915b1b708c4dc3a0234784b4d903a9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(IntSlider(value=0, description='Freq Slice:', max=122), Canvas(header_visible=False, toolbar=To…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ "# Example usage\n", - "# Assume raw_data and fit_data are your input matrices\n", - "raw_data = np.array(beline_sidpy) # Replace this with your actual raw data\n", - "fit_data = np.array(fit_results[0]) # Replace this with your actual fit data\n", + "# InteractiveVisualizer is BE-line-only (expects 3D inputs).\n", + "# For BEPS data, pick one (DC, field, cycle) slice.\n", + "raw_data = np.array(beps_small[:, :, :, 0, 0, 0]) # (X, Y, freq) at DC=0, field=0, cycle=0\n", + "fit_data = np.array(output[:, :, 0, 0, 0, :]) # (X, Y, 4 params) same slice\n", "\n", "# Instantiate the visualizer\n", - "visualizer = InteractiveVisualizer(raw_data, fit_data, freq_vec)\n", - "\n" + "visualizer = InteractiveVisualizer(raw_data, fit_data, freq_vec)" ] }, { @@ -816,7 +779,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.4" + "version": "3.10.0" } }, "nbformat": 4, From cda9d1974fd57c855ca061f3c9c3ee4d1849310b Mon Sep 17 00:00:00 2001 From: Jawad Chowdhury Date: Fri, 8 May 2026 11:43:53 -0400 Subject: [PATCH 2/4] notebook using SidpyRefactorFitter model, fixed visualization issues --- notebooks/be/BE_Processing_sidpy.ipynb | 195 ++----------------------- 1 file changed, 14 insertions(+), 181 deletions(-) diff --git a/notebooks/be/BE_Processing_sidpy.ipynb b/notebooks/be/BE_Processing_sidpy.ipynb index 7c328294..bef425d2 100644 --- a/notebooks/be/BE_Processing_sidpy.ipynb +++ b/notebooks/be/BE_Processing_sidpy.ipynb @@ -49,7 +49,7 @@ "text": [ "C:\\jawad_pc\\2_code\\20250912_code_pyc_bglib\\env_pb2\\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", - "2026-05-01 19:25:15,928 - BGlib.be.translators.labview_h5_patcher - INFO - File is already Pycroscopy ready.\n" + "2026-05-08 11:25:31,825 - BGlib.be.translators.labview_h5_patcher - INFO - File is already Pycroscopy ready.\n" ] } ], @@ -260,89 +260,18 @@ "source": [ "lb = [1E-6, freq_vec.min(), 50, -2*np.pi]\n", "ub = [1E-3, freq_vec.max(), 500, 2*np.pi]\n", - "beps_small = beps_raw[:2, :2, :, :, :1, :1]\n", + "beps_small = beps_raw[:2, :2, :, :, :, :]\n", "fitter = SidpyFitterRefactor(beps_small, SHO_fit_flattened, SHOestimateGuess, ind_dims=(freq_axis,), num_params=4, lower_bounds=lb, upper_bounds=ub)\n", "fitter.setup_calc()" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "C:\\jawad_pc\\2_code\\20250912_code_pyc_bglib\\env_pb2\\lib\\site-packages\\sidpy\\sid\\dataset.py:1517: UserWarning: Dimensional information will be lost. Please use fold, unfold to combine dimensions\n", - " warnings.warn('Dimensional information will be lost.\\\n", - "2026-05-01 19:25:21,876 - root - INFO - Starting _check_array\n", - "2026-05-01 19:25:21,896 - root - INFO - Finished _check_array in 0:00:00.020675\n", - "2026-05-01 19:25:21,899 - root - INFO - Starting init_scalable\n", - "2026-05-01 19:25:21,902 - dask_ml.cluster.k_means - INFO - Initializing with k-means||\n", - "2026-05-01 19:25:21,928 - dask_ml.cluster.k_means - INFO - Starting init iteration 1/ 8 , 1 centers\n", - "2026-05-01 19:25:21,953 - dask_ml.cluster.k_means - INFO - Finished init iteration 1/ 8 , 1 centers in 0:00:00.023995\n", - "2026-05-01 19:25:21,963 - dask_ml.cluster.k_means - INFO - Starting init iteration 2/ 8 , 3 centers\n", - "2026-05-01 19:25:21,986 - dask_ml.cluster.k_means - INFO - Finished init iteration 2/ 8 , 3 centers in 0:00:00.023730\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Starting Dask K-Means Guess with 5 clusters...\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2026-05-01 19:25:21,998 - dask_ml.cluster.k_means - INFO - Starting init iteration 3/ 8 , 4 centers\n", - "2026-05-01 19:25:22,023 - dask_ml.cluster.k_means - INFO - Finished init iteration 3/ 8 , 4 centers in 0:00:00.025654\n", - "2026-05-01 19:25:22,034 - dask_ml.cluster.k_means - INFO - Starting init iteration 4/ 8 , 7 centers\n", - "2026-05-01 19:25:22,057 - dask_ml.cluster.k_means - INFO - Finished init iteration 4/ 8 , 7 centers in 0:00:00.023276\n", - "2026-05-01 19:25:22,068 - dask_ml.cluster.k_means - INFO - Starting init iteration 5/ 8 , 8 centers\n", - "2026-05-01 19:25:22,093 - dask_ml.cluster.k_means - INFO - Finished init iteration 5/ 8 , 8 centers in 0:00:00.024689\n", - "2026-05-01 19:25:22,105 - dask_ml.cluster.k_means - INFO - Starting init iteration 6/ 8 , 9 centers\n", - "2026-05-01 19:25:22,128 - dask_ml.cluster.k_means - INFO - Finished init iteration 6/ 8 , 9 centers in 0:00:00.022756\n", - "2026-05-01 19:25:22,137 - dask_ml.cluster.k_means - INFO - Starting init iteration 7/ 8 , 12 centers\n", - "2026-05-01 19:25:22,161 - dask_ml.cluster.k_means - INFO - Finished init iteration 7/ 8 , 12 centers in 0:00:00.024653\n", - "2026-05-01 19:25:22,172 - dask_ml.cluster.k_means - INFO - Starting init iteration 8/ 8 , 14 centers\n", - "2026-05-01 19:25:22,196 - dask_ml.cluster.k_means - INFO - Finished init iteration 8/ 8 , 14 centers in 0:00:00.024030\n", - "2026-05-01 19:25:23,927 - root - INFO - Finished init_scalable in 0:00:02.027677\n", - "2026-05-01 19:25:23,929 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 0.\n", - "2026-05-01 19:25:24,774 - dask_ml.cluster.k_means - INFO - Shift: 0.4728\n", - "2026-05-01 19:25:24,775 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 0. in 0:00:00.846585\n", - "2026-05-01 19:25:24,776 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 1.\n", - "2026-05-01 19:25:24,803 - dask_ml.cluster.k_means - INFO - Shift: 0.0062\n", - "2026-05-01 19:25:24,805 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 1. in 0:00:00.028397\n", - "2026-05-01 19:25:24,806 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 2.\n", - "2026-05-01 19:25:24,830 - dask_ml.cluster.k_means - INFO - Shift: 0.0117\n", - "2026-05-01 19:25:24,831 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 2. in 0:00:00.024633\n", - "2026-05-01 19:25:24,831 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 3.\n", - "2026-05-01 19:25:24,851 - dask_ml.cluster.k_means - INFO - Shift: 0.0069\n", - "2026-05-01 19:25:24,852 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 3. in 0:00:00.021325\n", - "2026-05-01 19:25:24,854 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 4.\n", - "2026-05-01 19:25:24,878 - dask_ml.cluster.k_means - INFO - Shift: 0.0039\n", - "2026-05-01 19:25:24,880 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 4. in 0:00:00.025909\n", - "2026-05-01 19:25:24,880 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 5.\n", - "2026-05-01 19:25:24,904 - dask_ml.cluster.k_means - INFO - Shift: 0.0007\n", - "2026-05-01 19:25:24,906 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 5. in 0:00:00.025330\n", - "2026-05-01 19:25:24,907 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 6.\n", - "2026-05-01 19:25:24,931 - dask_ml.cluster.k_means - INFO - Shift: 0.0000\n", - "2026-05-01 19:25:24,932 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 6. in 0:00:00.026369\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Calculating cluster means and fitting priors...\n" - ] - } - ], + "outputs": [], "source": [ - "output = fitter.do_fit(use_kmeans=True, n_clusters=5, fit_parameter_labels=['Amplitude', 'Resonant Frequency', 'Quality Factor', 'Phase'])" + "output = fitter.do_fit(use_kmeans=True, n_clusters=4, fit_parameter_labels=['Amplitude', 'Resonant Frequency', 'Quality Factor', 'Phase'])" ] }, { @@ -356,8 +285,8 @@ "{0: X: X (nm) of size (2,),\n", " 1: Y: Y (nm) of size (2,),\n", " 2: DC_Offset: DC_Offset (V) of size (64,),\n", - " 3: Field: Field (generic) of size (1,),\n", - " 4: Cycle: Cycle (generic) of size (1,),\n", + " 3: Field: Field (generic) of size (2,),\n", + " 4: Cycle: Cycle (generic) of size (2,),\n", " 5: fit_parameters: Label (generic) of size (4,)}" ] }, @@ -373,13 +302,13 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "850f0181d6b849e093f705979a0f45c0", + "model_id": "a7483d17151a41dca4eddb833eecb08f", "version_major": 2, "version_minor": 0 }, @@ -532,98 +461,24 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 21, "metadata": {}, "outputs": [ - { - "data": { - "text/plain": [ - "(2, 2, 64, 1, 1, 4)" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "output.shape" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "c36f9f9f981041a9b9075cd3e1d6d1d3", + "model_id": "6961d3b0012f46f1a1e8b274204db9c0", "version_major": 2, "version_minor": 0 }, - "image/png": "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", - "text/html": [ - "\n", - "
\n", - "
\n", - " Figure\n", - "
\n", - " \n", - "
\n", - " " - ], "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + "VBox(children=(IntSlider(value=0, description='Freq Slice:', max=122), Canvas(header_visible=False, toolbar=To…" ] }, "metadata": {}, "output_type": "display_data" } ], - "source": [ - "plt.figure()\n", - "plt.plot(output._axes[2])" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[('Amplitude', 0),\n", - " ('Resonant Frequency', 1),\n", - " ('Quality Factor', 2),\n", - " ('Phase', 3)]" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "[(name, idx) for idx, name in enumerate(fit_labels)]" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], "source": [ "\"\"\"\n", "Interactive per-pixel SHO fit-quality visualizer for BE-line / BEPS-slice data.\n", @@ -721,30 +576,8 @@ " try:\n", " self.fig.canvas.draw_idle()\n", " except AttributeError:\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c3915b1b708c4dc3a0234784b4d903a9", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(IntSlider(value=0, description='Freq Slice:', max=122), Canvas(header_visible=False, toolbar=To…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ + " pass\n", + "\n", "# Example usage\n", "# InteractiveVisualizer is BE-line-only (expects 3D inputs).\n", "# For BEPS data, pick one (DC, field, cycle) slice.\n", From 9eed45b5fc825bb79ac74520b569515f1e524e12 Mon Sep 17 00:00:00 2001 From: Jawad Chowdhury Date: Fri, 8 May 2026 11:49:53 -0400 Subject: [PATCH 3/4] bug fix: fixed cycle indexing bug on the visualizer --- notebooks/be/BE_Processing_sidpy.ipynb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/notebooks/be/BE_Processing_sidpy.ipynb b/notebooks/be/BE_Processing_sidpy.ipynb index bef425d2..ead77fe5 100644 --- a/notebooks/be/BE_Processing_sidpy.ipynb +++ b/notebooks/be/BE_Processing_sidpy.ipynb @@ -18,7 +18,6 @@ "outputs": [], "source": [ "import os\n", - "import sys\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import h5py\n", @@ -432,7 +431,7 @@ "# Wrapper to convert voltage to index\n", "def update(dc_value, field_value, cycle_value, fit_value):\n", " dc_index = int(dc_value)\n", - " cycle_index = int(cycle_value)-1\n", + " cycle_index = int(cycle_value) ## -1\n", " plot_visualizer(dc_index, field_value, cycle_index, fit_value)\n", "\n", "# ==============================================\n", From 0f055c7f2c22d883be25a4b4bf706d7740ed9d0f Mon Sep 17 00:00:00 2001 From: Jawad Chowdhury Date: Fri, 12 Jun 2026 10:51:38 -0400 Subject: [PATCH 4/4] done: testing BE_processing_sidpy working good with all the visualization and the new refactored class --- notebooks/be/BE_Processing_sidpy.ipynb | 98 +++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 8 deletions(-) diff --git a/notebooks/be/BE_Processing_sidpy.ipynb b/notebooks/be/BE_Processing_sidpy.ipynb index ead77fe5..0876b0d1 100644 --- a/notebooks/be/BE_Processing_sidpy.ipynb +++ b/notebooks/be/BE_Processing_sidpy.ipynb @@ -48,7 +48,7 @@ "text": [ "C:\\jawad_pc\\2_code\\20250912_code_pyc_bglib\\env_pb2\\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", - "2026-05-08 11:25:31,825 - BGlib.be.translators.labview_h5_patcher - INFO - File is already Pycroscopy ready.\n" + "2026-06-12 10:50:07,949 - BGlib.be.translators.labview_h5_patcher - INFO - File is already Pycroscopy ready.\n" ] } ], @@ -266,9 +266,91 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\jawad_pc\\2_code\\20250912_code_pyc_bglib\\env_pb2\\lib\\site-packages\\sidpy\\sid\\dataset.py:1517: UserWarning: Dimensional information will be lost. Please use fold, unfold to combine dimensions\n", + " warnings.warn('Dimensional information will be lost.\\\n", + "2026-06-12 10:50:24,015 - root - INFO - Starting _check_array\n", + "2026-06-12 10:50:24,064 - root - INFO - Finished _check_array in 0:00:00.050186\n", + "2026-06-12 10:50:24,069 - root - INFO - Starting init_scalable\n", + "2026-06-12 10:50:24,071 - dask_ml.cluster.k_means - INFO - Initializing with k-means||\n", + "2026-06-12 10:50:24,141 - dask_ml.cluster.k_means - INFO - Starting init iteration 1/ 9 , 1 centers\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting Dask K-Means Guess with 4 clusters...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-06-12 10:50:24,213 - dask_ml.cluster.k_means - INFO - Finished init iteration 1/ 9 , 1 centers in 0:00:00.071166\n", + "2026-06-12 10:50:24,238 - dask_ml.cluster.k_means - INFO - Starting init iteration 2/ 9 , 1 centers\n", + "2026-06-12 10:50:24,310 - dask_ml.cluster.k_means - INFO - Finished init iteration 2/ 9 , 1 centers in 0:00:00.072084\n", + "2026-06-12 10:50:24,337 - dask_ml.cluster.k_means - INFO - Starting init iteration 3/ 9 , 5 centers\n", + "2026-06-12 10:50:24,406 - dask_ml.cluster.k_means - INFO - Finished init iteration 3/ 9 , 5 centers in 0:00:00.069253\n", + "2026-06-12 10:50:24,433 - dask_ml.cluster.k_means - INFO - Starting init iteration 4/ 9 , 7 centers\n", + "2026-06-12 10:50:24,512 - dask_ml.cluster.k_means - INFO - Finished init iteration 4/ 9 , 7 centers in 0:00:00.077562\n", + "2026-06-12 10:50:24,536 - dask_ml.cluster.k_means - INFO - Starting init iteration 5/ 9 , 13 centers\n", + "2026-06-12 10:50:24,602 - dask_ml.cluster.k_means - INFO - Finished init iteration 5/ 9 , 13 centers in 0:00:00.066245\n", + "2026-06-12 10:50:24,628 - dask_ml.cluster.k_means - INFO - Starting init iteration 6/ 9 , 15 centers\n", + "2026-06-12 10:50:24,694 - dask_ml.cluster.k_means - INFO - Finished init iteration 6/ 9 , 15 centers in 0:00:00.065630\n", + "2026-06-12 10:50:24,717 - dask_ml.cluster.k_means - INFO - Starting init iteration 7/ 9 , 17 centers\n", + "2026-06-12 10:50:24,781 - dask_ml.cluster.k_means - INFO - Finished init iteration 7/ 9 , 17 centers in 0:00:00.063115\n", + "2026-06-12 10:50:24,810 - dask_ml.cluster.k_means - INFO - Starting init iteration 8/ 9 , 18 centers\n", + "2026-06-12 10:50:24,870 - dask_ml.cluster.k_means - INFO - Finished init iteration 8/ 9 , 18 centers in 0:00:00.060724\n", + "2026-06-12 10:50:24,902 - dask_ml.cluster.k_means - INFO - Starting init iteration 9/ 9 , 20 centers\n", + "2026-06-12 10:50:24,966 - dask_ml.cluster.k_means - INFO - Finished init iteration 9/ 9 , 20 centers in 0:00:00.064427\n", + "2026-06-12 10:50:28,057 - root - INFO - Finished init_scalable in 0:00:03.988505\n", + "2026-06-12 10:50:28,060 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 0.\n", + "2026-06-12 10:50:30,476 - dask_ml.cluster.k_means - INFO - Shift: 0.1536\n", + "2026-06-12 10:50:30,478 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 0. in 0:00:02.418565\n", + "2026-06-12 10:50:30,479 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 1.\n", + "2026-06-12 10:50:30,524 - dask_ml.cluster.k_means - INFO - Shift: 0.0095\n", + "2026-06-12 10:50:30,525 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 1. in 0:00:00.045118\n", + "2026-06-12 10:50:30,526 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 2.\n", + "2026-06-12 10:50:30,567 - dask_ml.cluster.k_means - INFO - Shift: 0.0052\n", + "2026-06-12 10:50:30,569 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 2. in 0:00:00.042578\n", + "2026-06-12 10:50:30,570 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 3.\n", + "2026-06-12 10:50:30,606 - dask_ml.cluster.k_means - INFO - Shift: 0.0019\n", + "2026-06-12 10:50:30,607 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 3. in 0:00:00.037589\n", + "2026-06-12 10:50:30,609 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 4.\n", + "2026-06-12 10:50:30,654 - dask_ml.cluster.k_means - INFO - Shift: 0.0013\n", + "2026-06-12 10:50:30,657 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 4. in 0:00:00.047890\n", + "2026-06-12 10:50:30,659 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 5.\n", + "2026-06-12 10:50:30,706 - dask_ml.cluster.k_means - INFO - Shift: 0.0015\n", + "2026-06-12 10:50:30,708 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 5. in 0:00:00.049308\n", + "2026-06-12 10:50:30,710 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 6.\n", + "2026-06-12 10:50:30,760 - dask_ml.cluster.k_means - INFO - Shift: 0.0008\n", + "2026-06-12 10:50:30,762 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 6. in 0:00:00.051734\n", + "2026-06-12 10:50:30,764 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 7.\n", + "2026-06-12 10:50:30,810 - dask_ml.cluster.k_means - INFO - Shift: 0.0002\n", + "2026-06-12 10:50:30,812 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 7. in 0:00:00.048638\n", + "2026-06-12 10:50:30,815 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 8.\n", + "2026-06-12 10:50:30,861 - dask_ml.cluster.k_means - INFO - Shift: 0.0002\n", + "2026-06-12 10:50:30,864 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 8. in 0:00:00.049983\n", + "2026-06-12 10:50:30,866 - dask_ml.cluster.k_means - INFO - Starting Lloyd loop 9.\n", + "2026-06-12 10:50:30,920 - dask_ml.cluster.k_means - INFO - Shift: 0.0000\n", + "2026-06-12 10:50:30,922 - dask_ml.cluster.k_means - INFO - Finished Lloyd loop 9. in 0:00:00.055872\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Calculating cluster means and fitting priors...\n" + ] + } + ], "source": [ "output = fitter.do_fit(use_kmeans=True, n_clusters=4, fit_parameter_labels=['Amplitude', 'Resonant Frequency', 'Quality Factor', 'Phase'])" ] @@ -301,18 +383,18 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "a7483d17151a41dca4eddb833eecb08f", + "model_id": "5f14a9641eb74b8d93a850332241e0f4", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "HBox(children=(VBox(children=(Output(),), layout=Layout(width='45%')), VBox(children=(Output(), VBox(children=…" + "HBox(children=(VBox(children=(Output(outputs=({'output_type': 'display_data', 'data': {'text/plain': \"Canvas(t…" ] }, "metadata": {}, @@ -460,13 +542,13 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "6961d3b0012f46f1a1e8b274204db9c0", + "model_id": "d6019616f87b4179b800ea36bddea5d7", "version_major": 2, "version_minor": 0 },