From 712e384c95382f49fda86f53528839844ece7b4f Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Sat, 13 Jan 2024 22:29:12 +0100 Subject: [PATCH] Tested parsing on IKZ and PDI examples --- debug/spctrscpy.batch.sh | 10 +- debug/spctrscpy.dev.ipynb | 193 ++++++++++++++++-- .../readers/em/concepts/nxs_image_r_set.py | 4 +- .../readers/em/concepts/nxs_object.py | 9 +- .../readers/em/concepts/nxs_spectrum_set.py | 4 - pynxtools/dataconverter/readers/em/reader.py | 16 +- .../readers/em/subparsers/hfive_apex.py | 109 +++++++--- .../readers/em/subparsers/nxs_nion.py | 2 +- 8 files changed, 278 insertions(+), 69 deletions(-) diff --git a/debug/spctrscpy.batch.sh b/debug/spctrscpy.batch.sh index 0d2a219cc..fd9c22bad 100755 --- a/debug/spctrscpy.batch.sh +++ b/debug/spctrscpy.batch.sh @@ -1,11 +1,15 @@ #!/bin/bash -datasource="../../../../paper_paper_paper/scidat_nomad_ebsd/bb_analysis/data/development_spctrscpy/pdi/" +datasource="../../../../../paper_paper_paper/scidat_nomad_ebsd/bb_analysis/data/development_spctrscpy/pdi/" +datasource="../../../../../paper_paper_paper/scidat_nomad_ebsd/bb_analysis/data/development_spctrscpy/ikz/" + # apex examples ikz, pdi # examples="ikz/VInP_108_L2.h5 ikz/GeSn_13.h5 pynx/46_ES-LP_L1_brg.bcf pynx/1613_Si_HAADF_610_kx.emd pynx/EELS_map_2_ROI_1_location_4.dm3 pynx/H5OINA_examples_Specimen_1_Map_EDS_+_EBSD_Map_Data_2.h5oina" -examples="ikz/VInP_108_L2.h5" -examples="InGaN_nanowires_spectra.edaxh5" +examples="AlGaO.nxs" +examples="GeSi.nxs" +examples="VInP_108_L2.h5" +#examples="InGaN_nanowires_spectra.edaxh5" for example in $examples; do echo $example diff --git a/debug/spctrscpy.dev.ipynb b/debug/spctrscpy.dev.ipynb index c6b5871e2..f5162301d 100644 --- a/debug/spctrscpy.dev.ipynb +++ b/debug/spctrscpy.dev.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 15, + "execution_count": 4, "id": "6da1aea0-545b-446b-a3d1-1574af72f6c6", "metadata": {}, "outputs": [], @@ -11,12 +11,51 @@ "from rsciio import bruker, emd, digitalmicrograph\n", "from jupyterlab_h5web import H5Web\n", "import h5py\n", - "from matplotlib import pyplot as plt" + "from matplotlib import pyplot as plt\n", + "import xraydb\n", + "from ase.data import chemical_symbols" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 11, + "id": "8e721dee-7b6f-4dd0-b50e-ea8ff05d4682", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1807\n", + "['Mg-Ka3', 'Ge-Lb1', 'Ge-Lb6', 'Se-Ln', 'Se-Ll', 'Pm-Mg', 'Gd-Mb', 'Tb-Ma', 'Lu-Mz']\n" + ] + } + ], + "source": [ + "xray_lines = {}\n", + "for symbol in chemical_symbols[1:]:\n", + " # print(f\"{symbol}\")\n", + " for name, line in xraydb.xray_lines(symbol).items():\n", + " xray_lines[f\"{symbol}-{name}\"] = line.energy\n", + " # print(f\"{name}, {line.energy} eV\")\n", + "print(len(xray_lines))\n", + "\n", + "def get_xray_line_candidates(e_min=1200., e_max=1250.):\n", + " cand = []\n", + " for key, val in xray_lines.items():\n", + " if val < e_min:\n", + " continue\n", + " if val > e_max:\n", + " continue\n", + " cand.append(key)\n", + " return cand\n", + "\n", + "print(get_xray_line_candidates())" + ] + }, + { + "cell_type": "code", + "execution_count": 12, "id": "3889c47f-11c4-4bf3-97de-04fc52f0798d", "metadata": {}, "outputs": [ @@ -30,20 +69,22 @@ ], "source": [ "src = \"/home/kaiobach/Research/paper_paper_paper/scidat_nomad_ebsd/bb_analysis/data/development_spctrscpy\"\n", - "fnms = [(\"apex\", \"ikz/VInP_108_L2.h5\"),\n", - " (\"apex\", \"ikz/GeSn_13.h5\"),\n", + "fnms = [(\"ikz\", \"VInP_108_L2.h5\"),\n", + " (\"ikz\", \"GeSn_13.nxs\"),\n", " (\"bruker\", \"pynx/46_ES-LP_L1_brg.bcf\"),\n", " (\"emd\", \"pynx/1613_Si_HAADF_610_kx.emd\"),\n", " (\"digitalmicrograph\", \"pynx/EELS_map_2_ROI_1_location_4.dm3\"),\n", - " (\"oxfordinstruments\", \"pynx/H5OINA_examples_Specimen_1_Map_EDS_+_EBSD_Map_Data_2.h5oina\")]\n", + " (\"oxfordinstruments\", \"pynx/H5OINA_examples_Specimen_1_Map_EDS_+_EBSD_Map_Data_2.h5oina\"),\n", + " (\"pdi\", \"InGaN_nanowires_spectra.edaxh5\")]\n", "# pyUSID, HSMA\n", - "fnm = f\"{src}/{fnms[0][1]}\"\n", + "case = 0 # len(fnms) - 1\n", + "fnm = f\"{src}/{fnms[case][0]}/{fnms[case][1]}\"\n", "print(fnm)" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 14, "id": "a4d9ef96-3c70-4c12-80ba-ea4a7d716d47", "metadata": {}, "outputs": [ @@ -54,7 +95,7 @@ "" ] }, - "execution_count": 9, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -63,15 +104,139 @@ "H5Web(fnm)" ] }, + { + "cell_type": "code", + "execution_count": 16, + "id": "6b883a7a-f6aa-4151-8ee4-f3c8c79ccc72", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ", (200,), int32\n", + ", (200,), int32\n", + ", (200,), int32\n" + ] + } + ], + "source": [ + "with h5py.File(fnm, \"r\") as h5r:\n", + " src = \"/VInP/VInP_108_L2/Area 10/LineScan 1/ROIs/\"\n", + " for key in h5r[src].keys():\n", + " tmp = h5r[f\"{src}/{key}\"]\n", + " print(f\"{type(tmp)}, {np.shape(tmp)}, {tmp.dtype}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "e99588fe-67dc-48df-8d60-28187d8daa0a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ", (200, 1024), int32\n", + "0\t\tIn L\t\t849\n", + "0\t\tK K\t\t752\n", + "0\t\tP K\t\t938\n", + "1\t\tIn L\t\t857\n", + "1\t\tK K\t\t786\n", + "1\t\tP K\t\t1004\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGdCAYAAAA44ojeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABIqklEQVR4nO3deXxU5d0+/uvMmn2SyTKTkAQStrAbthDBaiGKiBYk1YJYW7XSBa1Cqy2/Kj4+2lJtH1Fal9avRazgDhSsxQIiLiQBwiKbSSCBrDOBLDOZhMxMZs7vj8mMBEFImMk5M3O9X6/zEs6cHD7jIZmL+3zu+wiiKIogIiIikhGF1AUQERERnY8BhYiIiGSHAYWIiIhkhwGFiIiIZIcBhYiIiGSHAYWIiIhkhwGFiIiIZIcBhYiIiGRHJXUBfeF2u1FfX4/Y2FgIgiB1OURERHQZRFFEW1sb0tLSoFB8+xhJUAaU+vp6ZGRkSF0GERER9UFNTQ3S09O/9ZigDCixsbEAPG8wLi5O4mqIiIjoclitVmRkZPg+x79NUAYU722duLg4BhQiIqIgczntGWySJSIiItlhQCEiIiLZYUAhIiIi2WFAISIiItlhQCEiIiLZYUAhIiIi2WFAISIiItlhQCEiIiLZYUAhIiIi2WFAISIiItlhQCEiIiLZYUAhIiIi2QnKhwUSEV0Ot1tE61knmmx2nLE50NzuQFO759eRaiXuuyYLKiX/nUYkRwwoRBQ0RFGEtbPLEzS6Q0dTux3NNgea2h04Y7N3v9a9v90Bt3jx8yVEqTF/cmb/vQEiumwMKEQkqQ5HF5psPcPFmfNCR9M5ox9O17ckjouIj1IjMVqDxGgtEmM0aOlwoLiyGev31TGgEMkUAwoR+ZW9y/V10DgvdPiCxjm3XM46Xb3+M2K0KiTGaJAYrYE+WoukGA0SY875dXcQSYzWICFaA/V5t3FMlk7k/3E7dp9sRnVTBzITo/z19onITxhQiPpBXetZHK6zSF2GX3Q6XT1uo5w5J3Q02Rxos3f1+pxalQJJMdrukOEJGOeGjsQYDZKiv349Qq28ovdg1EVg2pAkfFZxBhv21+HBgqFXdD4i8j8GFKIA63S6MOevX+CMzS51Kf1GpRA8QSNG67m1ct6oRmLM16FDH6NBtEYJQRD6tcZ54wfgs4ozWL+/Fr+cMaTf/3wi+na9Diiffvop/vSnP6G0tBQNDQ3YsGED5s6dCwBwOp149NFH8eGHH6KyshI6nQ4FBQX44x//iLS0NN85mpub8cADD2Dz5s1QKBQoLCzE888/j5iYGL+9MSK5+PeXDThjsyNWq8JQQ/D/HdeoFOeEjQuHjrhIlew/8GeOMiJacxinmjpQeqoFEwfppS6JiM7R64DS3t6OcePG4Z577sG8efN6vNbR0YF9+/bhsccew7hx49DS0oIHH3wQ3/ve97B3717fcQsXLkRDQwO2bt0Kp9OJu+++G4sWLcK6deuu/B0RyczaklMAgJ9dNxiLvztE4mrIK0qjwqwxqXivtBbv76tjQCGSGUEUxd63xHu/WBB6jKBcyJ49ezB58mScOnUKmZmZOHbsGEaOHIk9e/Zg4sSJAIAtW7bgpptuQm1tbY+RlouxWq3Q6XSwWCyIi4vra/lEAXe03oqbVn0GlULArmXTkRIbIXVJdI5dJ87gjldKEBuhwp7fFVxxbwsRfbvefH4HfIUii8UCQRAQHx8PACgqKkJ8fLwvnABAQUEBFAoFSkpKLngOu90Oq9XaYyMKBut2e0ZPZo4yMpzI0JSsRAyIj0RbZxe2HTNLXQ4RnSOgAaWzsxO/+c1vsGDBAl9SMplMSElJ6XGcSqWCXq+HyWS64HlWrFgBnU7n2zIyMgJZNpFf2Oxd2LCvDgCwMI9rbciRQiHg1twBAID13deKiOQhYAHF6XTi9ttvhyiKeOmll67oXMuWLYPFYvFtNTU1fqqSKHA2HahHu8OF7KRo5A9OlLocuohbx3sCys7y0zjdFj4zrYjkLiABxRtOTp06ha1bt/a4z2Q0GtHY2Njj+K6uLjQ3N8NoNF7wfFqtFnFxcT02IjkTRdHXHHtHXqbsZ7SEs8HJMbgqIx4ut4hNB+ulLoeIuvk9oHjDSUVFBbZt24bExJ7/cszPz0draytKS0t9+z7++GO43W7k5eX5uxwiSRysteBIvRUalQKF49OlLocuobB7FOX90lqJKyEir14HFJvNhgMHDuDAgQMAgKqqKhw4cADV1dVwOp34/ve/j71792Lt2rVwuVwwmUwwmUxwOBwAgBEjRuDGG2/Efffdh927d+OLL77A/fffj/nz51/WDB6iYLC22DN6cvOYVCREaySuhi7l5rFpUCsFHG2w4lgDm/CJ5KDXAWXv3r3Izc1Fbm4uAGDp0qXIzc3F8uXLUVdXh02bNqG2thZXXXUVUlNTfduuXbt851i7di1ycnIwY8YM3HTTTZg2bRr+/ve/++9dEUnI0uHE5i89twoWTmFzbDBIiNZgRo4BALBhP5tlieSg1wu1XXfddfi2pVMuZ1kVvV7PRdkoZK3fX4tOpxs5xliMz0yQuhy6TPPGD8CWIyZs2F+HR2YOh0oZ8FUYiOhb8DuQyI88zbHVADxTi9kcGzyuG56ChCg1TrfZ8cWJJqnLIQp7DChEfrS7qhnHG22I0igxt3t9DQoOGpUC3xvn6YNjsyyR9BhQiPzIO3oy56o0xEaoJa6GeqtwgmfG1UdHTGjrdEpcDVF4Y0Ah8pMzNjv+c7gBAHDH5IESV0N9MWaADkNSYmDvcuM/hy68sjUR9Q8GFCI/ea+0Fk6XiHHpOoxJ10ldDvWBIAiY510TZR9v8xBJiQGFyA/cbhHrfM2xHD0JZrfmDoAgACVVzahp7pC6HKKwxYBC5AefHz+D6uYOxEaocPO4VKnLoSuQqovE1MFJALgmCpGUGFCI/MD73J3C8emI0vR6eSGSGe9tnvX7ai9rbSci8j8GFKIrZLJ0YtsxzwMw78jjyrGhYOYoI6I0Spxs6sC+6lapyyEKSwwoRFfo7T01cLlFTB6kxzBDrNTlkB9Ea1W4cbTn6epsliWSBgMK0RXocrnx1p7u5lg+dyekeJ9C/cHBenQ6XRJXQxR+GFCIrsCOstNosHRCH63x/YubQkN+diLSdBGwdnbh468apS6HKOwwoBBdAW9z7G0T0qFVKSWuhvxJoRB8jytYz9s8RP2OAYWoj2qaO7Cz/DQAYMFk3t4JRd7ZPJ+UncYZm13iaojCCwMKUR+9ubsaoghcMzQJg5KipS6HAmBISizGpevQ5Rax6UC91OUQhRUGFKI+cHS58c7eGgDAQk4tDmneBwiu38/bPET9iQGFqA/+e9SEMzYHUmK1mDHCIHU5FEA3j02DWingcJ0VZaY2qcshChsMKER9sLbYM7V4/qQMqJX8Ngpl+mgNvjs8BQBHUYj6E3+yEvXS8UYbiiqboBCAH7A5NizM614TZeP+OrjcXPqeqD8woBD10pu7PaMn03NSMCA+UuJqqD9Mz0lBfJQaZqsdXxw/I3U5RGGBAYWoFzqdLrxX6hnmX5g3UOJqqL9oVAp8b1waAK6JQtRfGFCIeuHfXzbActaJAfGR+M6wZKnLoX7kvc2z5YgJNnuXxNUQhT4GFKJe8K4ce0deJpQKQeJqqD+NS9chOzkanU43PjzUIHU5RCGPAYXoMh2tt2JfdStUCgG3TUyXuhzqZ4Ig+B4gyNs8RIHHgEJ0mdbt9oyezBxlREpshMTVkBTm5g6AIADFlc2obemQuhyikMaAQnQZbPYubNhXB4Arx4azAfGRyM9OBOCZckxEgcOAQnQZNh2oR7vDheykaOQPTpS6HJKQt1n2/X11EEWuiUIUKAwoRJcgimKP5lhBYHNsOLtxtBGRaiWqzrRjf02r1OUQhSwGFKJLOFhrwZF6KzQqha9JksJXjFaFWaONANgsSxRIDChEl7C22DN6cvOYVCREaySuhuTAe5tn88EG2LtcEldDFJoYUIi+heWsE5u/rAcALJzC5ljyyB+cCGNcBCxnnfj4WKPU5RCFpF4HlE8//RS33HIL0tLSIAgCNm7c2OP19evX44YbbkBiYiIEQcCBAwe+cY7Ozk4sXrwYiYmJiImJQWFhIcxmc1/fA1HAbNhXi06nGznGWIzPTJC6HJIJpULA3NwBADzNskTkf70OKO3t7Rg3bhxeeOGFi74+bdo0PP300xc9x5IlS7B582a8++672LlzJ+rr6zFv3rzelkIUUJ7mWM+DAReyOZbOUzjeE1A+KWtEk80ucTVEoUfV2y+YNWsWZs2addHXf/jDHwIATp48ecHXLRYLXn31Vaxbtw7Tp08HAKxevRojRoxAcXExpkyZ0tuSiAJiz8kWVDTaEKVR+v61TOQ11BCLsek6fFlrweaD9fjx1CypSyIKKf3eg1JaWgqn04mCggLfvpycHGRmZqKoqKi/yyG6KO/U4jlXpSE2Qi1xNSRH87qD63ou2kbkd/0eUEwmEzQaDeLj43vsNxgMMJlMF/wau90Oq9XaYyMKpCabHf855Pn7eMfkgRJXQ3J1y7g0qBQCvqy1oMLcJnU5RCElKGbxrFixAjqdzrdlZGRIXRKFuPdKa+FwuTEuXYcx6TqpyyGZSozR4rs5KQDYLEvkb/0eUIxGIxwOB1pbW3vsN5vNMBqNF/yaZcuWwWKx+Laampp+qJTCldstYt1ub3MsR0/o23mbZTfur4PLzaXvifyl3wPKhAkToFarsX37dt++srIyVFdXIz8//4Jfo9VqERcX12MjCpQvTpzBqaYOxEaocPO4VKnLIZn7bk4KdJFqmKydKDrRJHU5RCGj17N4bDYbjh8/7vt9VVUVDhw4AL1ej8zMTDQ3N6O6uhr19Z7FrcrKygB4Rk6MRiN0Oh3uvfdeLF26FHq9HnFxcXjggQeQn5/PGTwkC2uLPaMnhePTEaXp9bcIhRmtSolbxqXijeJqvL+vFtOGJkldElFI6PUIyt69e5Gbm4vc3FwAwNKlS5Gbm4vly5cDADZt2oTc3FzMnj0bADB//nzk5ubi5Zdf9p1j5cqVuPnmm1FYWIjvfOc7MBqNWL9+vT/eD9EVMVs7sfWYZ9HAO/K4cixdHu/S91sOm2Czd0lcDVFoEMQgfF641WqFTqeDxWLh7R7yq1XbK/Ds1nJMHqTHOz+78C1HovOJoogZ/7cTlWfa8efbxuH7E/hQSaIL6c3nd1DM4iHqD10uN970NsfyuTvUC4IgYF53syyfcEzkHwwoRN0+KTuNBksn9NEa3Dj6wjPKiC7Gu9pwUWUT6lrPSlwNUfBjQCHq5l059rYJ6dCqlBJXQ8EmPSEKU7L1EEXPlGMiujIMKEQAapo78En5aQDAgsm8vUN9U9jdLPv+vloEYXsfkawwoBABeGtPNUQRuGZoEgYlRUtdDgWpWWNSEaFWoPJ0Ow7WWqQuhyioMaBQ2HN0ufH2Hk9j40JOLaYrEKNV4cZRnv6l90vZLEt0JRhQKOxtPWrGGZsdKbFazBhhkLocCnLeNVE2f1kPe5dL4mqIghcDCoU9b3Ps/EkZUCv5LUFXZuqQJBjitGjtcGLHV6elLocoaPGnMYW1E6dt2HWiCQoB+AGbY8kPlArBN+WYa6IQ9R0DCoW1N0s8C7NNz0nBgPhIiauhUDEv13ObZ0dZI5rbHRJXQxScGFAobHU6XXhvn7c5dqDE1VAoGW6MxegBcXC6RGw+WC91OURBiQGFwtaHhxrQ2uHEgPhIfGdYstTlUIjxronC2zxEfcOAQmFrbfftnTvyMqFUCBJXQ6HmlnFpUCkEHKy14Hhjm9TlEAUdBhQKS8carCg91QKVQsBtE/nkWfK/pBgtrhvuGZlbv49L3xP1FgMKhaV13aMnM0cZkRIbIXE1FKq8a6Js2F8Hl5tL3xP1BgMKhZ12exc2dD/MjSvHUiBNz0lBXIQKDZZOFFc2SV0OUVBhQKGws+lgPWz2LmQnRSN/cKLU5VAIi1Arccu4NACeBwgS0eVjQKGwIooi3ij2rBx7R14mBIHNsRRY3ts8Ww6b0G7vkrgaouDBgEJh5ctaC47UW6FRKXzTQIkCaXxmPAYlRqHD4cKWwyapyyEKGgwoFFa8z925eUwqEqI1EldD4UAQBN8oyvr9vM1DdLkYUChsWM46sal7Vc+FU9gcS/3n1u5n8+w60YT61rMSV0MUHBhQKGxs2FeLTqcbOcZYjM9MkLocCiMZ+ijkZekhisDGA1wThehyMKBQWBBF0bdy7EI2x5IEvD1P75fWQhS5JgrRpTCgUFjYc7IFFY02RKqVmNM93E7Un2aNMSJCrcCJ0+34stYidTlEsseAQmHB2xw756o0xEWoJa6GwlFshBozRxkB8AGCRJeDAYVCXpPNjv8c8kzvXJg3UOJqKJx5Z/NsOlgPR5db4mqI5I0BhULee6W1cLjcGJuuw5h0ndTlUBibOjgRKbFatHQ48UlZo9TlEMkaAwqFNLdbxLrdXzfHEklJpVRgbncPFJe+J/p2DCgU0r44cQanmjoQq1X5nolCJKV54z0B5eOvGtHS7pC4GiL5YkChkLa22DN6Mm/8AERpVBJXQwTkGOMwKi0OTpeID76sl7ocItliQKGQZbZ2YusxMwDgDjbHkox4m2Xf38dF24guhgGFQtbbe2rgcouYNCgBw42xUpdD5PO9cWlQKgQcqGnFidM2qcshkqVeB5RPP/0Ut9xyC9LS0iAIAjZu3NjjdVEUsXz5cqSmpiIyMhIFBQWoqKjocUxzczMWLlyIuLg4xMfH495774XNxm9S8p8ulxtv+ppjOXpC8pIcq8W1w5IBcE0UoovpdUBpb2/HuHHj8MILL1zw9WeeeQarVq3Cyy+/jJKSEkRHR2PmzJno7Oz0HbNw4UIcOXIEW7duxQcffIBPP/0UixYt6vu7IDrPJ2Wn0WDpREKUGjeONkpdDtE3eJe+37CvDm43l74nOl+vuwZnzZqFWbNmXfA1URTx3HPP4dFHH8WcOXMAAK+//joMBgM2btyI+fPn49ixY9iyZQv27NmDiRMnAgD+8pe/4KabbsKf//xnpKVxpgVdOe/KsbdNzECEWilxNUTfNGNECmIjVKi3dKK4qglXD06SuiQiWfFrD0pVVRVMJhMKCgp8+3Q6HfLy8lBUVAQAKCoqQnx8vC+cAEBBQQEUCgVKSkoueF673Q6r1dpjI7qYmuYOfFJ+GgCwYDLXPiF5ilArcfNYzz/I3i9lsyzR+fwaUEwmz3LiBoOhx36DweB7zWQyISUlpcfrKpUKer3ed8z5VqxYAZ1O59syMjL8WTaFmLf2VEMUgWlDkpCVFC11OUQXVdi9Jsp/Djegw9ElcTVE8hIUs3iWLVsGi8Xi22pqaqQuiWTK0eXG23s8TYdcOZbkbsLABAxMjEKHw4WPjlz4H2hE4cqvAcVo9DQjms3mHvvNZrPvNaPRiMbGns+g6OrqQnNzs++Y82m1WsTFxfXYiC5k61EzztjsSI7VomCk4dJfQCQhQRAwL9fTLLuea6IQ9eDXgJKVlQWj0Yjt27f79lmtVpSUlCA/Px8AkJ+fj9bWVpSWlvqO+fjjj+F2u5GXl+fPcigMeZtj50/KgFoZFAOEFOZu7X42z+fHz6DBclbiaojko9c/wW02Gw4cOIADBw4A8DTGHjhwANXV1RAEAQ899BCeeuopbNq0CYcOHcJdd92FtLQ0zJ07FwAwYsQI3Hjjjbjvvvuwe/dufPHFF7j//vsxf/58zuChK3LitA27TjRBIQDz2RxLQSIzMQqTB+khisDG/Vz6nsir1wFl7969yM3NRW5uLgBg6dKlyM3NxfLlywEAjzzyCB544AEsWrQIkyZNgs1mw5YtWxAREeE7x9q1a5GTk4MZM2bgpptuwrRp0/D3v//dT2+JwtWbJZ6F2b47PAUD4iMlrobo8hVO8IyirN9XC1HkmihEACCIQfjdYLVaodPpYLFY2I9CAIBOpwtTVmxHa4cT//jxREzPYf8JBQ9rpxOTntoGe5cbm++fhjHpOqlLIgqI3nx+8yY9hYQPDzWgtcOJAfGRuHZYyqW/gEhG4iLUuGGUZ5LA+1z6nggAAwqFiLXdt3cWTM6AUiFIXA1R783rXhNl08F6OLrcEldDJD0GFAp6xxqsKD3VApVCwO0TuYgfBadrhiQhOVaL5nYHdnavhEwUzhhQKOit6x49uWGUASlxEZc4mkieVEoF5l7lmcnIJxwTMaBQkGu3d2HDfs8CVwvzBkpcDdGVmdf9hOPtxxrR2uGQuBoiaTGgUFDbdLAeNnsXspKikZ+dKHU5RFdkRGocRqTGweFyY/OXDVKXQyQpBhQKat6VY++YnAkFm2MpBHgfIMjbPBTuGFAoaH1Z24rDdVZoVAoUTkiXuhwiv/jeVWlQKgTsr25F5Wmb1OUQSYYBhYLW2mJPc+zsManQR2skrobIP1JiI/CdoUkA4OuvIgpHDCgUlCxnndh00PPckoV5fO4OhRZvs+z6fXVwu4NusW8iv2BAoaC0cX8dzjpdGG6IxYSBCVKXQ+RX1480IDZChbrWsyipapa6HCJJMKBQ0BFF0dccu3BKJgSBzbEUWiLUStw8NhUAm2UpfDGgUNDZe6oF5WYbItVKzM0dIHU5RAHhvc3z4aEGnHW4JK6GqP8xoFDQWVvsGT2Zc1Ua4iLUEldDFBgTByYgQx+JdocLHx0xSV0OUb9jQKGg0tzuwIeHPD+suXIshTJBEDAv1zOKwiccUzhiQKGg8l5pDRwuN8am6zAmXSd1OUQB5X3C8RfHz8Bk6ZS4GqL+xYBCQcPtFn0PBuTUYgoHAxOjMWlQAtwi8K8DXBOFwgsDCgWNXSeacLKpA7FaFW4ZlyZ1OUT9wtss+/6+Wogi10Sh8MGAQkHDO7V43vgBiNKoJK6GqH/cNCYVGpUC5WYbjtRbpS6HqN8woFBQMFs78d+jZgDAHWyOpTCii1Tj+pEGAGyWpfDCgEJB4Z09NXC5RUwalIDhxlipyyHqV9/vvs2z6UA9nC63xNUQ9Q8GFJI9l1vEm7u9zbEcPaHwc83QJCTFaNDU7sCn5aelLoeoXzCgkOx9UtaIeksnEqLUuHG0UepyiPqdSqnAnKs8U455m4fCBQMKyd7a7qnFt03MQIRaKXE1RNLwromy7WgjLB1OiashCjwGFJK12pYO7ChrBAAsmMy1Tyh8jUrTIccYC4fLjQ8O1UtdDlHAMaCQrL21uwaiCEwbkoSspGipyyGSVGF3s+z6fVy0jUIfF5MgWXK5RXzwZT3e6F77hCvHEnkekLniP8dQeqoFVWfagzK0u9wiapo7UGZuQ4W5DWVmGyrMbahtOYvYCBX00RokxmiRFK1BYowG+mgtEmM0SIrRIDFaC320BkkxWkRqeLs31DGgkKy43SL+c9iE57aVo6LRBgAYZohBQfc6EEThLCUuAtcMTcbO8tPYsK8WS28YLnVJFyWKIupaz6Lc3IZysw3lpjaUN7ahwmyDvevCU6Vt9i40XOYzh6I0Sl+A8YaZxBgtEr2/PifM6KM10Kh4wyDYMKCQLIiiiP8eNWPl1nJ8ZWoD4FmgatF3svGjqwdBreQPFyIAKJyQjp3lp7F+fx0eKhgGhUKQtB5RFGG22ruDiGcrM9tw3NyGdofrgl+jVSkw1BCDYSmxGGqIxXBjDDL10ehwdKHJ5kBTuwNNNjua2h04Y7Ojud3h2W+z40y7A44uNzocLnQ0n0VN89nLqjMuQtUzwHh/3T1i4w01iTEaJERpoJT4/ysxoJDERFHEjrJGPLu1HIfrPMt4x2pVuPeaLNwzLQtxEWqJKySSlxtGGhCrVaG25Sz2nGxGXnZiv/3ZZ2x2z0jIObdmys1tsHZ2XfB4tVLA4OQYTwgxeP8biwx9VJ8DgCiKaHe4PGGlO7Q0tzt8YabJ5kCz99ftnl+73CKsnV2wdnah6kz7Jf8MQQD0UZru203nhpmvbzf5bj1FaxEXqYIgMND4GwMKSUIURXxacQbPbi3HwZpWAEC0Rom7p2bhvmuyoYtiMCG6kAi1EjeNScXbe2vw/r7agASU1g6H57bMOaMi5WYbmtsdFzxeqRAwKDEKw42xGJoSi2HdoyIDE6P9PvopCAJitCrEaFUYmHjpHhy3W4S109kjzJzxjtCcF2aabHa0nnVCFOH5fbsDFY2XrkmlEHy9M4Y4LX51/XCMSdf54d2Gt4AElLa2Njz22GPYsGEDGhsbkZubi+effx6TJk0C4Plwevzxx/HKK6+gtbUVU6dOxUsvvYShQ4cGohySmV3HPcFk76kWAECkWom7rh6In35nMPTRGomrI5K/eeMH4O29NfjwkAlPfG90nxtG2zqdqGjs7g8x21DR2IYyUxsa2+wXPF4QgEx9FIYZYjHMENP931hkJ0dDq5Jn06pCISA+SoP4KA2GpMRc8vgulxstHU40tdt73m4679aT979tnV3ocotobLOjsc2OYw2AWqnAK3dN7Id3F9oCElB+8pOf4PDhw/jnP/+JtLQ0vPHGGygoKMDRo0cxYMAAPPPMM1i1ahXWrFmDrKwsPPbYY5g5cyaOHj2KiIiIQJREMrC7qhnPbi1DcWUzAM996DunDMTPrh2M5FitxNURBY9Jg/RIT4hEbctZ/PeoybfK7MV0OLpwvNHmCSHmtu4ZNDbUtV68f2NAfGSPEDLMEIshKTEhP3tGpVQgOVZ72T+T7F0uX4/Ml7UW/H8bDmHPyWa43aLk/UHBThBFUfTnCc+ePYvY2Fj861//wuzZs337J0yYgFmzZuHJJ59EWloafvWrX+HXv/41AMBiscBgMOC1117D/PnzL/lnWK1W6HQ6WCwWxMXF+bN8CoDSUy1YubUcnx8/AwDQKBW4Iy8TP79uMAxxDKREffHs1nKs2l6Ba4clY809kwF4PixPNLb7RkK8t2lqWjpwsZ/0hjjtOSHEE0iGGmIRo2UHQG85XW6Me+K/6HC48J8Hr8GIVH4+na83n99+/xvY1dUFl8v1jZGQyMhIfP7556iqqoLJZEJBQYHvNZ1Oh7y8PBQVFV1WQKHgcLCmFSu3leOTMs/DzdRKAbdPzMDi7w5BWnykxNURBbd5uQOwansFPqs4jZ/9sxTljW041dQBl/vCSSQxWoOhhhgMN3hnzsRiWEos+738SK1UYMLABHxWcQYllU0MKFfI7wElNjYW+fn5ePLJJzFixAgYDAa8+eabKCoqwpAhQ2AymQAABkPPdS0MBoPvtfPZ7XbY7V/fE7Varf4um/zoSL0FK7dWYNsxMwBPA933x6fj/ulDkKGPkrg6otAwKCkaEwYmoPRUC7Yc+fpnZ1yEytOs2j1jZmj3qEhSDG+j9ocp2YmegFLVjB9PzZK6nKAWkDG8f/7zn7jnnnswYMAAKJVKjB8/HgsWLEBpaWmfzrdixQo88cQTfq6S/K3M1IaVW8t9PywVAnBrbjp+OWPIZXXbE1Hv/OHWMXhrT3V3v4hnVCQlVssprxLKy9ID8PTciaLIa3EFAhJQBg8ejJ07d6K9vR1WqxWpqan4wQ9+gOzsbBiNRgCA2WxGamqq72vMZjOuuuqqC55v2bJlWLp0qe/3VqsVGRkZgSid+uB4ow3PbSvHvw81QBQ9nf63jE3DgwVDMTj50l3zRNQ3w42xePyWUVKXQecYmx6PCLUCTe0OnDhtw5CUWKlLCloB7YKKjo5GdHQ0Wlpa8NFHH+GZZ55BVlYWjEYjtm/f7gskVqsVJSUl+PnPf37B82i1Wmi1HJ6Um5Nn2vH89gr860AdvLe9Z49JxYMFQzHMwG9KIgo/GpUC4zMTsOtEE4ormxlQrkBAAspHH30EURQxfPhwHD9+HA8//DBycnJw9913QxAEPPTQQ3jqqacwdOhQ3zTjtLQ0zJ07NxDlkJ/VNHdg1fYKrN9f52vIu2GkAUuuH8amMCIKe5Oz9Nh1ogklVc24c8pAqcsJWgEJKBaLBcuWLUNtbS30ej0KCwvx+9//Hmq1p1v8kUceQXt7OxYtWoTW1lZMmzYNW7Zs4RooMlfXehZ//fg43t1bg67uYDI9JwVLCoZx1UQiom55WYkAKlBS2cQ+lCvg93VQ+gPXQelfJksnXthxHG/tqYbT5fnr8p1hyVhSMBS5mQkSV0dEJC+dThfG/s9/4XC5sePX1yEriZMEvCRdB4VCR2NbJ1765ATWllTD0f149KsHJ2LJ9cMwaZBe4uqIiOQpQq3EVRnx2H2yGSWVTQwofcSAQt/QZLPjb59W4vWik+h0eoLJpEEJWHr9cOQP7r8npxIRBau8bD12n2zG7qpmzJ+cKXU5QYkBhXxa2h145bNKvLbrJDocLgBAbmY8fnX9cEwdksj7qERElykvKxF/wXGUVDVLXUrQYkAhWM468ernVfjH51Ww2bsAAGPTdVhy/TBcNyyZwYSIqJfGD4yHSiGgrvUsapo7uIp2HzCghLG2TidWf3ESr3xWibZOTzAZkRqHpdcPQ8GIFAYTIqI+itKoMCZdh/3VrSipamZA6QMGlDDUbu/CmqKT+PunlWjtcAIAhhlisKRgGGaOMvIR4UREfpCXlegJKJVN+P6EdKnLCToMKGHkrMOFN4pP4eWdJ9DU7gAAZCdH46GCYbh5TCqDCRGRH+Vl6/HyzhPYfZJ9KH3BgBIGOp0uvLm7Gi9+cgKn2zxPhR6UGIUHC4bie+MGQMlgQkTkdxMHJkAhAKeaOmCydMKo42KkvcGAEsLsXS68s7cWL3x8HCZrJwAgPSESv5wxFPNyB0ClVEhcIRFR6IqNUGNUmg6H6iwoqWrCnKsGSF1SUGFACUFOlxvvldbirx8fR13rWQBAmi4C908fiu9PSIdGxWBCRNQf8rL0OFRnQXFlMwNKLzGghJAulxsb9tdh1ccVqGn2BJOUWC3unz4EP5iUAa1KKXGFREThJS87Ef/v8yqUVDVJXUrQYUAJAS63iM0H6/H89gpUnWkHACTFaPDz64ZgYV4mItQMJkREUpg8SA9BACpPt6OxrRMpsexDuVwMKEHM7Rbx4eEGPLetAscbbQAAfbQGP7s2G3dOGYgoDS8vEZGUdFFq5BjjcKzBij1VLZg9NlXqkoIGP8GCkCiK+OiICSu3VqDM3AYA0EWqseg72fjR1YMQo+VlJSKSi7wsPY41WFFS1cSA0gv8JAsioihi+7FGrNxWjiP1VgBAbIQKP5mWjbunDUJchFriComI6Hx5WXq8tuskSiq5HkpvMKAEAVEUsbP8NFZuLcfBWgsAIFqjxD3TsvCTadnQRTGYEBHJ1eQsPQCgzNyG5nYH9NEaiSsKDgwoMiaKInadaMKzW8tReqoFABCpVuJHVw/Cou9k8y85EVEQSIzRYmhKDCoabdhd1YwbRxulLikoMKDIVEllE/5vazl2dz+qW6tS4IdTBuJn1w1GUoxW4uqIiKg38rL1qGi0oaSqiQHlMjGgyEzpqWY8u7UcXxz3zJnXKBW4Iy8Tv7huMFLiOD2NiCgY5WUl4o3iat8/OunSGFBk4kBNK1ZuLcfO8tMAALVSwA8mZWDxd4cgVRcpcXVERHQl8rr7UI42WGE564Qukr2Dl8KAIrHDdRY8t60c2441AgCUCgG3TUjH/dOHID0hSuLqiIjIH1LiIpCVFI2qM+3Ye7IZM0YYpC5J9hhQJPKVyYqVW8vx0REzAEAhAPPGp+OB6UMwMDFa4uqIiMjf8rL0qDrTjpIqBpTLwYDSz443tmHltgr8+8sGAIAgAHPGpeGXM4YiOzlG4uqIiChQ8rL1eGtPDUoq+Vyey8GA0k+qzrTj+W3l+NfBeoiiZ9/ssal4aMZQDDXESlscEREFXF5WIgDgcL0VNnsXV/2+BP7fCbDqpg6s+rgCG/bXweX2JJOZowx4qGAYRqTGSVwdERH1l7T4SGToI1HTfBalp1pw7bBkqUuSNQaUAKlt6cALO47j3b216OoOJjNyUrDk+mEYPUAncXVERCSFvKxE1DTXoqSyiQHlEhhQ/Mxk6cRfd1Tg7T01cLo8weTaYclYcv0wXJURL21xREQkqclZerxXWosSrodySQwoftLY1okXd5zAut3VcHS5AQBThyRiScEwTBykl7g6IiKSgyndfShf1rbirMOFSI1S4orkiwHlCjXZ7Hh55wn8s/gUOp2eYDJ5kB5LbxiGKdmJEldHRERykqGPRKouAg2WTuyrbsHUIUlSlyRbDCh91NLuwN8/q8SaXSfR4XABAHIz4/Gr64dj6pBECIIgcYVERCQ3giAgL0uPjQfqUVLZxIDyLRhQesly1olXP6vEP744CZu9CwAwNl2HpdcPw7XDkhlMiIjoW+VlJ3oCCvtQvhUDymVq63Ri9Rcn8cpnlWjr9ASTkalxWHr9MMwYkcJgQkREl2Vy93N59te0otPpQoSafSgXovD3CV0uFx577DFkZWUhMjISgwcPxpNPPgnRuzoZAFEUsXz5cqSmpiIyMhIFBQWoqKjwdyl+0W7vwgs7juOaZ3bg2a3laOvswnBDLF6+czw+eGAaCkYaGE6IiOiyZSdFIylGC0eXGwdrWqUuR7b8PoLy9NNP46WXXsKaNWswatQo7N27F3fffTd0Oh1++ctfAgCeeeYZrFq1CmvWrEFWVhYee+wxzJw5E0ePHkVERIS/S+qTsw4X/ll8Ei/vrERzuwMAMDg5Gg8VDMPsMalQKBhKiIio9wRBQF62Hv/+sgElVc3I44SKC/J7QNm1axfmzJmD2bNnAwAGDRqEN998E7t37wbgGT157rnn8Oijj2LOnDkAgNdffx0GgwEbN27E/Pnz/V1Sr3Q6XVhXUo0XPzmBMzY7AGBQYhQeLBiK740bACWDCRERXaEpWd6A0gRgqNTlyJLfb/FcffXV2L59O8rLywEABw8exOeff45Zs2YBAKqqqmAymVBQUOD7Gp1Oh7y8PBQVFV3wnHa7HVartccWCB9/Zca1f9qB//3gKM7Y7MjQR+JP3x+LbUuvxa256QwnRETkF95Rk9JTLb61s6gnv4+g/Pa3v4XVakVOTg6USiVcLhd+//vfY+HChQAAk8kEADAYej5q2mAw+F4734oVK/DEE0/4u9Rv0EdrYbbakaaLwAMzhuL7E9KhVvo9wxERUZgbmhIDfbQGze0OHKqzYMLABKlLkh2/f/q+8847WLt2LdatW4d9+/ZhzZo1+POf/4w1a9b0+ZzLli2DxWLxbTU1NX6s+GtXZcTj/901ETsevg4LJmcynBARUUAIgoBJgzyhxHObh87n90/ghx9+GL/97W8xf/58jBkzBj/84Q+xZMkSrFixAgBgNBoBAGazucfXmc1m32vn02q1iIuL67EFSsFIA7QqTvkiIqLAyute9r6kkuuhXIjfA0pHRwcUip6nVSqVcLs999iysrJgNBqxfft23+tWqxUlJSXIz8/3dzlERESylJftWQ9l78lmdLnYh3I+v/eg3HLLLfj973+PzMxMjBo1Cvv378ezzz6Le+65B4BnWOuhhx7CU089haFDh/qmGaelpWHu3Ln+LoeIiEiWcoxxiItQwdrZhSP1VozjE+978HtA+ctf/oLHHnsMv/jFL9DY2Ii0tDT89Kc/xfLly33HPPLII2hvb8eiRYvQ2tqKadOmYcuWLbJZA4WIiCjQlAoBk7P02HasEburmhlQziOI5y7xGiSsVit0Oh0sFktA+1GIiIgC6ZVPK/H7D4+hYEQK/t+PJkldTsD15vOb01SIiIgk4n0uz+6qZrjcQTdeEFAMKERERBIZlRaHGK2nD+UrU2AWIQ1WDChEREQSUSkVvkXaON24JwYUIiIiCXmnG3PBtp4YUIiIiCTkXbBtd1UzgnDeSsAwoBAREUlozAAdItVKtHQ4UdFok7oc2WBAISIikpBGpcD4gfEAgJJK3ubxYkAhIiKSmPc2T3EVG2W9GFCIiIgklte9HkpJJftQvBhQiIiIJDYuIx4alQJnbHZUnmmXuhxZYEAhIiKSWIRaidzuZ/Hs5m0eAAwoREREsvD1bR42ygIMKERERLKQl+1plC3heigAGFCIiIhkYXxmAtRKAQ2WTtQ0n5W6HMkxoBAREclApEaJsenxAIBiLnvPgEJERCQX5043DncMKERERDLh7UPZfZIjKAwoREREMjFhYAKUCgE1zWdR3xrefSgMKERERDIRo1VhdFocAKAkzPtQGFCIiIhkxDfdOMz7UBhQiIiIZMTXKBvmK8oyoBAREcnIxEF6CAJQdaYdjdZOqcuRDAMKERGRjOgi1RiZ6u1DCd9RFAYUIiIimZnsu80Tvo2yDChEREQyk5fFRlkGFCIiIpnxjqBUNNrQZLNLXI00GFCIiIhkRh+twXBDLABgd5j2oTCgEBERyVBednhPN2ZAISIikiFfHwoDChEREcnFpKwEAMBXJissHU6Jq+l/DChEREQylBIbgezkaIgisPtk+I2i+D2gDBo0CIIgfGNbvHgxAKCzsxOLFy9GYmIiYmJiUFhYCLPZ7O8yiIiIgt7X043Dbz0UvweUPXv2oKGhwbdt3boVAHDbbbcBAJYsWYLNmzfj3Xffxc6dO1FfX4958+b5uwwiIqKgNyWMG2VV/j5hcnJyj9//8Y9/xODBg3HttdfCYrHg1Vdfxbp16zB9+nQAwOrVqzFixAgUFxdjypQp/i6HiIgoaHnXQzlSb0FbpxOxEWqJK+o/Ae1BcTgceOONN3DPPfdAEASUlpbC6XSioKDAd0xOTg4yMzNRVFQUyFKIiIiCTqouEpn6KLhFYO+pFqnL6VcBDSgbN25Ea2srfvzjHwMATCYTNBoN4uPjexxnMBhgMpkueh673Q6r1dpjIyIiCgd53ufyhNmy9wENKK+++ipmzZqFtLS0KzrPihUroNPpfFtGRoafKiQiIpK3vGzveijh1SgbsIBy6tQpbNu2DT/5yU98+4xGIxwOB1pbW3scazabYTQaL3quZcuWwWKx+LaamppAlU1ERCQr3hGUQ7UWdDi6JK6m/wQsoKxevRopKSmYPXu2b9+ECROgVquxfft2376ysjJUV1cjPz//oufSarWIi4vrsREREYWDDH0UBsRHosstojSM+lACElDcbjdWr16NH/3oR1Cpvp4opNPpcO+992Lp0qXYsWMHSktLcffddyM/P58zeIiIiC7CO4oSTg8O9Ps0YwDYtm0bqqurcc8993zjtZUrV0KhUKCwsBB2ux0zZ87Eiy++GIgyiIiIQsLkLD3W768Lq0ZZQRRFUeoiestqtUKn08FisfB2DxERhbyqM+347p8/gUapwJf/cwMi1EqpS+qT3nx+81k8REREMjcoMQopsVo4XG7sr26Vupx+wYBCREQkc4IghN10YwYUIiKiIBBuC7YxoBAREQUB74MD91W3wNHllriawGNAISIiCgKDk2OQGK2BvcuNL2tbpS4n4BhQiIiIgoAgCL6nG5eEwXooDChERERBwtuHUlwZ+o2yDChERERBwjuTp/RUC5yu0O5DYUAhIiIKEsMNsYiPUqPD4cLhOovU5QQUAwoREVGQUCgETBoUHs/lYUAhIiIKInlh0ijLgEJERBRE8rI8fSh7qprhcgfd4/QuGwMKERFREBmZFodYrQpt9i4ca7BKXU7AMKAQEREFEaVCwMRBCQBCe7oxAwoREVGQ8U43DuVGWQYUIiKiIONdUXb3yWa4Q7QPhQGFiIgoyIwZoEOURonWDifKG9ukLicgGFCIiIiCjFqpwISBnj6UksrQvM3DgEJERBSEvl4PJTQbZRlQiIiIgtC5jbKiGHp9KAwoREREQWhsug5alQJnbA6cON0udTl+x4BCREQUhLQqJXIz4wGE5m0eBhQiIqIg5V32PhQbZRlQiIiIglRe9teNsqHWh8KAQkREFKTGZyZAo1TAbLXjVFOH1OX4FQMKERFRkIpQKzEuQwcg9PpQGFCIiIiCmK8PJcSey8OAQkREFMS8z+UJtUZZBhQiIqIgNmFgApQKAXWtZ1HbEjp9KAwoREREQSxaq8KYAd19KCE0isKAQkREFOTOnW4cKhhQiIiIgtyUEGyUDUhAqaurw5133onExERERkZizJgx2Lt3r+91URSxfPlypKamIjIyEgUFBaioqAhEKURERCFvwqAEKATgVFMHTJZOqcvxC78HlJaWFkydOhVqtRr/+c9/cPToUfzf//0fEhISfMc888wzWLVqFV5++WWUlJQgOjoaM2fORGdnaPxPJSIi6k9xEWqMTIsDEDq3eVT+PuHTTz+NjIwMrF692rcvKyvL92tRFPHcc8/h0UcfxZw5cwAAr7/+OgwGAzZu3Ij58+f7uyQiIqKQl5eViMN1VpRUNWPOVQOkLueK+X0EZdOmTZg4cSJuu+02pKSkIDc3F6+88orv9aqqKphMJhQUFPj26XQ65OXloaio6ILntNvtsFqtPTYiIiL6Wp5vPZTQGEHxe0CprKzESy+9hKFDh+Kjjz7Cz3/+c/zyl7/EmjVrAAAmkwkAYDAYenydwWDwvXa+FStWQKfT+baMjAx/l01ERBTUJmfpIQjAidPtON1ml7qcK+b3gOJ2uzF+/Hj84Q9/QG5uLhYtWoT77rsPL7/8cp/PuWzZMlgsFt9WU1Pjx4qJiIiCX3yUBsMNsQCA3SEwm8fvASU1NRUjR47ssW/EiBGorq4GABiNRgCA2WzucYzZbPa9dj6tVou4uLgeGxEREfXkvc2zOwQaZf0eUKZOnYqysrIe+8rLyzFw4EAAnoZZo9GI7du3+163Wq0oKSlBfn6+v8shIiIKG3nZobMeit8DypIlS1BcXIw//OEPOH78ONatW4e///3vWLx4MQBAEAQ89NBDeOqpp7Bp0yYcOnQId911F9LS0jB37lx/l0NERBQ2vA8O/MrUhpZ2h8TVXBm/B5RJkyZhw4YNePPNNzF69Gg8+eSTeO6557Bw4ULfMY888ggeeOABLFq0CJMmTYLNZsOWLVsQERHh73KIiIjCRlKMFkNSYgAAu08G9yiKIIqiKHURvWW1WqHT6WCxWNiPQkREdI7fbTiEtSXVuGdqFpbfMvLSX9CPevP5zWfxEBERhRBvH8ruk8HdKMuAQkREFEK8M3mO1lth7XRKXE3fMaAQERGFEENcBAYlRsEtAnuDuA+FAYWIiCjE5GV1TzeuZEAhIiIimcjL9tzmKQ7i9VAYUIiIiEKMt1H2cJ0FNnuXxNX0DQMKERFRiBkQH4n0hEi43CL2nWqRupw+YUAhIiIKQd5VZUuC9Lk8DChEREQhaEqQN8oyoBAREYUgb6PswdpWnHW4JK6m9xhQiIiIQlCmPgrGuAg4XSL2VwdfHwoDChERUQgSBCGopxszoBAREYUo74Jtu4OwUZYBhYiIKER5Z/Lsr26FvSu4+lAYUIiIiELU4ORoJMVoYe9y42CNRepyeoUBhYiIKEQJguB7unFJZXDd5mFAISIiCmHeRtmSIGuUZUAhIiIKYd5G2dJTLXC63BJXc/kYUIiIiELY0JQYxEepcdbpwqG64OlDYUAhIiIKYQqFgMmDvH0owXObhwGFiIgoxOVldz+XJ4jWQ2FAISIiCnHemTx7T7agK0j6UBhQiIiIQtyI1DjERqhgs3fhaINV6nIuCwMKERFRiFMGYR8KAwoREVEY8C57HyzroTCgEBERhQFvo+yek81wu0WJq7k0BhQiIqIwMDotDtEaJSxnnfjK1CZ1OZfEgEJERBQGVEoFJnj7UIJgujEDChERUZj4+sGB8u9DYUAhIiIKE1O6Hxy4+2QzRFHefSgMKERERGFizIB4RKgVaG534HijTepyvhUDChERUZjQqBQYn5kAACiW+XRjvweU//mf/4EgCD22nJwc3+udnZ1YvHgxEhMTERMTg8LCQpjNZn+XQURERBeQl9X9XJ5KeTfKBmQEZdSoUWhoaPBtn3/+ue+1JUuWYPPmzXj33Xexc+dO1NfXY968eYEog4iIiM6Tl/31gm1y7kNRBeSkKhWMRuM39lssFrz66qtYt24dpk+fDgBYvXo1RowYgeLiYkyZMiUQ5RAREVG3qzLioVEpcLrNjqoz7chOjpG6pAsKyAhKRUUF0tLSkJ2djYULF6K6uhoAUFpaCqfTiYKCAt+xOTk5yMzMRFFR0UXPZ7fbYbVae2xERETUexFqJa7KiAcA7JZxH4rfA0peXh5ee+01bNmyBS+99BKqqqpwzTXXoK2tDSaTCRqNBvHx8T2+xmAwwGQyXfScK1asgE6n820ZGRn+LpuIiChs5AXBc3n8fotn1qxZvl+PHTsWeXl5GDhwIN555x1ERkb26ZzLli3D0qVLfb+3Wq0MKURERH2Ul5WIv+A4SiqbIIoiBEGQuqRvCPg04/j4eAwbNgzHjx+H0WiEw+FAa2trj2PMZvMFe1a8tFot4uLiemxERETUN+MHxkOlEFBv6URty1mpy7mggAcUm82GEydOIDU1FRMmTIBarcb27dt9r5eVlaG6uhr5+fmBLoWIiIgARGlUGJuuAwAUy3S6sd8Dyq9//Wvs3LkTJ0+exK5du3DrrbdCqVRiwYIF0Ol0uPfee7F06VLs2LEDpaWluPvuu5Gfn88ZPERERP0oL7t7PRSZ9qH4vQeltrYWCxYsQFNTE5KTkzFt2jQUFxcjOTkZALBy5UooFAoUFhbCbrdj5syZePHFF/1dBhEREX2LyVl6vPTJCdnO5BFEOa/SchFWqxU6nQ4Wi4X9KERERH3Q1unEuCf+C7cIFC2bjlRd3yay9EZvPr/5LB4iIqIwFBuhxugBnj6Ukkr5jaIwoBAREYWpr9dDkV+jLAMKERFRmPr6wYEcQSEiIiKZmDRID0EAKs+0o9HaKXU5PTCgEBERhSldlBo5Rk+z6u6T8hpFYUAhIiIKY74+FJnd5mFAISIiCmNTsuXZKMuAQkREFMYmdzfKlpttaG53SFzN1xhQiIiIwpg+WoNhhhgAwG4ZjaIwoBAREYU573TjYhn1oTCgEBERhbnJ3Y2ycnouDwMKERFRmMvrbpQ9ZrLC0uGUuBoPBhQiIqIwlxIbgeykaIgisEcm66EwoBAREZFvFEUu040ZUIiIiOjr5/LIpA+FAYWIiIh8jbKH6yyw2bskroYBhYiIiACkxUciQx8JtwjslUEfCgMKERERAZDXbR4GFCIiIgJw7oMDpW+UZUAhIiIiAMCUbM8Iype1FnQ4pO1DYUAhIiIiAEB6QiTSdBHocovYd6pV0loYUIiIiAgAIAjCOcveS3ubhwGFiIiIfPK6b/MUS9woq5L0TyciIiJZmTo4CXfkZWLakCRJ62BAISIiIp/MxCj84dYxUpfBWzxEREQkPwwoREREJDsMKERERCQ7DChEREQkOwwoREREJDsMKERERCQ7AQ8of/zjHyEIAh566CHfvs7OTixevBiJiYmIiYlBYWEhzGZzoEshIiKiIBHQgLJnzx787W9/w9ixY3vsX7JkCTZv3ox3330XO3fuRH19PebNmxfIUoiIiCiIBCyg2Gw2LFy4EK+88goSEhJ8+y0WC1599VU8++yzmD59OiZMmIDVq1dj165dKC4uDlQ5REREFEQCFlAWL16M2bNno6CgoMf+0tJSOJ3OHvtzcnKQmZmJoqKiC57LbrfDarX22IiIiCh0BWSp+7feegv79u3Dnj17vvGayWSCRqNBfHx8j/0GgwEmk+mC51uxYgWeeOKJQJRKREREMuT3EZSamho8+OCDWLt2LSIiIvxyzmXLlsFisfi2mpoav5yXiIiI5MnvAaW0tBSNjY0YP348VCoVVCoVdu7ciVWrVkGlUsFgMMDhcKC1tbXH15nNZhiNxgueU6vVIi4ursdGREREocvvt3hmzJiBQ4cO9dh39913IycnB7/5zW+QkZEBtVqN7du3o7CwEABQVlaG6upq5OfnX9afIYoiALAXhYiIKIh4P7e9n+Pfxu8BJTY2FqNHj+6xLzo6GomJib799957L5YuXQq9Xo+4uDg88MADyM/Px5QpUy7rz2hrawMAZGRk+Ld4IiIiCri2tjbodLpvPSYgTbKXsnLlSigUChQWFsJut2PmzJl48cUXL/vr09LSUFNTg9jYWAiCEMBKg5fVakVGRgZqamp4S0wGeD3khddDXng95CdQ10QURbS1tSEtLe2Sxwri5YyzUNCxWq3Q6XSwWCz8hpcBXg954fWQF14P+ZHDNeGzeIiIiEh2GFCIiIhIdhhQQpRWq8Xjjz8OrVYrdSkEXg+54fWQF14P+ZHDNWEPChEREckOR1CIiIhIdhhQiIiISHYYUIiIiEh2GFCIiIhIdhhQgsinn36KW265BWlpaRAEARs3buzxutlsxo9//GOkpaUhKioKN954IyoqKnocYzKZ8MMf/hBGoxHR0dEYP3483n///X58F6FjxYoVmDRpEmJjY5GSkoK5c+eirKysxzGdnZ1YvHgxEhMTERMTg8LCQpjN5h7HVFdXY/bs2YiKikJKSgoefvhhdHV19edbCQn+uB4HDx7EggULkJGRgcjISIwYMQLPP/98f7+VkOCv7w+vpqYmpKenQxCEbzxsli7Nn9fjtddew9ixYxEREYGUlBQsXrw4IDUzoASR9vZ2jBs3Di+88MI3XhNFEXPnzkVlZSX+9a9/Yf/+/Rg4cCAKCgrQ3t7uO+6uu+5CWVkZNm3ahEOHDmHevHm4/fbbsX///v58KyFh586dWLx4MYqLi7F161Y4nU7ccMMNPf5/L1myBJs3b8a7776LnTt3or6+HvPmzfO97nK5MHv2bDgcDuzatQtr1qzBa6+9huXLl0vxloKaP65HaWkpUlJS8MYbb+DIkSP43e9+h2XLluGvf/2rFG8pqPnjepzr3nvvxdixY/ur/JDjr+vx7LPP4ne/+x1++9vf4siRI9i2bRtmzpwZmKJFCkoAxA0bNvh+X1ZWJgIQDx8+7NvncrnE5ORk8ZVXXvHti46OFl9//fUe59Lr9T2Oob5pbGwUAYg7d+4URVEUW1tbRbVaLb777ru+Y44dOyYCEIuKikRRFMUPP/xQVCgUoslk8h3z0ksviXFxcaLdbu/fNxBi+nI9LuQXv/iF+N3vfjfg9Ya6K7keL774onjttdeK27dvFwGILS0t/Vl6SOrL9WhubhYjIyPFbdu29UuNHEEJEXa7HQAQERHh26dQKKDVavH555/79l199dV4++230dzcDLfbjbfeegudnZ247rrr+rvkkGOxWAAAer0egOdf406nEwUFBb5jcnJykJmZiaKiIgBAUVERxowZA4PB4Dtm5syZsFqtOHLkSD9WH3r6cj0udh7vOajv+no9jh49iv/93//F66+/DoWCH1n+0pfrsXXrVrjdbtTV1WHEiBFIT0/H7bffjpqamoDUyKsdIrx/kZYtW4aWlhY4HA48/fTTqK2tRUNDg++4d955B06nE4mJidBqtfjpT3+KDRs2YMiQIRJWH/zcbjceeughTJ06FaNHjwbg6ffRaDSIj4/vcazBYIDJZPIdc2448b7ufY36pq/X43y7du3C22+/jUWLFgW65JDW1+tht9uxYMEC/OlPf0JmZmZ/lx2y+no9Kisr4Xa78Yc//AHPPfcc3nvvPTQ3N+P666+Hw+Hwe50qv5+RJKFWq7F+/Xrce++90Ov1UCqVKCgowKxZsyCes1jwY489htbWVmzbtg1JSUnYuHEjbr/9dnz22WcYM2aMhO8guC1evBiHDx/uMVpF0vHH9Th8+DDmzJmDxx9/HDfccIMfqws/fb0ey5Ytw4gRI3DnnXcGqLLw1Nfr4Xa74XQ6sWrVKt/3xJtvvgmj0YgdO3b4vReFIyghZMKECThw4ABaW1vR0NCALVu2oKmpCdnZ2QCAEydO4K9//Sv+8Y9/YMaMGRg3bhwef/xxTJw48YKNt3R57r//fnzwwQfYsWMH0tPTffuNRiMcDsc3ZhyYzWYYjUbfMed3yXt/7z2GeudKrofX0aNHMWPGDCxatAiPPvpof5Qdsq7kenz88cd49913oVKpoFKpMGPGDABAUlISHn/88X57D6HkSq5HamoqAGDkyJG+15OTk5GUlITq6mr/F9svnS7kdzivSfZCysvLRYVCIX700UeiKIril19+KQIQjx492uO4G264QbzvvvsCVWrIcrvd4uLFi8W0tDSxvLz8G697m87ee+89376vvvrqgk2yZrPZd8zf/vY3MS4uTuzs7Az8mwgh/rgeoiiKhw8fFlNSUsSHH364X+oOVf64HsePHxcPHTrk2/7xj3+IAMRdu3b1+J6hS/PH9fBOxji3SbapqanH54w/MaAEkba2NnH//v3i/v37RQDis88+K+7fv188deqUKIqi+M4774g7duwQT5w4IW7cuFEcOHCgOG/ePN/XOxwOcciQIeI111wjlpSUiMePHxf//Oc/i4IgiP/+97+leltB6+c//7mo0+nETz75RGxoaPBtHR0dvmN+9rOfiZmZmeLHH38s7t27V8zPzxfz8/N9r3d1dYmjR48Wb7jhBvHAgQPili1bxOTkZHHZsmVSvKWg5o/rcejQITE5OVm88847e5yjsbFRircU1PxxPc63Y8cOzuLpI39djzlz5oijRo0Sv/jiC/HQoUPizTffLI4cOVJ0OBx+r5kBJYh4vznP3370ox+JoiiKzz//vJieni6q1WoxMzNTfPTRR78xVbW8vFycN2+emJKSIkZFRYljx479xrRjujwXuhYAxNWrV/uOOXv2rPiLX/xCTEhIEKOiosRbb71VbGho6HGekydPirNmzRIjIyPFpKQk8Ve/+pXodDr7+d0EP39cj8cff/yC5xg4cGD/v6Eg56/vj3MxoPSdv66HxWIR77nnHjE+Pl7U6/XirbfeKlZXVwekZqG7cCIiIiLZYJMsERERyQ4DChEREckOAwoRERHJDgMKERERyQ4DChEREckOAwoRERHJDgMKERERyQ4DChEREckOAwoRERHJDgMKERERyQ4DChEREckOAwoRERHJzv8PmHiZvvkb5iMAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "with h5py.File(fnm, \"r\") as h5r:\n", + " # src = \"/InGaN_nanowires_spectra/InGaN nanowires/Area 1/Full Area 1\"\n", + " src = \"/VInP/VInP_108_L2/Area 10/LineScan 1/\"\n", + " if f\"{src}/LSD\" in h5r.keys():\n", + " # for key, val in enumerate(h5r[f\"{src}/LSD\"].attrs.items()):\n", + " # print(f\"{key}, {val}\")\n", + " tmp = np.asarray(h5r[f\"{src}/LSD\"][0])\n", + " print(f\"{type(tmp)}, {np.shape(tmp)}, {tmp.dtype}\")\n", + " for idx in np.arange(0, 2):\n", + " # src/ROIs/ is the integral\n", + " print(f\"{idx}\\t\\tIn L\\t\\t{np.sum(tmp[idx,323:335 + 1])}\")\n", + " print(f\"{idx}\\t\\tK K\\t\\t{np.sum(tmp[idx,326:337 + 1])}\")\n", + " print(f\"{idx}\\t\\tP K\\t\\t{np.sum(tmp[idx,197:206 + 1])}\")\n", + " # plt.plot(np.arange(323, 335 + 1), tmp[0,323:335 + 1])\n", + " plt.plot(np.arange(197, 206 + 1), tmp[0,197:206 + 1])\n", + " # for idx, val in enumerate(tmp.dtype.names):\n", + " # print(f\"{idx}, {val}, {tmp[val][0]}\")\n", + "\n", + " \"\"\"\n", + " if f\"{src}/SPC\" in h5r.keys():\n", + " spc = np.asarray(h5r[f\"{src}/SPC\"])\n", + " # print(f\"{type(spc)}, {np.shape(spc)}, {spc.dtype}\")\n", + " reqs = [\"eVOffset\", \"evPch\"] # , \"evPerChannel\", \"DeadTime\", \"CountRate\"]\n", + " for req in reqs: # \"\"SpectrumCounts\", \"\n", + " if req in spc.dtype.names:\n", + " print(f\"{req}, {spc[req][0]}\")\n", + " else:\n", + " raise ValueError(f\"Unable to find metadata entry {req}!\")\n", + " # for idx, val in enumerate(spc.dtype.names):\n", + " # print(f\"{idx}, {val}, {spc[val][0]}\")\n", + " print(\"DataStart\" in spc.dtype.names)\n", + " print(f\"{type(spc['SpectrumCounts'][0])}, {np.shape(spc['SpectrumCounts'][0])}, {spc['SpectrumCounts'][0].dtype}\") # [0])\n", + " \"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "7b58972c-dcd3-45ea-9fae-36c81de1ee9e", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'dat' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[35], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m plt\u001b[38;5;241m.\u001b[39mplot(\u001b[43mdat\u001b[49m[\u001b[38;5;241m0\u001b[39m, :])\n", + "\u001b[0;31mNameError\u001b[0m: name 'dat' is not defined" + ] + } + ], + "source": [ + "plt.plot(dat[0, :])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "441aaf8f-88df-47ea-9516-44f9666d717b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc341bf3-fefa-4a69-84d5-5abe576f2b29", + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": 24, "id": "f0a7f9ac-1ade-43d7-aedd-b2572d163b34", - "metadata": { - "jupyter": { - "source_hidden": true - } - }, + "metadata": {}, "outputs": [], "source": [ "\n", diff --git a/pynxtools/dataconverter/readers/em/concepts/nxs_image_r_set.py b/pynxtools/dataconverter/readers/em/concepts/nxs_image_r_set.py index 4a2ca2e58..da50a2101 100644 --- a/pynxtools/dataconverter/readers/em/concepts/nxs_image_r_set.py +++ b/pynxtools/dataconverter/readers/em/concepts/nxs_image_r_set.py @@ -65,9 +65,9 @@ def __init__(self): self.tmp: Dict = {} self.tmp["source"] = None for entry in NX_IMAGE_REAL_SPACE_SET_HDF_PATH: - if entry.endswith("-field") is True: + if entry.endswith("-field"): self.tmp[entry[0:len(entry) - len("-field")]] = NxObject(eqv_hdf="dataset") - elif entry.endswith("-attribute") is True: + elif entry.endswith("-attribute"): self.tmp[entry[0:len(entry) - len("-attribute")]] = NxObject(eqv_hdf="attribute") else: self.tmp[entry[0:len(entry) - len("-group")]] = NxObject(eqv_hdf="group") diff --git a/pynxtools/dataconverter/readers/em/concepts/nxs_object.py b/pynxtools/dataconverter/readers/em/concepts/nxs_object.py index 696be9a86..93c6f882f 100644 --- a/pynxtools/dataconverter/readers/em/concepts/nxs_object.py +++ b/pynxtools/dataconverter/readers/em/concepts/nxs_object.py @@ -28,7 +28,7 @@ class NxObject: def __init__(self, name: str = None, unit: str = None, - dtype=str, + dtype=None, value=None, **kwargs): if (name is not None) and (name == ""): @@ -44,10 +44,9 @@ def __init__(self, # use special values "unitless" for NX_UNITLESS (e.g. 1) and # "dimensionless" for NX_DIMENSIONLESS (e.g. 1m / 1m) self.dtype = dtype # use np.dtype if possible - if value is None or dtype is str: + if value is None or isinstance(dtype, str): self.unit = "unitless" - if value is not None: - self.value = value + self.value = value # value should be a numpy scalar, tensor, or string if possible self.eqv_hdf = None if "eqv_hdf" in kwargs: @@ -58,4 +57,4 @@ def __init__(self, def __repr__(self): """Report values.""" - return f"Name: {self.name}, unit: {self.unit}, dtype: {self.dtype}, eqv_hdf: {self.eqv_hdf}" + return f"Name: {self.name}, unit: {self.unit}, dtype: {self.dtype}, value: {self.value}, eqv_hdf: {self.eqv_hdf}" diff --git a/pynxtools/dataconverter/readers/em/concepts/nxs_spectrum_set.py b/pynxtools/dataconverter/readers/em/concepts/nxs_spectrum_set.py index 0e09e4ec9..d7be722a3 100644 --- a/pynxtools/dataconverter/readers/em/concepts/nxs_spectrum_set.py +++ b/pynxtools/dataconverter/readers/em/concepts/nxs_spectrum_set.py @@ -34,19 +34,16 @@ "PROCESS/mode-field", "PROCESS/PROGRAM-group", "PROCESS/source-group", - "spectrum_zerod-group", "spectrum_zerod/axis_energy-field", "spectrum_zerod/axis_energy@long_name-attribute", "spectrum_zerod/intensity-field", "spectrum_zerod/intensity@long_name-attribute", - "spectrum_oned-group", "spectrum_oned/axis_energy-field", "spectrum_oned/axis_energy@long_name-attribute", "spectrum_oned/axis_x-field", "spectrum_oned/axis_x@long_name-attribute", "spectrum_oned/intensity-field", "spectrum_oned/intensity@long_name-attribute", - "spectrum_threed-group", "spectrum_threed/axis_energy-field", "spectrum_threed/axis_energy@long_name-attribute", "spectrum_threed/axis_x-field", @@ -57,7 +54,6 @@ "spectrum_threed/axis_z@long_name-attribute", "spectrum_threed/intensity-field", "spectrum_threed/intensity@long_name-attribute", - "spectrum_twod-group", "spectrum_twod/axis_energy-field", "spectrum_twod/axis_energy@long_name-attribute", "spectrum_twod/axis_x-field", diff --git a/pynxtools/dataconverter/readers/em/reader.py b/pynxtools/dataconverter/readers/em/reader.py index 4ba4686ef..5a4f2b0b3 100644 --- a/pynxtools/dataconverter/readers/em/reader.py +++ b/pynxtools/dataconverter/readers/em/reader.py @@ -23,9 +23,9 @@ from pynxtools.dataconverter.readers.base.reader import BaseReader # from pynxtools.dataconverter.readers.em.concepts.nxs_concepts import NxEmAppDef -# from pynxtools.dataconverter.readers.em.subparsers.nxs_mtex import NxEmNxsMTexSubParser -# from pynxtools.dataconverter.readers.em.subparsers.nxs_pyxem import NxEmNxsPyxemSubParser -# from pynxtools.dataconverter.readers.em.subparsers.nxs_imgs import NxEmImagesSubParser +from pynxtools.dataconverter.readers.em.subparsers.nxs_mtex import NxEmNxsMTexSubParser +from pynxtools.dataconverter.readers.em.subparsers.nxs_pyxem import NxEmNxsPyxemSubParser +from pynxtools.dataconverter.readers.em.subparsers.nxs_imgs import NxEmImagesSubParser from pynxtools.dataconverter.readers.em.subparsers.nxs_nion import NxEmZippedNionProjectSubParser from pynxtools.dataconverter.readers.em.utils.default_plots import NxEmDefaultPlotResolver # from pynxtools.dataconverter.readers.em.geometry.convention_mapper import NxEmConventionMapper @@ -119,9 +119,9 @@ def read(self, # add further with resolving cases # if file_path is an HDF5 will use hfive parser - # sub_parser = "nxs_pyxem" - # subparser = NxEmNxsPyxemSubParser(entry_id, file_paths[0]) - # subparser.parse(template) + sub_parser = "nxs_pyxem" + subparser = NxEmNxsPyxemSubParser(entry_id, file_paths[0]) + subparser.parse(template) # TODO::check correct loop through! # sub_parser = "image_tiff" @@ -129,8 +129,8 @@ def read(self, # subparser.parse(template) # sub_parser = "zipped_nion_project" - subparser = NxEmZippedNionProjectSubParser(entry_id, file_paths[0]) - subparser.parse(template, verbose=True) + # subparser = NxEmZippedNionProjectSubParser(entry_id, file_paths[0]) + # subparser.parse(template, verbose=True) # for dat_instance in case.dat_parser_type: # print(f"Process pieces of information in {dat_instance} tech partner file...") diff --git a/pynxtools/dataconverter/readers/em/subparsers/hfive_apex.py b/pynxtools/dataconverter/readers/em/subparsers/hfive_apex.py index 6539417ea..b210365d2 100644 --- a/pynxtools/dataconverter/readers/em/subparsers/hfive_apex.py +++ b/pynxtools/dataconverter/readers/em/subparsers/hfive_apex.py @@ -54,24 +54,39 @@ def init_support(self): """Init supported versions.""" self.supported_version["tech_partner"] = ["EDAX, LLC"] self.supported_version["schema_name"] = ["EDAXH5"] - self.supported_version["schema_version"] = ["2.5.1001.0001"] + self.supported_version["schema_version"] = ["2.1.0009.0001", + "2.2.0001.0001", + "2.5.1001.0001"] self.supported_version["writer_name"] = ["APEX"] - self.supported_version["writer_version"] = ["2.5.1001.0001"] + self.supported_version["writer_version"] = ["2.1.0009.0001", + "2.2.0001.0001", + "2.5.1001.0001"] def check_if_supported(self): """Check if instance matches all constraints to qualify as supported H5OINA""" self.supported = 0 # voting-based with h5py.File(self.file_path, "r") as h5r: - # parse Company and PRODUCT_VERSION attribute values from the first group below / but these are not scalar but single value lists + # parse Company and PRODUCT_VERSION attribute values from the first group below + # but these are not scalar but single value lists # so much about interoperability - # but hehe for the APEX example from Sebastian and Sabine there is again no Company but PRODUCT_VERSION, 2 files, 2 "formats" + # but hehe for the APEX example from Sebastian and Sabine + # there is again no Company but PRODUCT_VERSION, 2 files, 2 "formats" grp_names = list(h5r["/"]) if len(grp_names) == 1: - if read_strings_from_dataset(h5r[grp_names[0]].attrs["Company"][0]) in self.supported_version["tech_partner"]: - self.supported += 1 - if read_strings_from_dataset(h5r[grp_names[0]].attrs["PRODUCT_VERSION"][0]) in self.supported_version["schema_version"]: - self.supported += 1 - if self.supported == 2: + if "Company" in h5r[grp_names[0]].attrs: + if read_strings_from_dataset( + h5r[grp_names[0]].attrs["Company"][0]) \ + in self.supported_version["tech_partner"]: + self.supported += 1 + if "PRODUCT_VERSION" in h5r[grp_names[0]].attrs: + if read_strings_from_dataset( + h5r[grp_names[0]].attrs["PRODUCT_VERSION"][0]) \ + in self.supported_version["schema_version"]: + self.supported += 1 + if self.supported >= 1: + # this is not as strict because IKZ example does not contain Company EDAX, LLC + # but what if there are HDF5 files whose PRODUCT_VERSION is one of Apex but the file + # is not an APEX file, in this case be behavior is undefined but likely will fail self.version = self.supported_version.copy() self.supported = True else: @@ -89,7 +104,7 @@ def parse_and_normalize(self): for sub_sub_grp_nm in sub_sub_grp_nms: if sub_sub_grp_nm.startswith("Area"): # get field-of-view (fov in edax jargon, i.e. roi) - if "/{grp_nm}/{sub_grp_nm}/{sub_sub_grp_nm}/FOVIMAGE" in h5r.keys(): + if f"/{grp_nm}/{sub_grp_nm}/{sub_sub_grp_nm}/FOVIMAGE" in h5r.keys(): ckey = self.init_named_cache(f"roi{cache_id}") self.parse_and_normalize_eds_fov( h5r, f"/{grp_nm}/{sub_grp_nm}/{sub_sub_grp_nm}/FOVIMAGE", ckey) @@ -105,6 +120,7 @@ def parse_and_normalize(self): self.parse_and_normalize_group_ebsd_header(h5r, ckey) self.parse_and_normalize_group_ebsd_phases(h5r, ckey) self.parse_and_normalize_group_ebsd_data(h5r, ckey) + self.parse_and_normalize_group_ebsd_complete(ckey) cache_id += 1 # TODO: conceptually the content of the three @@ -134,9 +150,6 @@ def parse_and_normalize(self): # and relative width/height of the sub-FOV # also supported in that Full Area has a region with (x,y) 0,0 # and relative width/height 1./1. - self.prfx = f"/{grp_nm}/{sub_grp_nm}/{sub_sub_grp_nm}/{area_grp_nm}" - print(f"Parsing {self.prfx}") - # SPC self.prfx = f"/{grp_nm}/{sub_grp_nm}/{sub_sub_grp_nm}/{area_grp_nm}" print(f"Parsing {self.prfx}") @@ -197,19 +210,20 @@ def parse_and_normalize(self): # groups is the same TODO but maybe the physical ROI which they reference # respective differs (TODO:: LineScan refers to FOV that is in the parent of the group) ckey = self.init_named_cache(f"eds{cache_id}") - self.parse_and_normalize_eds_lsd( + self.parse_and_normalize_eds_line_lsd( h5r, f"/{grp_nm}/{sub_grp_nm}/{sub_sub_grp_nm}/{area_grp_nm}", ckey) cache_id += 1 ckey = self.init_named_cache(f"eds_map{cache_id}") - self.parse_and_normalize_eds_rois( + self.parse_and_normalize_eds_line_rois( h5r, f"/{grp_nm}/{sub_grp_nm}/{sub_sub_grp_nm}/{area_grp_nm}", ckey) cache_id += 1 def parse_and_normalize_group_ebsd_header(self, fp, ckey: str): # no official documentation yet from EDAX/APEX, deeply nested, chunking, virtual ds if f"{self.prfx}/EBSD/ANG/DATA/DATA" not in fp: - raise ValueError(f"Unable to parse {self.prfx}/EBSD/ANG/DATA/DATA !") + # raise ValueError(f"Unable to parse {self.prfx}/EBSD/ANG/DATA/DATA !") + return # for a regular tiling of R^2 with perfect hexagons n_pts = 0 @@ -243,7 +257,8 @@ def parse_and_normalize_group_ebsd_header(self, fp, ckey: str): def parse_and_normalize_group_ebsd_phases(self, fp, ckey: str): grp_name = f"{self.prfx}/EBSD/ANG/HEADER/Phase" if f"{grp_name}" not in fp: - raise ValueError(f"Unable to parse {grp_name} !") + # raise ValueError(f"Unable to parse {grp_name} !") + return # Phases, contains a subgroup for each phase where the name # of each subgroup is the index of the phase starting at 1. @@ -311,7 +326,8 @@ def parse_and_normalize_group_ebsd_phases(self, fp, ckey: str): def parse_and_normalize_group_ebsd_data(self, fp, ckey: str): grp_name = f"{self.prfx}/EBSD/ANG/DATA/DATA" if f"{grp_name}" not in fp: - raise ValueError(f"Unable to parse {grp_name} !") + # raise ValueError(f"Unable to parse {grp_name} !") + return n_pts = self.tmp[ckey]["n_x"] * self.tmp[ckey]["n_y"] if np.shape(fp[f"{grp_name}"]) != (n_pts,) and n_pts > 0: @@ -378,6 +394,11 @@ def parse_and_normalize_group_ebsd_data(self, fp, ckey: str): # almost two decades of commercialization of the technique now get_scan_point_coords(self.tmp[ckey]) + def parse_and_normalize_group_ebsd_complete(ckey: str): + """Check if all relevant data for EBSD are available, if not clear the cache.""" + # TODO::implement check and clearing procedure + pass + def parse_and_normalize_eds_fov(self, fp, src: str, ckey: str): """Normalize and scale APEX-specific FOV/ROI image to NeXus.""" reqs = ["FOVIMAGE", "FOVIMAGECOLLECTIONPARAMS", "FOVIPR"] @@ -416,7 +437,7 @@ def parse_and_normalize_eds_fov(self, fp, src: str, ckey: str): = f"Position along {dim} ({scan_unit[dim]})" for key, val in self.tmp[ckey].tmp.items(): if key.startswith("image_twod"): - print(f"image_twod, key: {key}, val: {val}") + print(f"ckey: {ckey}, image_twod, key: {key}, val: {val}") def parse_and_normalize_eds_spc(self, fp, src: str, ckey: str): """Normalize and scale APEX-specific SPC (sum) spectrum to NeXus.""" @@ -426,31 +447,31 @@ def parse_and_normalize_eds_spc(self, fp, src: str, ckey: str): return if "NumberOfLines" in fp[f"{src}/SPC"].attrs.keys(): return - reqs = ["eVOffset", "evPch", "NumberOfPoints", "SpectrumCount"] + reqs = ["eVOffset", "evPch", "NumberOfPoints", "SpectrumCounts"] for req in reqs: - if req not in fp[f"{src}/SPC"].attrs.keys(): # also check for shape + if req not in fp[f"{src}/SPC"].dtype.names: # also check for shape raise ValueError(f"Required attribute named {req} not found in {src}/SPC !") self.tmp[ckey] = NxSpectrumSet() self.tmp[ckey].tmp["source"] = f"{src}/SPC" - e_zero = fp[f"{src}/SPC"].attrs["eVOffset"][0] - e_delta = fp[f"{src}/SPC"].attrs["eVPCh"][0] - e_n = fp[f"{src}/SPC"].attrs["NumberOfPoints"][0] + e_zero = fp[f"{src}/SPC"]["eVOffset"][0] + e_delta = fp[f"{src}/SPC"]["evPch"][0] + e_n = fp[f"{src}/SPC"]["NumberOfPoints"][0] self.tmp[ckey].tmp["spectrum_zerod/axis_energy"].value \ = e_zero + np.asarray(e_delta * np.linspace(0., int(e_n) - 1, num=int(e_n), endpoint=True), - e_zero.dtype) + e_zero.dtype) / 1000. # eV to keV self.tmp[ckey].tmp["spectrum_zerod/axis_energy@long_name"].value \ = "Energy (eV)" self.tmp[ckey].tmp["spectrum_zerod/intensity"].value \ - = np.asarray(fp[f"{src}/SPC"].attrs["SpectrumCount"][0], np.int32) + = np.asarray(fp[f"{src}/SPC"]["SpectrumCounts"][0], np.int32) self.tmp[ckey].tmp["spectrum_zerod/intensity@long_name"].value \ = f"Count (1)" for key, val in self.tmp[ckey].tmp.items(): if key.startswith("spectrum_zerod"): - print(f"spectrum_zerod, key: {key}, val: {val}") + print(f"ckey: {ckey}, spectrum_zerod, key: {key}, val: {val}") def parse_and_normalize_eds_spd(self, fp, src: str, ckey: str): """Normalize and scale APEX-specific spectrum cuboid to NeXus.""" @@ -493,12 +514,17 @@ def parse_and_normalize_eds_spd(self, fp, src: str, ckey: str): idx += chk_info[f"c{dim}"] for key, val in chk_bnds.items(): print(f"{key}, {val}") - spd_chk = np.zeros((nyxe["y"], nyxe["x"], nyxe["e"]), fp[f"{src}/SPD"].dtype) + spd_chk = np.zeros((nyxe["y"], nyxe["x"], nyxe["e"]), fp[f"{src}/SPD"][0, 0][0].dtype) print(f"edax: {np.shape(spd_chk)}, {type(spd_chk)}, {spd_chk.dtype}") + print("WARNING::Currently the parsing of the SPD is switched off for debugging but works!") + return for chk_bnd_y in chk_bnds["y"]: for chk_bnd_x in chk_bnds["x"]: spd_chk[chk_bnd_y[0]:chk_bnd_y[1], chk_bnd_x[0]:chk_bnd_x[1], :] \ = fp[f"{src}/SPD"][chk_bnd_y[0]:chk_bnd_y[1], chk_bnd_x[0]:chk_bnd_x[1]] + for key, val in self.tmp[ckey].tmp.items(): + if key.startswith("spectrum_oned"): + print(f"ckey: {ckey}, spectrum_threed, key: {key}, val: {val}") # compared to naive reading, thereby we read the chunks as they are arranged in memory # and thus do not discard unnecessarily data cached in the hfive chunk cache # by contrast, if we were to read naively for each pixel the energy array most of the @@ -515,7 +541,7 @@ def parse_and_normalize_eds_spd(self, fp, src: str, ckey: str): # specification details the metadata, i.e. energy per channel, start and end # we do not use the SPD instance right now - def parse_and_normalize_eds_lsd(self, fp, src: str, ckey: str): + def parse_and_normalize_eds_line_lsd(self, fp, src: str, ckey: str): """Normalize and scale APEX-specific line scan with one spectrum each to NeXus.""" # https://hyperspy.org/rosettasciio/_downloads/ # c2e8b23d511a3c44fc30c69114e2873e/SpcMap-spd.file.format.pdf @@ -585,8 +611,27 @@ def parse_and_normalize_eds_lsd(self, fp, src: str, ckey: str): = f"Count (1)" for key, val in self.tmp[ckey].tmp.items(): if key.startswith("spectrum_oned"): - print(f"spectrum_oned, key: {key}, val: {val}") + print(f"ckey: {ckey}, spectrum_oned, key: {key}, val: {val}") - def parse_and_normalize_eds_rois(self, fp, src: str, ckey: str): + def parse_and_normalize_eds_line_rois(self, fp, src: str, ckey: str): """Normalize and scale APEX-specific EDS element emission line maps to NeXus.""" - + # source of the information + pass + """ + "indexing/element_names-field", + "indexing/IMAGE_R_SET-group", + "indexing/IMAGE_R_SET/PROCESS-group", + "indexing/IMAGE_R_SET/PROCESS/peaks-field", + "indexing/IMAGE_R_SET/PROCESS/weights-field", + "indexing/PEAK-group", + "indexing/PEAK/ION-group", + "indexing/PEAK/ION/energy-field", + "indexing/PEAK/ION/energy_range-field", + "indexing/PEAK/ION/iupac_line_names-field", + "indexing/PROGRAM-group", + "indexing/summary-group", + "indexing/summary/axis_energy-field", + "indexing/summary/axis_energy@long_name-attribute", + "indexing/summary/intensity-field", + "indexing/summary/intensity@long_name-attribute" + """ diff --git a/pynxtools/dataconverter/readers/em/subparsers/nxs_nion.py b/pynxtools/dataconverter/readers/em/subparsers/nxs_nion.py index 076e7adde..789e28a86 100644 --- a/pynxtools/dataconverter/readers/em/subparsers/nxs_nion.py +++ b/pynxtools/dataconverter/readers/em/subparsers/nxs_nion.py @@ -80,7 +80,7 @@ def configure(self): def check_if_zipped_nionswift_project_file(self, verbose=False): """Inspect the content of the compressed project file to check if supported.""" - with open(self.file_path, 'rb', 0) as fp: + with open(self.file_path, "rb", 0) as fp: s = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ) magic = s.read(8) if verbose is True: