Compare commits

..
3 Commits
Author SHA1 Message Date
swim d0c8d8723a finding grain boundaries by fourier peak finding 2026-11-08 18:16:38 +09:00
swim 53d30f714e added shading to amorphous regions 2026-11-08 18:16:12 +09:00
swim 360d190439 minor updates 2026-11-08 18:15:50 +09:00
5 changed files with 2008 additions and 89 deletions

No files matched your search

+4 -4
View File
@@ -32,7 +32,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 3,
"id": "0e02178a",
"metadata": {},
"outputs": [
@@ -68,19 +68,19 @@
" 'f_472_4_obj_phase_roi_Niter50.tiff']"
]
},
"execution_count": 5,
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"basedir = \"/home/swim/Si_project/260707_BCAT_tif_file\"\n",
"basedir = \"/home/swim/shared/Si_project/260707_BCAT_tif_file\"\n",
"os.listdir(basedir)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 4,
"id": "f2b2c969-2f85-4443-961e-89e82d87fed1",
"metadata": {},
"outputs": [
+650 -53
View File
@@ -14,86 +14,683 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"id": "4a419040",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['outputs', 'probe', 'object', 'p']"
"name": "stdout",
"output_type": "stream",
"text": [
"['ADU', 'alpha0', 'cbed', 'df', 'rbf', 'rot_ang', 'scanstep', 'voltage']\n"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# fold_slice output\n",
"f = \"/home/swim/shared/Si_project/Si8V2_full/roi1_Ndp256/MLs_L1_p1_g64_Ndp192_pc1_noModel_Ns23_dz14.6087_reg0.2/Niter1000.mat\"\n",
"f = \"/home/swim/data/mose2-chen-natcomm/rawdata_1x_crop.mat\"\n",
"contents = scipy_loadmat(f)\n",
"print([key for key in contents.keys() if not key.startswith('__')])"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "8a7b58b2",
"execution_count": 9,
"id": "59ec3de4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"__header__\n",
"b'MATLAB 5.0 MAT-file, Platform: PCWIN64, Created on: Sat Feb 22 01:27:35 2020'\n",
"\n",
"__version__\n",
"1.0\n",
"\n",
"__globals__\n",
"[]\n",
"\n",
"ADU\n",
"[[151]]\n",
"\n",
"alpha0\n",
"[[21.4]]\n",
"\n",
"cbed\n",
"[[[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" ...\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]]\n",
"\n",
"\n",
" [[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[-1.03698730e-01 -1.22612572e+00 6.58904076e-01 ... 2.58400917e-01\n",
" -2.29316711e-01 1.52589941e+00]\n",
" [-3.22591066e+00 -3.82136226e-01 1.88740349e+00 ... 5.09323406e+00\n",
" 2.77259493e+00 6.05754852e-01]\n",
" [-2.08003330e+00 -1.63220310e+00 1.48578691e+00 ... 7.81043291e-01\n",
" -3.19456291e+00 -1.22145271e+00]\n",
" ...\n",
" [-3.48634720e-02 1.38346195e+00 1.46833897e+00 ... 4.16478491e+00\n",
" -1.58513546e+00 2.44732118e+00]\n",
" [ 1.34099627e+00 -6.04673195e+00 7.79750824e-01 ... 2.62490368e+00\n",
" 2.23099089e+00 1.71481514e+00]\n",
" [-2.09777451e+00 -3.59836483e+00 1.69059849e+00 ... -7.12826252e+00\n",
" 5.20671892e+00 4.77436352e+00]]\n",
"\n",
" [[ 1.62780762e-01 1.04035378e+00 -5.07461643e+00 ... -2.47511959e+00\n",
" -1.96283722e+00 -2.20762110e+00]\n",
" [-9.59431171e-01 -2.11565685e+00 -1.84611702e+00 ... -6.40286446e-01\n",
" 2.03907442e+00 -3.12776566e+00]\n",
" [-8.13553810e-01 -2.36572361e+00 1.75226641e+00 ... -2.95247722e+00\n",
" -9.28083420e-01 -3.95497322e+00]\n",
" ...\n",
" [-4.76838398e+00 -1.35005856e+00 2.73481846e+00 ... 3.43126440e+00\n",
" -3.31865597e+00 -1.28619933e+00]\n",
" [-1.39252424e+00 -7.80252457e-01 2.04623032e+00 ... 1.89138317e+00\n",
" -5.02529621e-01 -5.01870537e+00]\n",
" [ 3.16870499e+00 -3.33188534e+00 -1.04292202e+00 ... -2.86178303e+00\n",
" 1.47319853e+00 4.08430099e-02]]\n",
"\n",
" ...\n",
"\n",
" [[-9.33532715e-01 -3.05595970e+00 8.29070091e-01 ... 5.42856693e+00\n",
" 5.94084930e+00 1.69606543e+00]\n",
" [ 1.32944260e+02 -2.21197033e+00 -4.94243050e+00 ... -7.36599922e-01\n",
" -2.05723906e+00 7.75920868e-01]\n",
" [ 4.09013271e+00 -4.46203709e+00 8.65595245e+00 ... 2.95120931e+00\n",
" -1.02439690e+00 -9.05128670e+00]\n",
" ...\n",
" [-8.64697456e-01 -1.44637203e+00 -3.61495018e-01 ... -6.66504908e+00\n",
" -2.41496944e+00 2.61748719e+00]\n",
" [ 1.47511169e+02 -1.87656593e+00 -5.00831604e-02 ... -5.20493031e+00\n",
" -1.59884310e+00 -4.11501884e+00]\n",
" [-6.92760849e+00 2.57180119e+00 -3.13923550e+00 ... -2.95809650e+00\n",
" 1.39376892e+02 -2.05547047e+00]]\n",
"\n",
" [[-1.73712158e+00 -4.85954857e+00 -1.97451878e+00 ... 2.62497807e+00\n",
" -2.86273956e+00 -1.10752344e+00]\n",
" [ 1.40666485e-01 -1.55590773e-02 -4.74601936e+00 ... -5.54018879e+00\n",
" -8.60827923e-01 -7.02766800e+00]\n",
" [ 4.28654385e+00 5.73437405e+00 -4.14763594e+00 ... -8.52379560e-01\n",
" -2.82798576e+00 -5.85487556e+00]\n",
" ...\n",
" [-6.66828632e+00 -2.24996090e+00 2.83491611e+00 ... -1.46863794e+00\n",
" -2.21855831e+00 -1.18610168e+00]\n",
" [ 1.70757341e+00 -1.68015480e+00 1.14632797e+00 ... -2.00851917e+00\n",
" -2.40243196e+00 3.08139229e+00]\n",
" [ 1.26880264e+00 1.47768219e+02 2.05717564e+00 ... -1.76168537e+00\n",
" -1.42670381e+00 -6.85905933e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]]\n",
"\n",
"\n",
" [[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[-4.61126709e+00 -5.73369408e+00 -1.84866428e+00 ... -2.49167442e-01\n",
" 2.26311493e+00 1.01833105e+00]\n",
" [ 1.26652098e+00 -2.88970470e+00 -6.20164871e-01 ... -1.41433430e+00\n",
" 1.26502657e+00 -1.90181351e+00]\n",
" [ 3.41239834e+00 -1.13977146e+00 2.97821856e+00 ... 4.27347469e+00\n",
" -1.70213127e+00 1.27097893e+00]\n",
" ...\n",
" [ 2.45756817e+00 6.87589359e+00 -3.03922939e+00 ... -1.34278345e+00\n",
" 3.90729618e+00 1.93975282e+00]\n",
" [-7.16657209e+00 1.44569969e+00 3.27218246e+00 ... 5.11733532e+00\n",
" -1.27657747e+00 -4.79275322e+00]\n",
" [-1.60534286e+00 -2.10593319e+00 3.18303013e+00 ... -6.35830879e-01\n",
" 1.69915068e+00 2.66795158e-01]]\n",
"\n",
" [[ 3.06109619e+00 -3.06133080e+00 -2.17630100e+00 ... 2.42319584e+00\n",
" -6.45217896e-02 -3.09305668e-01]\n",
" [ 1.93888426e+00 -2.17341304e-01 2.05219841e+00 ... -1.74197102e+00\n",
" -4.06261015e+00 4.77054977e+00]\n",
" [-1.91523838e+00 -1.46740818e+00 4.65058184e+00 ... -2.05416179e+00\n",
" 9.70232010e-01 -2.05665779e+00]\n",
" ...\n",
" [-1.87006855e+00 2.54825687e+00 6.63313389e+00 ... -1.67042017e+00\n",
" -5.42034054e+00 -5.38788366e+00]\n",
" [ 3.50579119e+00 -8.81937027e-01 -8.05545425e+00 ... -3.21030140e+00\n",
" 3.95785809e-01 -1.12038994e+00]\n",
" [ 3.06702042e+00 5.56643009e+00 8.55393410e-01 ... 3.65324020e-02\n",
" -6.28486037e-01 1.93915844e+00]]\n",
"\n",
" ...\n",
"\n",
" [[ 1.81304932e+00 3.69062233e+00 -1.42434788e+00 ... -3.82485104e+00\n",
" -1.31256866e+00 2.44264746e+00]\n",
" [-3.09162617e-01 -6.46538830e+00 -3.19584846e+00 ... 1.00998211e+00\n",
" 4.68934298e+00 6.52250290e+00]\n",
" [-1.16328526e+00 1.28454494e+00 1.25402534e+02 ... 6.97791338e-01\n",
" -3.27781487e+00 6.95295334e-01]\n",
" ...\n",
" [ 1.10881882e+02 1.47300217e+02 -2.61491299e+00 ... -5.91846704e+00\n",
" -2.66838741e+00 3.64069283e-01]\n",
" [ 1.25774431e+00 2.87001610e+00 4.69649887e+00 ... 4.54165173e+00\n",
" -2.85226107e+00 -3.68436813e-01]\n",
" [ 1.81897354e+00 -3.68161678e+00 4.60734653e+00 ... -5.21151447e+00\n",
" -3.87653303e+00 -2.30888844e+00]]\n",
"\n",
" [[-1.09149170e+00 7.86081314e-01 6.71111107e-01 ... -7.29392052e-01\n",
" -1.21710968e+00 6.53810644e+00]\n",
" [ 7.78629637e+00 1.63007081e+00 1.89961052e+00 ... 2.10544109e+00\n",
" 5.78480196e+00 1.61796188e+00]\n",
" [ 1.93217373e+00 6.38000393e+00 2.14979935e+01 ... 1.79325032e+00\n",
" 2.81764412e+00 7.90754318e-01]\n",
" ...\n",
" [ 1.97734356e+00 6.39566898e+00 -1.51945400e+00 ... 2.17699194e+00\n",
" -5.57292843e+00 -5.40471733e-01]\n",
" [ 1.35320330e+00 -3.45249176e-02 1.79195786e+00 ... 3.63711071e+00\n",
" 8.24319839e+00 2.72702217e+00]\n",
" [-2.08556747e+00 1.55413849e+02 -1.29719448e+00 ... 2.88394451e+00\n",
" 2.21892595e+00 -2.21342945e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]]\n",
"\n",
"\n",
" ...\n",
"\n",
"\n",
" [[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[-3.85723877e+00 -1.97966576e+00 -3.09463596e+00 ... 4.50486088e+00\n",
" 1.71432495e-02 -1.22764063e+00]\n",
" [ 2.05492973e-02 -6.13567638e+00 -5.86613655e+00 ... -2.66030598e+00\n",
" 1.01905489e+00 -2.14778519e+00]\n",
" [ 1.66426659e-01 -1.38574314e+00 -1.26775312e+00 ... 2.02750325e+00\n",
" -2.94810295e+00 2.02500725e+00]\n",
" ...\n",
" [-6.78840351e+00 1.62992191e+00 -2.85201073e-01 ... 3.41124487e+00\n",
" 6.61324501e-01 -2.30621886e+00]\n",
" [ 2.58745623e+00 -4.80027199e+00 -3.97378922e+00 ... -1.12863636e+00\n",
" -5.22549152e-01 4.96127510e+00]\n",
" [-4.85131454e+00 3.64809513e+00 2.93705845e+00 ... -1.18818026e+01\n",
" 3.45317888e+00 2.08234787e-02]]\n",
"\n",
" [[-8.22393799e+00 -2.34636497e+00 -2.46133518e+00 ... 1.13816166e+00\n",
" -1.34955597e+00 -7.59433985e+00]\n",
" [-1.34614992e+00 -5.02375484e-01 2.76716423e+00 ... 2.97299480e+00\n",
" -3.47644329e-01 2.48551559e+00]\n",
" [-4.20027256e+00 -2.75244236e+00 -5.63445234e+00 ... 4.66080379e+00\n",
" -1.31480217e+00 -3.41691971e-01]\n",
" ...\n",
" [-1.55102730e-01 -7.36777306e-01 5.34809971e+00 ... -2.95545435e+00\n",
" -7.05374718e-01 -6.67291784e+00]\n",
" [ 5.22075701e+00 -1.66971207e-01 -3.34048843e+00 ... -1.49533558e+00\n",
" 1.10751629e-01 -1.40542412e+00]\n",
" [ 2.78198624e+00 2.28139591e+00 -6.42964077e+00 ... -6.24850178e+00\n",
" -2.91352034e+00 3.65412426e+00]]\n",
"\n",
" ...\n",
"\n",
" [[-3.73748779e+00 1.40085220e-01 2.51150131e-02 ... -6.37538815e+00\n",
" -1.86310577e+00 5.89211035e+00]\n",
" [-8.59699726e-01 -2.01592541e+00 -8.74638557e+00 ... -9.54055500e+00\n",
" -8.61194134e-01 -1.02803421e+00]\n",
" [ 2.86177635e-01 -1.26599216e+00 3.38519974e+01 ... 1.14725423e+00\n",
" 7.17164803e+00 1.44758224e-01]\n",
" ...\n",
" [-3.66865253e+00 -2.25032711e+00 5.38345490e+01 ... 5.30995846e-01\n",
" -7.21892452e+00 -1.86467826e-01]\n",
" [ 1.77072067e+01 -6.68052101e+00 1.14596176e+00 ... -3.00888538e+00\n",
" -3.40279818e+00 7.20810242e+01]\n",
" [ 2.68436432e-01 -4.23215389e+00 3.05680943e+00 ... -3.76205158e+00\n",
" 5.72929978e-01 -3.85942554e+00]]\n",
"\n",
" [[ 2.35894775e+00 2.23652077e+00 1.54121552e+02 ... 2.72104740e+00\n",
" -3.76667023e+00 -1.14541054e-02]\n",
" [ 2.36735821e-01 8.05102587e-02 2.35004997e+00 ... -4.44411945e+00\n",
" 6.23524141e+00 -9.31598663e-01]\n",
" [-2.61738682e+00 8.30443382e-01 -4.05156660e+00 ... 4.72436905e+01\n",
" 1.62680836e+01 2.41193771e-01]\n",
" ...\n",
" [-1.57221699e+00 1.08461084e+01 9.19309845e+01 ... -2.37256861e+00\n",
" -3.12248898e+00 9.09967721e-01]\n",
" [ 1.48803650e+02 4.15914536e-01 3.24239731e+00 ... 2.08755016e+00\n",
" -2.30636263e+00 1.77461624e-01]\n",
" [-1.63512802e+00 -3.13571835e+00 2.15324497e+00 ... 6.33438396e+00\n",
" 6.69365525e-01 5.23701000e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]]\n",
"\n",
"\n",
" [[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[ 6.40643311e+00 -3.71599388e+00 1.16903591e+00 ... -4.23146725e+00\n",
" 2.28081512e+00 -2.96396875e+00]\n",
" [-7.15778828e-01 2.12799549e+00 -6.02464676e-01 ... 1.60336590e+00\n",
" -6.71727324e+00 2.11588669e+00]\n",
" [ 1.43009853e+00 -1.22071266e-01 3.99591875e+00 ... -7.08824873e-01\n",
" -6.84431076e-01 -7.11320877e-01]\n",
" ...\n",
" [-7.52473164e+00 -3.10640621e+00 -1.02152920e+00 ... -3.25083256e-01\n",
" -1.07500362e+00 2.95745301e+00]\n",
" [-1.14887190e+00 -2.53660011e+00 -1.71011734e+00 ... 1.35035515e-01\n",
" 1.74112272e+00 -2.77505302e+00]\n",
" [-5.87642670e-01 -2.08823299e+00 3.20073032e+00 ... -2.61813068e+00\n",
" -7.28314924e+00 -2.71550465e+00]]\n",
"\n",
" [[-3.43695068e+00 -3.55937767e+00 -3.67434788e+00 ... -7.48510361e-02\n",
" -3.56256866e+00 -3.80735254e+00]\n",
" [-5.59162617e-01 -6.71538830e+00 -5.44584846e+00 ... -7.24001789e+00\n",
" 4.39342976e-01 -1.72749710e+00]\n",
" [-2.41328526e+00 -4.96545506e+00 -3.84746504e+00 ... -1.55220866e+00\n",
" -5.52781487e+00 -1.55470467e+00]\n",
" ...\n",
" [ 6.31884575e-01 1.05021000e+00 -8.64912987e-01 ... -2.16846704e+00\n",
" -6.91838741e+00 1.11406922e+00]\n",
" [ 7.74431229e-03 -3.37998390e+00 4.46498871e-01 ... -3.70834827e+00\n",
" -7.10226107e+00 -3.61843681e+00]\n",
" [-1.43102646e+00 -9.31616783e-01 2.35734653e+00 ... -8.46151447e+00\n",
" -2.12653303e+00 4.41111565e-01]]\n",
"\n",
" ...\n",
"\n",
" [[-4.35150146e+00 -4.47392845e+00 -1.58889866e+00 ... -3.98940182e+00\n",
" -1.47711945e+00 -7.21903324e-01]\n",
" [ 5.26286602e-01 1.37006104e+00 1.32639603e+02 ... 6.84543133e+00\n",
" -4.75207806e-01 -8.64204788e+00]\n",
" [-4.32783604e+00 -2.88000584e+00 -2.76201582e+00 ... -3.46675944e+00\n",
" 4.55763435e+00 -3.46925545e+00]\n",
" ...\n",
" [ 6.77173309e+01 1.35659218e-01 1.22053623e+00 ... -7.08301783e+00\n",
" 6.16706181e+00 -1.80048156e+00]\n",
" [-4.90680647e+00 -6.29453468e+00 1.53194809e+00 ... 2.43771019e+01\n",
" 9.83188152e-01 5.46701241e+00]\n",
" [-2.34557724e+00 -1.18461676e+01 -3.55720425e+00 ... -4.37606525e+00\n",
" -4.04108381e+00 -1.47343922e+00]]\n",
"\n",
" [[-9.73449707e-01 -9.58766937e-02 -2.10846901e-01 ... -1.61135006e+00\n",
" 1.90093231e+00 -3.43851566e-01]\n",
" [ 2.90433836e+00 2.74811268e+00 1.70176525e+01 ... 5.22348309e+00\n",
" -9.71560478e-02 -2.63996124e-01]\n",
" [ 3.05021572e+00 6.49804592e+00 -3.38396406e+00 ... 9.11292315e-01\n",
" 2.93568611e+00 2.90879631e+00]\n",
" ...\n",
" [ 1.09538555e+00 1.41513718e+02 5.98587990e-01 ... 1.29503393e+00\n",
" 2.54511356e+00 4.57757044e+00]\n",
" [-5.28754711e-01 -9.16482925e-01 3.90999985e+00 ... -1.24484730e+00\n",
" -5.63876009e+00 6.84506416e+00]\n",
" [ 2.03247452e+00 -1.46811581e+00 1.82084751e+00 ... 2.00198650e+00\n",
" 3.33696795e+00 1.90461254e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]]\n",
"\n",
"\n",
" [[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" ...\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]\n",
"\n",
" [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" ...\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]\n",
" [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 ... 0.00000000e+00\n",
" 0.00000000e+00 0.00000000e+00]]]]\n",
"\n",
"df\n",
"[[-500]]\n",
"\n",
"rbf\n",
"[[26]]\n",
"\n",
"rot_ang\n",
"[[-30]]\n",
"\n",
"scanstep\n",
"[[0.85]]\n",
"\n",
"voltage\n",
"[[80]]\n",
"\n"
]
}
],
"source": [
"for key in contents.keys():\n",
" print(key)\n",
" print(contents[key])\n",
" print()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "1f24ed6c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"mappingproxy({'reconstruct_ind': (dtype('O'), 0),\n",
" 'background': (dtype('O'), 8),\n",
" 'intensity_corr': (dtype('O'), 16),\n",
" 'probe_fourier_shift': (dtype('O'), 24),\n",
" 'rotation': (dtype('O'), 32),\n",
" 'shear': (dtype('O'), 40),\n",
" 'relative_pixel_scale': (dtype('O'), 48),\n",
" 'diffraction_deform_matrix': (dtype('O'), 56),\n",
" 'pixel_size': (dtype('O'), 64),\n",
" 'Np_p': (dtype('O'), 72),\n",
" 'probe': (dtype('O'), 80),\n",
" 'probe_support': (dtype('O'), 88),\n",
" 'probe_support_fft': (dtype('O'), 96),\n",
" 'object': (dtype('O'), 104),\n",
" 'probe_positions_0': (dtype('O'), 112),\n",
" 'probe_positions': (dtype('O'), 120),\n",
" 'Np_o': (dtype('O'), 128),\n",
" 'Npos': (dtype('O'), 136),\n",
" 'affine_matrix': (dtype('O'), 144),\n",
" 'noise': (dtype('O'), 152),\n",
" 'diffraction': (dtype('O'), 160),\n",
" 'mask': (dtype('O'), 168),\n",
" 'filename': (dtype('O'), 176),\n",
" 'path': (dtype('O'), 184),\n",
" 'z_distance': (dtype('O'), 192),\n",
" 'lambda': (dtype('O'), 200),\n",
" 'diff_pattern_blur': (dtype('O'), 208),\n",
" 'modes': (dtype('O'), 216),\n",
" 'probe_evolution': (dtype('O'), 224),\n",
" 'affine_matrix_fit': (dtype('O'), 232),\n",
" 'fourier_error_out': (dtype('O'), 240),\n",
" 'fourier_error_dp': (dtype('O'), 248),\n",
" 'probe_positions_model': (dtype('O'), 256),\n",
" 'affine_matrix_init': (dtype('O'), 264),\n",
" 'probe_positions_weight': (dtype('O'), 272),\n",
" 'detector_rotation': (dtype('O'), 280),\n",
" 'detector_scale': (dtype('O'), 288),\n",
" 'asymmetry': (dtype('O'), 296),\n",
" 'avgTimePerIter': (dtype('O'), 304),\n",
" 'fourier_error_threshold': (dtype('O'), 312)})"
"(124, 124, 60, 60)"
]
},
"execution_count": 27,
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"contents['outputs'].dtype.fields"
"contents['cbed'].shape"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "cba406f1",
"metadata": {},
"outputs": [],
"source": [
"from matplotlib import pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "d5a95408",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"np.float32(-36.020027)"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"contents['cbed'].min()"
]
},
{
"cell_type": "code",
"execution_count": 40,
"id": "22fb3775",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f18a10bd2b0>"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.imshow(\n",
" np.log1p((contents['cbed'] - contents['cbed'].min()) / contents['ADU'] + 1e-10).sum(axis=(0, 1))\n",
")"
]
}
],
@@ -160,7 +160,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "0a6acad0be424dec83a5234a9362898b",
"model_id": "6398ba34148e4fda86ce67d9eef2de5c",
"version_major": 2,
"version_minor": 0
},
@@ -181,7 +181,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "497da14575304610bc40120a1e2043ff",
"model_id": "97335076ddcc44d4a97df4f9813c5588",
"version_major": 2,
"version_minor": 0
},
@@ -202,7 +202,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2ed5546a726842ffb5ed46d0e850da3b",
"model_id": "d4511d64692b4e149b429378572bbd28",
"version_major": 2,
"version_minor": 0
},
@@ -223,7 +223,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "30832de7b6c04805971d9fcaba83108b",
"model_id": "3d399fea54864be38895c0f5ef00add9",
"version_major": 2,
"version_minor": 0
},
@@ -284,7 +284,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ec7460a8807f4512a2016bdf2ba06e96",
"model_id": "7e240cf27c6e403ea776427cb5711009",
"version_major": 2,
"version_minor": 0
},
@@ -298,7 +298,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "c872d0c0ba644ce6bdf6fb325c5ca2a1",
"model_id": "4322bffbb7be4e8680874fce071332f1",
"version_major": 2,
"version_minor": 0
},
@@ -312,7 +312,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "251920645cdf4d1684abe653d54bab04",
"model_id": "bc6040d669a248f48c8f6bac761a9840",
"version_major": 2,
"version_minor": 0
},
@@ -326,7 +326,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d6a6853af3f148068e67d1f8be0fd1f6",
"model_id": "1bec199574bc403bac57c8e8c72d6900",
"version_major": 2,
"version_minor": 0
},
@@ -880,15 +880,15 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 40,
"id": "76404cd6",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA94AAAKyCAYAAAAjLAa+AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAA9ntJREFUeJzs3Xt8jvUfx/HXvbHNsDmMOYy12sqpnBMikVMOSYUk1AodCSVU6CT90klOYw7JKQklqaURoYNDJaqJxV3mmM1xY/f1++ObMRs2du+6t72fj8f92H1f93Xf92eXuT/X53t9Dw7LsixERERERERExC287A5AREREREREJD9T4S0iIiIiIiLiRiq8RURERERERNxIhbeIiIiIiIiIG6nwFhEREREREXEjFd4iIiIiIiIibqTCW0RERERERMSNVHiLiIiIiIiIuJEKbxERERERERE3UuEtkgu+/vprHnzwQapUqULRokWpWLEid9xxBxs2bMjS63v37k2xYsUu+Pz+/fvx8fGhW7duF9wnKSkJf39/OnbsmO34s+Oqq66id+/eaY/j4+NxOBzMmDEjbduMGTNwOBzEx8fn2OeOHDkSh8Nxyf0sy2LevHk0adKEsmXL4ufnR0hICK1bt2bq1Knp9nU4HIwcOTLHYhQREc+3cuVKHA5Hprf169df8vXK2ZemnC0FUSG7AxApCCZOnMjBgwfp378/1apVY//+/YwdO5abbrqJL774gubNm1/R+5cpU4aOHTuyePFi/v33X0qWLJlhn3nz5nHixAkiIyOv6LMuZdGiRQQEBLj1M67E0KFDGTNmDA8//DBPP/00xYsX56+//uLrr79myZIlPPTQQ2n7rlu3jpCQEBujFRERu7z66qvceuut6bbVqFHjit9XOTvrlLMlP1HhLZILxo8fT9myZdNta9OmDeHh4bz66qtXXHgDREZGsnDhQmbPns3jjz+e4flp06YRHBxMu3btrvizLqZ27dpuff8rceLECd5++2169uxJVFRUuud69+6Ny+VKt+2mm27KzfBERMSDREREuC0PKGdfmnK25Dfqai6SC84vugGKFStGtWrV2L1792W957fffktQUBDt27fn2LFjtG7dmpCQEKZPn55h323btvHdd9/Rs2dPChW6cHvbme51c+bMYciQIZQvX55ixYrRoUMH9u7dy5EjR+jTpw9B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VvP58+czYMAAJkyYQOPGjZk8eTJt27Zl69atVK5cOdPXdOnShb179xIdHU14eDj79u3j9OnTuRy5iIhIwaKcLSIicvlsndW8QYMG1KlTJ22tPzDrHXbq1InRo0dn2H/58uV069aNHTt2UKpUqdwMVUREpEBTzhYREbl8tl3xTklJYcOGDTz77LPptrdq1Yq1a9dm+ppPPvmEevXq8frrrzNr1iyKFi1Kx44deemllyhSpEimr0lOTiY5OTntscvl4tChQ5QuXRqHw5Fzv5CIiEgOsSyLI0eOUKFCBby8bB8VppwtIiKSiezka9sK7wMHDpCamkpwcHC67cHBwSQkJGT6mh07drBmzRr8/PxYtGgRBw4c4NFHH+XQoUMXHDM2evRoRo0alePxi4iIuNvu3bsJCQmxOwzlbBERkYvISr62dYw3kKEF27KsC7Zqu1wuHA4Hs2fPJjAwEIA333yTu+++m/Hjx2fagj506FAGDhyY9jgxMZHKlSuze/duAgICcvA3ERERyRlJSUlUqlSJ4sWL2x1KOsrZIiIiZ2UnX9tWeAcFBeHt7Z2hpXzfvn0ZWtTPKF++PBUrVkxL4GDGl1mWhdPpJCIiIsNrfH198fX1zbA9ICBASVxERDyap3SvVs4WERG5sKzka9sGjvn4+FC3bl1iYmLSbY+JiaFRo0aZvqZx48b8888/HD16NG3bH3/8gZeXl0d0xRMREcmPlLNFRESujK0ztgwcOJCpU6cybdo0tm3bxlNPPcWuXbvo168fYLqc9ezZM23/7t27U7p0aR544AG2bt3KN998w9NPP82DDz54wYlaRERE5MopZ4uIiFw+W8d4d+3alYMHD/Liiy+yZ88eatSowbJlywgNDQVgz5497Nq1K23/YsWKERMTwxNPPEG9evUoXbo0Xbp04eWXX7brVxARESkQlLNFREQun63reNshKSmJwMBAEhMTNV5MREQ8knKVoeMgIiKeLDt5yv7FQUVERERERETyMRXeIiIiIiIiIm6kwltERERERETEjVR4i4iIiIiIiLiRCm8RERERERERN1LhLSIiIiIiIuJGKrxFRERERERE3EiFt4iIiIiIiIgbqfAWERERERERcSMV3iIiIiIiIiJupMJbRERERERExI1UeIuIiIiIiIi4kQpvERERERERETdS4S0iIiIiIiLiRiq8RURERERERNxIhbeIiIiIiIiIG6nwFhEREREREXEjFd4iIiIiIiIibqTCW0RERERERMSNVHiLiIiIiIiIuJEKbxERERERERE3UuEtIiIiIiIi4kYqvEVERERERETcSIW3iIiIiIiIiBup8BYRERERERFxIxXeIiIiIiIiIm6kwltERERERETEjVR4i4iLine truncated
"image/png": "iVBORw0KGgoAAAANSUhEUgAACBUAAAW+CAYAAAAyN4pZAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAuIwAALiMBeKU/dgABAABJREFUeJzs3XlcVFUfx/EvIAoK7vu+m+WCSAUYWmnmmmmSe1rS8lBqPT6ZbVqZlu25VmpZmRtpLqhZpikKmoCkuW+57yuoqMA8f9wghxlghhlWP+/X677kHs6550eZec/8zu+4mEwmkwAAAAAAAAAAAAAAANJxzesAAAAAAAAAAAAAAABA/kRSAQAAAAAAAAAAAAAAsIqkAgAAAAAAAAAAAAAAYBVJBQAAAAAAAAAAAAAAwCqSCgAAAAAAAAAAAAAAgFUkFQAAAAAAAAAAAAAAAKtIKgAAAAAAAAAAAAAAAFaRVAAAAAAAAAAAAAAAAKwiqQAAAAAAAAAAAAAAAFhFUgEAAAAAAAAAAAAAALCKpAIAAAAAAAAAAAAAAGAVSQUAAAAAAAAAAAAAAMAqkgoAAAAAAAAAAAAAAIBVJBUAAAAAAAAAAAAAAACrSCoAAAAAAAAAAAAAAABWkVQAAAAAAAAAAAAAAACsIqkAAAAAAAAAAAAAAABYRVIBAAAAAAAAAAAAAACwiqQCAAAAAAAAAAAAAABgFUkFAAAAAAAAAAAAAADAKpIKAAAAAAAAAAAAAACAVSQVAAAAAAAAAAAAAAAAq0gqAAAAAAAAAAAAAAAAVpFUAAAAAAAAAAAAAAAArCKpAAAAAAAAAAAAAAAAWEVSAQAAAAAAAAAAAAAAsIqkAgAAAAAAAAAAAAAAYBVJBQAAAAAAAAAAAAAAwKoieR0AAAC5JSkpSbGxsdqxY4fOnDmjmzdvqmTJkqpfv75atmypChUq5HWIKGQOHDigF154QevXr1e1atU0evRo9e7dO6/DgpOlpKRo+/bt2rlzp44fP64rV66oSJEiKlWqlOrWravmzZurUqVK2X5+bGyshg0bpri4ODVo0EAffPCB2rVr58SfAAAAAADgLKdPn9awYcP0888/q0yZMho2bJiGDRuW12EhB+zZs0fbt2/XkSNHlJCQIFdXV5UsWVK1a9dWkyZNVLNmzWw/mzUlAPmOCQCAQm7Xrl2mp59+2lS6dGmTJKuXq6urqU2bNqaffvrJlJKSkmuxjR492iyOUqVKOX2Ozz//3OLn/fDDD50+j8lkMrVp08Zirq1bt+bIXPldQkKCqV69ehb/PFasWJHhmG+++cai/4ULF7KcKzd+H+U38fHxFv+svvnmm1yNYcOGDaZBgwaZypUrl+GfLalX06ZNTePHjzedPXvWrjmOHz9uKlu2rNmzihYtavrzzz9z6KcCAAAACq5ff/01y7+b23rl5HtVdt/97LF48WKLOZ5//nmnzpFq4MCBFnMtWbIkR+bK71JSUkyBgYEW/zy++OKLDMesWbPGov+WLVuynCs3fh/lR+nfwUePHp2r82/dutX0wgsvmKpUqZLlnyP169c3vfHGG6YjR47YNUd21pQAIKdx/AEAoNC6efOmXnnlFTVp0kTTpk3TxYsXM+ybkpKitWvXqnv37nrwwQd16NCh3As0h/Xu3VtFipgXJ5o9e7bT5zlx4oQiIiLM2po2baqmTZs6fa6CYP369dq/f79F+7fffpsH0cCZ9u/frw4dOqhVq1aaOXOmzp07l+WYbdu26ZVXXlHdunX1wQcfKDk52aa5lixZovPnz5u13bhxQ3PmzMlW7AAAAEBhdvjw4bwOId/o2LGjypcvb9YWFhampKQkp85z48YNLVq0yKytXLly6tChg1PnKSj27NmjyMhIi/aZM2fmfjBwqtOnT6tv375q3ry5Jk2apBMnTmQ5Zt++fXr33XdVv359jRgxQomJiTbNxZoSgPyIpAIAQKGUkJCghx56SB988IHdL8y///677r77bsXExORQdLmrYsWKat++vVnbli1btHv3bqfOM3/+fKWkpJi19e/f36lzFAYuLi55HQIcsGjRIvn4+GjlypXZGn/58mW98sorevDBB3XhwoVsx8HvIwAAAMASSQX/cnd31+OPP27Wdvr0af32229OnWfFihW6dOmSWdvjjz8ud3d3p85T0PEOV7BFRUWpadOmmjNnjkwmk93jr1+/rg8//FB+fn4O/TnF7yMAealI1l0AAChYUlJS1L17d61du9bie2XLllXbtm1Vo0YNubu769ixY1q7dq2OHDli1u/MmTPq2LGj/vjjD9WuXTuXIs85AwYM0PLly83aZs+erbfffttpc8ybN8/s3sXFRX369HHa8wuaoKAg1a9fX/v27TNrHzRoUN4EBIf99NNPCg4O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 truncated
"text/plain": [
"<Figure size 1000x700 with 4 Axes>"
"<Figure size 2100x1500 with 4 Axes>"
]
},
"metadata": {},
@@ -905,7 +905,7 @@
"ys = np.array(ys)\n",
"Y = ys.sum(axis=0)\n",
"\n",
"fig, axs = plt.subplots(2, 2, figsize=(10, 7))\n",
"fig, axs = plt.subplots(2, 2, figsize=(7, 5), dpi=300)\n",
"\n",
"keys = ['2V', '5V', '8V', '30V']\n",
"\n",
@@ -915,7 +915,7 @@
" dz = DZ[key]\n",
" c = column_lists[key][72]\n",
" z = np.arange(len(c)) * dz\n",
" popt, perr, _ = fit(double_erf, np.arange(len(c)), c, plot=False, p0=[[0.1, 0.3, 3, 12]],maxfev=10000)\n",
" popt, perr, _ = fit(double_erf, np.arange(len(c)), c, plot=False, p0=[[0.1, 0.3, 3, 12]], maxfev=10000)\n",
" ax.plot(z + dz/ 2, c, 'k.')\n",
" xlim = (0, z[-1] + dz)\n",
" ax.set_xlim(xlim)\n",
@@ -925,6 +925,9 @@
" ax.set_xlabel(\"Depth (Å)\")\n",
" ax.set_ylabel(\"Phase (rad)\")\n",
" ax.set_ylim(-0.05, 0.6)\n",
" shade=\"#ddd\"\n",
" ax.axvspan(0, popt[2]*dz, color=shade)\n",
" ax.axvspan(popt[3]*dz, xlim[-1], color=shade)\n",
"\n",
"fig.tight_layout()\n",
"plt.show()\n"
@@ -932,13 +935,23 @@
},
{
"cell_type": "code",
"execution_count": 32,
"execution_count": 21,
"id": "669830e5",
"metadata": {},
"outputs": [],
"source": [
"plt.rcParams['font.family'] = \"Inter Variable ss02\""
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "fcd12e61",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABaYAAAVeCAYAAACKJuzmAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAuIwAALiMBeKU/dgABAABJREFUeJzs3XVcVNn7B/DPUAoCEgaoiIq5drdgrN2xNnbXWht2rq27dq2N3a6JjYliIFgooIBggAgokvf3Bz/4OtwBpphLfN6v17x275l7znkuDDg8c+5zZIIgCCAiIiIiIiIiIiIi0hE9qQMgIiIiIiIiIiIiotyFiWkiIiIiIiIiIiIi0ikmpomIiIiIiIiIiIhIp5iYJiIiIiIiIiIiIiKdYmKaiIiIiIiIiIiIiHSKiWkiIiIiIiIiIiIi0ikmpomIiIiIiIiIiIhIp5iYJiIiIiIiIiIiIiKdYmKaiIiIiIiIiIiIiHSKiWkiIiIiIiIiIiIi0ikmpomIiIiIiIiIiIhIp5iYJiIiIiIiIiIiIiKdYmKaiIiIiIiIiIiIiHSKiWkiIiIiIiIiIiIi0ikmpomIiIiIiIiIiIhIp5iYJiIiIiIiIiIiIiKdYmKaiIiIiIiIiIiIiHSKiWkiIiIiIiIiIiIi0ikmpomIiIiIiIiIiIhIp5iYJiIiIiIiIiIiIiKdYmKaiIiIiIiIiIiIiHSKiWkiIiIiIiIiIiIi0ikmpomIiIiIiIiIiIhIp5iYJiIiIiIiIiIiIiKdYmKaiIiIiIiIiIiIiHSKiWkiIiIiIiIiIiIi0ikDqQMgIt0JDw/HtWvXUo7t7OyQJ08eCSMiIiIiIiIiIiKpxMTEICAgIOXY0dERFhYWOpmbiWmiXOTatWvo3Lmz1GEQEREREREREVEWdPz4cXTq1Eknc7GUBxERERERERERERHpFBPTRERERERERERERKRTLOVBlIvY2dnJHR8/fhylS5eWKBoiIiIiIiIiIpLSq1ev5Mq+ps4dZSYmpolykdQbHZYuXRoVK1aUKBoiIiIiIiIiIspKUueOMhNLeRARERERERERERGRTjExTUREREREREREREQ6xcQ0EREREREREREREekUE9NEREREREREREREpFNMTBMRERERERERERGRTjExTUREREREREREREQ6xcQ0EREREREREREREekUE9NEREREREREREREpFNMTBMRERERERERERGRTjExTUREREREREREREQ6xcQ0EREREREREREREekUE9NEREREREREREREpFNMTBMRERERERERERGRTjExTUREREREREREREQ6xcQ0EREREREREREREekUE9NEREREREREREREpFNMTBMRERERERERERGRTjExTUREREREREREREQ6xcQ0EREREREREREREekUE9NEREREREREREREpFMGUgdAuhcfH4/AwEAEBAQgICAAX758wbdv3xAfHw9zc3NYWFigYMGCqF69OqytrXUen4+PD7y8vPDu3TtERUUhT548sLKyQvny5VGlShXkzZtX5zG9ffsWnp6eePv2LSIjI2FoaAgLCwuULVsW1apVg6mpqc5jIiIiIiIiIiIiyq6YmM7hEhIS8PjxY9y8eRP379+Hp6cnnj17hpiYGKX6lyhRAi1atMDgwYNRv379TIvz7du3WLt2LQ4cOIC3b9+meZ6JiQlatmyJ0aNH4+eff860eADg48eP2LhxI1xcXPDixYs0zzMyMoKjoyNGjBiBzp07Q19fP1PjIiIiIiIiIiIiyu5kgiAIUgdBmcPT0xMNGzZEVFSUVsarUqUK1q1bh0aNGmllPACIjY3F/PnzsXTpUsTGxqrUt1mzZti8eTMcHBy0Fg8ACIKA1atXY+bMmYiMjFSpb40aNbBlyxbUqFFDqzFpi7e3NypVqpRy7OXlhYoVK0oYERERERERERERSUXKXBFrTOdg375901pSGkhKdDdp0gRjxoxBfHy8xuN9+vQJzZo1w4IFC1ROSgPA5cuXUatWLbi6umocS7Lo6Gh07doVv/76q8pJaQB48OABGjRogN27d2stJiIiIiIiIiIiopyGiWlSiSAIWL9+PXr37o24uDi1xwkPD8fPP/+MmzdvahRPeHg4OnTogEuXLmk0DpC0ertLly44fvy4RuPExMRgwIABTE4TERERERERERGlgYnpXEQmk6FixYoYNWoU1q1bh4sXL8LX1xehoaGIjY1FVFQU3r17h6tXr2LZsmWoWbNmmmMdPnwYkyZNUjsWZ2dnPHr0SOFzrVq1wuHDhxEUFITY2FiEh4fj5s2bmDRpEvLlyyc6PyYmBj169MCbN2/UjgcAJk+ejPPnzyt8rl69eti1axf8/f0RGxuLyMhIeHh4YPbs2bCyshKd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 truncated
"image/png": "iVBORw0KGgoAAAANSUhEUgAABacAAAVbCAYAAAA1KRZrAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAuIwAALiMBeKU/dgABAABJREFUeJzs3XdcU9f7B/BPWArKEMS9BfdAxTrq3hO31r3raOuoq65at63WWieOVusWd9UKiuJWXDhw40DcKHvJSH5/8IWfNzeEm0ES4PN+vfJq77n3nPPcEBCenDxHplAoFCAiIiIiIiIiIiIiMiAzYwdARERERERERERERLkPk9NEREREREREREREZHBMThMRERERERERERGRwTE5TUREREREREREREQGx+Q0ERERERERERERERkck9NEREREREREREREZHBMThMRERERERERERGRwTE5TUREREREREREREQGx+Q0ERERERERERERERkck9NEREREREREREREZHBMThMRERERERERERGRwTE5TUREREREREREREQGx+Q0ERERERERERERERkck9NEREREREREREREZHBMThMRERERERERERGRwTE5TUREREREREREREQGx+Q0ERERERERERERERkck9NEREREREREREREZHBMThMRERERERERERGRwTE5TUREREREREREREQGx+Q0ERERERERERERERkck9NEREREREREREREZHBMThMRERERERERERGRwTE5TUREREREREREREQGx+Q0ERERERERERERERkck9NEREREREREREREZHBMThMRERERERERERGRwVkYOwAiMqyIiAicPXs2/bhkyZLIkyePESMiIiIiIiIiIiJj+fz5M0JCQtKPmzZtCgcHB4PMzeQ0US5z9uxZdO3a1dhhEBERERERERGRCTp06BC6dOlikLlY1oOIiIiIiIiIiIiIDI7JaSIiIiIiIiIiIiIyOJb1IMplSpYsKTg+dOgQXFxcjBQNEREREREREREZU1BQkKAErHLuKCsxOU2Uyyhvfuji4oKqVasaKRoiIiIiIiIiIjIlyrmjrMSyHkRERERERERERERkcExOExEREREREREREZHBMTlNRERERERERERERAbH5DQRERERERERERERGRyT00RERERERERERERkcExOExEREREREREREZHBMTlNRERERERERERERAbH5DQRERERERERERERGRyT00RERERERERERERkcExOExEREREREREREZHBMTlNRERERERERERERAbH5DQRERERERERERERGRyT00RERERERERERERkcExOExEREREREREREZHBMTlNRERERERERERERAbH5DQRERERERERERERGRyT00RERERERERERERkcExOExEREREREREREZHBWRg7ADIdr169wr179/D8+XNERUUhKSkJtra2KFKkCKpUqYIqVarAzMww72ekpKTg7t27CAwMxKdPnxATEwN7e3s4Ozujdu3acHV1NUgcX4qPj8fVq1fx7NkzfPr0CUlJSXB0dETRokVRr149FC5c2OAxERERERERERERZVdMTudyDx8+xN9//42DBw8iKChI7bUFCxaEh4cHxo0bh5o1a2ZJPNeuXcOaNWtw4MABREdHZ3hdoUKFMHDgQIwZMwbly5fPkliA1CT5kSNHsG7dOvj5+SEpKSnDaytXroyRI0di6NChcHBwyLKYiIiIiIiIiIiIcgKZQqFQGDsIMrznz5/jp59+wt69e6HNS6BPnz5YsWIFihQpopd4QkNDMX78eOzatUujfhYWFpg0aRLmzJkDa2trvcSS5vbt2xg+fDhu3LihUT9HR0csX74cgwcP1ms8+nLv3j1Uq1Yt/TgwMBBVq1Y1YkRERERERERERGQsxswVseZ0LrR161bUqFEDXl5eWiWmAWDPnj1wc3PDpUuXdI7n1q1bqFGjhsaJaQBITk7Gr7/+ivr16+Pt27c6x5Jm+/btqFu3rsaJaQAICwvDkCFD0L9/f7UrrYmIiIiIiIiIiHIzJqdzmUWLFmHw4MGIiYnReaz379+jTZs2uHz5stZj+Pv7o2nTpnj37p1Osdy5cwcNGzZESEiITuMAwNq1azFo0CCdE8s7d+6Eh4cHE9REREREREREREQqMDmdi/z111+YOXOmynOWlpbo0qULNmzYgBs3buDVq1d4//49bt26hV27dqFbt26wsrIS9YuNjUW3bt0QGhqqcTxv3rxBt27dEBUVJTqXJ08ejBo1CseOHcPz588RFhaGJ0+eYPfu3ejRowdkMpmoz4sXL9CtWzfEx8drHEsaX19fjBs3TuWK8sKFC+Pnn3/GhQsX8OrVK4SGhuLu3btYu3YtvvrqK5XjeXt7Y/z48VrHQ0RERERERERElFOx5nQu8ezZM1SvXh1xcXGic7169cKSJUtQrlw5tWPcu3cPgwcPVlnqYvDgwdiyZYtGMbVs2RKnT58WtX/99dfYtWsXSpYsmWHf69evo0uXLnjz5o3o3Pfff49Vq1ZpFAuQWo6jYsWK+Pjxo+jcqFGjsHz5ctjY2GTYf/v27Rg4cKDKc/v27UOPHj00jikrsOY0ERERERERERGlYc1pynJz5sxRmZhesGABvLy8Mk1MA0DVqlVx7tw5uLm5ic5t27YNQUFBkuPZs2ePysR027Zt4efnpzYxDQDu7u4YMWKEynPr1q3DnTt3JMeSZubMmSoT03PnzoWnp6faxDQADBgwAMWLF1d57scff1T5/BMREREREREREeVWTE7nApGRkfDy8hK1jxs3LsMyHxmxsbHB3r17YW5uLmiXy+XYvn27pDHkcjmmT58uai9Xrhz27dsHS0vLTMf4/Pkz/vrrL5XnUlJSVI6vTlBQEDZs2CBq7927N37++WdJY9y9e1flSm4AePnyJdasWaNRTERERERERERERDkZk9O5wKVLl5CYmChos7Kykpx0Vebi4oLOnTuL2lWthFbl8OHDeP78uah9/fr1yJ8/v6QxNm7ciNevX2d4/vjx43j8+LGksQBg1apVkMvlgjYHBwesXr1a8hhz585VWas6zerVq5GSkiJ5PCIiIiIiIiIiopyMyelc4MmTJ6K2WrVqwcnJSesxW7ZsKWp78OCBpL5r164VtTVp0gStWrWS1P/z589YsmSJ2msUCgU8PT0ljRcfH4/NmzeL2seNGwdnZ2dJY9y9excHDhxQe83Lly9x7NgxSeMRERERERERERHldBbGDoCynru7OxYvXixoc3Fx0WnM0qVLi9oiIiIy7RceHo4zZ86I2sePHy95buVV061bt0aDBg0wb948wXUHDx7E8uXLMx3P19cX0dHRgjYLCwt89913kmNSXjW9cOFC+Pj44Ny5c6KYPDw8JI9LRERERERERESUUzE5nQs0bNgQDRs21OuYFhbil46UkhzHjh1DcnKyoM3e3h4dO3aUNK+qVdO//PILChYsKEpOv3jxAnfv3kX16tXVjnn48GFRW6tWrVCoUCFJMSmvmnZ0dMQPP/yAggULipLTx44dg1wuh5kZP7RARERERERERES5GzNkpBVVpUKKFy+eaT9Vq6ZbtWqFPHnySJpXedV0q1at0LBhQ1SoUAHlypUTXX/27FmtYpKaLAfEq6Z//PFH2NraokOHDqJrQ0NDcf/+fcljExERERERERER5VRMTpNWjhw5ImqrX79+pv1u3LghamvWrJmkOTNaNa1uHFXzfSkiIgLPnj3TOiZVq6bHjRsHAChRooTKhHlmMREREREREREREeUGTE6Txs6ePQtfX19R+zfffKO2X2JiIu7duydqr127tqR5Va2a/vrrr9WOk1kiOCAgQLDqGQDy5s2LKlWqSIopo1XTusRERERERERERESUGzA5TRp5/PgxevbsKWqvW7cuWrZsqbbvy5cvkZSUJGqXkgjObNV0RuOoWhX9padPn4raKlasKKkmtLpV07rERERERERERERElBswOU2S7dy5E40aNcLHjx8F7dbW1ti0aRNkMpna/iEhIaK2AgUKwMHBIdO5M1s1DUBlCY3Y2FhERkZqFJOqcVTJbNV0RmN9eR9ERERERERERES5lYWxAyDTlJycjPfv3+P169fw9fXFvn37EBAQILrOysoKe/bsQY0aNTIdU1VStnDhwpn2U7Vqes6cOZLHev36Nezt7fUak/Kq6QIFCuCHH34QXVeoUCFJcxIREREREREREeU2TE4TAODVq1coWbKkRn3Kly+PHTt2oF69epKuV7WCuWDBgpn2U1413bJlSzRq1Eh0Xd68eZEvXz7ExsZmOq+uMalaNW1nZye6ztnZWdKcREREREREREREuQ2T06Sx2rVrY8SIERg+fDisrKwk90tISBC1WVtbq+0jpdb0l/LmzStKTsfHx+s1JlWrppVrTX8Zj7LExETI5XJJda0z8+HDB4SGhmrUJygoSOd5iYiIiIiIiIiIdMXkNGmsVatWcHV1hVwu16ifqiRxnjx51PbZtGmTpFXTaVQlg1UloHWJad68eZJWTWcUT1pMNjY2aueRYu3atZg7d67O4xARERERERERERkaN0Qkjf32229o3bo1ihUrhuXLlyMxMVHrsdRtoqjpqumMxvsykaxrTIGBgdi/f3/6sbpV0+rG0jQmIiIiIiIiIiKinIYrpwkAYGtri0mTJqUfy+VyxMbG4vXr1wgMDERwcLCoT3h4OCZNmoRNmzbBx8cn05rVqlYRf/78OcPrN23ahFevXqUft2jRQu2qaUD1KumMVi9rE5NyremJEydmuGo6o3gyi4mIiIiIiIiIiCg3YHKaAAD29vZYtmxZhuefPn2KzZs3Y9WqVYiKihKce/DgARo1aoQzZ86gbNmyGY6hqpZzRslbbVZNZzSeuhrSmsSkatX0+PHjNY7H0tIS5ubmavtJNXbsWPTq1UujPkFBQejatate5iciIiIiIiILine truncated
"text/plain": [
"<Figure size 1500x1500 with 1 Axes>"
]
@@ -985,13 +998,13 @@
"handles = []\n",
"\n",
"eb = plt.errorbar(voltages, damage, damage_err,\n",
" fmt=\"o\", capsize=5, capthick=1.5, elinewidth=1.5, label=\"Current study\", markersize=MARKERSIZE,\n",
" zorder=ZTOP, color='blue'\n",
" fmt=\"*\", capsize=5, capthick=1.5, elinewidth=1.5, label=\"Current study\", markersize=15,\n",
" zorder=ZTOP, color='red'\n",
" )\n",
"handles.append(eb)\n",
"\n",
"for i, (v, d, mk, lab) in enumerate(literature):\n",
" ln, = plt.plot(v, d, mk, label=lab, zorder=ZTOP - 1 - i, color=plt.colormaps['inferno'](i / 6), markersize=MARKERSIZE)\n",
" ln, = plt.plot(v, d, mk, label=lab, zorder=ZTOP - 1 - i, color=plt.colormaps['gray'](i / 6), markersize=MARKERSIZE)\n",
" handles.append(ln)\n",
"\n",
"plt.xlabel(\"FIB milling voltage (kV)\", fontsize=14)\n",
@@ -1010,23 +1023,23 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 23,
"id": "e3824127",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x7fb0064d1fd0>]"
"[<matplotlib.lines.Line2D at 0x7fc3e1359af0>]"
]
},
"execution_count": 24,
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAcYAAAGoCAYAAADcnEUDAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzs/Xe4Zcdd5wt/qmqtHU8+3X06J2WpJUuWJRtnOYJJHsCADVySYV7eGeZe+73jeTyBYJjx4DswzMNzB2ZgDHPxYDDGA7ZxxkGWo2wrSy11VOfuk9NOa62q948Kq9Y+RwZzsexndOp5du8+e6+9VoVf/cL3F0oYYwxbbattta221bbaVgNAfqs7sNW22lbbalttq307tS3BuNW22lbbalttq0VtSzButa221bbaVttqUdsSjFttq221rbbVtlrUtgTjVttqW22rbbWtFrUtwbjVttpW22pbbatFbUswbrWtttW22lbbalHbEoxbbattta221bZa1LYE41bbalttq221rRa1LcG41bbaVttqW22rRe3bVjDee++9vOY1r2FycpJ2u82dd97Jn/zJn3yru7XVttpW22pb7X/xlnyrO7BZ+/SnP82rX/1qarUaP/qjP8r4+Djve9/7+LEf+zFOnz7Nv/yX//Jb3cWtttW22lbbav+LNvHtVkQ8z3Ouv/56zp07xxe+8AVuu+02AFZXV/mO7/gOHn/8cR599FGuueaab3FPt9pW22pbbav9r9i+7aDUT37yk5w4cYI3vOENQSgCjI6O8m/+zb8hz3P+8A//8FvYw6221bbaVttq/yu3bzso9dOf/jQAr3rVqzZ85z/7zGc+83e+n9aaCxcuMDo6ihDiH6SPW22rbbWtttWenmaMYXV1ld27dyPl02PLfdsJxmPHjgFsCpVOTk6ybdu2cM1mrd/v0+/3w9/nz5/nxhtv/Ifv6Fbbalttq221p62dPXuWvXv3Pi3P+rYTjMvLywCMj49v+v3Y2Bjnzp17yt+//e1v51d/9Vc3fH7r9/9LUhrIzCAKSHoFIjfIXCNyDYDAgPe4GvsSuQZjQBuE1hgBCGFfSmCUBCEw0n3mvt/guBXuflqH+4p+bv/uDxBZHu5rpMC0m5hmik4kRSMBKcpn+w4K0EqgFRglKOru+f6RGmTm3w0yNwhjEIUdpygMQhtErpH9HAqNGGSIQWZnw4+tlmDqqe2Dkhgp7O+MDvOEASQY37/w7rvrnqsNIisQ/czOq5/5eoJupSAlRV1hEomR2HkFhLZ9tp+BEaBTgUlEuVbY8dpxgszcXGv73DBtxiCzAjEoINeIwQChDUYpSOyzi3YNk7jxCzuHIisQfg21G5O2NzVKluP3dKA1orDvspdBXtjP8hykxNRrkCh0I6VoJnbdE2nXOaIb498l6ESU9IlBFm4dDQg/D7ocsxxYOhd5gegN3DrYfiAlJnG0lSaYVNnxKlGun1sj4R5qYgKTAiOEWxtTWScxyC1NG4Mo7B4ySkGaYJRdbyMtLSEjmsbSslZuHyT2GUYJjCrH59dVxutgjKXzrAhjp9B27Flm6SdJQElMqtCNxK2vXS9R2L1g505bmhEClLR7LZFhzGWf3TIVGjEo7Ht3gOgPHC+wY9QjDXS7DlLY+/jnFW7MzhDKm47+/VoLR9OZ3auqr5F+H/m5LuyEiEzbedcGssx+HniKxDTrmJqy81pTgUcJKO9XLgMGwyMn/idzi0dp1CeZmrgKo3PmFp8gyztcu+Mu9o0csXOc5RQ6496F97M2mGOyfYCR8d2sda+wuHiC1uhOjtzxs6Skbr3sy0iBTuweM4lEJ7ZHwvVB5Abd7/LlT/97RkdHebrat51g/H/b3vrWt/LmN785/L2yssK+fftor6SkSRo2lNAKgUEIg/A7zVARLAgQaSnigmCSQ4IQAiOJhZe9xn3mLhTGEXNWIFVuN5JJEOS2D24zalnDiBpGSkRihZJnksIJNStksExJCnQnEszCPzIakHLMS7ku55ZpCalRRQZoRJIgTGo3v5IR03SMOy0FoxcyVjCZchMKqoLcKwWO6QiVI40TjO5lVIKRNYwUSKnsRvZCCb9m2o5XlwzUKDc+z6gixUYIz9R1UHo8ExeFQGjbMSEEKDD1FJMm6JrEtGuWgbkZFIVBicIxM22VAkHw0ptEOmHuFQr3LHe9xDGqLEeI3DGrBIREk6BMijECjRXGZV/LebPCsSoYvTBEuPnw37vbSJkjRIFlNtoKdWz/TKKgUbfKTi2xaxspd6LQFYUiTIaj9yBATXlNoG9V2JfW0M+sUim9ViPRpFZoOKYtnPIZlKy8fIad03Jeyw3pFRP/XIPAIIUGYRAit3tbFghpid6kCSiFThUiTdy+cntTanu9LoV52O9CoKJ9H/a2nwNtkMKOV2iF1CqsEUJQyDpG1p3QV259LP8JSqMxpD2JyZ1SqKySJEw5VoG23Y1+K7VVBESeQ6btXBQKtLR7WCUYJdG1ul1nJTGpI1ztaCi6n1/Ly4uPMrd4lPHR/dz6rJ9BpjWENmS9Ne69/3c5Pns3O0evp5mOIPIep9a+xtpgjkNjz+HaXS+jGGthUsWJC5/i9OlPcvn0Fzl06BWW72qNzLWlN7fWOvH7WZTRLwZy4wyXp9EV9m0nGL2l6C3H4baysvKU1iRAvV6nXq9v+FwWJjDKWNvCa7sm+qwiHL3AE6VwSqoMpNIiDT8rupw6/TesrJ6j11sky7qkaZtWaxv7dt7JzMh1gEQ4ARQ2kin7aPy764sQBG0rMAbXb4l/tnHdEpigekVC3DMvXWpu5QbBMjABSNcv6cfq7yMw0jIjY5yQFIJef4XLC48wv/QE6905BoM10qTJ+PgB9u97EROtPeEeWhRcWXmC2dXjLPcu0M1WEULQbm5n18xt7N77XIS0pqEVjDowD69lg7Qy1wneoICIaB5x6xuNE2Mq626iNTZKWEsqYphesFsmaJ/rySTLupy48ClWOhfo9pfI8i5p2qLV2s7eXc9lx8QN9jZSWCtTCHIz4NjCF7i8fox+sU49abNj+iYO77sLqdrOQi3XN/TbM0m/hm54Iqy7KEnXKyxaWyvVKRb+PjE64RW9IFSj+RBDLh0j4HNf/S16/SU2a3tm7uD6q74PIYVFVLA028mWOTH3ZeY7p+kX66SqQbu5nb0zd7Jjx82V/eMFgVewPH0h/Zr6zhCsnEAbWoMX6H68hnK/ynLMXigGC9312V8jfB8CCiAwGK4sPsrZi1+i050lL/o06uNMjB/k4MwLaKeTbhCCY4uf48TSFzedJykSXvqiX43G4vafU6bQANoKA+PXuRy/VyTsu7a/KZziYxx1+r2sopdf77DUdkxCliiXV7ZmFx8D4OD+l6BUarshIK2PsG/38zl26kOcW32IayZfgJaCc51HUSLlqvHnRWsh2L/vRZw79wUunr+XQwdeZve05zlBgTcIEUlD38FojZ/O9m0nGL1v8dixY9x+++2V7xYXF5mbm+P5z3/+N3xf2SuQaVHCgN7iKhyUqi3kEjRkb3l5rVJJdGoJS6cyaIwl5OT+MSVfHvS6XLz4VcbG9rFt240kSZNBvs783FEeOvqnzM88hxsPfS8mS5yWXARNNVgXKORABmZtpBNoualsDs+AApcMQs5rtnLIqjLIgbbwoINTg4bsITUPJSZyiIECOMgvUijOnv0ST577LM3GFFMTV1Ortel055mbf4zZuUc5ct0PMzN9BCEFnWyZB87/JUrWmG4dYPvoteQMmF05xuMnP8j8whM869o3QGLxMw/7xoLRJAZTCLupvTXh4Ey7Bg5izLWFVbWBwsKhlnk6c8P91qTKvpJyrr1CYQ0dVVEoMNBbW+bC3P2Mje5l+/QNJGmTQbbO3PxRHn7s3eyeeQ43HP4+O39KUmQ9vnzhz1gdzDLdOsCu+g2sZLOcufQFFpdPcfstP4dK66Xy4mnBK21DIL2IyNUYB+nGik8/RwxyC+Pmhf3OwYkkykJqzoIwypu/TthIK9hMZBkZYXmWShrs2/v8kpwcaY2N7kXXVan0C5jvPMn9F94HwPbWVTRrE2QiY7U/y8LyCXbsuLkUwk4oBqYZBLnBGg6lIioiyy6gEbmlaYxx0LWxdJ9Ia6HWEoyDywNdu9vabaPC36GZ8nnHj32Is+c/R602yvbpG1FJnbX1S1y49FUuzz7EHTf8LGNywimX9ia7R26k0Zyy8+1cMELICnTphaK19uzYTS4C/W1onncV1iVD4dY3z+33Utk1riWYRs1ZjI6+vaIGbi+L0qvh195AP18HoN6asha7V7YlNEamAVjonEHvfind3hx9vc62xgESmWBcv0SuqYmUifGDzM0/Rm9tllZjWwkjO2sQrPFikthiFKANKss3mYBvbvu2E4wveclLePvb387HPvYxfvRHf7Ty3cc+9rFwzTfaRKERqiRET4SB2RqncTlcPmiKSal9UYF1qtqm8OpUgBah2ZrkhS/810iZBIvLKEGmB9z3xf+bC5e/wr5dz2NcTlQgHcBpvCYQUOndEaUVEffffuXG5zRO4ZibsNLSWzmB+fjxxlaUjCym2AcU+WJKYSEiDRZGx/bx7FveyMT4wQqUurR8ivvveydHT7yf7VPXI4RAJXVu2P2d7Bm9CYXz+yhJvusVfOXEHzO39ASzcw+zY/vNbv1iDdmEOQrWkjQIIt9uUFC8pajDfOK17Aj+9ZBZaS269fLKhr/GWAHkfVqN0Wle+MJ/jRKqoqnnRZ+vfu33whqPqWkQgtPzX2J1MMuh8Tu4bvtL7f3ThGPz93Dy8md58txnOXzw5UEoxuhBWNu4BWEpnDAxwRKOmae3HPF04ulNWqXL/t/fz9GL16Ni36ej0SRpcPDqV4b7eavd6UoB+uz3Fnng4l9ST0a5Y9cP0VSjVhA365Ao8mQzayAaq59TYxABVyzpXMT7RFuapihCTADaYIQEoZxiJ4Nvs3R1uIFGPu2Line truncated
"image/png": "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 truncated
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
@@ -1059,13 +1072,13 @@
},
{
"cell_type": "code",
"execution_count": 25,
"execution_count": 24,
"id": "2e8a5fad",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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n9/TzRERER4ZHwCA4kRQRIVnCm2nTp3yyNgnT540thd1DUUAAEoCQREVnmlP5+PHj3tkbNM4kZGRXHoGAJQJBEVUePXr13drS0xMzPf+Qivi4+Pd2ho0aFDkcQEAKAkERVR4TZs2dWtzuVzav39/kcY9d+6ccYu9Jk2aFGlcAABKCkERFV6bNm2M7du3by/SuNu2bbM0HwAApQ1BERVe+/btje2bNm0q0rjff/+9pfkAAChtCIqo8Bo0aGC8bzAmJqZI45r6h4SEqFOnTkUaFwCAkkJQBCTddtttbm2//PJLvpePC5KYmKhvv/3Wrb1Xr14e2ZUFAICSQFAEJA0dOtTYPmvWLFvjzZkzR9nZ7vtP5TcPAAClEUERkNS5c2c1b97crf3DDz80LnFzJefOndObb77p1l6tWjX169fPbokAAJQ4giIgyeFw6PHHH3drz8jI0OjRo+VyuQo91sSJE43L4kyYMCHfvaUBACiNCIrA/zdixAi1bt3arT0mJkYPPfRQocLiq6++qvfee8+tvVatWnrkkUc8USYAACWGoAj8f76+vpo1a5b8/PzcXnvnnXd022235bsI99GjRzV8+HA98cQTxtfffvttVapUyaP1AgBQ3Nz/RQQqsI4dO+rll1/W//3f/7m9tnLlSjVt2lSdOnXS9ddfr4iICJ0/f17bt2/Xt99+q6ysLOOYjzzyiPr371/MlQMA4HkEReAyEydOVGJiol555RW311wulzZu3KiNGzcWaqzhw4fr9ddf93SJAACUCC49AwZ///vf9e677yowMNBWf19fXz333HOaN2+efHz4NgMAlE38CwbkY9y4cdq1a5fuvPNOS2GvV69e2rx5s6ZMmSKHw1GMFQIAULy49AxcQaNGjbR06VLFx8frP//5j9auXas9e/bo+PHjSktLU1BQkK666io1a9ZMN954owYMGKBmzZp5u2wAADyCoAgUQv369fXoo4/q0Ucf9XYpAACUGC49AwAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAAAjgiIAAACMCIoAAAAwIigCAADAiKAIAAAAI4IiAAAAjAiKAAAAMCIoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAAAjgiIAAACM/LxdAADvcTrS5eNILfTxidn+luc4me2w3EeSInyCLffJzrE1lRLTrHf0c9h7X1cF+VruE+xnby5fe93k72P97znIGWFrrrNZGZb7ZCjL1lwROVUt9/F3BNiay45zOem2+kVk2/unvGm49XNFPja/pg6nuCz3OZZq7+8522V9rlBHoK25Lrisf/2muzItHe902fs8eApnFAEAAGBEUAQAAIARQREAAABGBEUAAAAYERQBAABgRFAEAACAEUERAAAARgRFAAAAGBEUAQAAYERQBAAAgBFBEQAAAEYERQAAABgRFAEAAGBEUAQAAIARQREAAABGBEUAAAAYERQBAABgRFAEAACAEUERAAAARgRFAAAAGBEUAQAAYERQBAAAgBFBEQAAAEYERQAAABgRFAEAAGBEUAQAAIARQREAAABGBEUAAAAYERQBAABgRFAEAACAEUERAAAARgRFAAAAGBEUAQAAYERQBAAAgBFBEQAAAEYERQAAABgRFAEAAGBEUAQAAIARQREAAABGBEUAAAAYERQBAABgRFAEAACAEUERAAAARn7eLgCA96Q5UpTjKPyPgTRHSjFWk9dxG338swJtzRWSE2q5T7CCbM2VmRNiuU/jcH9bczWqbKubLmRZP4eQlG7vvIN/isNyn+POVFtz5chluU8NVbM1V2Vf639nwX72PodVA+3187H+qVdmjq2plJZl/XN/ISvT1lwXlG65z3nHOVtzZfikWe6TpQxLxztd5y3P4UmcUQQAAIARQREAAABGBEUAAAAYERQBAABgRFAEAACAEUERAAAARgRFAAAAGBEUAQAAYERQBAAAgBFBEQAAAEYERQAAABgRFAEAAGBEUAQAAIARQREAAABGBEUAAAAYERQBAABgRFAEAACAEUERAAAARgRFAAAAGBEUAQAAYERQBAAAgBFBEQAAAEYERQAAABgRFAEAAGBEUAQAAIARQREAAABGBEUAAAAYERQBAABgRFAEAACAEUERAAAARgRFAAAAGBEUAQAAYERQBAAAgBFBEQAAAEYERQAAABgRFAEAAGBEUAQAAIARQREAAABGBEUAAAAYERQBAABgRFAEAACAEUERAAAARgRFAAAAGPl5uwAA3uN0pUou32KdI1uZtvo5bPweG+6obmsuO0Idgbb6NQ73t9yndZUsW3NdHei01c+ZY/1zf8DH3ufjnNP6XJWyAmzNFexyWe4TGWj97+v3fta/r+pUsl6fJDWqZO/vOdPlsNxn1zl7nw9njvX3liF7X/dJPsct90l1nbE1V3qW9X45yrF0fFZ2muU5PIkzigAAADAiKAIAAMCIoAgAAAAjgiIAAACMCIoAAAAwIigCAADAiKAIAAAAI4IiAAAAjAiKAAAAMCIoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgLine truncated
"image/png": "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3In2g+L5hMvOJnOgiMvZ798kOfkAIpeeUaBVrFjR0hYeHm5pc7qaePLkSWN7pUqVvCsQAAAfIiiiQKtcubKl7dy5c7p06VKKNieriZJ08OBBS1twcLBKlSrloFoAAHIWQREF2tVXXy1/f+tl0b///jv5505XE6V/7wdMrVq1arZqBADAVwiKKNCCg4NVr149S/uWLVuSf556NbF9+/ZerSZK0tatWy1tTZo0sV8oAAA+QFBEgdesWTNL26pVqyRlbjVRklauXOnVfAAA5EYERRR4bdq0sbT99NNPio+PN64mms432b9/v/bt22dp93Y1EgAAXyMoosDr1q2b5e0pZ8+e1eLFizO1mjhnzhxLW4UKFXT99dc7qhMAgJxGUESBV758ed14442W9n79+jleTYyNjdWUKVMs7T169Ej3FYEAAOQmBEVA0kMPPZThOWPGjPF6vEmTJunEiROO5gEAILcgKAKSBgwYoAoVKqR5vF27dmrbtq1XYx04cEAvvPCCpb1Nmza67rrrnJYIAECOIygCkgoVKqSxY8emefz555/3apyzZ8+qa9euxtf2vfbaa47rAwDAFwiKwP83bNgw3XDDDcZjr776qvFS8pW2bNmili1bavfu3ZZjQ4YM0c0335wldQIAkFMIisD/5+fnpy+//FKhoaGWYytXrlStWrX0yCOPaPny5Tp8+LDOnz+v/fv3a968eerfv7+uv/56hYWFWfrWrVtXH330UU58BAAAslSArwsAcpOaNWtq3rx56tatm2JiYlIci46O1qRJkzRp0iSvxytXrpwWL16sEiVKZHWpAABkO1YUgVRuueUW/fTTT8aVRTtq1KihtWvXqm7dullUGQAAOYugCBjcfPPN+uuvv9SjRw/bfV0ulx588EFt3rxZtWrVyobqAADIGQRFIA2VK1fW4sWL9euvv+rOO+9U0aJF0z2/VKlSeuSRR7R9+3ZNnjyZy80AgDyPexSBDLRq1UqtWrVSQkKCtm7dql27duncuXOKjIxUSEiIypQpo8aNG6t+/fq8dQUAkK8QFAEvBQQE6Prrr+ddzQCAAoNLzwAAADAiKAIAAMCIoAgAAAAjgiIAAACMCIoAAAAwIigCAADAiKAIAAAAI4IiAAAAjAiKAAAAMCIoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAAAjgiIAAACMCIoAAAAwIigCAADAiKAIAAAAI4IiAAAAjAiKAAAAMArwdQEAfCvOFSM/V5TX559KDLQ9x5lEl+0+khTqF2y7T6Lb0VQ6FW2/Y4DL2ecqU9jfdp/gAGdz+TvrpkA/+7/OheNCHc11ISHWdp9YJTiaK9Rd2nafQFchR3M5cdEd46hfaKKz/53XLWF/vcjP4e+po5Ee233+iXL265zosT9XMVeQo7kiPPZ//8Z44m2dH+dx9n3ICqwoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAAAjgiIAAACMCIoAAAAwIigCAADAiKAIAAAAI4IiAAAAjAiKAAAAMCIoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAAAjgiIAAACMCIoAAAAwIigCAADAiKAIAAAAI4IiAAAAjAiKAAAAMCIoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAAAjgiIAAACMCIoAAAAwIigCAADAiKAIAAAAI4IiAAAAjAiKAAAAMCIoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAAAjgiIAAACMAnxdAADfinZFyu3y/q+CaFdkNlaTUriDPoEJQY7mKuIuZrtPsAo7miveXcR2n9olAh3NVau4o26KSLC/jnA6xtnaQ2Cky3af8LgoR3O55bHdp4LKOZqruL/9X7PgAGffw9JBzvr52f/WK97taCpFJ9j/3kckxDuaK0Ixtvtccl10NFesX7TtPgmKtXV+nOeS7TmyCiuKAAAAMCIoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAAAjgiIAAACMCIoAAAAwIigCAADAiKAIAAAAI4IiAAAAjAiKAAAAMCIoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAAAjgiIAAACMCIoAAAAwIigCAADAiKAIAAAAI4IiAAAAjAiKAAAAMCIoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAAAjgiIAAACMCIoAAAAwIigCAADAiKAIAAAAI4IiAAAAjAiKAAAAMCIoAgAAwIigCAAAACOCIgAAAIwIigAAADAiKAIAAMCIoAgAAACjAF8XAMC34jxRksc/W+dIVLyjfi4H/5Yt4brK0VxOFHMFOepXu0Sg7T6NSyY4mqtsUJyjfnFu+9/7MD9n34+LcfbnKppQyNFcwR6P7T6lguz/ev3bz/6fqypF7dcnSbWKOvt1jve4bPfZcdHZ9yPObf+zxcrZ7/vTfuG2+0R5zjuaKybBfj+33LbOT0iMtj1HVmFFEQAAAEYERQAAABgRFAEAAGBLine truncated
"text/plain": [
"<Figure size 600x1200 with 1 Axes>"
]
@@ -1120,13 +1133,13 @@
},
{
"cell_type": "code",
"execution_count": 26,
"execution_count": 25,
"id": "b5a59943",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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 truncated
"image/png": "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mJgqSBt4fLYb8GWXmVGSxYuhdWvTDr9VK9+EFAlyKkZE/FxRB1LnwX1bjtmBtMjKlaa1+V//auaFFOneXatjDuHTuThgVtV06gTLl5tC8NBLX5Mnm716ROQoWk0jEiDK1YH0wAF47jl48klzHBlpRkF69aresAGgQnvenKiFC+Gaa0xx8vrrcO21vv36In5Kq2lEgozL5aJjx45lnyjT0sylgr//3RQiPXrAhg0qRMrgs7k45VG/vllt89tvZhLxkCGm062IACpGRILDG29AmzZmE7ioKNOg64MPSnbMlaNUei5OZVx4obl0dt995vErr5j369BLaCIhTMWISLDIy4MrrjC76Pbura6gx1GpuTgnonZtmDgRFi0Cl8usZrr0UrOiSSTEac6ISKAqKICDJ1K8Xvj3v83usmH6HaMifL4bcHns2QP33GN2RP7wQ3NJTSQIqR28SDD74AN46in473/Vwj1Qeb3w7bdw8cUlzx04YPrAiAQJTWAVCUYHDsDw4XDzzfDTT/Cvf9lOJJXlcBxeiHg8ZkfgOXOsRRKxRcWISKDIyYEbboDnnzePH34YRo+2Gkl86IUXzDySm26CZ581IyciIULjgSKBYPt2uO46WLHCTIScNs2MjkjwGDfOjJZMmACPPgpbt5rjonlBIkFMIyMi/u6XX0w31RUr4NRTzf4yKkT8WqVazIeHw4svmgLE4YBJkyApCf78s8pyiviLShUjCxYsoHXr1tSpU4cOHTqwfPnycn1ednY2DoeDevXqVebbioSmyEhzcmreHL7+2vSsEL91wi3m778fZs40uyrPmmV2BM7MrJqwIn6iwsXIypUr6datG7169WLp0qWEh4eTkJBARkbGcT937NixXHDBBTTQ7H+R8mvUyLQT//prsz29+C2Px8OAAQOKO7sWFhYycODAim/Cd/PNZifg6GjIytJybQl6Ff4XPnbsWLp3786IESNo06YNDRs2BGDSpEnH/Lxt27Yxe/ZshgwZclTXQxE5wiefwHvvlTxu3twUJeLXfNpivmNH+OormD/fFCUiQazCVcHixYtJSkoCwO12s3btWsaMGcOiRYuO+XlPPPEE9957LydpDb3IsS1YYFZU9Opl+ohIwPB5i/nzzju8pf+778K2bSeQUMQ/VagYycrKYteuXbRo0QKAcePGMWzYMFq1asWmTZvK/Lx169Yxf/587rrrrnJ9n/z8fLKzsw+7iYSEhQuhWzfYt8/cd+hgO5FUQJW2mH/rLVOgXnGFChIJOhUqRnJycgCoXbs2O3bsYOHChfTp04fIyMjij5VmxIgRPPDAA9SsWbNc3+fZZ58lOjq6+BYTE1ORmCKBafFiuPFGyM83hci775oVFhJQ+vXrR3p6OqmpqaSnp9OvXz/ffOHLLoOmTWHjRkhMNDsAiwSJChUjkZGRAOTl5TFhwgQGDRpEREQEubm5xR870pIlS/jqq68YNGhQub/PyJEjycrKKr5t2bKlIjFFAs/nn0OXLmYZZ9euZr5IjRq2U0kluVwuOnbs6Nu9bpo1M8u6mzaFDRtMQbJ9u+++vohFFZrAER0dTYMGDVixYgUzZsxg9erVAKxfv57mzZuX+jmPPPII999/P3Xr1i3394mIiCAiIqIi0UQC18aNpgD580/TYfWDD1SISOnOOANSU83k1vXrTSO8L76ACvz/KuKPKjQy4nA4SExMpHfv3iQlJRVvejNr1iw6dep01Ot//fVXvvnmG8aMGUPNmjWpWbMmffv25ZdffqFmzZp8/fXXvvlTiASyuDi4+2646iqzg6sKESmDx+MhdfNmfnvnHdMAb8UK6NkT9u+3HU3khFR4Nc3w4cMBM8l09erVDB06lA0bNjBkyBAAunTpwj333APAaaedxrp16/jxxx9ZtWoVq1atKv78VatWccEFF/jqzyESuMLCTOfNuXNBI4JShkObqbk6duTf/fubrQESErTTrwS8Cv8LTkhIYO7cuYwYMYKpU6fSunVrFixYUHxtNCMjg1q1agEQHh5Oy5YtD/v8li1bcuaZZx71vEhIycsze5EMH15SgGhERMpQWjO1HmPHsmXpUk5r185yOpET5/B6/X9ryOzsbKKjo8nKyiq+NCQSsA4cgB494OOPzRD7Bx/YTiR+LjU1lcTExFKf79ixo3mwd6+ZT3LdddUbTuQYynv+VitUkerk9Zq9Rz7+GGrWhKFDbSeSAHDcZmp5eWbO0Q03wH/+YyGhyIlRMSJSnaZOhVdeMRvfvfMOXHKJ7UQSAI7bTK1WLTjnHFPs3nabWWkjEkB0mUakuixZYnpD7N8Pzz1n5ouIVIDH48HtdhMXF3d0D5P9++HKK+HLL6FFC/juO+1pI9aV9/ytYkSkOng8ZtXD9u1mR9aZM83oiIgv7dhh/p1t2QLXX28uB2pjUrFIc0ZE/MmmTaap2XnnweuvqxCRqtGwIcyebeYjzZsHTzxhO5FIuagYEakOl18O338Pc+ZAnTq200gwa9sWXnvNHE+eDL//bjePSDmoU45IVcrLM42pAOLj7WaR0HHbbbBzp9nv6JRTbKcROS6NjIhUleXL4cwzzW6Line truncated
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
@@ -1180,13 +1193,13 @@
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": 26,
"id": "242dd227",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAooAAAS+CAYAAABGTwoNAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAuIwAALiMBeKU/dgABAABJREFUeJzs3Xd8VFXeBvBnkkmZ9IQSklAl9Ca9hiC9Coj0KqMEEVkja1lFBEHXdXVBFAklSJMOAoqBAEIMTTqEEoqQBEhCGqROymTm/YM3kTD3ps7cac/38+HzMuecOfeXd3fh4dx7z5FptVotiIiIiIieY2PsAoiIiIjINDEoEhEREZEgBkUiIiIiEsSgSERERESCGBSJiIiISBCDIhEREREJYlAkIiIiIkEMikREREQkiEGRiIiIiAQxKBIRERGRIAZFIiIiIhLEoEhEREREghgUiYiIiEgQgyIRERERCWJQJCIiIiJBDIpEREREJIhBkYiIiIgEMSgSERERkSAGRSIiIiISxKBIRERERIIYFImIiIhIEIMiEREREQliUCQiIiIiQQyKRERERCSIQZGIiIiIBDEoEhEREZEgBkUiIiIiEsSgSERERESCGBSJiIiISBCDIhEREREJkhu7ACJzodVqcf36dVy7dg2PHj1CdnY2FAoFatSogWbNmqFVq1aQy/k/KSIishz8W42oDNevX8eyZcvw888/IykpSXScu7s7hg0bhrfffhudOnWSsEIiIiLDkGm1Wq2xiyAyRRkZGfjggw+watUqaDSaCn13zJgxWLZsGby9vQ1UHRERkeExKBIJuHv3LoYOHYobN25Ueo7atWtj3759aNu2rR4rIyIikg6DItFz7t+/jx49eiAuLq7Kc3l5eeHYsWNo1aqVHiojIiKSFt96JnpGfn4+Ro4cKRgSZTIZxo4di99++w1JSUkoKChAamoqjhw5gtdffx12dnY630lLS8Pw4cORnp4uRflERER6xRVFomd8/PHH+OKLL3Taa9Soge3bt6NXr16i342KisKIESNw9+5dnb4pU6Zg/fr1+iyViIjI4BgUif7f3bt30bx5c+Tl5ZVod3Z2xokTJ9CmTZsy57h//z46deqExMTEEu0ymQwnT55Ely5d9FozERGRIfHWM9H/+/LLL3VCIgB8/fXX5QqJAFCnTh38+OOPOu1arRaLFi2qco1E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 truncated
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAooAAAS2CAYAAACqHIhgAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAuIwAALiMBeKU/dgABAABJREFUeJzs3XdYVMe/BvB36UsVRRTsvWvsGEHsPUaNJbZoshrshvQYo7Gk/EzRmKigYtfErokRNSaKosbeO6KgIoKA9Law9w8vRNxzlgV2z7b38zw+152Zc/ZLfrn6ZuacGZlKpVKBiIiIiOglVoYugIiIiIiME4MiEREREQliUCQiIiIiQQyKRERERCSIQZGIiIiIBDEoEhEREZEgBkUiIiIiEsSgSERERESCGBSJiIiISBCDIhEREREJYlAkIiIiIkEMikREREQkiEGRiIiIiAQxKBIRERGRIAZFIiIiIhLEoEhEREREghgUiYiIiEgQgyIRERERCWJQJCIiIiJBDIpEREREJIhBkYiIiIgEMSgSERERkSAGRSIiIiISxKBIRERERIIYFImIiIhIEIMiEREREQliUCQiIiIiQTaGLoDIVOTl5eHKlSu4evUqEhISkJaWBjc3N1SsWBGtWrVCvXr1DF0iERGRTjEoEhXjzJkzWLp0KXbu3InU1FTRcZ6enhgzZgwmTZqEOnXqSFghERGRfshUKpXK0EUQGaP4+HjMmDEDv/76a4mus7GxwQcffIA5c+ZALpfrqToiIiL9Y1AkEnDx4kX06dMHsbGxpb5H8+bNsX//fnh5eemwMiIiIukwKBK95NSpU+jZsydSUlLKfK+aNWvi6NGjqFatmg4qIyIikhbfeiZ6QUxMDAYNGiQYEu3t7REQEIA///wT9+7dQ2JiIu7cuYPffvsNb7zxBmQymdo19+/fx6BBg5CZmSlF+URERDrFGUWiF3Tr1g3//POPWnvHjh3x66+/apwZPHv2LF5//XXExMSo9U2dOhU///yzTmslIiLSN84oEv2/LVu2CIbEXr164fDhw8UuH7dp0wbjx48X7Fu+fDkuX76skzqJiIikwhlFIgD5+fmoW7cu7t27V6S9du3auHTpEpydnYu9R3Z2NurUqYNHjx4J9vft2xd//vmnTuolIiKSAmcUiQDs2bNHLSQCQHBwsFYhEQBWrlwpGhIBIDQ0FLdv3y51jURERFJjUCQCsGzZMrW2Tp06oXv37lpdn52djW+//VbjGJVKhaCgoFLVR0REZAgMimTxkpKScOTIEbX2GTNmaH2Pl2cTe/TogdmzZ6uN27VrV6lqJCIiMgQ+o0gWb+PGjRgzZkyRNjc3Nzx58gT29vbFXi/0bOLx48fh4eGBBg0aqI2/fPkymjVrVvbCiYiI9IwzimTxhGYTu3fvrlVIBNRnE7t3745XX30V9evXR+3atdXGh4WFlbpWIiIiKTEoksU7d+6cWlvnzp21ulbo2cQvv/xS432Evo+IiMgYMSiSRcvJycG1a9fU2lu1aqXV9UKziR07dtR4HwZFIiIyFQyKZNGio6ORm5ur1t64ceNiry1uNlHsPpGRkSUrkoiIyEAYFMmiPXjwQK3N3d0d5cqVK/ba4mYTAQg+o5ieno7k5OSSF0tERCQxBkWyaEIbZFeqVKnY64RmE+fMmaP1vTRtzE1ERGQsGBTJognN7Hl4eBR73cuzid26dYOvr6/aOAcHBzg5OWn1vURERMbGxtAFEBlSVlaWWptcLtd4jTbPJr7IwcEB6enpRdoyMzO1L1KDuLg4xMfHl+ialJQUnD17Fq6urihXrhyqVaum9VZAREQkvezs7CKPSvn7+2v1iJQuMCiSRRMKbMWFplWrVmk1m1jAwcFBrU0ooJbGsmXLMHfuXJ3ci4iITMPu3bvx+uuvS/JdXHomeolMJhPtK+lsotj9eCASERGZAgZFsmhCs33Z2dmi41etWoWHDx8Wfu7atavG2URAePZQ6HuJiIiMDZeeyaIJPY8otixcmtlEsfsV9xyktiZPnoyhQ4eW6Jrr169j2LBhhZ93796NunXrFh3zzx3s/eaQ4PVvBw9FxdrFv/BDRES6ERERgYEDBxZ+rlatmmTfzaBIFs3V1VWt7enTp4JjhWYT/fz8NN4/OzsbaWlpau0uLi4lrFSYp6cnPD09y3SPunXrokmTJkXaalWtjdOLryA/T32JXBlthSavNVFrJyIiaUj5AiKXnsmieXt7q7XFxsaqtZV2NvHJkyeC7VWqVNGuQANxdJOjVpvqgn3X/74jcTVERGQoDIpk0apWrarWlpiYiJSUlCJtpZlNBIB79+6ptcnlcpQvX74U1UqrUbd6gu3RFx4i9Wm6YB8REZkXBkWyaNWrV4e1tbVa+40bNwp/X9rZROD584Avq1mzZolqNJQm3eoLtqtUwLW/bklcDRERGQKDIlk0uVyOhg0bqrVfuHCh8PcvzyZ26dJFq9lEALh48aJaW8uWLUteqAFUrF0BHrWEZz4vh94QbCciIvPCoEgWr3Xr1mptR44cAVC22UQAOHz4sFbfZ4xkMhma9VIP0QBw58Q9ZCTr5nQZIiIyXgyKZPE6deqk1nbo0CHk5uYKziYKjRdy9+5d3Lmj/uKHtrORxqBF38aC7fnKfFz767bE1RARkdQYFMni9e/fX+30lISEBOzZs6dMs4mbNm1Sa/Py8kKbNm1KVachVG3mBfcqboJ9l/dz+ZmIyNwxKJLFq1SpEjp06KDWPnTo0FLPJmZnZyM4OFitfcCAARqPCDQ2MpkMzfs0Euy7ffQuslLFT7EhIiLTx6BIBGDixInFjpkzZ47W91u+fDliYmJK9T3GpplIUFTm5OHaIb79TERkzhgUiQAMHz4cXl5eov2dO3eGv7+/VveKjIzEF198odbeqVMnvPLKK6Ut0WBqtKwK10rCJ8mc33NV4mqIiEhKDIpEAOzs7DB37lzR/lmzZml1n4SEBPTr10/w2L6vv/661PUZkpWVTPSlltvH7nLzbSIiM8agSPT/FAoF2rZtK9j31VdfCS4lv+jChQvw8fHBzZs31frGjBmDjh076qROQ2j1elPB9vw8Ff437Uc8fvxY4oqIiEgKDIpE/8/Kygq//vor3N3d1foOHz6MunXrYvLkydi/fz+ioqKQlJSEu3fvYtu2bRg2bBjatGmDiIgItWsbNGiAn3/+WYofQW886rsj31Ep2Hf3SDSqV6+OiRMnIisrS+LKiIhIn2wMXQCRMalTpw62bduG/v37q4WezMxMLF++HMuXL9f6fp6entizZw/c3IS3mDEFmZmZ6Nu3L3JiZOhQrotav7d9NTjBBcHBwbh58yZCQ0Mhl8sNUCkREekaZxSJXtKtWzccOnRIcGaxJGrXro3jx4+jQYMGOqrMMAIDAxEWFoYb6VdExzRyag4ACAsLQ2BgoFSlERGRnjEoEgno2LEjLl++jAEDBpT4WplMhoCAAJw/fx5169bVQ3XSiYmJQUhICADgmTIBsdmPBMc1dnoFwPP9IUNCQvjMIhGRmWBQJBJRtWpV7NmzB8eOHcOIESPg5OSkcXz58uUxefJkXLlyBUFBQSa93FwgJCQESuV/zybeSL8sOK6cbXlUs68BAFAqlYXhkoiITBufUSQqhq+vL3x9faFUKnHx4kVcv34diYmJSE9Ph6urKzw8PNCiRQs0atTIpE5d0UZ4eHiRzzfTL6OTe09Yy6zVxjZxboUH2fcBAMeOHZOiPCIi0jMGRSIt2djYoE2bNiZ1VnNZJScnF/mcmZ+ByIxbqOekvq9ifcfGOJy4D9mqLKSkpEhVIhER6RGXnolIlNDy+dW084Jjbaxs0cDp+X6Lrq6ueq2LiIikwaBIRKJ8fX3V2u5n3UWaUnjGsKlzSwCAn5+fXusiIiJpMCgSkSiFQgEbm6JPqKiQj2vpFwXHV7avCi95VSgUCgmqIyIifWNQJCJR3t7egqHvWtoF0WuGtBoJLy8vfZZFREQSYVAkIo0WLVoEf3//Im3PlIl4kHVPcLzjUzdkJGdKURoREekZgyIRaSSXyxEaGoqAgIAiy9AXU08Ljs/NUuLs9ktSlUdERHrEoEhExZLL5QgKCkJUVBTmz5+Pnj17wqOZG3KtcwTHH994Fvn5KomrJCIiXeM+ikSkNW9vb8yaNavw84FFR3Dwp6Nq457eS8Sd45Fo4FdHyvKIiEjHOKNIRKXmM6IVrKyFT6M5vu6MxNUQEZGuMSgSUam5VXZF014NBfuu/30b8fcSJK6IiIh0iUGRiMqk42jhIw1VKuBoyCmJqyEiIl1iUCSiMqnToSa8GlYS7Duz/SLSkzIkroiIiHSFQZGIykQmk8F/vI9gX26WEic3nZO4IiIi0hUGRSIqs5YDmsLV01mwL3zdGSizlRJXREREusCgSERlZmNnjY5j2wr2pcan4fyeqxJXREREusCgSEQ68eqoNrCT2wr2HQ4+wQ24iYhMEIMiEemEYzk52g59RbAv7u5TXNl/Q9qCiIiozBgUiUhnOinaQ2YlvAH3oZ+PQaXirCIRkSlhUCQinfGoUR6v9G8i2Bdz4wluHL4jcUVERFQWDIpEpFPdpviK9h36JZyzikREJoRBkYh0yquBJ5r0aCDYF3X+Ie6evC9tQUREVGoMikSkc92nis8qHvzpKGcViYhMBIMiEelc9RZVUN+vtmDf3VNRuHPinsQVERFRaTAoEpFedJ/qJ9q3//vDnFUkIjIBDIpEpBd12tdA3Q41BfuiLjziG9BERCaAQZGI9Kb3B51F+0K/P8LTWoiIjByDIhHpTa021dGwc13BvpjrsTythYjIyDEoEpFeaZpVPPDjEeQp86UrhoiISoRBkYj0qlozbzTr3VCw70nEU5zZflHagoiISGsMikSkd70CO0MmfAQ0Dvx4BNnpOZLWQ0RE2mFQJCK982rgiZavNxPsS4lLw5GVJyWuiIiItMGgSESS6PNBF1jbWQv2HVlLine truncated
"text/plain": [
"<Figure size 600x1200 with 1 Axes>"
]
@@ -1220,13 +1233,13 @@
},
{
"cell_type": "code",
"execution_count": 28,
"execution_count": 27,
"id": "d8b29d01",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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 truncated
"image/png": "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 truncated
"text/plain": [
"<Figure size 780x1200 with 2 Axes>"
]
@@ -1316,7 +1329,7 @@
},
{
"cell_type": "code",
"execution_count": 29,
"execution_count": 28,
"id": "23a55aa1",
"metadata": {},
"outputs": [
@@ -1333,7 +1346,7 @@
},
{
"data": {
"image/png": "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 truncated
"image/png": "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 truncated
"text/plain": [
"<Figure size 780x1200 with 2 Axes>"
]
+675
View File
@@ -0,0 +1,675 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "0e5a26dc",
"metadata": {
"execution": {
"iopub.execute_input": "2026-09-28T10:01:56.916372Z",
"iopub.status.busy": "2026-09-28T10:01:56.916287Z",
"iopub.status.idle": "2026-09-28T10:01:57.192257Z",
"shell.execute_reply": "2026-09-28T10:01:57.191949Z"
}
},
"outputs": [],
"source": [
"import os\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt, colormaps\n",
"import tifffile"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "7b1d6105",
"metadata": {
"execution": {
"iopub.execute_input": "2026-09-28T10:01:57.193312Z",
"iopub.status.busy": "2026-09-28T10:01:57.193168Z",
"iopub.status.idle": "2026-09-28T10:01:57.359007Z",
"shell.execute_reply": "2026-09-28T10:01:57.358776Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"(30, 755, 755)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"obj = tifffile.imread(\"./obj_phase_roi_Niter120.tiff\")\n",
"obj.shape"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "298c10f5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Pixel size: 0.24413245033112582 Angstrom\n"
]
}
],
"source": [
"ROI_LENGTH_A = 0.36 * 512\n",
"PIXEL_SIZE_A = ROI_LENGTH_A / obj.shape[-1]\n",
"print(f\"Pixel size: {PIXEL_SIZE_A} Angstrom\")\n",
"LAYER_DISTANCE_A = 10"
]
},
{
"cell_type": "markdown",
"id": "6131af01",
"metadata": {},
"source": [
"## Task 1 — estimate and remove the global column tilt\n",
"\n",
"Successive $z$ slices are registered with sub-pixel phase correlation after removing the slowly varying background and tapering the image edges. The cumulative registration shifts are fitted by a straight line; its slope is the global correction vector per slice. The physical column drift is the negative of that vector.\n",
"\n",
"The TIFF does not contain a physical $z$ spacing, so the result below is reported in lateral pixels per slice. The in-plane azimuth uses image coordinates: $+x$ is right, $+y$ is down, and angles increase clockwise."
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "633a13a8",
"metadata": {
"execution": {
"iopub.execute_input": "2026-09-28T10:01:57.359991Z",
"iopub.status.busy": "2026-09-28T10:01:57.359908Z",
"iopub.status.idle": "2026-09-28T10:02:00.049288Z",
"shell.execute_reply": "2026-09-28T10:02:00.048880Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Alignment correction (dy, dx): [0.19235818 0.05482759] pixels/slice = [4.69608743 1.33851936] mrad\n",
"Column drift (dy, dx): [-0.19235818 -0.05482759] pixels/slice = [-4.69608743 -1.33851936] mrad\n",
"Drift magnitude: 0.2000 pixels/slice\n",
"Directed azimuth: 254.09° from +x\n",
"Undirected tilt axis: 74.09° from +x\n",
"Drift over the full stack: [-5.57838727 -1.59000007] pixels = [-1.36186535 -0.38817061] Angstrom\n",
"Overlap crop (y, x): (slice(3, 752, None), slice(1, 754, None))\n",
"fixed_image.shape: (749, 753)\n",
"Saved: fixed_cropped_projection.tiff\n"
]
}
],
"source": [
"from scipy.ndimage import gaussian_filter, shift as ndi_shift\n",
"from scipy.signal.windows import tukey\n",
"from skimage.registration import phase_cross_correlation\n",
"\n",
"\n",
"def estimate_global_tilt(volume, upsample_factor=20, highpass_sigma=6.0):\n",
" \"\"\"Return the global alignment shift (dy, dx) per z slice.\"\"\"\n",
" stack = np.asarray(volume, dtype=np.float32)\n",
" if stack.ndim != 3 or stack.shape[0] < 2:\n",
" raise ValueError(\"volume must have shape (z, y, x) with at least two slices\")\n",
"\n",
" # Keep atom-scale contrast and suppress edge discontinuities before FFT\n",
" # registration. Registering neighbours avoids lattice-period ambiguity.\n",
" highpass = stack - gaussian_filter(\n",
" stack, sigma=(0, highpass_sigma, highpass_sigma)\n",
" )\n",
" edge_window = np.outer(\n",
" tukey(stack.shape[1], alpha=0.2),\n",
" tukey(stack.shape[2], alpha=0.2),\n",
" ).astype(np.float32)\n",
" registration_stack = highpass * edge_window[None, :, :]\n",
"\n",
" step_shifts = np.array(\n",
" [\n",
" phase_cross_correlation(\n",
" registration_stack[z - 1],\n",
" registration_stack[z],\n",
" upsample_factor=upsample_factor,\n",
" normalization=None,\n",
" )[0]\n",
" for z in range(1, stack.shape[0])\n",
" ]\n",
" )\n",
"\n",
" cumulative_shifts = np.vstack(\n",
" (np.zeros(2), np.cumsum(step_shifts, axis=0))\n",
" )\n",
" z_coordinates = np.arange(stack.shape[0], dtype=float)\n",
" alignment_per_slice = np.array(\n",
" [\n",
" np.polyfit(z_coordinates, cumulative_shifts[:, component], 1)[0]\n",
" for component in range(2)\n",
" ]\n",
" )\n",
" fitted_shifts = (\n",
" z_coordinates - z_coordinates.mean()\n",
" )[:, None] * alignment_per_slice\n",
" return alignment_per_slice, fitted_shifts, step_shifts, cumulative_shifts\n",
"\n",
"\n",
"def align_and_crop(volume, fitted_shifts):\n",
" \"\"\"Apply (dy, dx) shifts and crop to the overlap shared by all slices.\"\"\"\n",
" stack = np.asarray(volume, dtype=np.float32)\n",
" aligned = np.stack(\n",
" [\n",
" ndi_shift(\n",
" stack[z],\n",
" shift=tuple(fitted_shifts[z]),\n",
" order=3,\n",
" mode=\"constant\",\n",
" cval=0.0,\n",
" prefilter=True,\n",
" )\n",
" for z in range(stack.shape[0])\n",
" ]\n",
" )\n",
"\n",
" dy, dx = fitted_shifts.T\n",
" y0 = max(0, int(np.ceil(dy.max())))\n",
" y1 = min(stack.shape[1], stack.shape[1] + int(np.floor(dy.min())))\n",
" x0 = max(0, int(np.ceil(dx.max())))\n",
" x1 = min(stack.shape[2], stack.shape[2] + int(np.floor(dx.min())))\n",
" if y1 <= y0 or x1 <= x0:\n",
" raise ValueError(\"estimated shifts leave no common image area\")\n",
" return aligned[:, y0:y1, x0:x1], (slice(y0, y1), slice(x0, x1))\n",
"\n",
"\n",
"alignment_dy_dx, fitted_shifts, step_shifts, cumulative_shifts = \\\n",
" estimate_global_tilt(obj)\n",
"fixed_stack, overlap_crop = align_and_crop(obj, fitted_shifts)\n",
"fixed_image = fixed_stack.sum(axis=0)\n",
"\n",
"# A shift aligns the current slice to the preceding slice, so the actual\n",
"# movement of a column as z increases has the opposite sign.\n",
"tilt_dy_dx = -alignment_dy_dx\n",
"tilt_magnitude = np.hypot(*tilt_dy_dx)\n",
"tilt_azimuth = np.degrees(np.arctan2(tilt_dy_dx[0], tilt_dy_dx[1])) % 360\n",
"tilt_axis = tilt_azimuth % 180\n",
"total_tilt_dy_dx = tilt_dy_dx * (obj.shape[0] - 1)\n",
"\n",
"print(f\"Alignment correction (dy, dx): {alignment_dy_dx} pixels/slice = {alignment_dy_dx * PIXEL_SIZE_A / LAYER_DISTANCE_A * 1000} mrad\")\n",
"print(f\"Column drift (dy, dx): {tilt_dy_dx} pixels/slice = {tilt_dy_dx * PIXEL_SIZE_A / LAYER_DISTANCE_A * 1000} mrad\")\n",
"print(f\"Drift magnitude: {tilt_magnitude:.4f} pixels/slice\")\n",
"print(f\"Directed azimuth: {tilt_azimuth:.2f}° from +x\")\n",
"print(f\"Undirected tilt axis: {tilt_axis:.2f}° from +x\")\n",
"print(f\"Drift over the full stack: {total_tilt_dy_dx} pixels = {total_tilt_dy_dx * PIXEL_SIZE_A} Angstrom\")\n",
"print(f\"Overlap crop (y, x): {overlap_crop}\")\n",
"print(f\"fixed_image.shape: {fixed_image.shape}\")\n",
"\n",
"# Return a reusable image variable and an on-disk float32 TIFF.\n",
"fixed_image_path = \"fixed_cropped_projection.tiff\"\n",
"tifffile.imwrite(fixed_image_path, fixed_stack.astype(np.float32))\n",
"print(f\"Saved: {fixed_image_path}\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "1e9c2b93",
"metadata": {
"execution": {
"iopub.execute_input": "2026-09-28T10:02:00.050342Z",
"iopub.status.busy": "2026-09-28T10:02:00.050194Z",
"iopub.status.idle": "2026-09-28T10:02:00.339494Z",
"shell.execute_reply": "2026-09-28T10:02:00.339168Z"
}
},
"outputs": [
{
"data": {
"image/png": "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vFOx2WxKQ0ODEggExL0KCgqUrKwspbi4WLn33nuVgwcPKseOHVMmJyeVvLw8paCgQPn1r3+t7N+/X/nOd76jmEwm5aabbnrd57311lsVAMpHPvIR5fHHH1f+/Oc/Kz/96U+VW2+9VZzz/e9/XwGgXHfddcozzzyjPPDAA0pxcbHicDiUnp4ecd6NN96oGAwGpbCwUPnBD36gHDhwQNm7d6+iKIoCQMnJyVHq6uqUhx56SHn++eeVtrY2pb29XXE4HEptba3ywAMPKH/+85+Vm2++WdFqtcptt90mru3xeJSamhrFZrMpd9xxh7J3717liSeeUL7yla8ozz//vBIIBJQ9e/YoAJTPfOYzop/7+vrixpU6wRt9LqPRqFRVVSl33nmnsn//fuVb3/qWotFoztJnVKhQoeLvBT6fT3E4HMr69esVRVGUu+++WwGg/Pa3vxXnNDU1KZ/5zGcUAMqePXuUI0eOKENDQ6+5nl7oun3w4EGx9n/sYx9Tnn76aWX37t2Ky+U6Z3vD4bCyY8cORa/XK//2b/+mPPvss8rTTz+t3HLLLcrDDz+sKIrylsjN12rX7373O0Wj0Sgf+tCHlF27dil/+tOflKuuukrR6XTK/v37xbVPnTql2O12pbCwULnrrruUAwcOKL///e+Vj3/844rH41FmZmaEjPnFL35xli154403KgUFBeJ6b/S5cnNzlerqauWBBx5Q9u7dq1xzzTUKAOXw4cOvOy+Ki4uVj3/843HHzjUPaMuutNNjsZhyxRVXKMnJycrQ0JCiKIpy7733KgCUu+++W5x3oX25f/9+RafTKe95z3uUXbt2KY8//riyfv16JT8//yy+4vVwLo6D/bVq1Srl4YcfVp599lll48aNisFgUL71rW8pW7ZsUXbt2qU8+eSTSnl5uZKRkSH0N0VRlMcff1z51re+pTz55JPK4cOHlUceeUTZvn27kpaWFseRNDc3K2azWamrq1MeeeQR5emnn1auuOIKpbCw8Cz943vf+56i0WiUT3/608ru3buVXbt2KZs3b1ZsNpvS3t4e1/5IJKLY7XblX//1X99QX6j420El0FWoeIdgampKAaBce+21Z30XiUSUcDgsPrFYTHy3Urh0dnYqAJQvfOELcdd49dVXFQDKLbfcIo5t375dAaD88Y9/jDv3n/7pnxStVqsMDw+fs63RaFQJh8PKHXfcoaSkpMS150IIdEVRlJqamnOedyEEuqIoypVXXhmnrLwebrzxRsVms511XCbQFUVRjh8/ftb9VahQoULFOw+UHSs/JpNJ+eUvfxl37sMPP6wAUJ544om445QJ8vnnkickKH784x/HHX/00UcVAMpvfvMbcaygoEDR6XRKd3d33LmLine truncated
"text/plain": [
"<Figure size 1500x500 with 3 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Registration diagnostic and before/after comparison.\n",
"z_coordinates = np.arange(obj.shape[0])\n",
"fitted_path = (\n",
" z_coordinates[:, None] * alignment_dy_dx\n",
" + (cumulative_shifts - z_coordinates[:, None] * alignment_dy_dx).mean(axis=0)\n",
")\n",
"\n",
"fig, axes = plt.subplots(1, 3, figsize=(15, 5), constrained_layout=True)\n",
"axes[0].plot(z_coordinates, cumulative_shifts[:, 1], \"o\", ms=3, label=\"measured dx\")\n",
"axes[0].plot(z_coordinates, cumulative_shifts[:, 0], \"o\", ms=3, label=\"measured dy\")\n",
"axes[0].plot(z_coordinates, fitted_path[:, 1], \"-\", lw=1.5, label=\"linear dx fit\")\n",
"axes[0].plot(z_coordinates, fitted_path[:, 0], \"-\", lw=1.5, label=\"linear dy fit\")\n",
"axes[0].set(xlabel=\"z slice\", ylabel=\"alignment shift (pixels)\", title=\"Global tilt fit\")\n",
"axes[0].legend(fontsize=8)\n",
"axes[0].grid(alpha=0.2)\n",
"\n",
"original_cropped = obj[(slice(None),) + overlap_crop].sum(axis=0)\n",
"display_limits = np.percentile(\n",
" np.concatenate((original_cropped.ravel(), fixed_image.ravel())), (1, 99.8)\n",
")\n",
"for ax, image, title in zip(\n",
" axes[1:],\n",
" (original_cropped, fixed_image),\n",
" (\"Before correction\", \"After correction (fixed_image)\"),\n",
"):\n",
" ax.imshow(image, cmap=\"gray\", vmin=display_limits[0], vmax=display_limits[1])\n",
" ax.set_title(title)\n",
" ax.set_axis_off()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "1463886a",
"metadata": {},
"source": [
"## Per-layer reciprocal-lattice domain coloring\n",
"\n",
"This ports the calibrated Si $[110]$ reciprocal-grid method from `grain-boundaries.ipynb` to the tilt-corrected stack. The fit uses the summed stack for a high-SNR reference, greedily removes reflections belonging to each fitted orientation, and stops when the residual grid has fewer than 12 matched reflections or less than 15% of the dominant score.\n",
"\n",
"The source notebook's calibration, $92\\,\\mathrm{Å}/379$ pixels, is retained. Each accepted orientation gets a rotated ideal-grid mask. Reciprocal-space pixels shared by multiple masks are removed because they do not distinguish the grains; real-space atoms supported by more than one orientation still receive an additive mixture of the corresponding colors."
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "b825da5d",
"metadata": {
"execution": {
"iopub.execute_input": "2026-09-28T10:02:00.341856Z",
"iopub.status.busy": "2026-09-28T10:02:00.341761Z",
"iopub.status.idle": "2026-09-28T10:02:12.009745Z",
"shell.execute_reply": "2026-09-28T10:02:12.009493Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fitted reciprocal scale correction: 0.9950\n",
"Orientation 1: 72.50°, score= 407.07 (1.000 of dominant), matched reflections=36\n",
"Orientation 2: 2.00°, score= 165.96 (0.408 of dominant), matched reflections=20\n",
"Orientation 3: 143.50°, score= 136.48 (0.335 of dominant), matched reflections=14\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABN4AAAJjCAYAAADTddy3AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzsvXecJVWZ8P89lW++nfN0z/REJjLADEMOS4aXIAprIqqo+C7qqqhIUBRF3QVxWfWngu+CLCsmMKEgIEoamGGGSUzs6enu6Zxuqnx+f/R0S0+ABgm61PfzuZ+ZPnXq1FOnzr311FNPEFJKSURERERERERERERERERERERERMTrivJWCxAREREREREREREREREREREREfG/kcjwFhERERERERERERERERERERER8QYQGd4iIiIiIiIiIiIiIiIiIiIiIiLeACLDW0RERERERERERERERERERERExBtAZHiLiIiIiIiIiIiIiIiIiIiIiIh4A4gMbxEREREREREREREREREREREREW8AkeEtIiIiIiIiIiIiIiIiIiIiIiLiDSAyvEVERERERERERERERERERERERLwBRIa3iIiIiIiIiIiIiIiIiIiIiIiIN4DI8PZ3yp133okQgmefffYV+1588cW0tLS8ofJcf/31CCGm1PfBBx/k5JNPpr6+HtM0qa+v57jjjuOrX/3qpH4tLS1cfPHFLztWW1sbQoiJz3333TexLZfL8elPf5qTTz6ZqqoqhBBcf/31+x3nz3/+M5dffjmHHHIIpmkihKCtre2Ax73tttuYO3cupmkyffp0brjhBjzPm9TnlltumSRbf3//y57L68Gjjz6KEIJHH330Ffu+nuuira2NM844g/LycoQQXHXVVRPX5s4775zo98QTT3D99dczPDy8zxi33377pL6vJy937cfp6uri+uuv5/nnn39DZIgY49Ws0anwRq6bl9LS0sKZZ575mvY97rjjJv0WvPSzbt064K/zsr/P+eefz8UXX3zA7S/9vNJvZkRERMRbyVNPPcU73/lO6urqMAyD2tpazj//fJ588slXNc6r0TtfK8Vikeuvv/5vul+9nG7xZpzD3xOv9/3/zR7/reZ/2/lN5Tnv743jjjuOBQsWvNViRPwvRXurBYj438V3vvMdPvzhD/OOd7yDb3/725SXl7Nr1y6eeOIJ7rvvPq6++uqJvj//+c9Jp9NTGveaa67hjDPOYPbs2RNtAwMDfO9732Px4sWcc845fP/73z/g/g8//DAPPfQQBx98MOl0+mVval/+8pf5whe+wNVXX83JJ5/MypUrueaaa+js7OR73/veRL8LL7yQww8/nO9///v84Ac/mNJ5/K0sXbqUJ598koMOOuhNOd44H//4x3n66af54Q9/SG1tLXV1ddTW1vLkk0/S2to60e+JJ57ghhtu4OKLLyabzU4a4/bbb6eysvItuwl3dXVxww030NLSwpIlS94SGSJePW/1upkqM2bM4O67796n/aXfD4CvfOUrHH/88ZPaKioqUBSFK664YqJt1apVfPSjH92nf1VV1esseURERMTrw2233cZVV13FsmXLuPnmm2lubqa9vZ3/+I//4KijjuLWW2/lyiuvnNJYl19+OaeeeuobKm+xWOSGG24Axh64Xwsvp1u8GefwduKt0oHfLP63n19ExNudyPAW8bpy0003ccwxx0zyTAN43/veRxiGk9oOPvjgKY/b2trK4YcfPqmtubmZoaGhCW+zlzO8feELX+C6664D4Bvf+MYBDW8DAwPceOONfOADH+ArX/kKMKaMeZ7HNddcw1VXXTVxQ6ytraW2tpbf/e53Uz6P14rneQghSKfT+8zDm8G6detYtmwZ55xzzqT2t0KWiIi/R2Kx2JS+D7NmzTpgv5ca6WzbfsX+EREREX8v/OUvf+Gqq67i9NNP5+c//zma9tdHjAsvvJBzzz2Xf/mXf+Hggw/myCOPPOA4xWKReDxOY2MjjY2Nb4bobxj/G87h74m3SgfeH+N6+UvX+d/K631+Ukps2yYWi71uY0ZERLx2olDTfzDuvPNO5syZg2mazJs3j//3//7ffvu5rsuNN944ES5ZVVXFJZdcQl9f36R+9957LyeffDJ1dXXEYjHmzZvH1VdfTaFQeE3yDQwMUFdXt99tijJ5uf2tLsjjoVdTYe9jH4jf/e532LbNJZdcMqn9kksuQUrJL37xi1cr5gRSSr7yla/Q3NyMZVkceuih/OEPf+C4446b9KZ13NX8v/7rv/jkJz9JQ0MDpmmydevWA7qhT3Vd/Od//ieLFy8mmUySSqWYO3cun/vc5w4o8/jxtm7dym9/+9uJOW9ra9sn1PT666/nU5/6FADTp0+f6Pvoo4/S0tLC+vXreeyxxybaXxoGOzo6yr/+678yffp0DMOgoaGBq666ap91ODo6ygc+8AEqKipIJpOceuqpbN68+RXn/tFHH+Wwww4Dxq7luAwvDU+9//77WbFiBfF4nFQqxUknnTSl0JgwDLnxxhuZM2cOsViMbDbLokWLuPXWWyf6HCjsd39hKEIIrrzySu64446JMQ899FCeeuoppJR8/etfZ/r06SSTSU444QS2bt06af9xN/knn3ySI444glgsRktLC3fccQcAv/71r1m6dCnxeJyFCxfu13C8ZcsW3v3ud1NdXT2xpv7jP/5jn36bNm3i1FNPJR6PU1lZyRVXXEEul3vFORtn+/btXHjhhRNh6TU1NZx44okTITsvt25s2+aTn/wkS5YsIZPJUF5ezooVK/jlL3+5z3HCMOS2225jyZIlE9fo8MMP5/77739Z+W6//XY0TZsw2kdERERE7J+bbroJIQT/+Z//uY8xQtM0br/9doQQk9KOjN8DV61axfnnn09ZWdnEC4gDhWnee++9rFixgkQiQTKZ5JRTTmH16tWT+lx88cUkk0m2bt3K6aefTjKZpKmpiU9+8pM4jgOMpdAY9yC+4YYb9gnn37p1K5dccgmzZs0iHo/T0NDAWWedxQsvvDBxnFfSLfZ3DmEYcvPNN0/o59XV1bz//e+no6NjUr/xe/nKlSs5+uijicfjzJgxg69+9av7vMg+EFN5FvjqV7+Koig88MAD+8xhPB6fdL6bNm3in//5n6mpqcE0TaZNm8b73//+iTndH3vruC8df2+96JV01L114PGUL3vrQQCf+cxnMAxjUhqYhx56iBNPPJF0Ok08HufII4/k4YcfPqDsex93f3r5qxn3leZvfzr++Fpev349J554IolEgqqqKq688kqKxeKk8cf1x+985zvMmzcP0zT50Y9+BIyl3DnxxBNJpVLE43GOOOIIfv3rX+8jY2dnJx/84AdpamrCMAzq6+s5//zz6enpAV6d7jVV/la99w9/+ANnn302jY2NWJbFzJkz+dCHPrRPCqC+vr6Jcxv/Phx55JE89NBDLyvfz3/+c+LxOJdffjm+7wPwk5/8hOXLl5PJZCa+m5deeulrnoOItweRx9s/EHfeeSeXXHIJZ599Nt/85jcZGRnh+uuvx3GcSYalMAw5++yzefzxx/n0pz/NEUccwc6dO7nuuus47rjjePbZZyfefmzZsoXTTz+dq666ikQiwaZNm/ja177GM888wx//+MdXLeOKFSv46U9/yvXXX8+5557LggULUFX1dZuDN5rxfEwLFy6c1F5XV0dlZeXE9tfC5z//eW666SY++MEPct5557Fr1y4uv/xyPM+bFEI7zmc/+1lWrFjBd77zHRRFobq6mu7u7n36TXVd/Pd//zcf+chH+NjHPsY3vvENFEVh69atbNiw4YAyj7u9n3vuubS2tvKNb3xjYj527949qe/ll1/O4OAgt912Gz/72c8mDLAHHXQQP//5zzn//PPJZDLcfvvtAJimCYy93T722GPp6Ojgc5/7HIsWLWL9+vVce+21vPDCCzz00EMIIZBScs455/DEE09w7bXXcthhh/GXv/yF00477RXnfunSpdxxxx1ccsklE2HLwMSb6B//+Me85z3v4eSTT+aee+7BcRxuvvlmjjvuOB5++GGOOuqoA4598803c/3113PNNddwzDHH4HkemzZt2m+eu6nyq1/9itWrV/PVr34VIQSf+cxnOOOMM7jooovYvn073/72txkZGeETn/gE73jHO3j++ecnKffd3d1ccsklfPrTn6axsZHbbruNSy+9lF27dnHffffxuc99jkwmwxe/+EXOOecctm/fTn19PQAbNmzgiCOOYNq0aXzzm9+ktraWBx98kP/7f/8v/f39E0aonp4ejj32WHRd5/bbb6empoa77757ymFEAKeffjpBEHDzzTczbdo0+vv7eeKJJybm7uXWjeM4DA4O8q//+q80NDTgui4PPfQQ5513HnfccQfvf//7J45z8cUXc9ddd3HZZZfxxS9+EcMwWLVq1QHzPEop+dSnPsW3vvUtvv/970/5BcG4QjaOoij7GP3DMNyn3+v5xjwiIiLizSYIAh555BEOPfTQA3p4NTU1ccghh/DHP/6RIAgm6YbnnXceF154IVdcccXLvvj9yle+wjXXXDNxL3ddl69//escffTRPPPMM5NC9DzP4//8n//DZZddxic/+Un+9Kc/8aUvfYlMJsO1115LXV0dv/vd7zj11FO57LLLuPzyy4G/hvN3dXVRUVHBV7/6VaqqqhgcHORHP/oRy5cvZ/Xq1cyZM+cVdYv98eEPf5jvfe97XHnllZx55pm0tbXxhS98gUcffZRVq1ZRWVk50be7u5v3vOc9fPKTn+S6667j5z//OZ/97Gepr6+fdI/bH1N9FvjMZz7D448/zkUXXcTq1atpbm7mjjvu4Ec/+hHf//73J/ThNWvWcNRRR1FZWckXv/hFZs2axe7du7n//vtxXXfi3vxaeS066nvf+14+85nPcOedd3LjjTdOtAdBwF133cVZZ501MZ933XUX73//+zn77LPLine truncated
"text/plain": [
"<Figure size 1300x600 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from scipy.ndimage import maximum_filter\n",
"\n",
"\n",
"# Calibration and fit controls inherited from grain-boundaries.ipynb.\n",
"pixel_size_A = PIXEL_SIZE_A\n",
"d_004_A = 1.358\n",
"a_si_A = 4 * d_004_A\n",
"match_tolerance_px = 6\n",
"mask_radius_px = 8\n",
"minimum_matched_reflections = 12\n",
"minimum_relative_score = 0.15\n",
"\n",
"coloring_volume = np.asarray(fixed_stack, dtype=np.float32)\n",
"fit_image = coloring_volume[-1]\n",
"height, width = fit_image.shape\n",
"centre_y, centre_x = (np.asarray(fit_image.shape) - 1) / 2\n",
"yy, xx = np.ogrid[:height, :width]\n",
"\n",
"fit_fft = np.fft.fftshift(np.fft.fft2(fit_image))\n",
"fit_spectrum = np.log1p(np.abs(fit_fft))\n",
"radius_px = np.hypot(xx - centre_x, yy - centre_y)\n",
"\n",
"# Detect the strongest non-central local FFT maxima.\n",
"local_maximum = maximum_filter(fit_spectrum, size=7, mode=\"wrap\")\n",
"candidate_pixels = np.argwhere((fit_spectrum == local_maximum) & (radius_px > 8))\n",
"candidate_strength = fit_spectrum[candidate_pixels[:, 0], candidate_pixels[:, 1]]\n",
"strongest = np.argsort(candidate_strength)[-min(600, len(candidate_pixels)):]\n",
"candidate_pixels = candidate_pixels[strongest]\n",
"candidate_strength = candidate_strength[strongest]\n",
"\n",
"# Allowed diamond-cubic Si [110] reciprocal points. Coordinates are physical\n",
"# reciprocal units (1/Å) along [1 -1 0] and [001].\n",
"grid_hkls, grid_reciprocal_xy = [], []\n",
"for h in range(-12, 13):\n",
" for l in range(-12, 13):\n",
" if h == 0 and l == 0:\n",
" continue\n",
" all_odd = (h % 2 != 0) and (l % 2 != 0)\n",
" diamond_even = (h % 2 == 0) and (l % 2 == 0) and (l % 4 == 0)\n",
" if all_odd or diamond_even:\n",
" grid_hkls.append((h, -h, l))\n",
" grid_reciprocal_xy.append((np.sqrt(2) * h / a_si_A, l / a_si_A))\n",
"grid_hkls = np.asarray(grid_hkls)\n",
"grid_reciprocal_xy = np.asarray(grid_reciprocal_xy)\n",
"\n",
"\n",
"def projected_si110_grid(angle_deg, scale_factor):\n",
" \"\"\"Return in-frame (hkl, [y, x]) sites for a rotated ideal grid.\"\"\"\n",
" angle = np.deg2rad(angle_deg)\n",
" rotation = np.array(\n",
" [[np.cos(angle), -np.sin(angle)],\n",
" [np.sin(angle), np.cos(angle)]]\n",
" )\n",
" reciprocal_xy = scale_factor * grid_reciprocal_xy @ rotation.T\n",
" pixels = np.column_stack(\n",
" (\n",
" centre_y + reciprocal_xy[:, 1] * height * pixel_size_A,\n",
" centre_x + reciprocal_xy[:, 0] * width * pixel_size_A,\n",
" )\n",
" )\n",
" valid = (\n",
" (pixels[:, 0] >= 7) & (pixels[:, 0] < height - 7)\n",
" & (pixels[:, 1] >= 7) & (pixels[:, 1] < width - 7)\n",
" )\n",
" return grid_hkls[valid], pixels[valid]\n",
"\n",
"\n",
"def reciprocal_grid_score(angle_deg, scale_factor, pixels, strengths):\n",
" \"\"\"Score observed maxima near the specified ideal reciprocal grid.\"\"\"\n",
" _, targets = projected_si110_grid(angle_deg, scale_factor)\n",
" distance2 = ((targets[:, None, :] - pixels[None, :, :]) ** 2).sum(axis=2)\n",
" nearest = np.argmin(distance2, axis=1)\n",
" nearest_distance2 = distance2[np.arange(len(targets)), nearest]\n",
" matches = nearest_distance2 <= match_tolerance_px ** 2\n",
" score = np.sum(\n",
" strengths[nearest[matches]]\n",
" * (1 - nearest_distance2[matches] / match_tolerance_px ** 2)\n",
" )\n",
" return float(score), int(matches.sum())\n",
"\n",
"\n",
"# Fit the dominant detector rotation and a small scale correction.\n",
"dominant_score, dominant_angle, best_scale, dominant_match_count = -np.inf, None, None, 0\n",
"for scale in np.linspace(0.90, 1.10, 11):\n",
" for angle in np.arange(0, 180, 1):\n",
" score, match_count = reciprocal_grid_score(\n",
" angle, scale, candidate_pixels, candidate_strength\n",
" )\n",
" if score > dominant_score:\n",
" dominant_score, dominant_angle, best_scale, dominant_match_count = (\n",
" score, angle, scale, match_count\n",
" )\n",
"for scale in np.linspace(best_scale - 0.015, best_scale + 0.015, 13):\n",
" for angle in np.linspace(dominant_angle - 1, dominant_angle + 1, 41):\n",
" score, match_count = reciprocal_grid_score(\n",
" angle, scale, candidate_pixels, candidate_strength\n",
" )\n",
" if score > dominant_score:\n",
" dominant_score, dominant_angle, best_scale, dominant_match_count = (\n",
" score, angle, scale, match_count\n",
" )\n",
"\n",
"# Repeatedly rotate the calibrated grid against residual FFT maxima.\n",
"remaining_pixels = candidate_pixels.copy()\n",
"remaining_strength = candidate_strength.copy()\n",
"orientation_fits = []\n",
"for orientation_index in range(8):\n",
" best_residual = (-np.inf, None, 0)\n",
" for angle in np.arange(0, 180, 0.25):\n",
" score, match_count = reciprocal_grid_score(\n",
" angle, best_scale, remaining_pixels, remaining_strength\n",
" )\n",
" if score > best_residual[0]:\n",
" best_residual = (score, angle, match_count)\n",
"\n",
" score, angle, match_count = best_residual\n",
" if (\n",
" match_count < minimum_matched_reflections\n",
" or score < minimum_relative_score * dominant_score\n",
" ):\n",
" break\n",
" hkls, grid_pixels = projected_si110_grid(angle, best_scale)\n",
" orientation_fits.append(\n",
" {\n",
" \"angle_deg\": float(angle),\n",
" \"score\": float(score),\n",
" \"relative_score\": float(score / dominant_score),\n",
" \"matched_reflections\": int(match_count),\n",
" \"hkls\": hkls,\n",
" \"grid_pixels\": grid_pixels,\n",
" }\n",
" )\n",
"\n",
" # Exclude all residual candidates close to this orientation's full grid.\n",
" distance2 = (\n",
" (remaining_pixels[:, None, :] - grid_pixels[None, :, :]) ** 2\n",
" ).sum(axis=2)\n",
" keep = distance2.min(axis=1) > (2 * match_tolerance_px) ** 2\n",
" remaining_pixels = remaining_pixels[keep]\n",
" remaining_strength = remaining_strength[keep]\n",
"\n",
"if len(orientation_fits) < 2:\n",
" raise RuntimeError(\"Fewer than two statistically supported lattice orientations were found.\")\n",
"\n",
"\n",
"def reciprocal_disk_mask(points_yx, radius):\n",
" \"\"\"Draw circular masks locally, avoiding a full-frame temporary per spot.\"\"\"\n",
" mask = np.zeros((height, width), dtype=bool)\n",
" integer_radius = int(np.ceil(radius))\n",
" for y, x in points_yx:\n",
" y0 = max(0, int(np.floor(y)) - integer_radius)\n",
" y1 = min(height, int(np.floor(y)) + integer_radius + 2)\n",
" x0 = max(0, int(np.floor(x)) - integer_radius)\n",
" x1 = min(width, int(np.floor(x)) + integer_radius + 2)\n",
" patch_y, patch_x = np.ogrid[y0:y1, x0:x1]\n",
" mask[y0:y1, x0:x1] |= (\n",
" (patch_y - y) ** 2 + (patch_x - x) ** 2 <= radius ** 2\n",
" )\n",
" return mask\n",
"\n",
"\n",
"orientation_masks = np.stack(\n",
" [\n",
" reciprocal_disk_mask(fit[\"grid_pixels\"], mask_radius_px)\n",
" for fit in orientation_fits\n",
" ]\n",
")\n",
"\n",
"# Reflections common to multiple grids carry no orientation information.\n",
"shared_reciprocal_pixels = orientation_masks.sum(axis=0) > 1\n",
"orientation_masks &= ~shared_reciprocal_pixels[None, :, :]\n",
"\n",
"grain_colors = np.array(\n",
" [\n",
" [0.10, 0.45, 1.00], # dominant: blue\n",
" [1.00, 0.12, 0.05], # second: red\n",
" [0.15, 1.00, 0.20], # third: green\n",
" [1.00, 0.25, 0.90], # extra orientations, if statistically supported\n",
" [1.00, 0.75, 0.05],\n",
" [0.10, 1.00, 0.95],\n",
" [0.75, 0.35, 1.00],\n",
" [0.65, 1.00, 0.10],\n",
" ],\n",
" dtype=np.float32,\n",
")[:len(orientation_fits)]\n",
"\n",
"print(f\"Fitted reciprocal scale correction: {best_scale:.4f}\")\n",
"for index, fit in enumerate(orientation_fits, start=1):\n",
" print(\n",
" f\"Orientation {index}: {fit['angle_deg']:6.2f}°, \"\n",
" f\"score={fit['score']:7.2f} \"\n",
" f\"({fit['relative_score']:.3f} of dominant), \"\n",
" f\"matched reflections={fit['matched_reflections']}\"\n",
" )\n",
"\n",
"# Show the measured spectrum, fitted grids, and orientation-exclusive masks.\n",
"fig, axes = plt.subplots(1, 2, figsize=(13, 6), constrained_layout=True)\n",
"axes[0].imshow(\n",
" fit_spectrum,\n",
" cmap=\"magma\",\n",
" vmin=np.percentile(fit_spectrum, 5),\n",
" vmax=np.percentile(fit_spectrum, 99.9),\n",
")\n",
"axes[0].plot(candidate_pixels[:, 1], candidate_pixels[:, 0], \"w.\", ms=1, alpha=0.2)\n",
"for fit, color in zip(orientation_fits, grain_colors):\n",
" grid_pixels = fit[\"grid_pixels\"]\n",
" axes[0].plot(\n",
" grid_pixels[:, 1], grid_pixels[:, 0], \"+\", color=color, ms=4, mew=0.8,\n",
" label=f\"{fit['angle_deg']:.2f}°\",\n",
" )\n",
"axes[0].set_title(\"Ideal Si [110] grids fitted to summed-stack FFT\")\n",
"axes[0].legend(loc=\"upper right\", fontsize=8)\n",
"\n",
"mask_rgb = np.zeros((height, width, 3), dtype=np.float32)\n",
"for mask, color in zip(orientation_masks, grain_colors):\n",
" mask_rgb += mask[..., None] * color\n",
"axes[1].imshow(np.clip(mask_rgb, 0, 1))\n",
"axes[1].set_title(\"Orientation-exclusive reciprocal masks\")\n",
"for axis in axes:\n",
" axis.set_axis_off()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "47070371",
"metadata": {
"execution": {
"iopub.execute_input": "2026-09-28T10:02:12.012144Z",
"iopub.status.busy": "2026-09-28T10:02:12.012061Z",
"iopub.status.idle": "2026-09-28T10:02:15.084841Z",
"shell.execute_reply": "2026-09-28T10:02:15.084581Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Saved (30, 749, 753, 3) RGB stack to /home/swim/sandbox/silicon-grain-boundaries/colored_grains_by_layer.tiff\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAEFEAAAhWCAYAAAAqk/AiAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAuIwAALiMBeKU/dgABAABJREFUeJzs3XmcHUW9Pv6nqvucM2v2nUAS9kR2CBBANoGwCF4IXL8qAgoICIKCV1EREOWC1+V3ZRG4IKC4IfsOgomyBAgJYRMSCAnZEybJ7HO27qrfH9Xdp/ucPjNnlmQmk+f9egVmerqrq7fqqk9XVwuttQYRERERERERERERERERERERERERERERERERERERERER0VZO9ncGiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIj6AgdRICIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIqJBgYMoEBEREREREREREREREREREREREREREREREREREREREdGgwEEUiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiGhQ4CAKRERERERERERERERERERERERERERERERERERERERERDQocBAFIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIhoUOIgCEREREREREREREREREREREREREREREREREREREREREQ0KHESBiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiAYFDqJARERERERERERERERERERERERERERERERERERERERERIMCB1EgIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiokGBgygQERERERERERERERERERERERERERERERERERERERER0aDAQRSIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIaFDgIApERERERERERERERERERERERERERERERERERERERERENChwEAUiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiGhQ4iAIRERERERERERERERERERERERERERERERERERERERERDQocRIGIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIBgUOokBEREREREREREREREREREREREREREREREREREREREREgwIHUSAiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiKiQYGDKBARERERERERERERERERERERERERERERERERERERERHRoMBBFIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIhoUOAgCkREREREREREREREREREREREREREREREREREREREREQ0KHAQBSIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIaFDiIAhERERERERERERERERERERERERERERERERERERERERENChxEgYiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIgGBQ6iQERERERERERERERERERERERERERERERERERERERERESDAgdRICIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIqJBgYMoEBEREREREREREREREREREREREREREREREREREREREdGgwEEUiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiGhQ4CAKRERERERERERERERERERERERERERERERERERERERERDQocBAFIqIB6Mgjj4QQIvh35JFH9neWqJsmT54cOYbnnHPOZl/nP//5z8g6hRD45z//udnXS0RERERERAMb4wxbP8YZiIiIiIiIqK8wTrD1Y5yAiIiIiIiIBgrGGbZ+jDMQERHRYGb3dwaIiHpKa40PP/wQS5YswcqVK9Ha2opsNov6+noMHz4cI0aMwB577IHJkyf3d1aJiGgQUEph4cKFeO+99/Dpp58im82irq4OU6ZMwf7774+JEyf2dxaJiIiIqBcYZyAiov6yatUqvPPOO/jkk0/Q0tICpRTq6uowYcIE7LTTTpg2bRpSqVR/Z5OIiIhom8I4ARERbQtaW1vx73//Gx999BEaGxvR2tqK2tpaDB8+HNtttx2mT5+OoUOH9nc2iYiIiLZ6jDMQEREREfUPDqJARFuV9vZ2PPjgg3j44Yfxr3/9C83NzV0uM2rUKBx00EGYNWsWZs2ahSFDhmyBnBIR0WCxevVq/PKXv8R9992HjRs3lp1v3333xcUXX4xzzjkHlmVtwRwSERERUU8xzkBERP1l7dq1uPPOO/HnP/8Zixcv7nTeZDKJffbZB8cddxxOO+007Lvvvlsol0RERETbFsYJiIhoS3JdFx988AHmz58f/Hv77beRyWQi811zzTW49tpr+2Sdzc3NePbZZzFnzhzMmTMHH374YafzCyGwxx574KyzzsLXv/51jBgxok/yQURERLQtYJyBiIi2pC0ZZ7j22mvxk5/8pFdpdEZrvdnSJqJtDwdRIKKtQnt7O37+85/jlltuQWNjY7eW3bBhA5566ik89dRTuPjii3H66afjmmuuwU477bSZcktERIPFHXfcge9+97toa2vrct6FCxfivPPOw80334z7778fu+222xbIIRERERH1BOMMRETUX3K5HK6//nr88pe/REdHR8XLzJs3D/PmzcOrr76KF154YTPnkoiIiGjbwjgBERFtCY7j4C9/+QsWLFiA+fPnY+HChRXHBnrr8ccfx5133om///3vyOVyFS+ntca7776L//qv/8I111yDn/3sZ7jssssgpdyMuSUiIiLaujHOQEREW0J/xhmIiLYmjGQS0YD3/PPPY9ddd8VPf/rTbgcSiqXTadx3332YOnUqLr300pIRtYiIiHzf/e53ceGFF1Y0gELY22+/jQMPPBCvvfbaZsoZEREREfUG4wxERNRfVq1ahYMPPhjXXXcdOy8QERERDRCMExAR0ZbS1taGs846C7/5zW/wyiuvbNHYwK9//Ws8+eST3RpAoVhHRwcuv/xyHHfccWhvb+/D3BERERENHowzEBHRltKfcYbNacaMGf2dBSIaZOz+zgARUWduvPFG/PCHP4TWOvbvw4cPx+c+9zlMmzYNo0ePxujRo6G1RlNTE5YtW4b58+fj1VdfRTqdjiyXz+dx88034/LLL8fkyZO3wJYQEdHW5Be/+AV+9atflUyvra3Fl770Jey1114YNWoUVq5ciZdeeglPPfVU5F7V0tKCE088EQsWLMCUKVO2ZNaJiIiIqBOMMxARUX9ZtmwZDj/8cKxatarkb8OHD8fxxx+PvffeG2PGjEFdXR2am5uxevVqvPPOO3j55Zfx6aef9kOuiYiIiAY3xgmIiGhbN2zYMBx66KE44IADMGbMGIwaNQodHR1YtmwZZs+ejZdffrlkmX/84x845ZRT8PTTTyOVSvVDromIiIgGJsYZiIhoWzFu3DjsvffevU7n7bffLpl23nnn9TpdIqIwDqJARAPWVVddheuvvz72bzNnzsRVV12FGTNmwLKsTtPp6OjAE088gZtvvhmvvPLK5sgqERENIm+++SZ++MMflkz/whe+gHvuuQfDhw+PTP/e976H999/H6eeeio+/PDDYHpjYyO+/OUvY+7cuRBCbPZ8ExEREVHnGGcgIqL+0tjYiJkzZ5YMoDB27FjceOONOPPMM2Hb5R/Zaa3xxhtv4A9/+APWrVu3ubNLREREtE1gnICIiAaS8ePHY//994dSCk8//fRmXdfQoUPxxS9+Eeeccw4OOuggSClj5/vJT36Ct956C+eddx4WLFgQ+dvs2bNxww034Nprr92seSUiIiLaWjDOQEREA8nmjjNceOGFuPDCC3uVxmuvvYYZM2ZEptXV1eGLX/xir9IlIioWH/0kIupnd911V2wgYfz48Zg9ezaeffZZHHbYYV0GEgCgpqYGX/ziF/Hyyy/jH//4B/bYY4/NkWUiIhokvvWtb8FxnMi0M844Aw8//HDJAAq+adOmYe7cudh5550j01977TXce++9myurRERERFQhxhmIiKg/nXfeefjoo48i0w4++GAsWrQI55xzTqcDKACAEAIHHnggbrnlFjzwwAObM6tERERE2wTGCYiIqD+NHj0axx9/PK666io8+uijWLVqFdasWYMnnngCZ5xxxmZb7/jx4/Gb3/wGa9euxR133IEZM2aUHUDBt88++2Du3Lk4/vjjS/7285//vGTASCIiIqJtEeMMRETUn/orztBbd911V8m0//f//h9qa2v7ITdENJhxEAUiGnA++OADfOtb3yqZvttuu2Hu3Lk46qijepz20UcfjQULFuC73/1ub7JIRESD1OzZszF37tzItLFjx+L222/vsvPAyJEjcffdd5fM99///d9QSvV5XomIiIioMowzEBFRf3rkkUfw8MMPR6bts88+eO655zBs2LBupyeE6KOcEREREW2bGCcgIqL+Ul9fj08++QSffvopnnnmGfz0pz/FF77wBWy33Xabfd1XXnklli5diksvvRTV1dXdWjaZTOKBBx7A+PHjI9MzmQwHeyQiIqJtHuMMRETUX/ozztBb7e3tuP/++0umn3feef2QGyIa7DiIAhENOBdeeCEymUxk2ogRIzB79mxMnjy51+knk0n84he/wJ///Gckk8lep0dERIPHbbfdVjLte9/7HkaMGFHR8p/97Gdx4oknRqYtWbIEzz//fJ/kj4iIiIi6j3EGIiLqL0opfO9734tMs20bd999N4YMGdJPuSIiIiLatjFOQERE/cWyLEyaNKlf1n388cejqqqqx8vX1dXFvrz35JNP9iZbRERERFs9xhmIiKi/9Gecobfuv/9+tLW1RabtscceOOigg/opR0Q0mNn9nQEiorCnn34aL774Ysn03/72t5gwYUKfrutLX/pSj5ft6OjA66+/jjVr1qChoQGZTAajR4/Line truncated
"text/plain": [
"<Figure size 4200x2100 with 8 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from scipy import fft as scipy_fft\n",
"\n",
"\n",
"# Reconstruct every accepted orientation independently in every z layer.\n",
"# scipy.fft keeps float32 input as complex64, limiting peak memory usage.\n",
"orientation_amplitudes = np.empty(\n",
" (len(orientation_fits), *coloring_volume.shape), dtype=np.float32\n",
")\n",
"for layer_index, layer in enumerate(coloring_volume):\n",
" layer_fft = scipy_fft.fftshift(scipy_fft.fft2(layer))\n",
" for orientation_index, mask in enumerate(orientation_masks):\n",
" filtered = scipy_fft.ifft2(scipy_fft.ifftshift(layer_fft * mask))\n",
" orientation_amplitudes[orientation_index, layer_index] = np.abs(filtered)\n",
"\n",
"# A global robust scale per orientation preserves brightness consistency in z.\n",
"for orientation_index in range(len(orientation_fits)):\n",
" amplitude = orientation_amplitudes[orientation_index]\n",
" low, high = np.percentile(amplitude, (2, 99.7))\n",
" if high <= low:\n",
" orientation_amplitudes[orientation_index].fill(0)\n",
" else:\n",
" orientation_amplitudes[orientation_index] = np.clip(\n",
" (amplitude - low) / (high - low), 0, 1\n",
" )\n",
"\n",
"# The original signal provides continuous atom support and suppresses Fourier\n",
"# ringing. Orientation contributions remain additive, so boundary atoms mix.\n",
"atom_support = np.empty_like(coloring_volume)\n",
"for layer_index, layer in enumerate(coloring_volume):\n",
" low, high = np.percentile(layer, (5, 99.5))\n",
" if high <= low:\n",
" atom_support[layer_index].fill(0)\n",
" else:\n",
" atom_support[layer_index] = np.clip((layer - low) / (high - low), 0, 1) ** 1.5\n",
"\n",
"colored_grain_float = np.zeros((*coloring_volume.shape, 3), dtype=np.float32)\n",
"for amplitude, color in zip(orientation_amplitudes, grain_colors):\n",
" colored_grain_float += amplitude[..., None] * color\n",
"colored_grain_float = np.clip(colored_grain_float, 0, 1)\n",
"colored_grain_float *= atom_support[..., None]\n",
"colored_grain_stack = np.round(255 * colored_grain_float).astype(np.uint8)\n",
"\n",
"colored_grain_path = os.path.abspath(\"colored_grains_by_layer.tiff\")\n",
"tifffile.imwrite(\n",
" colored_grain_path,\n",
" colored_grain_stack,\n",
" photometric=\"rgb\",\n",
" metadata={\"axes\": \"ZYXS\"},\n",
")\n",
"print(f\"Saved {colored_grain_stack.shape} RGB stack to {colored_grain_path}\")\n",
"\n",
"# Preview representative layers and a maximum-color projection.\n",
"preview_layers = np.unique(\n",
" np.linspace(0, coloring_volume.shape[0] - 1, 6).round().astype(int)\n",
")\n",
"fig, axes = plt.subplots(2, 4, figsize=(14, 7), constrained_layout=True, dpi=300)\n",
"for axis, layer_index in zip(axes.flat, preview_layers):\n",
" axis.imshow(colored_grain_stack[layer_index])\n",
" axis.set_title(f\"Colored layer z={layer_index}\")\n",
" axis.set_axis_off()\n",
"\n",
"axes.flat[-2].imshow(colored_grain_stack.max(axis=0))\n",
"axes.flat[-2].set_title(\"RGB maximum projection\")\n",
"axes.flat[-2].set_axis_off()\n",
"axes.flat[-1].imshow(\n",
" fit_image,\n",
" cmap=\"gray\",\n",
" vmin=np.percentile(fit_image, 2),\n",
" vmax=np.percentile(fit_image, 99.7),\n",
")\n",
"axes.flat[-1].set_title(\"Corrected summed projection\")\n",
"axes.flat[-1].set_axis_off()\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "lemon",
"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.12.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -0,0 +1,634 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "a7e52d53",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt, colormaps\n",
"import tifffile"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "74171f8c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['f_410_1_obj_phase_roi_Niter100.tiff',\n",
" 'f_410_2_obj_phase_roi_Niter100.tiff',\n",
" 'f_410_3_obj_phase_roi_Niter100.tiff',\n",
" 'f_410_4_obj_phase_roi_Niter100.tiff',\n",
" 'f_420_1_obj_phase_roi_Niter120.tiff',\n",
" 'f_420_2_obj_phase_roi_Niter120.tiff',\n",
" 'f_420_3_obj_phase_roi_Niter120.tiff',\n",
" 'f_420_4_obj_phase_roi_Niter120.tiff',\n",
" 'f_430_1_obj_phase_roi_Niter80.tiff',\n",
" 'f_430_2_obj_phase_roi_Niter80.tiff',\n",
" 'f_430_3_obj_phase_roi_Niter80.tiff',\n",
" 'f_430_4_obj_phase_roi_Niter80.tiff',\n",
" 'f_450_1_obj_phase_roi_Niter90.tiff',\n",
" 'f_450_2_obj_phase_roi_Niter90.tiff',\n",
" 'f_450_3_obj_phase_roi_Niter90.tiff',\n",
" 'f_450_4_obj_phase_roi_Niter90.tiff',\n",
" 'f_471_1_obj_phase_roi_Niter50.tiff',\n",
" 'f_471_2_obj_phase_roi_Niter50.tiff',\n",
" 'f_471_3_obj_phase_roi_Niter50.tiff',\n",
" 'f_471_4_obj_phase_roi_Niter50.tiff',\n",
" 'f_471_5_obj_phase_roi_Niter230.tiff',\n",
" 'f_471_6_obj_phase_roi_Niter230.tiff',\n",
" 'f_471_7_obj_phase_roi_Niter230.tiff',\n",
" 'f_472_1_obj_phase_roi_Niter50.tiff',\n",
" 'f_472_2_obj_phase_roi_Niter50.tiff',\n",
" 'f_472_3_obj_phase_roi_Niter50.tiff',\n",
" 'f_472_4_obj_phase_roi_Niter50.tiff']"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"basedir = \"/home/swim/shared/Si_project/260707_BCAT_tif_file\"\n",
"os.listdir(basedir)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "80e55aa7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Shape : (30, 379, 379)\n",
"Dtype : uint8\n",
"H × W : 30 × 379\n",
"Pixel Size : 3.07 A/px\n"
]
}
],
"source": [
"tiff = 'f_430_2_obj_phase_roi_Niter80.tiff'\n",
"image = tifffile.imread(os.path.join(basedir, tiff))\n",
"\n",
"roi_A = 92\n",
"A_per_px = roi_A / image.shape[0] # A/pixel\n",
"Si_distance_px = 1.358 / A_per_px\n",
"\n",
"\n",
"print(f\"Shape : {image.shape}\")\n",
"print(f\"Dtype : {image.dtype}\")\n",
"print(f\"H × W : {image.shape[0]} × {image.shape[1]}\")\n",
"print(f\"Pixel Size : {A_per_px:.2f} A/px\")\n",
"\n",
"# fig, ax = plt.subplots(figsize=(7, 7))\n",
"# ax.imshow(image[image.shape[0] // 2], cmap='gray')\n",
"# ax.set_title(f\"Raw Image ({image.shape[0]} × {image.shape[1]} px)\")\n",
"# ax.axis('on') # 픽셀 좌표 눈금 표시\n",
"# plt.tight_layout()\n",
"# plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "b6ac9727",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(np.float64(-0.5), np.float64(378.5), np.float64(378.5), np.float64(-0.5))"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 600x300 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, axs = plt.subplots(1, 2, figsize=(6, 3))\n",
"ax1, ax2 = axs\n",
"\n",
"layer = image[3]\n",
"\n",
"ax1.imshow(layer)\n",
"ax1.axis('off')\n",
"\n",
"ax2.imshow(np.log1p(abs(np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(layer))))))\n",
"ax2.axis('off')"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "si110-grid-fit",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABiUAAAGbCAYAAACrnJPxAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzsnXeYHVX9/1/Tbt9esimkQAi9Sgu9hRqKCIIiTaQIIigoRSBUhVgBQZAvGmmCgqCoSBPQH80gSu+QQEKy2exm660zc35/zH6Gc3c3ySZS9byeZ59kZ+fOnDlz5py570+zlFIKg8FgMBgMBoPBYDAYDAaDwWAwGAyGDxn7426AwWAwGAwGg8FgMBgMBoPBYDAYDIb/DYxRwmAwGAwGg8FgMBgMBoPBYDAYDAbDR4IxShgMBoPBYDAYDAaDwWAwGAwGg8Fg+EgwRgmDwWAwGAwGg8FgMBgMBoPBYDAYDB8JxihhMBgMBoPBYDAYDAaDwWAwGAwGg+EjwRglDAaDwWAwGAwGg8FgMBgMBoPBYDB8JBijhMFgMBgMBoPBYDAYDAaDwWAwGAyGjwRjlDAYDAaDwWAwGAwGg8FgMBgMBoPB8JFgjBIGg8FgMBgMBoPBYDAYDAaDwWAwGD4SjFHCYDAYDIZPGHPmzMGyrBF/zjjjDObNm4dlWcyZMyf+zOOPP84FF1xAd3f3sONdc801Vft+kFiWxQUXXLDCfUZq7/K44IILsCzrg2nccpD+nTdv3kr3feqpp/jsZz/LxIkTSSaTjBkzhunTp3P66adX7bfzzjuz8847r/R4+r38wQ9+UPW3c889l5kzZzJ+/Hgsy+Loo48e8RgvvvgiJ510EtOnTyebzWJZFo888shyz3nbbbex6aabkkqlGDduHKeddhr9/f1V+9x9991VbXv66adXei3/KZ+0cWEwGAwGg8FgMBgMho8GY5QwGAwGg+ETyi9/+UueeOKJqp+vf/3rjB07lieeeIJ999033vfxxx/nwgsv/MiNEqNhpPZ+GvjTn/7EtttuS29vL7Nnz+b+++/niiuuYLvttuP222+v2veaa67hmmuuGdVxjz32WJ544gkOP/zwqu0//vGP6ezsZP/99yeRSCz3808//TR33303jY2N7Lbbbis81y233MIXvvAFttxyS+69915mzZrFnDlzOOigg6r222mnnXjiiSc499xzR3UNHwSf1nFhMBgMBoPBYDAYDIb/DPfjboDBYDAYDIaR2XDDDdliiy1G/Ns222zzEbdm9Ukmk5+q9gqzZ89mypQp3Hfffbju+69Mhx12GLNnz67ad/311x/1cSdMmDBif/T19WHbkb/ITTfdtNzPH3HEERx11FEA3HHHHdxzzz0j7hcEAd/61rfYY489uP766wHYZZddqKmp4fDDD+fee+9l7733BqChoYFtttmGV155ZdTXsboEQYDv+5/acWEwGAwGg8FgMBgMhv8MEylhMBgMBsOnjKFpby644AK+9a1vATBlypQ4Bc8jjzzC5MmTefHFF3n00Ufj7ZMnT46P1dvbyxlnnMGUKVNIJBKMHz+e0047jYGBgapz9vb2ctxxx9HU1EQul2OvvfbitddeW632Cn/605/YdNNNSSaTTJkyZVg6I0EpxTXXXMOmm25KOp2moaGBgw8+mLfeeqtqvwceeIADDjiACRMmkEqlmDp1KieccAJLly4dVTuH0tnZSXNzc5VBQhDjgTDa9E0rYugx/9P9nnzySRYtWsQxxxxTtf2QQw4hl8tx1113rXIbda6//nqmTZtGMplk/fXX59Zbb+Xoo4+uGl9y72fPns0ll1zClClTSCaTPPzww//xuDAYDAaDwWAwGAwGw6cTEylhMBgMBsMnFPEo1xlJIP/KV75CV1cXV111Fb/73e8YO3YsEHnv33XXXRx88MHU1dXF6YWSySQA+XyenXbaiQULFnDOOeew8cYb8+KLL3L++efz/PPP8+CDD2JZFkopDjzwQB5//HHOP/98ttxySx577LHYy351eOihhzjggAOYPn06t912G0EQMHv2bNrb24fte8IJJzBnzhy+/vWvc/nll9PV1cVFF13Etttuy7PPPsuYMWMAePPNN5k+fTpf+cpXqKurY968efzoRz9i++235/nnn8fzvFVq4/Tp0/m///s/vv71r3P44Yez+eabr/IxPk5eeOEFADbeeOOq7Z7nse6668Z/Xx1+/vOfc8IJJ/C5z32OH//4x/T09HDhhRdSKpVG3P/KK69k2rRp/OAHP6C2tpa11157xP1WZVwYDAaDwWAwGAwGg+HTiTFKGAwGg8HwCWWk1DaVSmXYtgkTJjBx4kQANttssypP9c0224x0Ok1tbe2w41155ZU899xzPPXUU3GaqN12243x48dz8MEH85e//IW9996b++67j4cffpgrrriCr3/96wDMmDGDRCLBd77zndW6tu985zuMGTOGBx54gFQqBcCee+5Z1XaIvP2vv/56fvjDH/LNb34z3r7DDjswbdo0fvSjH3H55ZcDcOKJJ8Z/V0qx7bbbsvPOOzNp0iTuvfde9t9//1Vq42WXXcYrr7zCVVddxVVXXYXneWy55Zbst99+fO1rXyOXy63WtX9UdHZ2AtDY2Djsb42NjaMq9D0SYRgya9Ystt56a+644454+/bbb8/UqVMZN27csM+kUinuu+++KqPOSOcf7bgwGAwGg8FgMBgMBsOnF5O+yWAwGAyGTyg33ngjc+fOrfoZKVJidfnjH//IhhtuyKabborv+/HPnnvuGad/Anj44YcBhhVm/uIXv7ha5x0YGGDu3LkcdNBBsfAMUFNTw3777TesjZZl8aUvfamqjW1tbWyyySZxGwGWLFnCiSeeyBprrIHruniex6RJkwB4+eWXV7mdTU1N/P3vf2fu3LlcdtllHHDAAbz22mucffbZbLTRRqudFuqjxrKsVdq+Ml599VUWL17M5z//+artEydOZLvtthvxM/vvv/9Ko0xWZVwYDAaDwWAwGAwGg+HTi4mUMBgMBoPhE8p666233ELXHwTt7e288cYbyxWLRXTv7OzEdV2ampqq/t7W1rZa5122bBlhGI74+aHb2tvbUUrFKZqGsuaaawKR9/4ee+zBe++9x3nnncdGG21ENpslDEO22WYbCoXCarUVYIsttojvQ6VS4cwzz+THP/4xs2fPHlbw+pOE3K/Ozs5h/dfV1TViBMVokAiMke7JmDFjePvtt4dtl5RiK2JVxoXBYDAYDAaDwWAwGD69GKOEwWAwGAz/ozQ3N5NOp/nFL36x3L9DJG77vk9nZ2eVYWLx4sWrdd6GhgYsyxrx80O3NTc3Y1kWf//73+NaGDqy7YUXXuDZZ59lzpw5HHXUUfHf33jjjdVq4/LwPI9Zs2bx4x//+D+qyfBRsNFGGwHw/PPPs/7668fbfd/nlVde4Qtf+MJqHVfGwEh1HpY3JkYTlbEq48JgMBgMBoPBYDAYDJ9eTPomg8FgMBj+CxBxfqSIgGQyOeL2mTNn8uabb9LU1BRHA+g/ksd/l112AeCWW26p+vytt966Wm3NZrNstdVW/O53v6NYLMbb+/r6uOeee4a1USnFwoULR2yjCO8ieg81XFx33XWr1UaARYsWjbhdUkGNVDvhk8TWW2/N2LFjmTNnTtX2O+64g/7+fg466KDVOu4666xDW1sbv/nNb6q2v/POOzz++OOr29xVGhcGg8FgMBgMBoPBYPj0YiIlDAaDwWD4L0DE+SuuuIKjjjoKz/NYZ511qKmpYaONNuK2227j9ttvZ8011ySVSrHRRhtx2mmnceedd7LjjjvyjW98g4033pgwDHnnnXe4//77Of3009l6663ZY4892HHHHfn2t7/NwMAAW2yxBY899hg33XTTarf34osvZq+99mLGjBmcfvrpBEHA5ZdfTjabpaurK95vu+224/jjj+eYY47h6aefZscddySbzbJo0SL+3//7f2y00UZ89atfZd1112WttdbirLPOQilFY2Mj99xzDw888MBqt3HPPfdkwoQJ7Lfffqy77rqEYci///1vfvjDH5LL5Tj11FNX+9gj8eijj9LR0QFAEATMnz8/LiS900470dLSAkA+n+fPf/4zEBUCl88uXbqUbDbL3nvvDYDjOMyePZsjjjiCE044gS984Qu8/vrrfPvb32bGjBnstddeq9VO27a58MILOeGEEzj44IP58pe/THd3NxdeeCFjx47Ftlff52W048JgMBgMBoPBYDAYDJ9ejFHCYDAYDIb/AnbeeWfOPvtsfvWrX3H99dcThiEPP/wwO++8MxdeeCGLFi3iuOOOo6+vj0mTJjFv3jyy2Sx///vfueyyy/j5z3/O22+/TTqdZuLEiey+++5xpIRt2/zhD3/gm9/8JrNnz6ZcLrPddtvx5z//mXXXXXe12jtjxgzuvvtuzj33XA499FDa2to46aSTKBQKXHjhhVX7XnfddWyzzTZcd911XHPNNYRhyLhx49huu+3YaqutgCit0j333MOpp57KCSecgOu67L777jz44INMnDhxtdp47rnn8vvf/54f//jHLFq0iFKpxNixY9l99905++yzWW+99VbruMtj1qxZPProo/HvjzzySFWx8Z133hmICnofcsghVZ+94IILAOJ7K3zpS1/CcRwuu+wy5syZQ2NjI0ceeSSXXnrpf9TW448/HsuymD17Np/97GeZPHkyZ511Fr///e955513Vvu4qzIuDAaDwWAwGAwGg8Hw6cRSSqmPuxEGg8FgMBgM/wtYlsV5553H+eefj+M4o6q18FGglCIIAm688UaOPfZY5s6du8pF1ru7u5k2bRoHHnggP//5zz+klhoMBoPBYDAYDAaD4dOOqSlhMBgMBoPB8BFy8cUX43keP/zhDz/upsT8/ve/x/M8jj322FHtv3jxYk455RR+97vf8eijj3LjjTeyyy670NfX94GntTIYDAaLine truncated
"text/plain": [
"<Figure size 1600x400 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Match the FFT to an ideal diamond-cubic Si [110] diffraction grid.\n",
"# For zone axis [110], h + k = 0. The supplied fcc/diamond extinction\n",
"# rules leave: (h, -h, l), with h and l both odd, or both even with l = 4n.\n",
"layer = image[3].astype(float)\n",
"height, width = layer.shape\n",
"A_per_px_xy = roi_A / height\n",
"d_004_A = 1.358 # given above; for Si, d_004 = a / 4\n",
"a_si_A = 4 * d_004_A\n",
"\n",
"fft_shifted = np.fft.fftshift(np.fft.fft2(layer))\n",
"spectrum = np.log1p(np.abs(fft_shifted))\n",
"centre_y, centre_x = (np.asarray(layer.shape) - 1) / 2\n",
"yy, xx = np.ogrid[:height, :width]\n",
"radius_px = np.hypot(xx - centre_x, yy - centre_y)\n",
"\n",
"# Detect candidate Bragg maxima once. Keep only the strongest candidates so\n",
"# the rotation/scale fit is driven by diffraction peaks rather than background.\n",
"neighbourhood = 3\n",
"local_maximum = spectrum.copy()\n",
"for dy in range(-neighbourhood, neighbourhood + 1):\n",
" for dx in range(-neighbourhood, neighbourhood + 1):\n",
" local_maximum = np.maximum(local_maximum, np.roll(np.roll(spectrum, dy, 0), dx, 1))\n",
"candidate_pixels = np.argwhere((spectrum == local_maximum) & (radius_px > 8))\n",
"candidate_strength = spectrum[candidate_pixels[:, 0], candidate_pixels[:, 1]]\n",
"strongest = np.argsort(candidate_strength)[-min(600, len(candidate_pixels)):]\n",
"candidate_pixels = candidate_pixels[strongest]\n",
"candidate_strength = candidate_strength[strongest]\n",
"\n",
"# Build all allowed reciprocal-lattice points in the [110] zone. Coordinates\n",
"# are expressed along [1 -1 0] (horizontal) and [001] (vertical).\n",
"grid_hkls, grid_xy = [], []\n",
"base_scale_px = width * A_per_px_xy / a_si_A # pixels per reciprocal 1/a\n",
"for h in range(-12, 13):\n",
" for l in range(-12, 13):\n",
" if h == 0 and l == 0:\n",
" continue\n",
" all_odd = (h % 2 != 0) and (l % 2 != 0)\n",
" diamond_even = (h % 2 == 0) and (l % 2 == 0) and (l % 4 == 0)\n",
" if all_odd or diamond_even:\n",
" grid_hkls.append((h, -h, l))\n",
" grid_xy.append((np.sqrt(2) * h * base_scale_px, l * base_scale_px))\n",
"grid_hkls = np.asarray(grid_hkls)\n",
"grid_xy = np.asarray(grid_xy)\n",
"\n",
"match_tolerance_px = 4.5\n",
"def projected_grid(angle_deg, scale_factor):\n",
" angle = np.deg2rad(angle_deg)\n",
" rotation = np.array([[np.cos(angle), -np.sin(angle)],\n",
" [np.sin(angle), np.cos(angle)]])\n",
" xy = scale_factor * grid_xy @ rotation.T\n",
" pixels = np.column_stack((centre_y + xy[:, 1], centre_x + xy[:, 0]))\n",
" valid = ((pixels[:, 0] >= 4) & (pixels[:, 0] < height - 4)\n",
" & (pixels[:, 1] >= 4) & (pixels[:, 1] < width - 4))\n",
" return grid_hkls[valid], pixels[valid]\n",
"\n",
"def grid_score(angle_deg, scale_factor):\n",
" _, targets = projected_grid(angle_deg, scale_factor)\n",
" distance2 = ((targets[:, None, :] - candidate_pixels[None, :, :]) ** 2).sum(axis=2)\n",
" nearest = np.argmin(distance2, axis=1)\n",
" # Gaussian distance weighting rewards agreement with many allowed spots.\n",
" return np.sum(candidate_strength[nearest] * np.exp(-distance2[np.arange(len(targets)), nearest]\n",
" / (2 * match_tolerance_px ** 2)))\n",
"\n",
"# Fit detector rotation and a small scale correction to the measured FFT.\n",
"best_score, best_angle, best_scale = -np.inf, None, None\n",
"for scale in np.linspace(0.94, 1.06, 7):\n",
" for angle in np.arange(0, 180, 2):\n",
" score = grid_score(angle, scale)\n",
" if score > best_score:\n",
" best_score, best_angle, best_scale = score, angle, scale\n",
"for scale in np.linspace(best_scale - 0.015, best_scale + 0.015, 7):\n",
" for angle in np.linspace(best_angle - 2, best_angle + 2, 17):\n",
" score = grid_score(angle, scale)\n",
" if score > best_score:\n",
" best_score, best_angle, best_scale = score, angle, scale\n",
"\n",
"# Retain only observed candidate peaks that are close to allowed, fitted-grid sites.\n",
"fitted_hkls, fitted_pixels = projected_grid(best_angle, best_scale)\n",
"distance2 = ((fitted_pixels[:, None, :] - candidate_pixels[None, :, :]) ** 2).sum(axis=2)\n",
"nearest = np.argmin(distance2, axis=1)\n",
"matched = []\n",
"used_candidates = set()\n",
"for hkl, distance, candidate_index in zip(fitted_hkls, distance2[np.arange(len(fitted_pixels)), nearest], nearest):\n",
" if distance <= match_tolerance_px ** 2 and int(candidate_index) not in used_candidates:\n",
" matched.append((hkl, candidate_pixels[candidate_index]))\n",
" used_candidates.add(int(candidate_index))\n",
"if not matched:\n",
" raise RuntimeError('The fitted Si [110] grid did not match any FFT candidates.')\n",
"\n",
"mask_radius_px = 6\n",
"si110_grid_mask = np.zeros(layer.shape, dtype=bool)\n",
"for _, (y, x) in matched:\n",
" si110_grid_mask |= (xx - x) ** 2 + (yy - y) ** 2 <= mask_radius_px ** 2\n",
"si110_grid_fft = fft_shifted * si110_grid_mask\n",
"si110_grid_image = np.fft.ifft2(np.fft.ifftshift(si110_grid_fft)).real\n",
"\n",
"fig, axes = plt.subplots(1, 4, figsize=(16, 4), constrained_layout=True)\n",
"axes[0].imshow(layer, cmap='gray'); axes[0].set_title('Input layer')\n",
"axes[1].imshow(spectrum, cmap='magma')\n",
"axes[1].set_title(f'Fitted ideal Si [110] grid\\nrotation={best_angle:.2f}°, scale={best_scale:.3f}')\n",
"axes[2].imshow(np.log1p(np.abs(si110_grid_fft)), cmap='magma', vmin=0, vmax=spectrum.max())\n",
"axes[2].set_title(f'Matched allowed peaks ({len(matched)})')\n",
"axes[3].imshow(si110_grid_image, cmap='gray'); axes[3].set_title('Grid-matched inverse FFT')\n",
"for hkl, pixel in zip(fitted_hkls, fitted_pixels):\n",
" axes[1].plot(pixel[1], pixel[0], 'w+', ms=4, mew=0.7, alpha=0.45)\n",
"for hkl, (y, x) in matched:\n",
" axes[1].plot(x, y, 'co', ms=6, mfc='none', mew=1.2)\n",
"for ax in axes:\n",
" ax.axis('off')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "e928013c",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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mRVt2XfffStSVknKqNNPP32Dv/f4448DfkRFOZ/61KfYeuutefTRRyu2t7S08KlPfapi2/bbb8+KFSsqjrntttuyww47VOx39NFHb+TM/0F9fT1PPfUUS5cu5dJLL+WQQw7hzTff5Dvf+Q4zZsygp6dnTMf5uJFolbFufy/eeOMNOjs7+exnP1uxvb29nd1222293zn44IPfM8okk8mwdOlSDj/8cKLRaLA9lUpx0EEHva+2ajQajUaj0Wg0Go1m86CNEhqNRqPRbGZuuukmli5dymOPPcapp57Ka6+9xlFHHRV83tvbC/wjhVI5bW1teJ5Hf3//Rn9jeHiY3XffnSVLlnDxxRfzxBNPsHTpUu68804Acrnce7azq6sLpRTNzc3Ytl3x99xzzwVCubS3paVl1DHWt21d9thjD+666y4cx+H4449n/PjxbLfddtx6660VbXnppZdGtSOVSqGUCtrS3d2NZVkb/d336l/5XKivrx+1XyQSqejD3t7e933+5ey0005861vf4ne/+x1r1qzhrLPOYvny5aOKXf+zIX20bt8B9PX1UVdX976OK8eTNGHlrG8brP+6rkt/fz+e522Wa6bRaDQajUaj0Wg0ms2Lrimh0Wg0Gs1mZuuttw6KW++55564rssvf/lLbr/9do488shA4O3o6Bj13TVr1mCaJrW1tRv9jccee4w1a9bwxBNPBNERAAMDA2NuZ0NDA4Zh8NRTTxGJREZ9LtukvZ2dnaP26ezsrChGvCEOOeQQDjnkEAqFAs899xyXXHIJRx99NJMmTWL27Nk0NDQQi8W47rrrNthWgMbGRlzXpbOzc4PidHn/jh8/vuKzNWvWVNSTGCv19fUbPP/3i23bLFy4kCuvvPID1WT4KJgxYwYA//d//xfUNAFwHIfXX3+9wui2Kci1Wl+dhw317ViiMmprazEMY7NfM41Go9FoNBqNRqPRfHB0pIRGo9FoNB8yixYtora2lvPOOw/P85g2bRrjxo3jlltuQSkV7JfJZLjjjjuYPXs28Xgc+IdhYN3IBxFm1zUm/M///M+o39/QMRYsWIBSinfffZeddtpp1J8I0bvssgvRaJSbb7654vvPPvtsRYqjsRCJRJgzZw6XXXYZAH/961+Dtrz99tvU19evty1i+Nh///0B+NnPfrbB39hrr70A+PWvf12xfenSpbz22mvMmzdvk9oMvnHplVde4cUXX6zYfsstt4zp++szQME/0my1tbVtcps+SmbNmkVrays33HBDxfbbb7+d4eFhDj/88Pd13GnTptHS0sJvf/vbiu0rV67k2Weffb/NJZFI8KlPfYo777yTfD4fbE+n09xzzz3v+7gajUaj0Wg0Go1Go/ng6EgJjUaLine truncated
"text/plain": [
"<Figure size 1600x400 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Second-dominant Si [110] grain. Run the preceding grid-fit cell first.\n",
"# Keep the first grain's calibrated grid scale fixed; search only its rotation.\n",
"# Remove every candidate close to the first orientation's full ideal grid.\n",
"first_grid_pixels = fitted_pixels\n",
"distance2_to_first = ((candidate_pixels[:, None, :] - first_grid_pixels[None, :, :]) ** 2).sum(axis=2)\n",
"keep_residual = distance2_to_first.min(axis=1) > (2 * match_tolerance_px) ** 2\n",
"second_candidate_pixels = candidate_pixels[keep_residual]\n",
"second_candidate_strength = candidate_strength[keep_residual]\n",
"if len(second_candidate_pixels) == 0:\n",
" raise RuntimeError('No FFT candidates remain after excluding the first grid.')\n",
"\n",
"second_scale = best_scale\n",
"def second_grid_score(angle_deg):\n",
" _, targets = projected_grid(angle_deg, second_scale)\n",
" distance2 = ((targets[:, None, :] - second_candidate_pixels[None, :, :]) ** 2).sum(axis=2)\n",
" nearest = np.argmin(distance2, axis=1)\n",
" nearest_distance2 = distance2[np.arange(len(targets)), nearest]\n",
" matches = nearest_distance2 <= match_tolerance_px ** 2\n",
" return np.sum(second_candidate_strength[nearest[matches]]\n",
" * (1 - nearest_distance2[matches] / match_tolerance_px ** 2))\n",
"\n",
"# Coarse-to-fine rotation-only fit of the strongest remaining Si [110] grid.\n",
"second_score, second_angle = -np.inf, None\n",
"for angle in np.arange(0, 180, 1):\n",
" score = second_grid_score(angle)\n",
" if score > second_score:\n",
" second_score, second_angle = score, angle\n",
"for angle in np.linspace(second_angle - 1, second_angle + 1, 41):\n",
" score = second_grid_score(angle)\n",
" if score > second_score:\n",
" second_score, second_angle = score, angle\n",
"\n",
"second_hkls, second_grid_pixels = projected_grid(second_angle, second_scale)\n",
"relative_rotation = (second_angle - best_angle + 90) % 180 - 90\n",
"distance2 = ((second_grid_pixels[:, None, :] - second_candidate_pixels[None, :, :]) ** 2).sum(axis=2)\n",
"nearest = np.argmin(distance2, axis=1)\n",
"second_matched, used_candidates = [], set()\n",
"for hkl, distance, candidate_index in zip(second_hkls, distance2[np.arange(len(second_grid_pixels)), nearest], nearest):\n",
" if distance <= match_tolerance_px ** 2 and int(candidate_index) not in used_candidates:\n",
" second_matched.append((hkl, second_candidate_pixels[candidate_index]))\n",
" used_candidates.add(int(candidate_index))\n",
"if not second_matched:\n",
" raise RuntimeError('No second Si [110] grid peaks matched the residual FFT.')\n",
"\n",
"# Pass every allowed peak in the fitted second-grain grid, including weak sites\n",
"# that were not strong enough to be used as orientation-matching candidates.\n",
"second_mask = np.zeros(layer.shape, dtype=bool)\n",
"for y, x in second_grid_pixels:\n",
" second_mask |= (xx - x) ** 2 + (yy - y) ** 2 <= mask_radius_px ** 2\n",
"second_fft = fft_shifted * second_mask\n",
"second_grain_image = np.fft.ifft2(np.fft.ifftshift(second_fft)).real\n",
"\n",
"fig, axes = plt.subplots(1, 4, figsize=(16, 4), constrained_layout=True)\n",
"axes[0].imshow(layer, cmap='gray'); axes[0].set_title('Input layer')\n",
"axes[1].imshow(spectrum, cmap='magma')\n",
"axes[1].set_title(f'Rotated second Si [110] grid\\nΔrotation={relative_rotation:.2f}°')\n",
"axes[2].imshow(np.log1p(np.abs(second_fft)), cmap='magma', vmin=0, vmax=spectrum.max())\n",
"axes[2].set_title(f'All allowed second-grid peaks ({len(second_grid_pixels)})')\n",
"axes[3].imshow(second_grain_image, cmap='gray'); axes[3].set_title('Second-grain inverse FFT')\n",
"for pixel in first_grid_pixels:\n",
" axes[1].plot(pixel[1], pixel[0], 'w+', ms=3, mew=0.5, alpha=0.18)\n",
"for pixel in second_grid_pixels:\n",
" axes[1].plot(pixel[1], pixel[0], 'y+', ms=4, mew=0.8, alpha=0.5)\n",
"for _, (y, x) in second_matched:\n",
" axes[1].plot(x, y, 'co', ms=6, mfc='none', mew=1.2)\n",
"for ax in axes:\n",
" ax.axis('off')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "52b69c9b",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABxMAAAHhCAYAAAClRpDpAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzsnWeYU9XWgN+UyUymN5hKHWlSRToiTaSLerFhAbtYUK9YsFHkimLv5do+L6hYsAAiFhBRuvQqbYABZmB6n0nZ34+dk0yYyUmmJaDnfZ48MMlOzjrn7LPXXmvttbZOCCHQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQOA19oAXQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NA4M9GCiRoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGjWiBRM1NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDRqRAsmamhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGho1IgWTNTQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0KgRLZiooaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaFRI1owUUNDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDo0a0YKKGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhkaNaMFEDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ2NGtGCiX9D1q5dyxVXXEFSUhImk4nExETGjx/PmjVravU7M2bMQKfT1UmGX3/9FZ1Ox6+//lqn7/vKoEGDGDRokE9tW7ZsyaRJkxpVHo26c/z4cWbMmMGWLVsCLUqtSU9PR6fT8fzzzwdaFA0NjQbio48+QqfT1fiaOnWq87n/6KOPGuyYb775ZoP+ni/4QzeuXr2aGTNmkJ+fX+ff+P7775kxY0aNn/3d9LvS9zZu3Oi17aRJk2jZsmXjC6WhofG3ZN26dVx22WU0b96c4OBgEhIS6Nu3Lw888ECgRWsQ/KkfdDqdRz3VUKjpQl/55JNPePnll2v8zB/n8HehNn4IDY2zgaq2T01+PCEE55xzDjqdrtH6vr/8Ktrz6zun69HG9tsdOHCA4ODgWvuv/U19/OUa/qe+fhaLxUJaWprH+dM/DS2Y+Dfjtddeo3///mRkZDB37lx+/vlnnn/+eY4dO8YFF1zA66+/7vNv3XLLLXUewLt3786aNWvo3r17nb6v8c/j+PHjzJw586wMJmpoaPx9+fDDD1mzZo3ba8qUKSQlJbFmzRpGjx7dYMcKRDDx66+/5oknnmjUY6xevZqZM2fWO5g4c+bMGj/zxzloaGho/N1YsmQJ/fr1o7CwkLlz5/Ljjz/yyiuv0L9/fxYsWBBo8c461qxZwy233NKox1DThb6iFkz0xzloaGic2URERPD+++9Xe3/lypUcOHCAiIiIAEilEShOt7Ma2283depUhg0bRt++fRvl9zX+mdTXzxIUFMSTTz7JrFmzyMnJaTjBzlKMgRZAo+H4448/uO+++xg1ahRff/01RqPr9l599dVcdtll3HvvvZx33nn079/f4++UlpYSGhpKamoqqampdZIlMjKSPn361Om7/1TKysowm82BFsPv2Gw2rFZroMXQ0NDQqJFOnTrRo0ePGj/zRc8pOvVMQ9E55513XqBFqTd/h3PQ0NDQ8Ddz586lVatWLFu2rJrdOHfu3ABKdvYghKC8vByz2fy3sH3/DufgjTN1XqahcaZw1VVXMX/+fN544w0iIyOd77///vv07duXwsLCAEqn4W/8aWft3r2bb775hh9++MFvx6wtmg7553LNNdfw73//m3feeYdHH3000OIEFC0z8W/EnDlz0Ol0vPXWW24GIYDRaOTNN99Ep9PxzDPPON9XUrM3bdrE+PHjiYmJIS0tze2zqlRUVPDAAw+QmJhIaGgoF154IX/++We11PeaypxOmjSJ8PBw9u/fz6hRowgPD6dZs2Y88MADVFRUuB1n5syZ9O7dm9jYWCIjI+nevTvvv/8+QogGulpQXl7OAw88QLdu3YiKiiI2Npa+ffvy7bffurUbOnQo7du3r3ZspcxD1ayUyspKZs+eTfv27QkODqZJkybceOONnDp1yu27LVu2ZMyYMSxcuJDzzjuPkJAQ1VWmmzdvZsyYMTRt2pTg4GCSk5MZPXo0GRkZAKrl9k4vV6Pc182bN3P55ZcTGRlJVFQU1113nUc5v/76a7p06UJISAitW7fm1VdfrXacI0eOcN111zll7NChAy+88AJ2u93ZRpFz7ty5zJ49m1atWhEcHMyKFSvo2bMnADfeeKOzvIZamR2lDMfy5cu59dZbiYuLIzIykhtuuIGSkhIyMzO58soriY6OJikpialTp2KxWNx+w9d+tnz5cgYNGkRcXBxms5nmzZvzr3/9i9LSUo/yWSwWJk6cSHh4OIsXL/bYTkND4+ykpnFXTacePHiQq6++muTkZGcpuaFDhzpXdbZs2ZKdO3eycuVK5xjorXxleXk506ZNo1WrVphMJlJSUrjrrruqZQCq6ZyaSsAVFhYydepUt9+97777KCkpcWun0+m4++67+d///keHDh0IDQ2la9eubmPejBkzePDBBwFo1apVtfJJCxYs4OKLLyYpKQmz2UyHDh145JFH3I41adIk3njjDecxlVd6errHc6iNTnr++ed58cUXadWqFeHh4fTt25e1a9eqXnt/kJeXx4033khsbCxhYWGMHTuWgwcPqn6nNvMBgH379jFhwgS366Rcaw0Njb83OTk5xMfHV7MbAfT66m6CBQsW0LdvX8LCwggPD2f48OFs3ry5Wrt169YxduxY4uLiCAkJIS0tjfvuu8+tze+//87QoUOJiIggNDSUfv36sWTJErc2ylx/xYoVTJ48mfj4eOLi4rj88ss5fvy4W1uLxcJDDz3ktFEvuOAC1q9f7/O1yM3N5c477yQlJQWTyUTr1q157LHHqtmoit57++236dChA8HBwfzf//2f87PTx9jMzExuv/12UlNTMZlMtGrVipkzZ7otpPRVF3nThW+88QYXXnghTZs2JSwsjM6dOzN37lw3+2fQoEEsWbKEw4cPu/1G1fM7/Rx27NjBuHHjiImJISQkhG7dujnPWUGx/T/99FMee+wxkpOTiYyM5KKLLmLv3r0+34eGRm1eJoTgzTffpFu3bpjNZmJiYhg/fnw1PSuEYO7cubRo0YKQkBC6d+/O0qVLA3E6Ghp+4ZprrgHg008/db5XUFDAV199xU033VTjd/ztV/HX82u323nttdecx4mOjqZPnz589913bm3mzp3r9AE2bdqUG264wemrUxg0aBCdOnVizZo19OvXD7PZTMuWLfnwww8BWS2ge/fuhIaG0rlz52oBtdr48XyVyZufEdztrF9//dWr327jxo1ccsklxMbGEhISwnnnncfnn3/u0/V+6623SExMZNiwYdU+++CDD+jatSshISHExsZy2WWXsXv3bufnL7/8Mjqdjv3791f77sMPP4zJZCI7O9v53s8//8zQoUOJjIwkNDSU/v3788svv7h9T02H1IQvdi24fOM7d+5k6NChhIWF0aRJE+6++27VZ6ExUGTZs2cPw4cPJywsjKSkJGfcYO3atVxwwQWEhYXRtm3bavr/1KlT3HnnnZx77rmEh4fTtGlThgwZwqpVq6odKyMjg/HjxxMREUF0dDTXXnstGzZsqNF29aUf+TpPVPOz+BoXADCZTFx11VW8++67DRqbOBvRMhP/JthsNlasWEGPHj08ZhM2a9aM888/n+XLl2Oz2TAYDM7PLr/8cq6++mruuOOOagNdVW688UYWLFjAQw89xJAhQ9i1axeXXXaZz6uTLBYLl1xyCTfffDMPPPAAv/32G0899RRRUVE8+eSTznbp6encfvvtNG/eHJAD2D333MOxY8fc2tWHiooKcnNzmTp1KikpKVRWVvLzzz9z+eWX8+GHH3LDDTcAcO+99zJu3Dh++eUXLrroIuf3ly5dyoEDB5yBNbvdzrhx41i1ahUPPfQQ/fr14/Dhw0yfPp1BgwaxceNGt8zDTZs2sXv3bh5//HFatWpFWFhYjXKWlJQwbNgwWrVqxRtvvEFCQgKZmZmsWLGCoqKiOp//ZZddxpVXXskdd9zBzp07eeKJJ9i1axfr1q0jKCjI2W7Lli3cd999zJgxg8TERObPn8+9995LZWUlU6dOBaQC6devH5WVlTz11FO0bNmSxYsXM3XqVA4cOMCbb77pduxXX32Vtm3b8vzzzxMZGUlCQgIffvghN954I48//rgzQOtLZuwtt9zC5ZdfzmeffcbmzZt59NFHsVqt7N27l8svv5zbbruNn3/+mWeffZbk5GT+/e9/O7/rSz9LT09n9OjRDBgwgA8++IDo6GiOHTvGDz/8QGVlZY2rkvLz87n88svZvXs3K1eu5Pzzz6/l3dHQ0DhTqCl7uibHa1Vq0qmjRo3CZrMxd+5cmjdvTnZ2NqtXr3YG/r7++mvGjx9PVFSUc8wMDg72eAwhBJdeeim//PIL06ZNY8CAAWzbto3p06c7y7FW/b6vOqe0tJSBAweSkZHBo48+SpcuXdi5cydPPvkk27dv5+eff3ZzPC5ZsoQNGzYwa9YswsPDmTt3Lpdddhl79+6ldevW3HLLLeTm5vLaa6+xcOFCkpKSADj33HMBGcwaNWoU9913H2FhYezZs4dnn32W9evXs3z5cgCeeOIJSkpK+PLLL93Kryu/dTq11UlvvPEG7du3d5Z9e+KJJxg1ahSHDh0iKirK4z1obG6++WaGDRvGJ598wtGjR3n88ccZNGgQ27ZtIzo6ut6/v2vXLvr160fz5s154YUXSExMZNmyZUyZMoXs7GymT59e/5PQ0NA4Y+nbty/vvfceU6ZM4dprr6V79+5uNkBVnn76aR5//HHnXL2yspLnnnuOAQMGsH79eueYvmzLine truncated
"text/plain": [
"<Figure size 1800x500 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Composite of the two fitted Si [110] grain reconstructions.\n",
"# Run the first-grid and second-grid cells before this cell.\n",
"def display_strength(filtered_image):\n",
" amplitude = np.abs(filtered_image)\n",
" low, high = np.percentile(amplitude, (1, 99.5))\n",
" if high == low:\n",
" return np.zeros_like(amplitude)\n",
" return np.clip((amplitude - low) / (high - low), 0, 1)\n",
"\n",
"first_blue = display_strength(si110_grid_image)\n",
"second_red = display_strength(second_grain_image)\n",
"\n",
"# Use the original layer as a real-space support mask. Pixels below this\n",
"# contrast level cannot receive Fourier-filtered color.\n",
"mask_low, mask_high = np.percentile(layer, (5, 95))\n",
"support_threshold = 0.5 # increase to reject more low-signal pixels\n",
"if mask_high == mask_low:\n",
" original_mask = np.ones(layer.shape, dtype=bool)\n",
"else:\n",
" original_support = np.clip((layer - mask_low) / (mask_high - mask_low), 0, 1)\n",
" original_mask = original_support >= support_threshold\n",
"\n",
"composite = np.zeros((*layer.shape, 3))\n",
"composite[..., 0] = second_red # second orientation: red\n",
"composite[..., 1] = first_blue # first orientation: blue\n",
"composite *= original_mask[..., None]\n",
"\n",
"first_rgb = np.zeros_like(composite)\n",
"first_rgb[..., 1] = first_blue\n",
"first_rgb *= original_mask[..., None]\n",
"second_rgb = np.zeros_like(composite)\n",
"second_rgb[..., 0] = second_red\n",
"second_rgb *= original_mask[..., None]\n",
"\n",
"fig, axes = plt.subplots(1, 4, figsize=(18, 5), constrained_layout=True)\n",
"axes[0].imshow(original_mask, cmap='gray'); axes[0].set_title('Original-layer support mask')\n",
"axes[1].imshow(first_rgb); axes[1].set_title('First orientation — blue')\n",
"axes[2].imshow(second_rgb); axes[2].set_title('Second orientation — red')\n",
"axes[3].imshow(composite); axes[3].set_title('Masked composite (overlap = magenta)')\n",
"for ax in axes:\n",
" ax.axis('off')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "216b020a",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 24,
"id": "25609e99",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Saved (32, 379, 379, 3) RGB stack to /home/swim/sandbox/silicon-grain-boundaries/colored.tiff\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAeEAAAH2CAYAAABHmTQtAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzsnXecXNV5v587vW3vXaveGyDRhRC9d2Njg+3EODiOSeIkduK4l7jgOAlOwHZibAPGmN6RBEJCQkK9d2l7b9P7zD2/P85ISLBzZ3ZnNSP7N8/nMzY7Onfn7Mzc857zlu+rCCEEefLkyZMnT56so8v1BPLkyZMnT57/X8kb4Tx58uTJkydH5I1wnjx58uTJkyPyRjhPnjx58uTJEXkjnCdPnjx58uSIvBHOkydPnjx5ckTeCOfJkydPnjw5Im+E8+TJkydPnhyRN8J58uTJkydPjsgb4TwfYc+ePXzmM5+hubkZi8WCw+Fg8eLF/PjHP2ZkZGTMv+/Tn/40kyZNmviJZkBbWxuKovCb3/wmK6/38MMPM3XqVEwmE4qi4HK5svK6ZyPf+ta3UBQl19MYN//6r//KDTfcQF1dHYqi8OlPfzrpWCEEjz32GEuWLMFut1NYWMjixYt56aWXsjfhPGc1eSOc5zR+9atfcc4557B161b+8R//kTfffJMXXniBO++8k0cffZS/+Iu/yPUU/+TYtWsXX/rSl1i+fDlr1qxh06ZNFBQU5HpaecbJz372M4aHh7npppswmUyaYx944AEeeOABVqxYwcsvv8wzzzzDJz7xCQKBQJZmm+dsx5DrCeQ5e9i0aRMPPPAAV155JS+++CJms/nkv1155ZV8+ctf5s0338zhDCXBYBCr1ZrT17dYLGmf5vbv3w/A5z73OZYsWTIhcwgEAthstgn5XXlOJ9V76/V60enk+eXxxx9POu7FF1/kF7/4BU8//TR33XXXyeevvvrqiZtsnj958ifhPCf5wQ9+gKIo/PKXvzzNAJ/AZDJx0003nfxZVVV+/OMfM3PmTMxmM5WVldx77710dXWlfK1QKMQ///M/09zcjMlkoq6ujr/+67/+iJt20qRJ3HDDDTz//PMsWrQIi8XCt7/9bQD6+vr4/Oc/T319PSaTiebmZr797W8Ti8VO+x09PT3cddddFBQUUFRUxMc+9jH6+vrSek9+85vfoCgKq1at4rOf/SwVFRXYbDbC4TAATz/9NBdccAF2ux2Hw8HVV1/Nzp07T15/2WWX8clPfhKApUuXfsR9+dZbb7FixQoKCwux2WxcdNFFvP3226fN4YT7dseOHdxxxx2UlJQwZcoUQLo7/+d//oeFCxditVopKSnhjjvuoKWl5bTfcdlllzF37ly2bt3KJZdcgs1mY/Lkyfzwhz9EVdXTxrpcLr785S8zefLkk5/rddddx6FDh06OiUQifO973zv52VdUVPCZz3yGwcHBtN7XD/P0009z1VVXUVNTg9VqZdasWXz1q1/F7/efHPP444+jKAqbNm36yPXf+c53MBqN9PT0TNh7m4wTBjgV//mf/8mkSZNOM8B58nwEkSePECIWiwmbzSaWLl2a9jX333+/AMQXv/hF8eabb4pHH31UVFRUiIaGBjE4OHhy3H333SeamppO/qyqqrj66quFwWAQX//618WqVavEQw89JOx2u1i0aJEIhUInxzY1NYmamhoxefJk8etf/1q88847YsuWLaK3t1c0NDSIpqYm8Ytf/EK89dZb4rvf/a4wm83i05/+9MnrA4GAmDVrligqKhIPP/ywWLlypfjSl74kGhsbBSAee+wxzb/xscceE4Coq6sT999/v3jjjTfEs88+K2KxmPj+978vFEURn/3sZ8Wrr74qnn/+eXHBBRcIu90u9u/fL4QQYv/+/eJf//VfT77Wpk2bxLFjx4QQQjz++ONCURRxyy23iOeff1688sor4oYbbhB6vV689dZbJ+fwzW9+UwCiqalJfOUrXxGrV68WL774ohBCiM997nPCaDSKL3/5y+LNN98Uv//978XMmTNFVVWV6OvrO/k7li1bJsrKysS0adPEo48+KlavXi2+8IUvCED89re/PTnO4/GIOXPmCLvdLr7zne+IlStXiueee048+OCDYs2aNUIIIeLxuLjmmmuE3W4X3/72t8Xq1avF//7v/4q6ujoxe/ZsEQgENN/TE3/PqXz3u98VP/vZz8Rrr70m1q5dKx599FHR3Nwsli9ffnJMOBwW1dXV4p577jnt2mg0Kmpra8Wdd9558rmJeG/TwW63i/vuu+8jz0ejUWE2m8Wtt94qfvrTn4rGxkah0+lEc3Oz+MlPfiJUVU37NfL8eZM3wnmEEEL09fUJQNx9991pjT948KAAxBe+8IXTnt+8ebMAxL/8y7+cfO7DRvjNN98UgPjxj3982rVPP/20AMQvf/nLk881NTUJvV4vDh8+fNrYz3/+88LhcIj29vbTnn/ooYcEcNIIPvLIIwIQL7300mnjPve5z43JCN97772nPd/R0SEMBoP4m7/5m9Oe93q9orq6Wtx1110f+R1bt249+Zzf7xelpaXixhtvPO36eDwuFixYIJYsWXLyuROG4hvf+MZpYzdt2iQA8dOf/vS05zs7O4XVahX/9E//dPK5ZcuWCUBs3rz5tLGzZ88WV1999cmfv/Od7whArF69Oul78tRTTwlAPPfcc6c9v3XrVgGI//mf/0l67al/TzJUVRXRaFSsW7dOAGL37t2nXWsymUR/f//J5058b9atWyeEmJj3Nl2SGeHe3l4BiMLCQlFfXy9++9vfirffflv81V/91Ufujzz/f5N3R+cZF++88w7ARzJDlyxZwqxZsz7i9juVNWvWjHrtnXfeid1u/8i18+fPZ/r06ac99+qrr7J8+XJqa2uJxWInH9deey0A69atOznPgoKC09zoAJ/4xCfS+0MT3H777af9vHLlSmKxGPfee+9pr2+xWFi2bBlr167V/H0bN25kZGSE++6777TrVVXlmmuuYevWrae5Ykebw6uvvoqiKHzyk5887XdUV1ezYMGCj8yhurr6IzHp+fPn097efvLnN954g+nTp3PFFVcknfurr75KcXExN95442mvu3DhQqqrq1P+7aPR0tLCJz7xCaqrq9Hr9RiNRpYtWwbAwYMHT4574IEHAJlAeIKf//znzJs3j0svvRSYmPc2U064+D0eD8888wz33nsvl19+OY888gi33HIL//7v/47P55vQ18zzp0k+MSsPAOXl5dhsNlpbW9MaPzw8DEBNTc1H/q22tva0hX20aw0GAxUVFac9rygK1dXVJ3/3CUZ7jf7+fl555RWMRuOorzE0NHTytaqqqj7y79XV1UnnNxofnkN/fz8A55133qjjU8UNT1x/xx13JB0zMjKC3W7XnIMQYtS/D2Dy5Mmn/VxWVvaRMWazmWAwePLnwcFBGhsbU87d5XIlzQw+8d6ni8/n45JLLsFisfC9732P6dOnY7PZ6Ozs5LbbbjttflVVVXzsYx/jF7/4BV/96lfZv38/69ev5xe/+MVp84PM3ttMKSkpQVEUCgoKOP/880/7t2uvvZYXX3yRAwcOTFiiXp4/XfJGOA8Aer2eFStW8MYbb9DV1UV9fb3m+BMLem9v70fG9vT0UF5ernltLBZjcHDwNEMshKCvr+8jhm20LOTy8nLmz5/P97///VFfo7a29uRrbdmy5SP/nm5iVrI5nPj7nn32WZqamsb0u069/uGHH/7IIn2CDxvX0eagKArr168fNZFutOdSUVFRkTKxrry8nLKysqSZ8mMtv1qzZg09PT2sXbv25OkXSFpL/eCDD/L444/z0ksv8eabb1JcXMw999xz2vwgs/c2U6xWK9OmTRv1eyaEANJP8Mrz503eCOc5yT//8z/z+uuv87nPfY6XXnrpIyedaDTKm2++yY033sjll18OwBNPPHGa0dy6dSsHDx7ka1/7WtLXWbFiBT/+8Y954okn+Lu/+7uTzz/33HP4/X5WrFiRcq433HADr7/+OlOmTKGkpCTpuOXLl/PHP/6Rl19++TSX9O9///uUr6HF1VdfjcFg4Pjx4+NyZV500UUUFxdz4MABvvjFL45rDjfccAM//OEP6e7unrAM3GuvvZZvfOMbrFmz5uRnPNrr/uEPfyAej7N06dKMX/OEAfzwpuHU0+2pnHPOOVx44YX86Ec/Yt++fdx///2nnWon4r2dCG6//Xb+7d/+jY0bN3LhhReefP7111/H4XAwZ86cnM0tz9lD3gjnOckFF1zAI488whe+8AXOOeccHnjgAebMmUM0GmXnzp388pe/ZO7cudx4443MmDGD+++/n4cffhidTse1115LW1sbX//612loaDjNuH6YK6+8kquvvpqvfOUreDweLrroIvbs2cM3v/lNFi1axKc+9amUc/3Od77D6tWrufDCC/nSl77EjBkzCIVCtLW18frrr/Poo49SX1/Pvffey89+9jPuvfdevv/97zNt2jRef/11Vq5cmdF7NWnSJL7zne/wta99jZaWFq655hpKSkro7+9ny5Yt2O32k6VUo+FwOHj44Ye57777GBkZ4Y477qCyspLBwUF2797N4OAgjzzyiOYcLrroIu6//34+85nPsG3bNi699FLsdju9vb1s2LCBefPmnYyhpsvf/u3f8vTTT3PzzTfz1a9+lSVLlhAMBlm3bh033HADy5cv5+677+bJJ5/kuuuu48EHH2TJkiUYjUa6urp45513uPnmm7n11lvTfs0LL7yQkpIS/uqv/opvfvObGI1GnnzySXbv3p30mgcffJCPfexjKIrCF77whdP+bSLeWy3WrVt3shQrHo/T3t7Os88+C8CyZctOenf+4R/+gSeffJI777yT7373u9TX1/Pss8/y8ssv89BDD+W01j3PWUSOE8PynIXs2rVL3HfffaKxsVGYTKaTpUPf+MY3xMDAwMlLine truncated
"text/plain": [
"<Figure size 600x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Color the complete TIFF stack using the two orientations fitted on the reference layer.\n",
"# Run the first-grid and second-grid cells before this cell.\n",
"volume = image.astype(float)\n",
"\n",
"# Fixed reciprocal-space masks from the reference layer are applied to every TIFF layer.\n",
"fft_volume = np.fft.fftshift(np.fft.fft2(volume, axes=(-2, -1)), axes=(-2, -1))\n",
"first_volume = np.fft.ifft2(\n",
" np.fft.ifftshift(fft_volume * si110_grid_mask[None, :, :], axes=(-2, -1)), axes=(-2, -1)\n",
").real\n",
"second_volume = np.fft.ifft2(\n",
" np.fft.ifftshift(fft_volume * second_mask[None, :, :], axes=(-2, -1)), axes=(-2, -1)\n",
").real\n",
"\n",
"def normalize_volume(filtered_volume):\n",
" amplitude = np.abs(filtered_volume)\n",
" low, high = np.percentile(amplitude, (1, 99.5))\n",
" if high == low:\n",
" return np.zeros_like(amplitude)\n",
" return np.clip((amplitude - low) / (high - low), 0, 1)\n",
"\n",
"first_blue_volume = normalize_volume(first_volume)\n",
"second_red_volume = normalize_volume(second_volume)\n",
"\n",
"# Build an original-image support mask per layer to suppress Fourier ringing.\n",
"stack_support_threshold = globals().get('support_threshold', 0.5)\n",
"support_volume = np.zeros(volume.shape, dtype=bool)\n",
"for index, original_layer in enumerate(volume):\n",
" low, high = np.percentile(original_layer, (5, 95))\n",
" if high == low:\n",
" support_volume[index] = True\n",
" else:\n",
" scaled = np.clip((original_layer - low) / (high - low), 0, 1)\n",
" support_volume[index] = scaled >= stack_support_threshold\n",
"\n",
"colored_stack = np.zeros((*volume.shape, 3), dtype=np.uint8)\n",
"colored_stack[..., 0] = np.round(255 * second_red_volume * support_volume).astype(np.uint8) # second: red\n",
"colored_stack[..., 1] = np.round(255 * first_blue_volume * support_volume).astype(np.uint8) # first: blue\n",
"\n",
"output_path = os.path.abspath('colored.tiff')\n",
"tifffile.imwrite(output_path, colored_stack, photometric='rgb', metadata={'axes': 'ZYXS'})\n",
"print(f'Saved {colored_stack.shape} RGB stack to {output_path}')\n",
"\n",
"reference_index = image.shape[0] // 2\n",
"plt.figure(figsize=(6, 6))\n",
"plt.imshow(colored_stack[reference_index])\n",
"plt.title(f'Colored reference layer {reference_index}')\n",
"plt.axis('off')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 70,
"id": "colored-alpha-stack",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Saved (32, 379, 379, 3) RGBA stack to /home/swim/sandbox/silicon-grain-boundaries/colored_alpha.tiff\n"
]
},
{
"data": {
"image/png": "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H/zgB/zRH/0Rra2tRCIRVq9ezV/91V+VvOvtb387X/3qV/U75ae3t/eMfejv7+fNb34zTU1NhEIhVq9ezZe+9CVs29bXyHfXF7/4Rb785S+zePFiKioquOiii3jyySfPag6GhoZ497vfTWdnJ8FgkLa2Nm6++eaS9fRS2vKFL3yBz33ucyxatIhIJMLll1/OkSNHyOfz/NVf/RVtbW1UV1dz4403MjY2VtIWmed77rmHDRs2EA6HWbJkCf/0T/90WrvPpk3w4vLEfNn0xebqbOW6Mv4wUbaAl4FlWTz88MOcd955Z7Rad3Z2snnzZrZv345lWfh8Pv231772tbzhDW/gf/yP/3Hal5YX73jHO/jBD37ARz7yEa688koOHjzIjTfeyNzc3Fm1M5/Pc8MNN/Cud72LD33oQzz22GP87d/+LdXV1XziE5/Q1/X29vKe97yHrq4uQMW1/9mf/RlDQ0Ml1/0mOJt3/Pmf/zl33nkn3/ve97j11lv1vQcPHuThhx/WBzfAe97zHr797W/zgQ98gM997nNMTU1xxx13sHXrVvbt20dzc7O+dnh4mDe/+c185CMf4R/+4R8wzd9cj/b973+f9773vfzZn/0ZX/ziFzFNk2PHjnHw4EF9zcjICFu2bME0TT7xiU+wdOlSdu7cyd/93d/R29vLt771LUBZG175yldy6tQpPvOZz7BixQruvfdeXv/6159VW6ampgD45Cc/SUtLC4lEgnvuuYfLL7+chx56SCsUzqbNZ8Jvukb+z//5P3R3d/OVr3wF27b5/Oc/zzXXXMOjjz7KRRddVHLtTTfdxOtf/3re9a538dxzz/HRj34UgDvvvFNfc/z4cW655RYtBO7bt4+///u/59ChQyXXlVFGGWX8ujh58iRAiWX64YcfplAocMMNN7zk5zmOo5WvmUyG3bt385WvfIVt27axePHikmsHBwf5xS9+wU033URjYyNve9vb+Lu/+zsee+wxLrvsshd9z2te8xoeeughPvrRj3LJJZewf/9+PvnJT2oX+FAopK/fs2cPPT09/PVf/zWLFy8mFost+NxUKsVll13G4OAgH/vYx9iwYQMHDhzgE5/4BM899xy//OUvSwwJ9957L7t37+aOO+6goqKCz3/+89x4440cPnyYJUuWcOuttzI1NcX//t//mx/96Ee0trYCsGbNGgCOHj3Ktddey+23304sFuPQoUN87nOfY9euXWzfvh2Av/mbvyGZTHL33XeXhPHJs+ZjfHycrVu3ksvl+Nu//VsWLVrEz372Mz784Q9z/Phxvva1r5Vc/9WvfpVVq1bxla98Rb/v2muv5eTJk1p5shCGhoY4//zzyefzeqwmJyd54IEHmJ6eprm5+ddqy4YNG/jqV7/KzMwMH/rQh3j1q1/NBRdcQCAQ4M4776Svr48Pf/jD3HrrrfzkJz8puX/v3r3cfvvtfOpTn6KlpYXvfve7/Pmf/zm5XI4Pf/jDL2l8fh154sXm6qXIdWX8AcIp4w8eIyMjDuC84Q1veMHrXv/61zuAMzo66jiO43zyk590AOcTn/jEadfK3wQHDhxwAOcv//IvS677j//4Dwdw3va2t+nPHn74YQdwHn74Yf3Z2972Ngdw/vM//7Pk/muvvdZZuXLlGdtsWZaTz+edO+64w6mvr3ds29Z/u+yyy5zLLrvsBft8Nte92DvOOeeckutvu+02p6qqyonH447jOM7OnTsdwPnSl75Uct3AwIATiUScj3zkIyXPA5yHHnroRdv9Qm1/29ve5nR3d+vf3//+9zs1NTUv+Kz3vOc9TkVFhdPX11fy+Re/+EUHcA4cOOA4juN8/etfdwDnv//7v0uu+9M//VMHcL71rW+dVdsFhULByefzzite8QrnxhtvfEltPhu8lDVy8uRJB3Da2tqcdDqtP5+bm3Pq6uqcV77ylfoz2QOf//znS9733ve+1wmHwyXvWag93/nOdxyfz+dMTU39xn0so4wy/nDwrW99ywGcJ5980snn8048Hnd+/vOfOy0tLc6ll17q5PN5fe1nP/tZB3B+/vOfn/acfD5f8uNFd3e3A5z2s2XLFmd4ePi0Z91xxx0l7zlx4oRjGIbzlre85UX78/Of/3zBs/QHP/iBAzj/8i//UtIun8/nHD58+LTndHd3l8gan/nMZxzTNJ3du3eXXHf33Xc7gHPffffpzwCnubnZmZub05+NjIw4pmk6n/nMZ/RnX/jCFxzAOXny5Av2ybZtJ5/PO48++qgDOPv27dN/e9/73uecSTyf34e/+qu/cgDnqaeeKrnutttucwzD0OMg313r1693CoWCvm7Xrl0O4PzHf/zHC7b3ne98pxMIBJyDBw+e8ZqX2paNGzc6lmXp677yla84gHPDDTeU3H/77bc7gDM7O1syDoZhOHv37i259qqrrnKqqqqcZDL5ktp0NvLEQrLpmebqpch1ZfxhouyCXsZZw3Fdxea7lt90000veu+jjz4KwOte97qSz2+++ebTXN7PBMMwePWrX13y2YYNG+jr6yv5bPv27bzyla+kuroan89HIBDgE5/4BJOTk6e5Mf2Line truncated
"text/plain": [
"<Figure size 1000x500 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# RGBA version: use the original TIFF intensity as continuous alpha, not a cutoff mask.\n",
"# Run the two orientation-filter cells first. Output: ./colored_alpha.tiff\n",
"volume = image.astype(float)\n",
"fft_volume = np.fft.fftshift(np.fft.fft2(volume, axes=(-2, -1)), axes=(-2, -1))\n",
"first_volume = np.fft.ifft2(\n",
" np.fft.ifftshift(fft_volume * si110_grid_mask[None, :, :], axes=(-2, -1)), axes=(-2, -1)\n",
").real\n",
"second_volume = np.fft.ifft2(\n",
" np.fft.ifftshift(fft_volume * second_mask[None, :, :], axes=(-2, -1)), axes=(-2, -1)\n",
").real\n",
"\n",
"def normalize_for_display(values, percentiles=(1, 99.5)):\n",
" low, high = np.percentile(values, percentiles)\n",
" if high == low:\n",
" return np.zeros_like(values)\n",
" return np.clip((values - low) / (high - low), 0, 1)\n",
"\n",
"# RGB encodes filtered orientation strength; alpha continuously follows original intensity.\n",
"first_blue_volume = normalize_for_display(np.abs(first_volume))\n",
"second_red_volume = normalize_for_display(np.abs(second_volume))\n",
"original_alpha = beta.cdf(normalize_for_display(volume), 3, 8)\n",
"\n",
"colored_alpha_stack = np.zeros((*volume.shape, 3), dtype=np.uint8)\n",
"colored_alpha_stack[..., 0] = np.round(255 * (second_red_volume * (original_alpha))).astype(np.uint8) # second: red\n",
"colored_alpha_stack[..., 1] = np.round(255 * (first_blue_volume * (original_alpha))).astype(np.uint8) # first: blue\n",
"# colored_alpha_stack[..., 2] = np.ones_like(original_alpha) * 255\n",
"# colored_alpha_stack[..., 3] = np.round(255 * (original_alpha)).astype(np.uint8) # original: alpha\n",
"\n",
"output_path = os.path.abspath('colored_alpha.tiff')\n",
"tifffile.imwrite(\n",
" output_path, colored_alpha_stack, photometric='rgb', extrasamples='unassalpha',\n",
" metadata={'axes': 'ZYXS'},\n",
")\n",
"print(f'Saved {colored_alpha_stack.shape} RGBA stack to {output_path}')\n",
"\n",
"reference_index = image.shape[0] // 2\n",
"fig, axes = plt.subplots(1, 2, figsize=(10, 5), constrained_layout=True)\n",
"axes[0].imshow(original_alpha[reference_index], cmap='gray', vmin=0, vmax=1)\n",
"axes[0].set_title('Original layer used as alpha')\n",
"axes[1].imshow(colored_alpha_stack[reference_index])\n",
"axes[1].set_title('RGBA orientation composite')\n",
"for ax in axes:\n",
" ax.axis('off')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 69,
"id": "05c7b076",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x7f03c9cd2270>]"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from scipy.stats import beta\n",
"\n",
"x = np.linspace(0, 1)\n",
"\n",
"plt.plot(x, beta.cdf(x, 4, 8))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "lemon",
"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.12.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}