From dd50bc0c6678bd6685b97d1b06903850e2410222 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Wed, 16 Aug 2023 12:56:44 -0700 Subject: [PATCH 01/25] updated test notebook --- CHANGELOG.md | 2 + .../harmony_concise_api_test.ipynb | 225 +++++++++++++----- 2 files changed, 171 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b58acbd9..9d078b13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - PODAAC-5424 - Update concise test in uat to test only POCLOUD collections ### Changed + - Issue-68 + - Updated jupyter notebook ### Deprecated ### Removed ### Fixed diff --git a/jupyter_notebooks/harmony_concise_api_test.ipynb b/jupyter_notebooks/harmony_concise_api_test.ipynb index 4ff691cf..f9a2de83 100644 --- a/jupyter_notebooks/harmony_concise_api_test.ipynb +++ b/jupyter_notebooks/harmony_concise_api_test.ipynb @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "id": "3c95100d", "metadata": {}, "outputs": [], @@ -58,7 +58,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "id": "0c9b70ea", "metadata": { "tags": [ @@ -67,7 +67,7 @@ }, "outputs": [], "source": [ - "collection_id = 'C1940473819-POCLOUD'\n", + "collection_id = 'C2205121485-POCLOUD'\n", "max_results = 2\n", "venue = \"OPS\"" ] @@ -82,7 +82,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 40, "id": "5ccd035f", "metadata": {}, "outputs": [], @@ -109,10 +109,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 41, "id": "b11675ac", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "if venue == \"UAT\":\n", " harmony_client = Client(auth=(username, password), env=Environment.UAT)\n", @@ -144,10 +155,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 42, "id": "36ce8016", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "curl -X GET -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Authorization: *****' -H 'Connection: keep-alive' -H 'Cookie: urs_user_already_logged=yes; state=s%3A1c51c3d53a38e6af99f0366288cd18bf.p404RcPg%2BvidV0pdWb9gqeHVcz4Hld5s5Q5PexRzbXs; token=*****; _urs-gui_session=a61daf78fa6987f16d1ffc770d775b69' -H 'User-Agent: CPython/3.8.12 harmony-py/0.4.2 Darwin/22.6.0 python-requests/2.27.1' 'https://harmony.earthdata.nasa.gov/C2205121485-POCLOUD/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?forceAsync=true&format=application%2Fx-netcdf4&maxResults=2&concatenate=true&skipPreview=true'\n" + ] + } + ], "source": [ "print(harmony_client.request_as_curl(request))\n", "\n", @@ -166,10 +185,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 43, "id": "0d13a446", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "0790ef60-4c3b-4189-b9ac-d9dad2aafafe\n", + "{'status': 'running', 'message': 'CMR query identified 1308 granules, but the request has been limited to process only the first 2 granules because you requested 2 maxResults.', 'progress': 0, 'created_at': datetime.datetime(2023, 8, 16, 17, 32, 22, 669000, tzinfo=tzutc()), 'updated_at': datetime.datetime(2023, 8, 16, 17, 32, 22, 669000, tzinfo=tzutc()), 'created_at_local': '2023-08-16T10:32:22-07:00', 'updated_at_local': '2023-08-16T10:32:22-07:00', 'data_expiration': datetime.datetime(2023, 9, 15, 17, 32, 22, 669000, tzinfo=tzutc()), 'data_expiration_local': '2023-09-15T10:32:22-07:00', 'request': 'https://harmony.earthdata.nasa.gov/C2205121485-POCLOUD/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?forceAsync=true&format=application%2Fx-netcdf4&maxResults=2&concatenate=true&skipPreview=true', 'num_input_granules': 2}\n", + "\n", + "Waiting for the job to finish\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + " [ Processing: 100% ] |###################################################| [|]\n" + ] + } + ], "source": [ "print(f'\\n{job1_id}')\n", "\n", @@ -189,10 +227,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 44, "id": "168e7b11", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Downloading results:\n", + "\n", + "C2205121485-POCLOUD_merged.nc4\n", + "\n", + "Done downloading.\n" + ] + } + ], "source": [ "print('\\nDownloading results:')\n", "filename = None\n", @@ -217,7 +268,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 45, "id": "04db3295", "metadata": { "scrolled": true @@ -226,30 +277,19 @@ "source": [ "#some collections time variabe has a time dimension which can cause an exception when we concatenate and makes time two dimension\n", "dt = nc.Dataset(filename,'r')\n", - "group = list(dt.groups)\n", + "groups = list(dt.groups)\n", "dt.close()\n", - "\n", - "if len(group) == 0:\n", - " group = None\n", - "else:\n", - " group = group[0]\n", " \n", "drop_variables = [\n", " 'time',\n", " 'sample',\n", " 'meas_ind',\n", " 'wvf_ind',\n", - " 'ddm'\n", + " 'ddm',\n", + " 'averaged_l1'\n", "]\n", - " \n", - "try:\n", - " ds = xr.open_dataset(filename, group=group, decode_times=False)\n", - "except xr.core.variable.MissingDimensionsError:\n", - " ds = xr.open_dataset(filename, group=group, decode_times=False, drop_variables=drop_variables)\n", - "\n", - "print(list(ds.variables))\n", - " \n", - "assert len(ds.coords['subset_index']) == max_results" + "if len(groups) == 0:\n", + " groups = [None]" ] }, { @@ -262,36 +302,96 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 46, "id": "a733274d", - "metadata": {}, - "outputs": [], + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['subset_files', 'ddm_source', 'spacecraft_id', 'spacecraft_num', 'prn_code', 'sv_num', 'antenna', 'sample_time', 'lat', 'lon', 'sc_lat', 'sc_lon', 'sc_alt', 'wind_speed', 'fds_nbrcs_wind_speed', 'fds_les_wind_speed', 'wind_speed_uncertainty', 'azimuth_angle', 'sc_roll', 'commanded_sc_roll', 'mean_square_slope', 'mean_square_slope_uncertainty', 'incidence_angle', 'nbrcs_mean', 'les_mean', 'range_corr_gain', 'fresnel_coeff', 'merra2_wind_speed', 'num_ddms_utilized', 'sample_flags', 'fds_sample_flags', 'sum_neg_brcs_value_used_for_nbrcs_flags', 'ddm_obs_utilized_flag', 'ddm_num_averaged_l1', 'ddm_channel', 'ddm_les', 'ddm_nbrcs', 'ddm_sample_index', 'ddm_averaged_l1_utilized_flag']\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABLYAAAIiCAYAAADVQUH6AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAABHA0lEQVR4nO39e7htZVk//r9v2eJZUUFFDkKKGhqibclDmSgqWYkZKXYQ/VBkqXkoFbNfpuUvzdLy46mdovgpxXOSIYp4LI8bRAQUJdAEUfAEHgoE7+8fc2yde7HWXnPtvdaea671el3XutYYz3ieMe65HNfcXG/H84zq7gAAAADArLnOtAsAAAAAgO0h2AIAAABgJgm2AAAAAJhJgi0AAAAAZpJgCwAAAICZJNgCAAAAYCYJtgAAAIB1raqOr6pLq+rsZTrfKVX1nap615z211TVZ6rqrKp6a1XdeMLzHVxVH6uqc4axj1qOOtcCwRYAAACw3r0uyeHLeL4XJfmdedqf2t136+6Dkvx3kifO7VBVH6yq/eY0/yDJY7r7LkOdf19Vuy1jvTNLsAUAAACsa9394STfGm+rqtsPT16dXlUfqao7L+F8pyX57jztVwznriQ3SNITnu8L3f3FYfurSS5Nssek9axlgi0AAACAa9uU5End/bNJ/iTJK5bjpFX12iRfS3LnJP93O8YfkmTXJP+1HPXMug3TLgAAAABgNRnWvrpPkreMHq5KklxvOPaIJM+bZ9jF3f2Qxc7d3Y+rql0yCrUeleS1VfW4JE8eutwhyclVdVWSC7v718bq2jPJ/0tydHf/aLs+3Boj2AIAAADY2nWSfKe7D557oLvfnuTtO3Ly7r6mqk5M8owkr+3u1yZ5bTJaYyvJY7v7S+NjquqmSf49ybO7++M7cv21xFREAAAAgDHDWlgXVtVvJKM1sarqbjtyzuEcd9iyneRhST4/4dhdk7wjyeu7+607UsdaI9gCAAAA1rWqemOSjyW5U1VdVFXHJPmtJMdU1WeSnJPkiCWc7yNJ3pLkgcP5HpKkkpxQVZ9N8tkke2b+KY3zeWSS+yV5bFWdOfwcPGEtx1fVpVV19gLHb15V76iqs6rqk1V117FjT66qs6vqnKp6ylj7wVX18aGOzcO6X1NR3RMtwA8AAADAjKmq+yX5XkZPe911nuMvSvK97n7u8ObHl3f3A4eA68QkhyS5KskpSR7f3edX1XuTvKS7311VD03yjO6+/876TOM8sQUAAACwRnX3h5N8axtdDkzy/qHv55PsV1W3TvLTST7R3T/o7quTfCjJI7acNslNh+2bJfnqStQ+CcEWAAAAwPr1mQyB1TCl8HZJ9k5ydpJfqKpbVtUNkzw0yT7DmKckeVFVfSXJ3yZ51s4ueos181bE3Xffvffbb79plwGsgCty3rXabpo7TaESAABge5x++unf6O49pl3HznaHqv7BCl/jktH6X/871rSpuzct4RQvSPIPVXVmRmt/fTrJNd39uap6YZL3Jvl+kjOTXDOM+YMkT+3ut1XVI5O8JslhO/RBttOaWWNr48aNvXnz5mmXASyzU3LotdoOzwemUAkAALC9qur07t447Tp2tttW9e+v8DX+Iln0b1tV+yV513xrbM3pV0kuTHLQ8GbI8WP//yQXdfcrquryJLt1dw9jLu/um85zyhVnKiKwagm1AAAAVlZV7VZVuw67v5vkw1tCraq61fB734ymK75h6PfVJL84bD8gyRd3XsVbWzNTEYG1RagFAACw46rqjUnun2T3qrooyXOSXDdJuvtVGS0Sf0JVdUbTGo8ZG/62qrplkh8meUJ3f2do/72Mpi9uyGga5LE74aPMS7AFrDpCLQAAgOXR3Y9e5PjHktxxgWO/sED7fyT52R2vbseZigisKkItAAAAJiXYAlYNoRYAAABLIdgCVgWhFgAAAEsl2AKmTqgFAADA9hBsAVMl1AIAAGB7CbaAqbl2qPUIoRYAAAAT2zDtAoD1aW6oJdACAABgqTyxBex0Qi0AAACWg2AL2KmEWgAAACwXwRaw0wi1AAAAWE6CLWDFfTffFWoBAACw7CweD6yoa7/5UKgFAADA8vDEFrBihFoAAACsJMEWsCKEWgAAAKw0wRaw7IRaAAAA7AyCLWBZCbUAAADYWQRbwLIRagEAALAzCbaAZSHUAgAAYGeberBVVU+tqnOq6uyqemNVXb+q9q+qT1TV+VX1pqraddp1AgsTagEAADANUw22qmqvJH+UZGN33zXJLkmOSvLCJC/p7jsk+XaSY6ZXJbAtQi0AAACmZepPbCXZkOQGVbUhyQ2TXJLkAUneOhw/IcnDp1MasC1CLQAAAKZpqsFWd1+c5G+T/HdGgdblSU5P8p3uvnrodlGSvaZTIbAQoRYAAADTNu2piDdPckSS/ZPcNsmNkhy+hPHHVtXmqtp82WWXrVCVwFxCLQAAAFaDaU9FPCzJhd19WXf/MMnbk9w3yW7D1MQk2TvJxfMN7u5N3b2xuzfuscceO6diWOeEWgAAAKwW0w62/jvJvarqhlVVSR6Y5NwkH0hy5NDn6CTvnFJ9wBihFgAAAKvJtNfY+kRGi8SfkeSzQz2bkjwzydOq6vwkt0zymqkVCSQRagEAALD6bFi8y8rq7uckec6c5guSHDKFcoB5CLUAAABYjaY9FRFY5YRaAAAArFaCLWBBQi0AAABWM8EWMC+hFgAAAKudYAu4FqEWAAAAs0CwBWxFqAUAAMCsEGwBPybUAgAAYJYItoAkQi0AAABmj2ALEGoBAAAwkwRbsM4JtQAAAJhVgi1Yx4RaAAAAzDLBFqxTQi0AAABmnWAL1iGhFgAAAGuBYAvWGaEWAAAAa4VgC9YRoRYAAABriWAL1gmhFgAAAGuNYAvWAaEWAAAAa5FgC9a4uaFW5TihFgAAAGvChmkXAKycuaGWQAsAAIC1xBNbsEYJtQAAAFjrBFuwBgm1AAAAWA8EW7DGCLUAAABYL6yxBWvEKfnbJP++VZtQCwAAgLVMsAVrwNyntBKhFgAAAGufqYgw44RaAAAArFeCLZhhQi0AAADWM8EWzCihFgAAAIupquOr6tKqOnuB4/evqsur6szh58/Hjh1eVedV1flVddxY+xOHtq6q3XfG51iIYAtmkFALAACACb0uyeGL9PlIdx88/DwvSapqlyQvT/JLSQ5M8uiqOnDo/59JDkvy5ZUpeXKCLZgxQi0AAAAm1d0fTvKt7Rh6SJLzu/uC7r4qyYlJjhjO+enu/tLyVbn9BFswQ4RaAAAArIB7V9VnqurdVXWXoW2vJF8Z63PR0LaqbJh2AcBkhFoAAACz5bY3SJ5zp5W9xl+cmd2ravNY06bu3rSEU5yR5Hbd/b2qemiSf01ywHLWuJIEWzADhFoAAAAs4BvdvXF7B3f3FWPbJ1fVK4YF4S9Oss9Y172HtlXFVERY5YRaAAAArJSquk1V1bB9SEZZ0TeTfCrJAVW1f1XtmuSoJCdNr9L5eWILVjGhFgAAADuiqt6Y5P5Jdq+qi5I8J8l1k6S7X5XkyCR/UFVXJ/mfJEd1dye5uqqemOQ9SXZJcnx3nzOc84+SPCPJbZKcVVUnd/fv7txPNiLYglVKqAUAAMCO6u5HL3L8ZUletsCxk5OcPE/7S5O8dFkK3EGmIsIqJNQCAACAxQm2YJURagEAAMBkBFuwigi1AAAAYHKCLVglhFoAAACwNIItWAWEWgAAALB0gi2YMqEWAAAAbB/BFkyRUAsAAAC2n2ALpkSoBQAAADtGsAVTINQCAACAHSfYgp1MqAUAAADLQ7AFO5FQCwAAAJaPYAt2EqEWAAAALK+pB1tVtVtVvbWqPl9Vn6uqe1fVLarq1Kr64vD75tOuE3aEUAsAAACW39SDrST/kOSU7r5zkrsl+VyS45Kc1t0HJDlt2IeZJNQCAACAlTHVYKuqbpbkfklekyTdfVV3fyfJEUlOGLqdkOTh06gPdpRQCwAAAFbOtJ/Y2j/JZUleW1WfrqpXV9WNkty6uy8Z+nwtya3nG1xVx1bV5qrafNlll+2kkmEyQi0AAABYWdMOtjYkuUeSV3b33ZN8P3OmHXZ3J+n5Bnf3pu7e2N0b99hjjxUvFiYl1AIAAICVN+1g66IkF3X3J4b9t2YUdH29qvZMkuH3pVOqD5ZMqAUAAAA7x1SDre7+WpKvVNWdhqYHJjk3yUlJjh7ajk7yzimUB0sm1AIAAICdZ8O0C0jypCT/UlW7JrkgyeMyCtzeXFXHJPlykkdOsT6YyLVDrQ05PKdOpRYAAABYD6YebHX3mUk2znPogTu5FNhuc0MtT2kBAADAypv2Glsw84RaAAAAMB2CLdgBQi0AAACYHsEWbCehFgAAAEyXYAu2g1ALAAAApm/qi8fDLDklT01y5lZtQi0AAACYDsEWTGjuU1qJUAsAAACmyVREmIBQCwAAAFYfwRYsQqgFAAAAq5NgC7ZBqAUAAACrl2ALFiDUAgAAgNVNsAXzEGoBAADA6ifYgjmEWgAAADAbBFswRqgFAAAAs0OwBQOhFgAAAMwWwRZEqAUAAACzSLDFuifUAgAAgNkk2GJdE2oBAADA7BJssW4JtQAAAGC2CbZYl4RaAAAAMPsEW6w7Qi0AAABYGwRbrCtCLQAAAFg7BFusG0ItAAAAWFsEW6wLQi0AAABYewRbrHlCLQAAAFibBFusaUItAAAAWLsEW6xZQi0AAABY2wRbrElCLQAAAFj7BFusOUItAAAAWB8EW6wpQi0AAABYPwRbrBlCLQAAAFhfBFusCUItAAAAWH8EW8w8oRYAAACsT4ItZppQCwAAABZWVYdX1XlVdX5VHTfP8dtV1WlVdVZVfbCq9h479sKqOnv4edRY+wOq6oyh/YSq2rCzPs9cgi1mllALAAAAFlZVuyR5eZJfSnJgkkdX1YFzuv1tktd390FJnpfkr4exv5zkHkkOTvJzSf6kqm5aVddJckKSo7r7rkm+nOTonfBx5iXYYiZdO9TaU6gFAAAAWzskyfndfUF3X5XkxCRHzOlzYJL3D9sfGDt+YJIPd/fV3f39JGclOTzJLZNc1d1fGPqdmuTXV/AzbNPUHhWD7XXtUOvAHJ6XT6UWAAAAWNDeSV64wtd4SHavqs1jLZu6e9OwvVeSr4wduyijp6/GfSbJI5L8Q5JfS3KTqrrl0P6cqvq7JDdMcmiSc5N8I8mGqtrY3ZuTHJlkn2X+VBMTbDFT5oZa182f5YF54JSqAQAAgKn7Rndv3IHxf5LkZVX12CQfTnJxkmu6+71Vdc8kH01yWZKPDe1dVUcleUlVXS/Je5Ncs0OfYAcItpgZc0MtUw8BAABgmy7O1k9T7T20/Vh3fzWjJ7ZSVTdO8uvd/Z3h2POTPH849oYkXxjaP5bkF4b2Bye540p+iG2xxhYzQagFAAAAS/apJAdU1f5VtWuSo5KcNN6hqnYfFoRPkmclOX5o32WYkpiqOijJQRk9nZWqutXw+3pJnpnkVTvhs8zLE1usekItAAAAWLruvrqqnpjkPUl2SXJ8d59TVc9Lsrm7T0py/yR/XVWd0VTEJwzDr5vkI1WVJFck+e3uvno49vSq+pWMHph6ZXe/P1Mi2GJVE2oBAADA9uvuk5OcPKftz8e235rkrfOM+9+M3ow43zmfnuTpy1vp9jEVkVVLqAUAAABsiye2WHVOyQuTnLJVm1ALAAAAmEuwxaoy9ymtRKgFAAAAzM9URFYNoRYAAACwFKsi2BpeIfnpqnrXsL9/VX2iqs6vqjcNr6RkDRNqAQAAAEu1KoKtJE9O8rmx/RcmeUl33yHJt5McM5Wq2CmEWgAAAMD2mHqwVVV7J/nlJK8e9ivJA/KTV02ekOThUymOFSfUAgAAALbX1IOtJH+f5BlJfjTs3zLJd7r76mH/oiR7TaEuVphQCwAAANgRUw22qupXklza3adv5/hjq2pzVW2+7LLLlrk6VpJQCwAAANhR035i675JHlZVX0pyYkZTEP8hyW5VtWHos3eSi+cb3N2buntjd2/cY489dka9LAOhFgAAALAcphpsdfezunvv7t4vyVFJ3t/dv5XkA0mOHLodneSdUyqRZSbUAgAAAJbLtJ/YWsgzkzytqs7PaM2t10y5HpaBUAsAAABYThsW77JzdPcHk3xw2L4gySHTrIflJdQCAAAAlttqfWKLNUSoBQAAAKwEwRYrSqgFAAAArBTBFitGqAUAAACsJMEWK0KoBQAAAKw0wRbLTqgFAAAA7AyCLZaVUAsAAADYWQRbLBuhFgAAALAzCbZYFkItAAAAYGcTbLHDhFoAAADANAi22CFCLQAAAGBaBFtsN6EWAAAAME2CLbaLUAsAAACYNsEWSybUAgAAAFYDwRZLItQCAAAAVgvBFhMTagEAAACriWCLiVw71LqZUAsAAACYKsEWi7p2qPWzOTz/Oo1SAAAAAH5sw7QLYHW7dqj1sByep06lFgAAAIBxgi0WdO1Q6+k5PA+dSi0AAAAAcwm2mNfcUOv6eU7un/tPpxgAAACAeQi2uJa5odbd8obsmT2nVA0AAADA/ARbbGVuqOXNhwAAAMBq5a2I/JhQCwAAAJglgi2SCLUAAACA2SPYQqgFAAAAzCTB1jon1AIAAABmlWBrnfpCviDUAgAAAGaaYGsd+q/8Vy7I72/VJtQCAAAAZo1ga535TD6TL+Z3t2oTagEAAACzSLC1jpyRU3NJnrJVm1ALAAAAmFUbpl0AO8fn895cmr/eqk2oBQAAAMwywdY6cE5Oylfykq3ahFoAAADArBNsrXHn5G35Sl62VZtQCwAAAFgLBFtr2Pvy57k6H9mqTagFAAAArBWCrTXq1Dwj1+RTW7UJtQAAAIC1RLC1Bp2SRyW5dKs2oRYAAACw1gi21phT8qAkV2/VJtQCAAAA1iLB1hpySg69VptQCwAAAFirrjPtAlgeQi0AAABgvRFsrQFCLQAAAGA+VXV4VZ1XVedX1XHb6PfrVdVVtXHY37WqXltVn62qz1TV/Yf2m1TVmWM/36iqv98pH2YepiLOOKEWAAAAMJ+q2iXJy5M8KMlFST5VVSd197lz+t0kyZOTfGKs+feSpLt/pqpuleTdVXXP7v5ukoPHxp6e5O0r+kG2wRNbM0yoBQAAAGzDIUnO7+4LuvuqJCcmOWKefn+Z5IVJ/nes7cAk70+S7r40yXeSbBwfVFV3THKrJB9Z9sontM0ntqrqpROc44ru/rNlqocJCbUAAABgdbvipjfOKQ/euHjHHfLB3atq81jDpu7eNGzvleQrY8cuSvJz46Or6h5J9unuf6+qp48d+kySh1XVG5Psk+Rnh9+fHOtzVJI3dXcvz2dZusWmIh6R5M8X6XNcEsHWTiTUAgAAAAbf6O7tSs+q6jpJXpzksfMcPj7JTyfZnOTLST6a5Jo5fY5K8jvbc+3lsliw9ZLuPmFbHarq5stYD4u4dqhVOXz0ZCAAAADAuIszespqi72Hti1ukuSuST5YVUlymyQnVdXDuntzkqdu6VhVH03yhbH9uyXZ0N2nr1z5i9vmGlvd/fdJUlX3nXtsS9uWPtujqvapqg9U1blVdU5VPXlov0VVnVpVXxx+C88i1AIAAACW5FNJDqiq/atq14yesDppy8Huvry7d+/u/bp7vyQfT/Kw7t5cVTesqhslSVU9KMnVcxadf3SSN+60T7KASReP/78Tti3V1Un+uLsPTHKvJE+oqgMzmt54WncfkOS0YX9dmxtq7ZoDhFoAAADAgrr76iRPTPKeJJ9L8ubuPqeqnldVD1tk+K2SnFFVn0vyzFx7yuEjswqCrcUWj793kvsk2aOqnjZ26KZJdtnRi3f3JUkuGba/O/yx9spoba/7D91OSPLBjP6I69K1Q6275AF52ZSqAQAAAGZFd5+c5OQ5bfOup97d9x/b/lKSO23jvD+1HPUNi9cv5ofd/dn5Diy2xtauSW489LvJWPsVSY6cqMIJVdV+Se6e5BNJbj2EXknytSS3Xs5rzZK5odb1co8cmr+bUjUAAAAAy+pDGU2ZrG302T/JfvMd2Gaw1d0fSvKhqnpdd385+fGK+Tfu7iu2q9x5VNWNk7wtyVO6+4phwbItNXRVzfvayKo6NsmxSbLvvvsuVzmrxtxQa9/8Xg7Mb06pGgAAAIBl96nufsC2OlTVgmsxTbrG1l9X1U2HRcPOTnJuVT19CUVuq7jrZhRq/Ut3v31o/npV7Tkc3zPJpfON7e5N3b2xuzfusccey1HOqjE31Lp9/lioBQAAAKwpi4Vai/WZNNg6cHhC6+FJ3p3RI2BzFw1bsho9mvWaJJ/r7hePHTopydHD9tFJ3rmj15olc0Ot/fPUHJBfmVI1AAAAADtfVd15sT6TBlvXHZ6seniSk7r7h0nmnR64RPfNKCB7QFWdOfw8NMkLkjyoqr6Y5LBhf12YG2rdNS/KnbLYiwoAAAAA1pz3LtZhscXjt/jHJF9K8pkkH66q22W0gPwO6e7/yMKLgz1wR88/a+aGWnfOX2fvbJxSNQAAAAArq6peutChJLstNn6iYKu7X5pk/EJfrqpDF+rP0s0NtQ7OP+Y2ueOUqgEAAADYKR6X5I+TXDnPsUcvNnjSJ7ZSVb+c5C5Jrj/W/LxJx7OwuaHWTwm1AAAAgPXhU0nO7u6Pzj1QVX+x2OCJgq2qelWSGyY5NMmrkxyZ5JNLKpN5zQ21fjqvy+1yuylVAwAAALBTHZnkf+c70N37LzZ40sXj79Pdj0ny7e5+bpJ7Jx4p2lFzQ61fyLuEWgAAAMC60d3f6u4fbO/4SYOt/xl+/6Cqbpvkh0n23N6Lcu1Q637599woN5pSNQAAAAA7X1Vt2pE+k66x9a6q2i3Ji5KckaQzmpLIdpgbah2eD0ypEgAAAICpenhVzTsVcVBJFnyB4aRvRfzLYfNtVfWuJNfv7ssnr5EthFoAAAAAP/b0Cfp8ZKEDky4ef8OMXr24b3f/XlXtW1W/0N3vmrBIItQCAAAAGNfdJ+zI+EnX2HptkiszWjQ+SS5O8lc7cuH1RqgFAAAAsLwmDbZu391/k9Gi8RlWq68Vq2oNuTAXCrUAAAAAVsCki8dfVVU3yGjR+FTV7TN6gottOCVvTvLKrdqEWgAAAADzq6obDg9UTWTSJ7aek+SUJPtU1b8kOS3JM7ajvnXjlLwiQi0AAACAxVXVfarq3CSfH/bvVlWvWGzcpG9FPLWqzkhyr4ymID65u78xdvG7dPc521f62nNK/jLJ+7dqE2oBAAAALOglSR6S5KQk6e7PVNX9Fhs06VTEdPc3k/z7Aof/X5J7THquteyUPDzJ5Vu1CbUAAAAAtq27v1K11ZLu1yw2ZuJgaxEWks+133yYCLUAAAAAJvCVqrpPkq6q6yZ5cpLPLTZo0jW2FtPLdJ6ZJdQCAAAA2G6PT/KEJHsluTjJwcP+Ni3XE1vrmlALAAAAYPsNa7n/1lLHLdcTW1ct03lmjlALAAAAYMdU1QlVtdvY/s2r6vjFxk0UbFXVfavqRsP2b1fVi6vqdluOd/e9tqPmmSfUAgAAAFgWB3X3d7bsdPe3k9x9sUGTPrH1yiQ/qKq7JfnjJP+V5PXbUeSaIdQCAAAAWDbXqaqbb9mpqltkgiW0Jl1j6+ru7qo6IsnLuvs1VXXMdhY684RaAAAAAMvq75J8rKreMuz/RpLnLzZo0mDru1X1rCS/k+QXquo6Sa67XWXOOKEWAAAAwPIZcqbzkzwiyQOG5kd097mLjZ002HpUkt9M8n+6+2tVtW+SF21PsbNMqAUAAACwvLr7R1X18u6+e5JFw6xxE62x1d1fS/K2JNcbmr6R5B1LqnLGCbUAAAAAVsxpVfXrVVVLGTTpWxF/L8lbk/zj0LRXkn9dUnkzTKgFAAAAsKJ+P8lbklxZVVdU1Xer6orFBk06FfEJSQ5J8okk6e4vVtWttrvUGSLUAgAAAFhZ3X2T7Rk3abB1ZXdfteVpsKrakKS354KzRKgFAAAAsPKq6n7ztXf3h7c1btJg60NV9adJblBVD0ryh0n+bWklzhahFgAAAMBO8/Sx7etnNHPw9PzkLYnzmjTYOi7JMUk+m9Gcx5OTvHrpNc4GoRYAAADAztPdvzq+X1X7JPn7xcZNFGwNr1385yQf7u7ztqvCGSHUAgAAAJi6i5L89GKdJgq2quphSV6UZNck+1fVwUme190P25EKVxuhFgAAAMDOV1X/Nz9Zz/06SQ5OcsZi4yadivicjOY2fjBJuvvMqtp/yVWuYkItAAAAgKnZPLZ9dZI3dvd/LjZo0mDrh919+Za3Ig7WzFsRhVoAAAAA09PdJ1TVrknuODRNtBTWpMHWOVX1m0l2qaoDkvxRko8uvczVR6gFAAAAMF1Vdf8kJyT5UpJKsk9VHd3dH97WuOtMeP4nJblLkiuTvCHJ5Umesn2lrh5CLQAAAIBV4e+SPLi7f7G775fkIUlestigRZ/Yqqpdkvx7dx+a5Nk7XOYqIdQCAAAAWDWu290/nn7Y3V+oqusuNmjRYKu7r6mqH1XVzbr78h2tcjUQagEAAACsKpur6tVJ/nnY/+1svaD8vCZdY+t7ST5bVacm+f6Wxu7+o6VWOW1CLQAAAIBV5w+SPCGjdd2T5CNJXrHYoEmDrbcPPzNNqAUAAACw+nT3lUlenOTFVXWLJHsPbds0UbDV3SfsYH1TJ9QCAAAAWJ2q6oNJHpZRVnV6kkur6qPd/dRtjZso2KqqzybpOc2XZzTX8a+6+5tLrngnEmoBAAAArGo36+4rqup3k7y+u59TVWctNmjSqYjvTnJNkjcM+0cluWGSryV5XZJfXXq9O8e1Q63DcvjaebkjAAAAwFqwoar2TPLIZPLgZtJg67DuvsfY/mer6ozuvkdV/fZSqtyZ5oZantICAAAAWJWel+Q9Sf6juz9VVT+V5IuLDZo02Nqlqg7p7k8mSVXdM8kuw7Grt6falSbUAgAAAJgN3f2WJG8Z278gya8vNm7SYOt3kxxfVTce9r+b5Her6kZJ/nqJta44oRYAAADA2jfpWxE/leRnqupmw/7lY4ffvBKFbS+hFgAAAMD6cJ1JOlXVravqNUlO7O7Lq+rAqjpmJQurqsOr6ryqOr+qjptkjFALAAAA4CcWy1eq6npV9abh+Ceqar+xY88a2s+rqodMes6daaJgK6M3H74nyW2H/S8kecoK1JMkqapdkrw8yS8lOTDJo6vqwG2NuSLnbbUv1AIAAADWswnzlWOSfLu775DkJUleOIw9MMlRSe6S5PAkr6iqXbYns1lCvb9cVc+oqj/f8rPYmEmDrd27+81JfpQk3X11kmt2oNbFHJLk/O6+oLuvSnJikiMmHSzUAgAAAJgoXzkiyQnD9luTPLCqamg/sbuv7O4Lk5w/nG+HMpuFVNWrkjwqyZOSVJLfSHK7xcZNunj896vqlkl6uNi9kly+7SE7ZK8kXxnbvyjJz83tVFXHJjk2SW617/WSCLUAAACA1eGS7JkX5pkrfJUP7l5Vm8caNnX3pmF7knzlx326++qqujzJLYf2j88Zu9ewvWhmsx3u090HVdVZ3f3cqvq7JO9ebNCkwdbTkpyU5PZV9Z9J9khy5PbXujyG/6E2JckdN96khVoAAADAOvON7t447SKWwf8Mv39QVbdN8s0key42aNK3Ip5RVb+Y5E4ZPQ52Xnf/cHsrncDFSfYZ2997aFvQTXOnFSwHAAAAYOZMkq9s6XNRVW1IcrOMQqVtjV1SZjOhd1XVbklelOSMjGYNvnqxQdsMtqrqEQscumNVpbvfvtQqJ/SpJAdU1f4Z/XGOSvKbK3QtAAAAgLVoknzlpCRHJ/lYRrPz3t/dXVUnJXlDVb04o5cJHpDkkxk98LQSmc3fdPeVSd5WVe9Kcv0k/7vYoMWe2PrV4fetktwnyfuH/UOTfDTJigRbw5zOJ2b0JsZdkhzf3eesxLUAAAAA1qKF8pWqel6Szd19UpLXJPl/VXV+km9lFFRl6PfmJOcmuTrJE7r7miRZoczmY0nuMVz7yiRXVtUZW9oWss1gq7sfNxT83iQHdvclw/6eSV634zVv89onJzl5Ja8BAAAAsJbNl69095+Pbf9vRm8gnG/s85M8f5Jzbq+quk1Gi9LfoKruntETYUly0yQ3XGz8pIvH77Ml1Bp8Pcm+SykUAAAAAOZ4SJLHZrRW14vH2r+b5E8XGzxpsHVaVb0nyRuH/Ucled/kNQIAAADA1rr7hCQnVNWvd/fbljp+0rciPrGqfi3J/YamTd39jqVeDAAAAADm6u63VdUvJ7lLRgvHb2l/3rbGTfrEVoYgS5gFAAAAwLKqqldltKbWoUlendEbGj+52LjrLHLSd01w4UX7AAAAAMA23Ke7H5Pk29393CT3TnLHxQYt9sTWz1fVSds4XkkOnLxGAAAAALiW/xl+/6Cqbpvkm0n2XGzQYsHWERNc+KoJ+gAAAADAQt5VVbsleVGSM5J0RlMSt2mbwVZ3f2hZSgMAAACABXT3Xw6bbxuWvbp+d1++2LiJF48HAAAAgOVUVY/YxrF099u3NV6wBQAAAMC0/Orw+1ZJ7pPk/cP+oUk+mmR5gq2qukGSfbv7vO0oEgAAAAC20t2PS5Kqem+SA7v7kmF/zySvW2z8dSa5SFX9apIzk5wy7B+8yNsSAQAAAGBS+2wJtQZfT7LvYoMmfWLrL5IckuSDSdLdZ1bV/kssEAAAAADmc1pVvSfJG4f9RyV532KDJg22ftjdl1fVeFsvrT4AAAAAuLbufmJV/VqS+w1Nm7r7HYuNmzTYOqeqfjPJLlV1QJI/ymgBLwAAAADYYUOQtWiYNW6iNbaSPCnJXZJcmdEjYVckecpSLgQAAAAAy2miJ7a6+wdJnj38AAAAAMDUbTPYqqp/yzbW0uruhy17RQAAAACsO1V1iyTp7m9NOmaxJ7b+dvj9iCS3SfLPw/6jM3rtIgAAAABsl6raN8nfJHlgku+MmuqmSd6f5Lju/tK2xm8z2OruDw0X+bvu3jh26N+qavMO1A0AAAAAb0ry90l+q7uvSZKq2iXJbyQ5Mcm9tjV40sXjb1RVP7Vlp6r2T3Kj7akWAAAAAAa7d/ebtoRaSdLd13T3iUluudjgiRaPT/LUJB+sqguSVJLbJfn97akWAAAAAAanV9UrkpyQ5CtD2z5Jjk7y6cUGT/pWxFOq6oAkdx6aPt/dV25HsQAAAACwxWOSHJPkuUn2GtouSvJvSV6z2OCJgq2qesycprtVVbr79UsoFAAAAAB+rLuvSvLK4WfJJp2KeM+x7etntFL9GUkEWwAAAABMxaRTEZ80vl9Vu2W0Mj0AAAAATMWkb0Wc6/tJ9l/OQgAAAABgKSZdY+vfkvSwe50kByZ5y0oVBQAAAMDaV1VP29bx7n7xto5PusbW345tX53ky9190YRjAQAAAGA+N9mRwZMGWw/t7meON1TVC+e2AQAAAMCkuvu5OzJ+0jW2HjRP2y/tyIUBAAAAIEmq6o5VdVpVnT3sH1RVf7bYuG0GW1X1B1X12SR3qqqzxn4uTHLW8pQOAAAAwDr3T0meleSHSdLdZyU5arFBi01FfEOSdyf56yTHjbV/t7u/tX11AgAAAMBWbtjdn6yq8barFxu0WLDV3f2lqnrC3ANVdQvhFgAAAADL4BtVdfsknSRVdWSSSxYbNMkTW7+S5PThxOOxWSf5qe0qFQAAAAB+4glJNiW5c1VdnOTCJL+12KBtBlvd/SvD7/2Xo0IAAAAAmMeXu/uwqrpRkut093cnGbTYE1tJkqq6xzzNlw8XXXS+IwAAAABsw4VVdUqSNyV5/6SDtvlWxDGvSPLxjB4J+6dh+y1JzquqBy+xUAAAAAAYd+ck78toSuKFVfWyqvr5xQZNGmx9Ncndu3tjd/9skoOTXJDkQUn+ZvvqBQAAAICku3/Q3W/u7kckuXuSmyb50GLjJg227tjd54xd7Nwkd+7uC7arWgAAAAAYU1W/WFWvyOglhtdP8sjFxky0xlaSc6rqlUlOHPYfleTcqrpekh9uT7EAAAAAkCRV9aUkn07y5iRP7+7vTzJu0mDrsUn+MMlThv3/TPInGYVahy6hTgAAAACY66DuvmKpgyYKtrr7f5L83fAz1/eWelEAAAAAGHObqnpHklt3912r6qAkD+vuv9rWoInW2Kqq+1bVqVX1haq6YMvPclQNAAAAwLr3T0melWHJq+4+K8lRiw2adCria5I8NaPFu67ZzgIBAAAAYD437O5PVtV429WLDZr0rYiXd/e7u/vS7v7mlp/tKnNQVS+qqs9X1VlV9Y6q2m3s2LOq6vyqOq+qHrIj1wEAAABg1ftGVd0+SSdJVR2Z5JLFBk0abH1gCKLuXVX32PKzA8UmyalJ7trdByX5QkaPm6WqDszoUbO7JDk8ySuqapcdvBYAAAAAq9cTkvxjkjtX1cUZvcDw8YsNmnQq4s8NvzeOtXWSByyhwK1093vHdj+e5Mhh+4gkJ3b3lUkurKrzkxyS5GPbey0AAAAAVq/uviDJYVV1oyTX6e7vVtVTkvz9tsZN+lbEQ3e4wm37P0neNGzvlVHQtcVFQxsAAAAAa1h3f39s92lZjmCrqm6W5DlJ7jc0fSjJ87r78kXGvS/JbeY59OzufufQ59kZLQb2L5PUMuf8xyY5Nkn23XffpQ4HAAAAYPWqxTpMOhXx+CRnJ3nksP87SV6b5BHbGtTdh22zuqrHJvmVJA/s7h6aL06yz1i3vYe2+c6/KcmmJNm4cWPP1wcAAACAmbRo1jNpsHX77v71sf3nVtWZ21XSoKoOT/KMJL/Y3T8YO3RSkjdU1YuT3DbJAUk+uSPXAgAAAGD1qarvZv4Aq5LcYLHxk74V8X+q6ufHLnrfJP8z4diFvCzJTZKcWlVnVtWrkqS7z0ny5iTnJjklyRO6+5odvBYAAAAAY6rqFlV1alV9cfh98wX6XTNkN2dW1Ulj7ftX1Seq6vyqelNV7Tq0P62qzq2qs6rqtKq63UI1dPdNuvum8/zcpLsXfSBr0mDr8UleXlVfqqovZRRK/f6EY+fV3Xfo7n26++Dh5/Fjx57f3bfv7jt197t35DoAAAAAzOu4JKd19wFJThv25/M/Y/nNw8baX5jkJd19hyTfTnLM0P7pJBu7+6Akb03yNytT/oTBVnd/prvvluSgJAd1992TPGCligIAAABgxR2R5IRh+4QkD590YFVVRtnQW+eO7+4PjC079fGM1k9fEZOusZUk6e4rxnYXfeUiAAAAwHr1vW/dNB98w+ErfZndq2rz2P6m4WV7k7h1d18ybH8tya0X6Hf94RpXJ3lBd/9rklsm+U53Xz30uSjJXvOMPSbJis3GW1KwNceir1wEAAAAYEV9o7s3LnSwqt6X5DbzHHr2+E53d1Ut9BbC23X3xVX1U0neX1WfTXL5YoVV1W8n2ZjkFxfru712JNha9JWLAAAAAExPdx+20LGq+npV7dndl1TVnkkuXeAcFw+/L6iqDya5e5K3JdmtqjYMT23tneTisXMfllF49ovdfeWyfaA5trnGVlV9t6qumOfnu0luu1JFAQAAALDiTkpy9LB9dJJ3zu1QVTevqusN27snuW+Sc7u7k3wgyZFzx1fV3ZP8Y5KHdfe8Ydly2WawtaOvXAQAAABg1XpBkgdV1ReTHDbsp6o2VtWrhz4/nWRzVX0moyDrBd197nDsmUmeVlXnZ7Tm1muG9hcluXGSt1TVmVV10kp9AOEUAAAAwDrU3d9M8sB52jcn+d1h+6NJfmaB8RckOWSe9gWnPy63bT6xBQAAAACrlWALAAAAgJkk2AIAAABgJgm2AAAAAJhJgi0AAAAAZpJgCwAAAICZJNgCAAAAYCYJtgAAAACYSYItAAAAAGaSYAsAAACAmSTYAgAAAGAmCbYAAAAAmEmCLQAAAABmkmALAAAAgJkk2AIAAABgJgm2AAAAAJhJgi0AAAAAZpJgCwAAAICZJNgCAAAAYCYJtgAAAACYSYItAAAAAGaSYAsAAACAmSTYAgAAAGAmCbYAAAAAmEmCLQAAAABmkmALAAAAgJkk2AIAAABgJgm2AAAAAJhJgi0AAAAAZpJgCwAAAICZJNgCAAAAYCYJtgAAAACYSYItAAAAAGaSYAsAAACAmSTYAgAAAGAmCbYAAAAAmEmCLQAAAABmkmALAAAAgJkk2AIAAABgJk092KqqP66qrqrdh/2qqpdW1flVdVZV3WPaNQIAAACw+kw12KqqfZI8OMl/jzX/UpIDhp9jk7xyCqUBAAAAsMpN+4mtlyR5RpIeazsiyet75ONJdquqPadSHQAAAACr1tSCrao6IsnF3f2ZOYf2SvKVsf2Lhrb5znFsVW2uqs2XXXbZClUKAAAAwGq0YSVPXlXvS3KbeQ49O8mfZjQNcbt196Ykm5Jk48aNvUh3AAAAANaQFQ22uvuw+dqr6meS7J/kM1WVJHsnOaOqDklycZJ9xrrvPbQBAAAAwI9NZSpid3+2u2/V3ft1934ZTTe8R3d/LclJSR4zvB3xXkku7+5LplEnAAAAAKvXij6xtZ1OTvLQJOcn+UGSx023HAAAAABWo1URbA1PbW3Z7iRPmF41AAAAAMyCqb0VEQAAAAB2hGALAAAAgJkk2AIAAABgJgm2AAAAAJhJgi0AAACAdaiqblFVp1bVF4ffN1+g3wur6uzh51Fj7Q+oqjOG9hOqasPQfvOqekdVnVVVn6yqu67UZxBsAQAAAKxPxyU5rbsPSHLasL+VqvrlJPdIcnCSn0vyJ1V106q6TpITkhzV3XdN8uUkRw/D/jTJmd19UJLHJPmHlfoAgi0AAACA9emIjMKpDL8fPk+fA5N8uLuv7u7vJzkryeFJbpnkqu7+wtDv1CS/Pjbm/UnS3Z9Psl9V3XolPoBgCwAAAGB9unV3XzJsfy3JfOHTZ5IcXlU3rKrdkxyaZJ8k30iyoao2Dv2OHNq3jHlEklTVIUlul2TvlfgAG1bipAAAAADr3n8neeKKX2X3qto8tr+puzdt2amq9yW5zTzjnj2+091dVT23U3e/t6rumeSjSS5L8rEk1wz9j0rykqq6XpL3JrlmGPaCJP9QVWcm+WyST48dW1aCLQAAAIDZ9Y3u3rjQwe4+bKFjVfX1qtqzuy+pqj2TXLrAOZ6f5PnDmDck+cLQ/rEkvzC0PzjJHYf2K5I8bmivJBcmuWDpH21xpiICAAAArE8n5ScLvh+d5J1zO1TVLlV1y2H7oCQHZfR0VqrqVsPv6yV5ZpJXDfu7VdWuwyl+N6M1uq5YiQ/giS0AAACA9ekFSd5cVcdk9FbDRybJsG7W47v7d5NcN8lHRg9e5Yokv93dVw/jn15Vv5LRg1Ov7O73D+0/neSEYWrjOUmOWakPINgCAAAAWIe6+5tJHjhP++aMnrRKd/9vRm85nG/805M8fZ72j2WYlrjSTEUEAAAAYCYJtgAAAACYSYItAAAAAGaSYAsAAACAmSTYAgAAAGAmCbYAAAAAmEmCLQAAAABmkmALAAAAgJkk2AIAAABgJgm2AAAAAJhJgi0AAAAAZpJgCwAAAICZJNgCAAAAYCYJtgAAAACYSYItAAAAAGaSYAsAAACAmSTYAgAAAGAmCbYAAAAAmEmCLQAAAABmkmALAAAAgJkk2AIAAABgJgm2AAAAAJhJgi0AAAAAZpJgCwAAAICZJNgCAAAAYCYJtgAAAACYSYItAAAAAGaSYAsAAACAmSTYAgAAAGAmCbYAAAAAmEmCLQAAAABmkmALAAAAgJk01WCrqp5UVZ+vqnOq6m/G2p9VVedX1XlV9ZBp1ggAAADA6rRhWheuqkOTHJHkbt19ZVXdamg/MMlRSe6S5LZJ3ldVd+zua6ZVKwAAAACrzzSf2PqDJC/o7iuTpLsvHdqPSHJid1/Z3RcmOT/JIVOqEQAAAIBVaprB1h2T/EJVfaKqPlRV9xza90rylbF+Fw1t11JVx1bV5qrafNlll61wuQAAAACsJis6FbGq3pfkNvMcevZw7VskuVeSeyZ5c1X91FLO392bkmxKko0bN/aOVQsAAADALFnRYKu7D1voWFX9QZK3d3cn+WRV/SjJ7kkuTrLPWNe9hzYAAAAA+LFpTkX81ySHJklV3THJrkm+keSkJEdV1fWqav8kByT55LSKBAAAAGB1mtpbEZMcn+T4qjo7yVVJjh6e3jqnqt6c5NwkVyd5gjciAgAAADDX1IKt7r4qyW8vcOz5SZ6/cysCAAAAYJZMcyoiAAAAAGw3wRYAAAAAM0mwBQAAAMBMEmwBAAAAMJMEWwAAAADMJMEWAAAAADNJsAUAAADATBJsAQAAADCTBFsAAAAAzCTBFgAAAAAzSbAFAAAAwEwSbAEAAACsQ1X1G1V1TlX9qKo2bqPfl6rqs1V1ZlVtHmu/RVWdWlVfHH7ffGi/c1V9rKqurKo/WcnPINgCAAAAWJ/OTvKIJB+eoO+h3X1wd48HYMclOa27D0hy2rCfJN9K8kdJ/nY5i52PYAsAAABgHeruz3X3eTtwiiOSnDBsn5Dk4cN5L+3uTyX54Y5VuDjBFgAAAADb0kneW1WnV9WxY+237u5Lhu2vJbn1zi5sw86+IAAAAMC6cM1Xk28/d6Wvsvv4uldJNnX3pi07VfW+JLeZZ9yzu/udE17j57v74qq6VZJTq+rz3b3V9MXu7qrqJVe/gwRbAAAAALPrG3PWvdpKdx+2oxfo7ouH35dW1TuSHJLRulxfr6o9u/uSqtozyaU7eq2lMhURAAAAgHlV1Y2q6iZbtpM8OKNF55PkpCRHD9tHJ5n0CbBlI9gCAAAAWIeq6teq6qIk907y71X1nqH9tlV18tDt1kn+o6o+k+STSf69u08Zjr0gyYOq6otJDhv2U1W3Gc77tCR/VlUXVdVNV+IzmIoIAAAAsA519zuSvGOe9q8meeiwfUGSuy0w/ptJHjhP+9eS7L2sxS7AE1sAAAAAzCTBFgAAAAAzSbAFAAAAwEwSbAEAAAAwkwRbAAAAAMwkwRYAAAAAM0mwBQAAAMBMEmwBAAAAMJMEWwAAAADMJMEWAAAAADNJsAUAAADATBJsAQAAADCTBFsAAAAAzCTBFgAAAAAzSbAFAAAAwEwSbAEAAAAwkwRbAAAAAMwkwRYAAAAAM0mwBQAAAMBMEmwBAAAAMJMEWwAAAADMJMEWAAAAADNJsAUAAADATBJsAQAAADCTBFsAAAAAzKSpBVtVdXBVfbyqzqyqzVV1yNBeVfXSqjq/qs6qqntMq0YAAAAAVq9pPrH1N0me290HJ/nzYT9JfinJAcPPsUleOZXqAAAAAFjVphlsdZKbDts3S/LVYfuIJK/vkY8n2a2q9pxGgQAAAACsXhumeO2nJHlPVf1tRgHbfYb2vZJ8ZazfRUPbJTu1OgAAAABWtRUNtqrqfUluM8+hZyd5YJKndvfbquqRSV6T5LAlnv/YjKYrZt99993BagEAAACYJSsabHX3gkFVVb0+yZOH3bckefWwfXGSfca67j20zXf+TUk2JcnGjRt7R+sFAAAAYHZMc42tryb5xWH7AUm+OGyflOQxw9sR75Xk8u42DREAAACArUxzja3fS/IPVbUhyf9mmFKY5OQkD01yfpIfJHncdMoDAAAAYDWbWrDV3f+R5Gfnae8kT9j5FQEAAAAwS6Y5FREAAAAAtptgCwAAAICZJNgCAAAAYCYJtgAAAACYSYItAAAAAGaSYAsAAACAmSTYAgAAAGAmCbYAAAAAmEmCLQAAAABmkmALAAAAgJkk2AIAAABgJgm2AAAAAJhJgi0AAAAAZpJgCwAAAICZJNgCAAAAYCYJtgAAAACYSYItAAAAAGaSYAsAAACAmSTYAgAAAFiHqupFVfX5qjqrqt5RVbst0O/wqjqvqs6vquPG2vevqk8M7W+qql2H9vtV1RlVdXVVHbmSn0GwBQAAALA+nZrkrt19UJIvJHnW3A5VtUuSlyf5pSQHJnl0VR04HH5hkpd09x2SfDvJMUP7fyd5bJI3rGj1EWwBAAAArEvd/d7uvnrY/XiSvefpdkiS87v7gu6+KsmJSY6oqkrygCRvHfqdkOThw3m/1N1nJfnRStafCLYAAAAASP5PknfP075Xkq+M7V80tN0yyXfGgrEt7TvVhp19wZVy+umnf6+qzpt2HcyM3ZN8Y9pFMBPcKyyF+4VJuVdYCvcLk3KvsBQ7+3653U681ipyyXuSv9h9hS9y/araPLa/qbs3bdmpqvcluc08457d3e8c+jw7ydVJ/mVFK10BaybYSnJed2+cdhHMhqra7H5hEu4VlsL9wqTcKyyF+4VJuVdYCvfLztHdh6+CGg7b1vGqemySX0nywO7uebpcnGSfsf29h7ZvJtmtqjYMT21tad+pTEUEAAAAWIeq6vAkz0jysO7+wQLdPpXkgOENiLsmOSrJSUMI9oEkW956eHSSd650zXMJtgAAAADWp5cluUmSU6vqzKp6VZJU1W2r6uQkGZ7GemKS9yT5XJI3d/c5w/hnJnlaVZ2f0ZpbrxnG37OqLkryG0n+sarOyQpZS1MRNy3eBX7M/cKk3CsshfuFSblXWAr3C5Nyr7AU7hfS3XdYoP2rSR46tn9ykpPn6XdBRm9NnNv+qcz/hsVlV/NPnwQAAACA1c1URAAAAABm0poItqrq8Ko6r6rOr6rjpl0Pq0tVfamqPjvMF948tN2iqk6tqi8Ov28+7TqZjqo6vqouraqzx9rmvT9q5KXDd81ZVXWP6VXOzrbAvfIXVXXx8P1yZlU9dOzYs4Z75byqesh0qmYaqmqfqvpAVZ1bVedU1ZOHdt8tXMs27hffL2ylqq5fVZ+sqs8M98pzh/b9q+oTwz3xpmFh51TV9Yb984fj+031A7BTbeN+eV1VXTj23XLw0O7fImbWzAdbVbVLkpcn+aUkByZ5dFUdON2qWIUO7e6Dx15ne1yS07r7gCSnDfusT69LMvcVvAvdH7+U5IDh59gkr9xJNbI6vC7XvleS5CXD98vBw9oDGf4dOirJXYYxrxj+vWJ9uDrJH3f3gUnuleQJwz3hu4X5LHS/JL5f2NqVSR7Q3XdLcnCSw6vqXklemNG9cock305yzND/mCTfHtpfMvRj/VjofkmSp499t5w5tPm3iJk188FWRouUnd/dF3T3VUlOTHLElGti9TsiyQnD9glJHj69Upim7v5wkm/NaV7o/jgiyet75ONJdquqPXdKoUzdAvfKQo5IcmJ3X9ndFyY5P/Msqsna1N2XdPcZw/Z3M3p70F7x3cI8tnG/LMT3yzo1fEd8b9i97vDTSR6Q5K1D+9zvli3fOW9N8sCqqp1TLdO2jftlIf4tYmathWBrryRfGdu/KNv+jwHWn07y3qo6vaqOHdpu3d2XDNtfS3Lr6ZTGKrXQ/eH7hvk8cXhk//ixac3uFZIkw9Sfuyf5RHy3sIg590vi+4U5qmqXqjozyaVJTk3yX0m+091XD13G74cf3yvD8cuT3HKnFsxUzb1funvLd8vzh++Wl1TV9YY23y3MrLUQbMFifr6775HR47VPqKr7jR/s0atBvR6Uebk/WMQrk9w+o0f8L0nyd1OthlWlqm6c5G1JntLdV4wf893CXPPcL75fuJbuvqa7D06yd0ZP6t15uhWxms29X6rqrkmeldF9c88kt0jyzOlVCMtjLQRbFyfZZ2x/76ENkiTdffHw+9Ik78joPwK+vuXR2uH3pdOrkFVoofvD9w1b6e6vD//R+KMk/5SfTAdyr6xzVXXdjEKKf+nutw/NvluY13z3i+8XtqW7v5PkA0nundGUsQ3DofH74cf3ynD8Zkm+uXMrZTUYu18OH6Y/d3dfmeS18d3CGrAWgq1PJTlgeBvIrhktpnnSlGtilaiqG1XVTbZsJ3lwkrMzukeOHrodneSd06mQVWqh++OkJI8Z3hpzrySXj00rYh2as/bEr2X0/ZKM7pWjhjdS7Z/RQqyf3Nn1MR3DGjavSfK57n7x2CHfLVzLQveL7xfmqqo9qmq3YfsGSR6U0ZpsH0hy5NBt7nfLlu+cI5O8f3halHVggfvl82P/B0tltB7b+HeLf4uYSRsW77K6dffVVfXEJO9JskuS47v7nCmXxepx6yTvGNbJ3JDkDd19SlV9Ksmbq+qYJF9O8sgp1sgUVdUbk9w/ye5VdVGS5yR5Qea/P05O8tCMFur9QZLH7fSCmZoF7pX7D6/J7iRfSvL7SdLd51TVm5Ocm9Ebz57Q3ddMoWym475JfifJZ4e1TZLkT+O7hfktdL882vcLc+yZ5IThLZjXSfLm7n5XVZ2b5MSq+qskn84oKM3w+/9V1fkZvfzkqGkUzdQsdL+8v6r2SFJJzkzy+KG/f4uYWSW0BwAAAGAWrYWpiAAAAACsQ4ItAAAAAGaSYAsAAACAmSTYAgAAAGAmCbYAAAAAmEmCLQAAAABmkmALAFaxqvreCp//5Krabfj5w+0Yf/+qetcS+19eVScvcPx1VXXkUuuYRcPf4j5j+0+tqv+uqpdNsy4AgFki2AKAday7H9rd30myW5IlB1vb6SPd/dCVvEBVbVjJ8y+T+yf5cbDV3S9J8udTqwYAYAYJtgBgxlTVwVX18ao6q6reUVU3H9o/WFUvrKpPVtUXquoXhvYbVtWbq+rcof8nqmrjcOxLVbV7khckuX1VnVlVL5r7JFZVvayqHjtsH15Vn6+qM5I8YqzPjarq+OH6n66qIyb4LDWc+7yqel+SW40d+9mq+lBVnV5V76mqPYf2ew6ffUutZw/tj62qk6rq/UlOW6ieqtplGPep4Ty/P7TvWVUfHs579pa/3wJ1P7iqPlZVZ1TVW6rqxkP7nw/nPbuqNlVVDe1/NPz9z6qqE6tqvySPT/LU4XoLXgsAgIUJtgBg9rw+yTO7+6Akn03ynLFjG7r7kCRPGWv/wyTf7u4Dk/z/kvzsPOc8Lsl/dffB3f30hS5cVddP8k9JfnU4z23GDj87yfuH6x+a5EVVdaNFPsuvJblTkgOTPCbDE0xVdd0k/zfJkd39s0mOT/L8Ycxrk/x+dx+c5Jo557vHMOYXt1HPMUku7+57Jrlnkt+rqv2T/GaS9wznvVuSMxf4G+ye5M+SHNbd90iyOcnThsMv6+57dvddk9wgya8M7cclufvwv9nju/tLSV6V5CXD3/wji/ydAACYxyw8pg8ADKrqZkl26+4PDU0nJHnLWJe3D79PT7LfsP3zSf4hSbr77Ko6awdKuHOSC7v7i0M9/5zk2OHYg5M8rKr+ZNi/fpJ9k3xuG+e7X5I3dvc1Sb46PG2VjMKuuyY5dXjoaZckl1TVbklu0t0fG/q9IT8Jj5Lk1O7+1iL1PDjJQWNred0syQFJPpXk+CFU+9fuPnOBmu+VURD3n0NtuybZUs+hVfWMJDdMcosk5yT5tyRnJfmXqvrXJP+6jb8HAABLINgCgLXlyuH3Ndmxf+evztZPdl9/gjGV5Ne7+7wduO74uc7p7ntv1TgKtrbl+4vVM0wPfFJ3v+daF626X5JfTvK6qnpxd79+gdpO7e5Hzxl7/SSvSLKxu79SVX+Rn/zdfjmjEO9Xkzy7qn5mkc8BAMAETEUEgBnS3Zcn+fbYmky/k+RD2xiSJP+Z5JFJUlUHJpkvVPlukpuM7X85yYFVdb0hTHrg0P75JPtV1e2H/fFw5z1JnjS2rtTdJ/hIH07yqGHdqz0zmjKYJOcl2aOq7j2c67pVdZdhofvvVtXPDf2O2sa5F6rnPUn+YHgyK1V1x2E9rtsl+Xp3/1OSV2c0rXE+H09y36q6wzD+RlV1x/wkxPrGsObWkcPx6yTZp7s/kOSZGT0hduNc+28OAMASeWILAFa3G1bVRWP7L05ydJJXVdUNk1yQ5HGLnOMVSU6oqnMzCqbOSXL5eIfu/mZV/eewEPu7u/vpVfXmJGcnuTDJp4d+/1tVxyb596r6QZKP5CfhzF8m+fskZw1hzoXZeprgfN6R5AFJzk3y3xmm9HX3VcNUwZcO0y83DOc+J6M1sv6pqn6UUah3+Tzn3VY9r85omuYZQ+h1WZKHZ/SWwqdX1Q+TfC+jNb+upbsvq9FC+m+squsNzX/W3V+oqn8a/mZfy2hqYzKaRvnPw+eoJC/t7u9U1b8leeuwqP2TrLMFALB01d3TrgEAWEFVtUuS6w6h1O2TvC/Jnbr7qinUcv8kf9LdiwVe2zrHjbv7e8P2cUn27O4nL0+F0zUEZhu7+4nTrgUAYBZ4YgsA1r4bJvnAMPWukvzhNEKtwVVJ7lpVJ3f3Q7fzHL9cVc/K6L9jvpzksctV3DRV1VOTPD7J26ZdCwDArPDEFgDAAqrqE0muN6f5d7r7s9OoBwCArQm2AAAAAJhJ3ooIAAAAwEwSbAEAAAAwkwRbAAAAAMwkwRYAAAAAM0mwBQAAAMBM+v8AvUudSnxITkEAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ - "variable = None\n", - "variables = list(ds.variables)\n", + "for group in groups:\n", + "\n", + " try:\n", + " ds = xr.open_dataset(filename, group=group, decode_times=False)\n", + " except xr.core.variable.MissingDimensionsError:\n", + " ds = xr.open_dataset(filename, group=group, decode_times=False, drop_variables=drop_variables)\n", "\n", - "for v in variables:\n", - " if v not in ['subset_files', 'lat', 'lon', 'latitude', 'longitude', 'beam_clat', 'beam_clon']:\n", - " variable = v\n", - " break;\n", + " assert len(ds.coords['subset_index']) == max_results\n", "\n", - "if \"lon\" in variables:\n", - " x = \"lon\"\n", - "elif \"longitude\" in variables:\n", - " x = \"longitude\"\n", - "elif \"beam_clon\" in variables:\n", - " x = \"beam_clon\"\n", - "elif \"sp_lon\" in variables:\n", - " x = \"sp_lon\"\n", + " variable = None\n", + " variables = list(ds.variables)\n", + " print(variables)\n", " \n", - "if \"lat\" in variables:\n", - " y = \"lon\"\n", - "elif \"latitude\" in variables:\n", - " y = \"longitude\"\n", - "elif \"beam_clat\" in variables:\n", - " y = \"beam_clat\"\n", - "elif \"sp_lat\" in variables:\n", - " y = \"sp_lat\"\n", + " for v in variables:\n", + " if v not in ['subset_files', 'lat', 'lon', 'latitude', 'longitude', 'beam_clat', 'beam_clon']:\n", + " variable = v\n", + " break;\n", + "\n", + " if \"lon\" in variables:\n", + " x = \"lon\"\n", + " elif \"longitude\" in variables:\n", + " x = \"longitude\"\n", + " elif \"beam_clon\" in variables:\n", + " x = \"beam_clon\"\n", + " elif \"sp_lon\" in variables:\n", + " x = \"sp_lon\"\n", + " elif \"cellon\" in variables:\n", + " x = \"cellon\"\n", + " else:\n", + " x = None\n", + "\n", + " if \"lat\" in variables:\n", + " y = \"lon\"\n", + " elif \"latitude\" in variables:\n", + " y = \"longitude\"\n", + " elif \"beam_clat\" in variables:\n", + " y = \"beam_clat\"\n", + " elif \"sp_lat\" in variables:\n", + " y = \"sp_lat\"\n", + " elif \"cellat\" in variables:\n", + " y = \"cellat\"\n", + " else:\n", + " y = None\n", + " \n", + " if y is not None and x is not None:\n", + " break\n", + " \n", + " ds.close()\n", + "\n", + "if x is None or y is None:\n", + " raise Exception(\"Lon and Lat variables are not found\")\n", " \n", "for index in range(0, max_results):\n", " \n", @@ -321,10 +421,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 47, "id": "748cdb33", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ "ds.plot.scatter(\n", " y=y,\n", From 4d77f6ba5e530d7047b86cafb22dc6ea1b23214f Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Tue, 22 Aug 2023 16:14:55 -0700 Subject: [PATCH 02/25] update notebook test to not use notebooks --- notebook_test.py | 168 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 159 insertions(+), 9 deletions(-) diff --git a/notebook_test.py b/notebook_test.py index 9ae6e798..3aaa7fb9 100644 --- a/notebook_test.py +++ b/notebook_test.py @@ -1,3 +1,8 @@ +import os +import matplotlib.pyplot as plt +import netCDF4 as nc +import xarray as xr +from harmony import BBox, Client, Collection, Request, Environment import papermill as pm import argparse @@ -7,6 +12,7 @@ from utils.enums import Venue import itertools + def parse_args(): """ Parses the program arguments @@ -28,7 +34,7 @@ def parse_args(): parser.add_argument('-n', '--notebook', help='Notebook to run', - required=True, + required=False, metavar='') parser.add_argument('-i', '--input_file', @@ -44,6 +50,146 @@ def parse_args(): args = parser.parse_args() return args + +def get_username_and_password(venue): + if venue == "UAT": + return os.environ.get("UAT_USERNAME"), os.environ.get("UAT_PASSWORD") + elif venue == "OPS": + return os.environ.get('OPS_USERNAME'), os.environ.get('OPS_PASSWORD') + else: + raise ValueError("Invalid venue") + + +def get_x_y_variables(variables): + x_var_candidates = ["lon", "longitude", "beam_clon", "sp_lon", "cellon"] + y_var_candidates = ["lat", "latitude", "beam_clat", "sp_lat", "cellat"] + + x_var, y_var = None, None + for var in variables: + if x_var is None and var in x_var_candidates: + x_var = var + if y_var is None and var in y_var_candidates: + y_var = var + if x_var and y_var: + break + + return x_var, y_var + + +def test(collection_id, venue): + + max_results = 2 + + username, password = get_username_and_password(venue) + environment = Environment.UAT if venue == "UAT" else Environment.PROD + harmony_client = Client(auth=(username, password), env=environment) + + collection = Collection(id=collection_id) + + request = Request( + collection=collection, + concatenate=True, + max_results=max_results, + skip_preview=True, + format="application/x-netcdf4", + ) + + request.is_valid() + + print(harmony_client.request_as_curl(request)) + + job1_id = harmony_client.submit(request) + + print(f'\n{job1_id}') + + print(harmony_client.status(job1_id)) + + print('\nWaiting for the job to finish') + + harmony_client.wait_for_processing(job1_id, show_progress=True) + results = harmony_client.result_json(job1_id) + + print('\nDownloading results:') + #filename = harmony_client.download_all(job1_id, overwrite=True)[0].result() + + futures = harmony_client.download_all(job1_id) + file_names = [f.result() for f in futures] + print('\nDone downloading.') + + filename = file_names[0] + # Handle time dimension and variables dropping + dt = nc.Dataset(filename, 'r') + groups = list(dt.groups) + dt.close() + + drop_variables = [ + 'time', + 'sample', + 'meas_ind', + 'wvf_ind', + 'ddm', + 'averaged_l1' + ] + if not groups: + groups = [None] + + for group in groups: + try: + ds = xr.open_dataset(filename, group=group, decode_times=False) + except xr.core.variable.MissingDimensionsError: + ds = xr.open_dataset(filename, group=group, decode_times=False, drop_variables=drop_variables) + + assert len(ds.coords['subset_index']) == max_results + variables = list(ds.variables) + x_var, y_var = get_x_y_variables(variables) + + for v in variables: + if v not in ['subset_files', 'lat', 'lon', 'latitude', 'longitude', 'beam_clat', 'beam_clon']: + variable = v + break + + if x_var is not None and y_var is not None: + break + + ds.close() + + if x_var is None or y_var is None: + raise Exception("Lon and Lat variables are not found") + + for index in range(0, max_results): + ax = ds.isel(subset_index=index).plot.scatter( + y=y_var, + x=x_var, + hue=variable, + s=1, + levels=9, + cmap="jet", + aspect=2.5, + size=9 + ) + plt.xlim(0., 360.) + plt.ylim(-90., 90.) + plt.show(block=False) + plt.close(ax.figure) + + ax = ds.plot.scatter( + y=y_var, + x=x_var, + hue=variable, + s=1, + levels=9, + cmap="jet", + aspect=2.5, + size=9 + ) + plt.xlim(0., 360.) + plt.ylim(-90., 90.) + plt.show(block=False) + plt.close(ax.figure) + + ds.close() + + def run(): """ Run from command line. @@ -56,10 +202,10 @@ def run(): environment = _args.env notebook = _args.notebook inputFile = _args.input_file - output_location = _args.output_path if _args.output_path else '.' + output_location = _args.output_path if _args.output_path else '.' - notebook_path = path.realpath(path.dirname(notebook)) - notebook_name = path.basename(notebook) + #notebook_path = path.realpath(path.dirname(notebook)) + #notebook_name = path.basename(notebook) success = [] fails = [] @@ -67,6 +213,7 @@ def run(): if path.exists(inputFile): venue = Venue.from_str(environment) collections = FileHandler.get_file_content_list_per_line(inputFile) + print(collections) # limit number of collections tested to 1 for collection in itertools.islice(collections, 1): if "POCLOUD" not in collection and venue == "uat": @@ -74,11 +221,13 @@ def run(): try: print(collection) - pm.execute_notebook( - notebook, - f"{notebook_path}/output/{collection}_{environment}_output_{notebook_name}", - parameters=dict(collection_id=collection, venue=venue.name) - ) + + test(collection, venue.name) + # pm.execute_notebook( + # notebook, + # f"{notebook_path}/output/{collection}_{environment}_output_{notebook_name}", + # parameters=dict(collection_id=collection, venue=venue.name) + # ) success.append(collection) except Exception as ex: print(ex) @@ -97,5 +246,6 @@ def run(): with open(fail_outfile, 'w') as the_file: the_file.writelines(x + '\n' for x in fails) + if __name__ == '__main__': run() From da3467de118b680c79b5d36e534af70d8c2f0720 Mon Sep 17 00:00:00 2001 From: jonathansmolenski Date: Tue, 22 Aug 2023 23:29:51 +0000 Subject: [PATCH 03/25] Update uat_associations.txt with new collections --- cmr/uat_associations.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/cmr/uat_associations.txt b/cmr/uat_associations.txt index cfde6e34..1d950075 100644 --- a/cmr/uat_associations.txt +++ b/cmr/uat_associations.txt @@ -66,3 +66,4 @@ C1238538240-POCLOUD C1238543220-POCLOUD C1238621111-POCLOUD C1238687282-POCLOUD +C1238658392-POCLOUD From 08e9a27d6dee837ef7c1f1aa8bafbe4840888c3c Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Tue, 22 Aug 2023 16:33:53 -0700 Subject: [PATCH 04/25] changes to drop variables --- notebook_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notebook_test.py b/notebook_test.py index 3aaa7fb9..773b472f 100644 --- a/notebook_test.py +++ b/notebook_test.py @@ -135,7 +135,7 @@ def test(collection_id, venue): for group in groups: try: - ds = xr.open_dataset(filename, group=group, decode_times=False) + ds = xr.open_dataset(filename, group=group, decode_times=False, drop_variables=drop_variables) except xr.core.variable.MissingDimensionsError: ds = xr.open_dataset(filename, group=group, decode_times=False, drop_variables=drop_variables) From 562ede61d305bef17943f91190d5d2d79011dfe7 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Wed, 23 Aug 2023 10:02:05 -0700 Subject: [PATCH 05/25] update tests --- notebook_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notebook_test.py b/notebook_test.py index 773b472f..312bd5c9 100644 --- a/notebook_test.py +++ b/notebook_test.py @@ -3,7 +3,7 @@ import netCDF4 as nc import xarray as xr from harmony import BBox, Client, Collection, Request, Environment -import papermill as pm +#import papermill as pm import argparse from os import path From dfbda3749354e1458b854f2807e51d66d4b5bc35 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Wed, 23 Aug 2023 10:19:57 -0700 Subject: [PATCH 06/25] update tests --- notebook_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notebook_test.py b/notebook_test.py index 312bd5c9..3d9e2b64 100644 --- a/notebook_test.py +++ b/notebook_test.py @@ -106,7 +106,7 @@ def test(collection_id, venue): print('\nWaiting for the job to finish') - harmony_client.wait_for_processing(job1_id, show_progress=True) + #harmony_client.wait_for_processing(job1_id) results = harmony_client.result_json(job1_id) print('\nDownloading results:') From edeb4c022618628faaab969cf60bf1ed748205f0 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Wed, 23 Aug 2023 12:08:59 -0700 Subject: [PATCH 07/25] update python libraries --- poetry.lock | 94 +++-------------------------------------------------- 1 file changed, 5 insertions(+), 89 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6c6cf2c5..76c2eb6c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "alabaster" version = "0.7.13" description = "A configurable sidebar-enabled Sphinx theme" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -16,7 +15,6 @@ files = [ name = "ansiwrap" version = "0.8.4" description = "textwrap, but savvy to ANSI colors and styles" -category = "dev" optional = false python-versions = "*" files = [ @@ -31,7 +29,6 @@ textwrap3 = ">=0.9.2" name = "astroid" version = "2.13.2" description = "An abstract syntax tree for Python with inference support." -category = "dev" optional = false python-versions = ">=3.7.2" files = [ @@ -51,7 +48,6 @@ wrapt = [ name = "attrs" version = "22.2.0" description = "Classes Without Boilerplate" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -70,7 +66,6 @@ tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy name = "babel" version = "2.11.0" description = "Internationalization utilities" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -85,7 +80,6 @@ pytz = ">=2015.7" name = "boto3" version = "1.26.51" description = "The AWS SDK for Python" -category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -105,7 +99,6 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] name = "botocore" version = "1.29.51" description = "Low-level, data-driven core of boto 3." -category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -123,21 +116,19 @@ crt = ["awscrt (==0.15.3)"] [[package]] name = "certifi" -version = "2022.12.7" +version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, ] [[package]] name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." -category = "main" optional = false python-versions = "*" files = [ @@ -214,7 +205,6 @@ pycparser = "*" name = "cftime" version = "1.6.2" description = "Time-handling functionality from netcdf4-python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -248,7 +238,6 @@ numpy = ">1.13.3" name = "charset-normalizer" version = "3.0.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false python-versions = "*" files = [ @@ -346,7 +335,6 @@ files = [ name = "click" version = "8.1.3" description = "Composable command line interface toolkit" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -361,7 +349,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -373,7 +360,6 @@ files = [ name = "coverage" version = "7.0.5" description = "Code coverage measurement for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -440,7 +426,6 @@ toml = ["tomli"] name = "deprecation" version = "2.1.0" description = "A library to handle automated deprecations" -category = "main" optional = false python-versions = "*" files = [ @@ -455,7 +440,6 @@ packaging = "*" name = "dill" version = "0.3.6" description = "serialize all of python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -470,7 +454,6 @@ graph = ["objgraph (>=1.7.2)"] name = "docutils" version = "0.17.1" description = "Docutils -- Python Documentation Utilities" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -482,7 +465,6 @@ files = [ name = "entrypoints" version = "0.4" description = "Discover and load entry points from installed packages." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -494,7 +476,6 @@ files = [ name = "exceptiongroup" version = "1.1.0" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -509,7 +490,6 @@ test = ["pytest (>=6)"] name = "fastjsonschema" version = "2.16.2" description = "Fastest Python implementation of JSON schema" -category = "dev" optional = false python-versions = "*" files = [ @@ -524,7 +504,6 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc name = "flake8" version = "6.0.0" description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" optional = false python-versions = ">=3.8.1" files = [ @@ -541,7 +520,6 @@ pyflakes = ">=3.0.0,<3.1.0" name = "harmony-service-lib" version = "1.0.22" description = "A library for Python-based Harmony services to parse incoming messages, fetch data, stage data, and call back to Harmony" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -562,7 +540,6 @@ urllib3 = ">=1.26.9,<1.27.0" name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -574,7 +551,6 @@ files = [ name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -586,7 +562,6 @@ files = [ name = "importlib-metadata" version = "6.0.0" description = "Read metadata from Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -606,7 +581,6 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -618,7 +592,6 @@ files = [ name = "isort" version = "5.11.4" description = "A Python utility / library to sort Python imports." -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -636,7 +609,6 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"] name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -654,7 +626,6 @@ i18n = ["Babel (>=2.7)"] name = "jmespath" version = "1.0.1" description = "JSON Matching Expressions" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -666,7 +637,6 @@ files = [ name = "jsonschema" version = "4.17.3" description = "An implementation of JSON Schema validation for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -686,7 +656,6 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "jupyter-client" version = "7.4.9" description = "Jupyter protocol implementation and client libraries" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -711,7 +680,6 @@ test = ["codecov", "coverage", "ipykernel (>=6.12)", "ipython", "mypy", "pre-com name = "jupyter-core" version = "5.1.3" description = "Jupyter core package. A base package on which Jupyter projects rely." -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -732,7 +700,6 @@ test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] name = "lazy-object-proxy" version = "1.9.0" description = "A fast and thorough lazy object proxy." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -778,7 +745,6 @@ files = [ name = "markupsafe" version = "2.1.2" description = "Safely add untrusted strings to HTML/XML markup." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -838,7 +804,6 @@ files = [ name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -850,7 +815,6 @@ files = [ name = "nbclient" version = "0.7.2" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -860,7 +824,7 @@ files = [ [package.dependencies] jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" nbformat = ">=5.1" traitlets = ">=5.3" @@ -873,7 +837,6 @@ test = ["ipykernel", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>= name = "nbformat" version = "5.7.3" description = "The Jupyter Notebook format" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -895,7 +858,6 @@ test = ["pep440", "pre-commit", "pytest", "testpath"] name = "nest-asyncio" version = "1.5.6" description = "Patch asyncio to allow nested event loops" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -907,7 +869,6 @@ files = [ name = "netcdf4" version = "1.6.2" description = "Provides an object-oriented python interface to the netCDF version 4 library." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -948,7 +909,6 @@ numpy = ">=1.9" name = "numpy" version = "1.24.1" description = "Fundamental package for array computing in Python" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -986,7 +946,6 @@ files = [ name = "packaging" version = "23.0" description = "Core utilities for Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -998,7 +957,6 @@ files = [ name = "papermill" version = "2.4.0" description = "Parametrize and run Jupyter and nteract Notebooks" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1032,7 +990,6 @@ test = ["attrs (>=17.4.0)", "azure-datalake-store (>=0.0.30)", "azure-storage-bl name = "platformdirs" version = "2.6.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1048,7 +1005,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest- name = "pluggy" version = "1.0.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1064,7 +1020,6 @@ testing = ["pytest", "pytest-benchmark"] name = "pycodestyle" version = "2.10.0" description = "Python style guide checker" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1076,7 +1031,6 @@ files = [ name = "pycparser" version = "2.21" description = "C parser in Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1088,7 +1042,6 @@ files = [ name = "pyflakes" version = "3.0.1" description = "passive checker of Python programs" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1100,7 +1053,6 @@ files = [ name = "pygments" version = "2.14.0" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1115,7 +1067,6 @@ plugins = ["importlib-metadata"] name = "pylint" version = "2.15.10" description = "python code static checker" -category = "dev" optional = false python-versions = ">=3.7.2" files = [ @@ -1145,7 +1096,6 @@ testutils = ["gitpython (>3)"] name = "pynacl" version = "1.5.0" description = "Python binding to the Networking and Cryptography (NaCl) library" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1172,7 +1122,6 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] name = "pyrsistent" version = "0.19.3" description = "Persistent/Functional/Immutable data structures" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1209,7 +1158,6 @@ files = [ name = "pystac" version = "0.5.6" description = "Python library for working with Spatiotemporal Asset Catalog (STAC)." -category = "main" optional = false python-versions = "*" files = [ @@ -1227,7 +1175,6 @@ validation = ["jsonschema (==3.2.0)"] name = "pytest" version = "7.2.1" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1251,7 +1198,6 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2. name = "pytest-cov" version = "4.0.0" description = "Pytest plugin for measuring coverage." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1270,7 +1216,6 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -1285,7 +1230,6 @@ six = ">=1.5" name = "python-json-logger" version = "2.0.4" description = "A python library adding a json log formatter" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1297,7 +1241,6 @@ files = [ name = "pytz" version = "2022.7.1" description = "World timezone definitions, modern and historical" -category = "dev" optional = false python-versions = "*" files = [ @@ -1309,7 +1252,6 @@ files = [ name = "pywin32" version = "305" description = "Python for Window Extensions" -category = "dev" optional = false python-versions = "*" files = [ @@ -1333,7 +1275,6 @@ files = [ name = "pyyaml" version = "6.0" description = "YAML parser and emitter for Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1383,7 +1324,6 @@ files = [ name = "pyzmq" version = "25.0.0" description = "Python bindings for 0MQ" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1473,7 +1413,6 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1495,7 +1434,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "s3transfer" version = "0.6.0" description = "An Amazon S3 Transfer Manager" -category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -1513,7 +1451,6 @@ crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] name = "setuptools" version = "66.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1530,7 +1467,6 @@ testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs ( name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1542,7 +1478,6 @@ files = [ name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "dev" optional = false python-versions = "*" files = [ @@ -1554,7 +1489,6 @@ files = [ name = "sphinx" version = "4.5.0" description = "Python documentation generator" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1590,7 +1524,6 @@ test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] name = "sphinx-rtd-theme" version = "1.1.1" description = "Read the Docs theme for Sphinx" -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" files = [ @@ -1609,7 +1542,6 @@ dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] name = "sphinxcontrib-applehelp" version = "1.0.3" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1625,7 +1557,6 @@ test = ["pytest"] name = "sphinxcontrib-devhelp" version = "1.0.2" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1641,7 +1572,6 @@ test = ["pytest"] name = "sphinxcontrib-htmlhelp" version = "2.0.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1657,7 +1587,6 @@ test = ["html5lib", "pytest"] name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1672,7 +1601,6 @@ test = ["flake8", "mypy", "pytest"] name = "sphinxcontrib-qthelp" version = "1.0.3" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1688,7 +1616,6 @@ test = ["pytest"] name = "sphinxcontrib-serializinghtml" version = "1.1.5" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1704,7 +1631,6 @@ test = ["pytest"] name = "tenacity" version = "8.1.0" description = "Retry code until it succeeds" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1719,7 +1645,6 @@ doc = ["reno", "sphinx", "tornado (>=4.5)"] name = "textwrap3" version = "0.9.2" description = "textwrap from Python 3.6 backport (plus a few tweaks)" -category = "dev" optional = false python-versions = "*" files = [ @@ -1731,7 +1656,6 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1743,7 +1667,6 @@ files = [ name = "tomlkit" version = "0.11.6" description = "Style preserving TOML library" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1755,7 +1678,6 @@ files = [ name = "tornado" version = "6.3.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -category = "dev" optional = false python-versions = ">= 3.8" files = [ @@ -1776,7 +1698,6 @@ files = [ name = "tqdm" version = "4.64.1" description = "Fast, Extensible Progress Meter" -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" files = [ @@ -1797,7 +1718,6 @@ telegram = ["requests"] name = "traitlets" version = "5.8.1" description = "Traitlets Python configuration system" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1813,7 +1733,6 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] name = "typing-extensions" version = "4.4.0" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1825,7 +1744,6 @@ files = [ name = "urllib3" version = "1.26.14" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -1842,7 +1760,6 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "wrapt" version = "1.14.1" description = "Module for decorators, wrappers and monkey patching." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -1916,7 +1833,6 @@ files = [ name = "zipp" version = "3.11.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" optional = false python-versions = ">=3.7" files = [ From aee35a084378e72a24ddd25866e03324f1e11372 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Wed, 23 Aug 2023 12:21:21 -0700 Subject: [PATCH 08/25] update notebook test --- notebook_test.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/notebook_test.py b/notebook_test.py index 3d9e2b64..4a58bfc5 100644 --- a/notebook_test.py +++ b/notebook_test.py @@ -3,7 +3,6 @@ import netCDF4 as nc import xarray as xr from harmony import BBox, Client, Collection, Request, Environment -#import papermill as pm import argparse from os import path @@ -106,11 +105,9 @@ def test(collection_id, venue): print('\nWaiting for the job to finish') - #harmony_client.wait_for_processing(job1_id) results = harmony_client.result_json(job1_id) print('\nDownloading results:') - #filename = harmony_client.download_all(job1_id, overwrite=True)[0].result() futures = harmony_client.download_all(job1_id) file_names = [f.result() for f in futures] @@ -134,10 +131,8 @@ def test(collection_id, venue): groups = [None] for group in groups: - try: - ds = xr.open_dataset(filename, group=group, decode_times=False, drop_variables=drop_variables) - except xr.core.variable.MissingDimensionsError: - ds = xr.open_dataset(filename, group=group, decode_times=False, drop_variables=drop_variables) + + ds = xr.open_dataset(filename, group=group, decode_times=False, drop_variables=drop_variables) assert len(ds.coords['subset_index']) == max_results variables = list(ds.variables) @@ -204,9 +199,6 @@ def run(): inputFile = _args.input_file output_location = _args.output_path if _args.output_path else '.' - #notebook_path = path.realpath(path.dirname(notebook)) - #notebook_name = path.basename(notebook) - success = [] fails = [] @@ -221,13 +213,7 @@ def run(): try: print(collection) - test(collection, venue.name) - # pm.execute_notebook( - # notebook, - # f"{notebook_path}/output/{collection}_{environment}_output_{notebook_name}", - # parameters=dict(collection_id=collection, venue=venue.name) - # ) success.append(collection) except Exception as ex: print(ex) From d5fc3e11f58ce85883c6a1250f1a45e2325e698e Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Wed, 23 Aug 2023 12:55:42 -0700 Subject: [PATCH 09/25] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d078b13..8efd2f03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Issue-68 - Updated jupyter notebook + - Update notebook test to use python code directly instead of using jupyter notebook + - Updated python libraries ### Deprecated ### Removed ### Fixed From 39a61f0e26f5c097aefaab0f5269f7d52b99c137 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Wed, 23 Aug 2023 13:31:35 -0700 Subject: [PATCH 10/25] update tests names --- .github/workflows/jupyter_test.yml | 18 ++++++++---------- notebook_test.py => add_collection_test.py | 0 2 files changed, 8 insertions(+), 10 deletions(-) rename notebook_test.py => add_collection_test.py (100%) diff --git a/.github/workflows/jupyter_test.yml b/.github/workflows/jupyter_test.yml index 1866a4db..74a998c8 100644 --- a/.github/workflows/jupyter_test.yml +++ b/.github/workflows/jupyter_test.yml @@ -1,5 +1,5 @@ # This is a test pipeline, that verifies and updates the associations in cmr -name: Jupyter Test +name: Add Collection Test # Controls when the workflow will run on: # Allows you to run this workflow manually from the Actions tab @@ -40,9 +40,7 @@ jobs: - name: Install dependencies run: | pip3 install --upgrade pip - pip3 install papermill pip3 install xarray - pip3 install jupyter pip3 install black pip3 install matplotlib pip3 install netCDF4 @@ -54,10 +52,10 @@ jobs: run: | cmr_association_diff -e uat -t service -a "cmr/uat_associations.txt" -p POCLOUD -n 'PODAAC Concise' -o ${{ env.UAT_OUTPUT_FILE }} --token ${{ secrets.LAUNCHPAD_TOKEN_UAT }} cmr_association_diff -e ops -t service -a "cmr/ops_associations.txt" -p POCLOUD -n 'PODAAC Concise' -o ${{ env.OPS_OUTPUT_FILE }} --token ${{ secrets.LAUNCHPAD_TOKEN_OPS }} - - name: Run Jupyter notebooks + - name: Run Add Collection Test run: | - python3 "notebook_test.py" -n "jupyter_notebooks/harmony_concise_api_test.ipynb" -e uat -i ${{ env.UAT_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} - python3 "notebook_test.py" -n "jupyter_notebooks/harmony_concise_api_test.ipynb" -e ops -i ${{ env.OPS_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} + python3 "add_collection_test.py" -e uat -i ${{ env.UAT_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} + python3 "add_collection_test.py" -e ops -i ${{ env.OPS_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} - name: Check UAT files id: check_UAT_output_files run: | @@ -90,22 +88,22 @@ jobs: if: | steps.check_UAT_output_files.outputs.SUCCESS_EXISTS == 'true' run: | - echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\nJupyter-test UAT result: SUCCESS\nSuccessfully ran Concise Notebook on the following collections:\n${{ steps.check_UAT_output_files.outputs.SUCCESS_CONTENT }}\n" >> $GITHUB_ENV + echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test UAT result: SUCCESS\nSuccessfully ran Concise Notebook on the following collections:\n${{ steps.check_UAT_output_files.outputs.SUCCESS_CONTENT }}\n" >> $GITHUB_ENV - name: Slack Report update - Add info for UAT check - FAILURE if: | steps.check_UAT_output_files.outputs.FAIL_EXISTS == 'true' run: | - echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\nJupyter-test UAT result: FAILURE\nFailed to run Concise Notebook on the following collections:\n${{ steps.check_UAT_output_files.outputs.FAIL_CONTENT }}\n" >> $GITHUB_ENV + echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test UAT result: FAILURE\nFailed to run Concise Notebook on the following collections:\n${{ steps.check_UAT_output_files.outputs.FAIL_CONTENT }}\n" >> $GITHUB_ENV - name: Slack Report update - Add info for OPS check - SUCCESS if: | steps.check_OPS_output_files.outputs.SUCCESS_EXISTS == 'true' run: | - echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\nJupyter-test OPS result: SUCCESS\nSuccessfully ran Concise Notebook on the following collections:\n${{ steps.check_OPS_output_files.outputs.SUCCESS_CONTENT }}\n" >> $GITHUB_ENV + echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test OPS result: SUCCESS\nSuccessfully ran Concise Notebook on the following collections:\n${{ steps.check_OPS_output_files.outputs.SUCCESS_CONTENT }}\n" >> $GITHUB_ENV - name: Slack Report update - Add info for OPS check - FAILURE if: | steps.check_OPS_output_files.outputs.FAIL_EXISTS == 'true' run: | - echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\nJupyter-test OPS result: FAILURE\nFailed to run Concise Notebook on the following collections:\n${{ steps.check_OPS_output_files.outputs.FAIL_CONTENT }}\n" >> $GITHUB_ENV + echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test OPS result: FAILURE\nFailed to run Concise Notebook on the following collections:\n${{ steps.check_OPS_output_files.outputs.FAIL_CONTENT }}\n" >> $GITHUB_ENV - name: Slack Report update - Add action link on Failure if: | steps.check_UAT_output_files.outputs.FAIL_EXISTS == 'true' || diff --git a/notebook_test.py b/add_collection_test.py similarity index 100% rename from notebook_test.py rename to add_collection_test.py From 9de25e370156c82949b4f537258d5535135c0aff Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Thu, 24 Aug 2023 10:03:28 -0700 Subject: [PATCH 11/25] fix checking venue to lower case --- add_collection_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/add_collection_test.py b/add_collection_test.py index 4a58bfc5..8fe16a4d 100644 --- a/add_collection_test.py +++ b/add_collection_test.py @@ -51,9 +51,9 @@ def parse_args(): def get_username_and_password(venue): - if venue == "UAT": + if venue.lower() == "uat": return os.environ.get("UAT_USERNAME"), os.environ.get("UAT_PASSWORD") - elif venue == "OPS": + elif venue.lower() == "ops": return os.environ.get('OPS_USERNAME'), os.environ.get('OPS_PASSWORD') else: raise ValueError("Invalid venue") From 832f8098d2c2f4f4ebdde5b851a1b0081387f264 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Thu, 24 Aug 2023 10:16:32 -0700 Subject: [PATCH 12/25] debugging tests --- .github/workflows/jupyter_test.yml | 4 ++-- add_collection_test.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/jupyter_test.yml b/.github/workflows/jupyter_test.yml index 74a998c8..75e0de6b 100644 --- a/.github/workflows/jupyter_test.yml +++ b/.github/workflows/jupyter_test.yml @@ -54,8 +54,8 @@ jobs: cmr_association_diff -e ops -t service -a "cmr/ops_associations.txt" -p POCLOUD -n 'PODAAC Concise' -o ${{ env.OPS_OUTPUT_FILE }} --token ${{ secrets.LAUNCHPAD_TOKEN_OPS }} - name: Run Add Collection Test run: | - python3 "add_collection_test.py" -e uat -i ${{ env.UAT_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} - python3 "add_collection_test.py" -e ops -i ${{ env.OPS_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} + python3 add_collection_test.py -e uat -i ${{ env.UAT_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} + python3 add_collection_test.py -e ops -i ${{ env.OPS_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} - name: Check UAT files id: check_UAT_output_files run: | diff --git a/add_collection_test.py b/add_collection_test.py index 8fe16a4d..bf6bf944 100644 --- a/add_collection_test.py +++ b/add_collection_test.py @@ -234,4 +234,5 @@ def run(): if __name__ == '__main__': + print("Start running test .......") run() From ce09159f6c8d23a6530401f729e4e6b3fe0ce417 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Thu, 24 Aug 2023 10:33:49 -0700 Subject: [PATCH 13/25] testing larger runners --- .github/workflows/jupyter_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jupyter_test.yml b/.github/workflows/jupyter_test.yml index 75e0de6b..f5117e44 100644 --- a/.github/workflows/jupyter_test.yml +++ b/.github/workflows/jupyter_test.yml @@ -10,7 +10,7 @@ jobs: build: name: Test Execution # The type of runner that the job will run on - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 2xlarge steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 From 5f0b742e2b5185e5689020d29a5fc1e6af366fb7 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Thu, 24 Aug 2023 10:42:01 -0700 Subject: [PATCH 14/25] debug tests --- .github/workflows/jupyter_test.yml | 2 +- add_collection_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/jupyter_test.yml b/.github/workflows/jupyter_test.yml index f5117e44..75e0de6b 100644 --- a/.github/workflows/jupyter_test.yml +++ b/.github/workflows/jupyter_test.yml @@ -10,7 +10,7 @@ jobs: build: name: Test Execution # The type of runner that the job will run on - runs-on: ubuntu-20.04 2xlarge + runs-on: ubuntu-latest steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 diff --git a/add_collection_test.py b/add_collection_test.py index bf6bf944..fc83ffcd 100644 --- a/add_collection_test.py +++ b/add_collection_test.py @@ -235,4 +235,4 @@ def run(): if __name__ == '__main__': print("Start running test .......") - run() + #run() From 863390e771f6916c0618b50bae88d5fbfb5e12b7 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Thu, 24 Aug 2023 12:04:04 -0700 Subject: [PATCH 15/25] debug test --- add_collection_test.py | 82 +++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/add_collection_test.py b/add_collection_test.py index fc83ffcd..7f32ac08 100644 --- a/add_collection_test.py +++ b/add_collection_test.py @@ -151,38 +151,38 @@ def test(collection_id, venue): if x_var is None or y_var is None: raise Exception("Lon and Lat variables are not found") - for index in range(0, max_results): - ax = ds.isel(subset_index=index).plot.scatter( - y=y_var, - x=x_var, - hue=variable, - s=1, - levels=9, - cmap="jet", - aspect=2.5, - size=9 - ) - plt.xlim(0., 360.) - plt.ylim(-90., 90.) - plt.show(block=False) - plt.close(ax.figure) - - ax = ds.plot.scatter( - y=y_var, - x=x_var, - hue=variable, - s=1, - levels=9, - cmap="jet", - aspect=2.5, - size=9 - ) - plt.xlim(0., 360.) - plt.ylim(-90., 90.) - plt.show(block=False) - plt.close(ax.figure) - - ds.close() +# for index in range(0, max_results): +# ax = ds.isel(subset_index=index).plot.scatter( +# y=y_var, +# x=x_var, +# hue=variable, +# s=1, +# levels=9, +# cmap="jet", +# aspect=2.5, +# size=9 +# ) +# plt.xlim(0., 360.) +# plt.ylim(-90., 90.) +# plt.show(block=False) +# plt.close(ax.figure) +# +# ax = ds.plot.scatter( +# y=y_var, +# x=x_var, +# hue=variable, +# s=1, +# levels=9, +# cmap="jet", +# aspect=2.5, +# size=9 +# ) +# plt.xlim(0., 360.) +# plt.ylim(-90., 90.) +# plt.show(block=False) +# plt.close(ax.figure) +# +# ds.close() def run(): @@ -220,17 +220,17 @@ def run(): fails.append(collection) # Create output files - if output_location: - success_outfile = path.realpath(f'{output_location}/{_args.env}_success.txt') - fail_outfile = path.realpath(f'{output_location}/{_args.env}_fail.txt') + #if output_location: + # success_outfile = path.realpath(f'{output_location}/{_args.env}_success.txt') + # fail_outfile = path.realpath(f'{output_location}/{_args.env}_fail.txt') - if success: - with open(success_outfile, 'w') as the_file: - the_file.writelines(x + '\n' for x in success) + # if success: + # with open(success_outfile, 'w') as the_file: + # the_file.writelines(x + '\n' for x in success) - if fails: - with open(fail_outfile, 'w') as the_file: - the_file.writelines(x + '\n' for x in fails) + # if fails: + # with open(fail_outfile, 'w') as the_file: + # the_file.writelines(x + '\n' for x in fails) if __name__ == '__main__': From 01e37ec5da6f6ad3d9c7558e7484e333e270e048 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Thu, 24 Aug 2023 12:41:11 -0700 Subject: [PATCH 16/25] debug test --- add_collection_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/add_collection_test.py b/add_collection_test.py index 7f32ac08..9b199a57 100644 --- a/add_collection_test.py +++ b/add_collection_test.py @@ -235,4 +235,4 @@ def run(): if __name__ == '__main__': print("Start running test .......") - #run() + run() From 5ab3d0ca72289852b471714cabec6ed61dcd0ff3 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Thu, 24 Aug 2023 12:59:11 -0700 Subject: [PATCH 17/25] debug test --- add_collection_test.py | 49 ++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/add_collection_test.py b/add_collection_test.py index 9b199a57..eb5d308a 100644 --- a/add_collection_test.py +++ b/add_collection_test.py @@ -151,39 +151,22 @@ def test(collection_id, venue): if x_var is None or y_var is None: raise Exception("Lon and Lat variables are not found") -# for index in range(0, max_results): -# ax = ds.isel(subset_index=index).plot.scatter( -# y=y_var, -# x=x_var, -# hue=variable, -# s=1, -# levels=9, -# cmap="jet", -# aspect=2.5, -# size=9 -# ) -# plt.xlim(0., 360.) -# plt.ylim(-90., 90.) -# plt.show(block=False) -# plt.close(ax.figure) -# -# ax = ds.plot.scatter( -# y=y_var, -# x=x_var, -# hue=variable, -# s=1, -# levels=9, -# cmap="jet", -# aspect=2.5, -# size=9 -# ) -# plt.xlim(0., 360.) -# plt.ylim(-90., 90.) -# plt.show(block=False) -# plt.close(ax.figure) -# -# ds.close() - + for index in range(0, max_results): + ax = ds.isel(subset_index=index).plot.scatter( + y=y_var, + x=x_var, + hue=variable, + s=1, + levels=9, + cmap="jet", + aspect=2.5, + size=9 + ) + plt.xlim(0., 360.) + plt.ylim(-90., 90.) + plt.show(block=False) + plt.clf() + plt.close(ax.figure) def run(): """ From 47c483760393f3f32bb54876c39651b21976e412 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Thu, 24 Aug 2023 13:22:25 -0700 Subject: [PATCH 18/25] debug test --- add_collection_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/add_collection_test.py b/add_collection_test.py index eb5d308a..370d42dc 100644 --- a/add_collection_test.py +++ b/add_collection_test.py @@ -164,7 +164,7 @@ def test(collection_id, venue): ) plt.xlim(0., 360.) plt.ylim(-90., 90.) - plt.show(block=False) + #plt.show(block=False) plt.clf() plt.close(ax.figure) From 5a77f3b0ef7ed13484d4a7091992049f0649b054 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Mon, 28 Aug 2023 12:48:01 -0700 Subject: [PATCH 19/25] updated concise tests --- .github/workflows/build-pipeline.yml | 6 +- .github/workflows/jupyter_test.yml | 2 - add_collection_test.py | 214 +++++++++++++++++++-------- 3 files changed, 156 insertions(+), 66 deletions(-) diff --git a/.github/workflows/build-pipeline.yml b/.github/workflows/build-pipeline.yml index 9abd7805..f6c306a4 100644 --- a/.github/workflows/build-pipeline.yml +++ b/.github/workflows/build-pipeline.yml @@ -141,17 +141,19 @@ jobs: git tag -a "${{ env.software_version }}" -m "Version ${{ env.software_version }}" git push origin "${{ env.software_version }}" - name: Publish UMM-S with new version - uses: podaac/cmr-umm-updater@0.2.3 + uses: podaac/cmr-umm-updater@0.5.0 if: | github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release') with: - umm-s-json: 'cmr/concise_cmr_umm_s.json' + umm-json: 'cmr/concise_cmr_umm_s.json' provider: 'POCLOUD' env: ${{ env.venue }} version: ${{ env.software_version }} timeout: 60 disable_removal: 'true' + umm_type: 'umm-s' + use_associations: 'false' env: cmr_user: ${{secrets.CMR_USER}} cmr_pass: ${{secrets.CMR_PASS}} diff --git a/.github/workflows/jupyter_test.yml b/.github/workflows/jupyter_test.yml index 75e0de6b..7eefcace 100644 --- a/.github/workflows/jupyter_test.yml +++ b/.github/workflows/jupyter_test.yml @@ -40,9 +40,7 @@ jobs: - name: Install dependencies run: | pip3 install --upgrade pip - pip3 install xarray pip3 install black - pip3 install matplotlib pip3 install netCDF4 pip3 install git+https://github.com/nasa/harmony-py.git pip3 install git+https://github.com/podaac/cmr-umm-updater.git diff --git a/add_collection_test.py b/add_collection_test.py index 370d42dc..bcd210a4 100644 --- a/add_collection_test.py +++ b/add_collection_test.py @@ -1,15 +1,15 @@ import os -import matplotlib.pyplot as plt +from os import path +from urllib.parse import urlparse +import itertools +import unittest +import numpy as np import netCDF4 as nc -import xarray as xr +import requests from harmony import BBox, Client, Collection, Request, Environment import argparse - -from os import path - from utils import FileHandler from utils.enums import Venue -import itertools def parse_args(): @@ -75,12 +75,115 @@ def get_x_y_variables(variables): return x_var, y_var +def verify_dims(merged_group, origin_group, both_merged): + for dim in origin_group.dimensions: + if both_merged: + unittest.TestCase().assertEqual(merged_group.dimensions[dim].size, origin_group.dimensions[dim].size) + else: + unittest.TestCase().assertGreaterEqual(merged_group.dimensions[dim].size, origin_group.dimensions[dim].size) + + +def verify_attrs(merged_obj, origin_obj, both_merged): + ignore_attributes = [ + 'request-bounding-box', 'request-bounding-box-description', 'PODAAC-dataset-shortname', + 'PODAAC-persistent-ID', 'time_coverage_end', 'time_coverage_start' + ] + + merged_attrs = merged_obj.ncattrs() + origin_attrs = origin_obj.ncattrs() + + for attr in origin_attrs: + if attr in ignore_attributes: + # Skip attributes which are present in the Java implementation, + # but not (currently) present in the Python implementation + continue + + if not both_merged and attr not in merged_attrs: + # Skip attributes which are not present in both merged and origin. + # This is normal operation as some attributes may be omited b/c + # they're inconsistent between granules + continue + + merged_attr = merged_obj.getncattr(attr) + if both_merged and isinstance(merged_attr, int): + # Skip integer values - the Java implementation seems to omit + # these values due to its internal handling of all values as + # Strings + continue + + origin_attr = origin_obj.getncattr(attr) + if isinstance(origin_attr, np.ndarray): + unittest.TestCase().assertTrue(np.array_equal(merged_attr, origin_attr)) + else: + if attr != "history_json": + unittest.TestCase().assertEqual(merged_attr, origin_attr) + + +def verify_variables(merged_group, origin_group, subset_index, both_merged): + for var in origin_group.variables: + merged_var = merged_group.variables[var] + origin_var = origin_group.variables[var] + + verify_attrs(merged_var, origin_var, both_merged) + + if both_merged: + # both groups require subset indexes + merged_data = merged_var[subset_index[0]] + origin_data = origin_var[subset_index[1]] + else: + # merged group requires a subset index + merged_data = np.resize(merged_var[subset_index], origin_var.shape) + origin_data = origin_var + + # verify variable data + if isinstance(origin_data, str): + unittest.TestCase().assertEqual(merged_data, origin_data) + else: + unittest.TestCase().assertTrue(np.array_equal(merged_data, origin_data, equal_nan=True)) + + +def verify_groups(merged_group, origin_group, subset_index, both_merged=False): + verify_dims(merged_group, origin_group, both_merged) + verify_attrs(merged_group, origin_group, both_merged) + verify_variables(merged_group, origin_group, subset_index, both_merged) + + for child_group in origin_group.groups: + merged_subgroup = merged_group[child_group] + origin_subgroup = origin_group[child_group] + verify_groups(merged_subgroup, origin_subgroup, subset_index, both_merged) + + +# GET TOKEN FROM CMR +def get_token(cmr_root, username, password): + token_api = "https://{}/api/users/tokens".format(cmr_root) + response = requests.get(token_api, auth=(username, password)) + content = response.json() + if len(content) > 0: + return content[0].get('access_token') + else: + create_token_api = "https://{}/api/users/token".format(cmr_root) + response = requests.post(create_token_api, auth=(username, password)) + content = response.json() + return content.get('access_token') + + +def download_file(url, local_path, headers): + response = requests.get(url, stream=True, headers=headers) + if response.status_code == 200: + with open(local_path, 'wb') as file: + for chunk in response.iter_content(chunk_size=8192): + file.write(chunk) + print("Original File downloaded successfully.") + else: + print(f"Failed to download the file. Status code: {response.status_code}") + + def test(collection_id, venue): max_results = 2 username, password = get_username_and_password(venue) - environment = Environment.UAT if venue == "UAT" else Environment.PROD + environment = Environment.UAT if venue.lower() == "uat" else Environment.PROD harmony_client = Client(auth=(username, password), env=environment) collection = Collection(id=collection_id) @@ -115,58 +218,45 @@ def test(collection_id, venue): filename = file_names[0] # Handle time dimension and variables dropping - dt = nc.Dataset(filename, 'r') - groups = list(dt.groups) - dt.close() - - drop_variables = [ - 'time', - 'sample', - 'meas_ind', - 'wvf_ind', - 'ddm', - 'averaged_l1' - ] - if not groups: - groups = [None] + merge_dataset = nc.Dataset(filename, 'r') - for group in groups: + cmr_base_url = "https://cmr.earthdata.nasa.gov/search/granules.umm_json?readable_granule_name=" + edl_root = 'urs.earthdata.nasa.gov' - ds = xr.open_dataset(filename, group=group, decode_times=False, drop_variables=drop_variables) + if venue.lower() == 'uat': + cmr_base_url = "https://cmr.uat.earthdata.nasa.gov/search/granules.umm_json?readable_granule_name=" + edl_root = 'uat.urs.earthdata.nasa.gov' + + token = get_token(edl_root, username, password) + headers = { + "Authorization": f"Bearer {token}" + } - assert len(ds.coords['subset_index']) == max_results - variables = list(ds.variables) - x_var, y_var = get_x_y_variables(variables) + original_files = merge_dataset.variables['subset_files'] + assert len(original_files) == max_results - for v in variables: - if v not in ['subset_files', 'lat', 'lon', 'latitude', 'longitude', 'beam_clat', 'beam_clon']: - variable = v - break + for file in original_files: - if x_var is not None and y_var is not None: - break + file_name = file.rsplit(".", 1)[0] + print(file_name) + cmr_query = f"{cmr_base_url}{file_name}&collection_concept_id={collection_id}" + print(cmr_query) + + response = requests.get(cmr_query, headers=headers) + + result = response.json() + links = result.get('items')[0].get('umm').get('RelatedUrls') + for link in links: + if link.get('Type') == 'GET DATA': + data_url = link.get('URL') + parsed_url = urlparse(data_url) + local_file_name = os.path.basename(parsed_url.path) + download_file(data_url, local_file_name, headers) + + for i, file in enumerate(original_files): + origin_dataset = nc.Dataset(file) + verify_groups(merge_dataset, origin_dataset, i) - ds.close() - - if x_var is None or y_var is None: - raise Exception("Lon and Lat variables are not found") - - for index in range(0, max_results): - ax = ds.isel(subset_index=index).plot.scatter( - y=y_var, - x=x_var, - hue=variable, - s=1, - levels=9, - cmap="jet", - aspect=2.5, - size=9 - ) - plt.xlim(0., 360.) - plt.ylim(-90., 90.) - #plt.show(block=False) - plt.clf() - plt.close(ax.figure) def run(): """ @@ -203,17 +293,17 @@ def run(): fails.append(collection) # Create output files - #if output_location: - # success_outfile = path.realpath(f'{output_location}/{_args.env}_success.txt') - # fail_outfile = path.realpath(f'{output_location}/{_args.env}_fail.txt') + if output_location: + success_outfile = path.realpath(f'{output_location}/{_args.env}_success.txt') + fail_outfile = path.realpath(f'{output_location}/{_args.env}_fail.txt') - # if success: - # with open(success_outfile, 'w') as the_file: - # the_file.writelines(x + '\n' for x in success) + if success: + with open(success_outfile, 'w') as the_file: + the_file.writelines(x + '\n' for x in success) - # if fails: - # with open(fail_outfile, 'w') as the_file: - # the_file.writelines(x + '\n' for x in fails) + if fails: + with open(fail_outfile, 'w') as the_file: + the_file.writelines(x + '\n' for x in fails) if __name__ == '__main__': From b4bc67e87831010df807e6e0bbefe13ef22bd1b6 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Mon, 28 Aug 2023 13:03:20 -0700 Subject: [PATCH 20/25] fix indentation --- add_collection_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/add_collection_test.py b/add_collection_test.py index bcd210a4..dc80d0d1 100644 --- a/add_collection_test.py +++ b/add_collection_test.py @@ -226,7 +226,7 @@ def test(collection_id, venue): if venue.lower() == 'uat': cmr_base_url = "https://cmr.uat.earthdata.nasa.gov/search/granules.umm_json?readable_granule_name=" edl_root = 'uat.urs.earthdata.nasa.gov' - + token = get_token(edl_root, username, password) headers = { "Authorization": f"Bearer {token}" @@ -293,7 +293,7 @@ def run(): fails.append(collection) # Create output files - if output_location: + if output_location: success_outfile = path.realpath(f'{output_location}/{_args.env}_success.txt') fail_outfile = path.realpath(f'{output_location}/{_args.env}_fail.txt') From 5897bbf14064325c12e45cd7c1f00316b44fea9f Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Mon, 28 Aug 2023 14:30:08 -0700 Subject: [PATCH 21/25] renaming add collection test github actions yml --- .github/workflows/add-collection-test.yml | 156 ++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 .github/workflows/add-collection-test.yml diff --git a/.github/workflows/add-collection-test.yml b/.github/workflows/add-collection-test.yml new file mode 100644 index 00000000..a156eb6b --- /dev/null +++ b/.github/workflows/add-collection-test.yml @@ -0,0 +1,156 @@ +# This is a test pipeline, that verifies and updates the associations in cmr +name: Add Collection Test +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + # First job in the workflow installs and verifies the software + build: + name: Test Execution + # The type of runner that the job will run on + runs-on: ubuntu-latest + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.9 + - name: Create Output Directory + run: mkdir test_output + - name: Set environment variables + run: | + echo "UAT_OUTPUT_FILE=test_output/output/uat_output_json.txt" >> $GITHUB_ENV + echo "OPS_OUTPUT_FILE=test_output/output/ops_output_json.txt" >> $GITHUB_ENV + echo "OUTPUT_DIR=test_output/output" >> $GITHUB_ENV + echo "UAT_SUCCESS_FILE=uat_success.txt" >> $GITHUB_ENV + echo "OPS_SUCCESS_FILE=ops_success.txt" >> $GITHUB_ENV + echo "UAT_FAILURE_FILE=uat_fail.txt" >> $GITHUB_ENV + echo "OPS_FAILURE_FILE=ops_fail.txt" >> $GITHUB_ENV + echo "SLACK_REPORT_CONTENT=" >> $GITHUB_ENV + - name: Set environment variables for notebook + run: | + echo "OPS_USERNAME=${{ secrets.EDL_USER }}" >> $GITHUB_ENV + echo "OPS_PASSWORD=${{ secrets.EDL_PASS }}" >> $GITHUB_ENV + echo "UAT_USERNAME=${{ secrets.EDL_USER }}" >> $GITHUB_ENV + echo "UAT_PASSWORD=${{ secrets.EDL_PASS }}" >> $GITHUB_ENV + - name: Create prerequisites + run: | + mkdir ${{ env.OUTPUT_DIR }} + realpath ${{ env.OUTPUT_DIR }} + - name: Install dependencies + run: | + pip3 install --upgrade pip + pip3 install black + pip3 install netCDF4 + pip3 install git+https://github.com/nasa/harmony-py.git + pip3 install git+https://github.com/podaac/cmr-umm-updater.git + pip3 install git+https://github.com/podaac/cmr-association-diff.git@6193079a14e36f4c9526aa426015c2b6be41f0e2 + pip3 install python-dateutil --upgrade + - name: Run CMR Association diff scripts + run: | + cmr_association_diff -e uat -t service -a "cmr/uat_associations.txt" -p POCLOUD -n 'PODAAC Concise' -o ${{ env.UAT_OUTPUT_FILE }} --token ${{ secrets.LAUNCHPAD_TOKEN_UAT }} + cmr_association_diff -e ops -t service -a "cmr/ops_associations.txt" -p POCLOUD -n 'PODAAC Concise' -o ${{ env.OPS_OUTPUT_FILE }} --token ${{ secrets.LAUNCHPAD_TOKEN_OPS }} + - name: Run Add Collection Test + run: | + python3 add_collection_test.py -e uat -i ${{ env.UAT_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} + python3 add_collection_test.py -e ops -i ${{ env.OPS_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} + - name: Check UAT files + id: check_UAT_output_files + run: | + echo "::set-output name=SUCCESS_EXISTS::$(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.UAT_SUCCESS_FILE }} ]; then echo "true"; else echo "false"; fi)" + echo "::set-output name=FAIL_EXISTS::$(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.UAT_FAILURE_FILE }} ]; then echo "true"; else echo "false"; fi)" + echo "::set-output name=SUCCESS_CONTENT::$(cat ${{ env.OUTPUT_DIR }}/${{ env.UAT_SUCCESS_FILE }} | sed 's/$/,/' | tr '\n' ' ')" + echo "::set-output name=FAIL_CONTENT::$(cat ${{ env.OUTPUT_DIR }}/${{ env.UAT_FAILURE_FILE }} | sed 's/$/,/' | tr '\n' ' ')" + echo + echo + echo "Success File: $(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.UAT_SUCCESS_FILE }} ]; then echo "true"; else echo "false"; fi)" + echo "Failed File: $(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.UAT_FAILURE_FILE }} ]; then echo "true"; else echo "false"; fi)" + echo "Success Content: $(cat ${{ env.OUTPUT_DIR }}/${{ env.UAT_SUCCESS_FILE }} | sed 's/$/,/' | tr '\n' ' ')" + echo + echo "Failed Content: $(cat ${{ env.OUTPUT_DIR }}/${{ env.UAT_FAILURE_FILE }} | sed 's/$/,/' | tr '\n' ' ')" + - name: Check OPS files + id: check_OPS_output_files + run: | + echo "::set-output name=SUCCESS_EXISTS::$(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.OPS_SUCCESS_FILE }} ]; then echo "true"; else echo "false"; fi)" + echo "::set-output name=FAIL_EXISTS::$(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.OPS_FAILURE_FILE }} ]; then echo "true"; else echo "false"; fi)" + echo "::set-output name=SUCCESS_CONTENT::$(cat ${{ env.OUTPUT_DIR }}/${{ env.OPS_SUCCESS_FILE }} | sed 's/$/,/' | tr '\n' ' ')" + echo "::set-output name=FAIL_CONTENT::$(cat ${{ env.OUTPUT_DIR }}/${{ env.OPS_FAILURE_FILE }} | sed 's/$/,/' | tr '\n' ' ')" + echo + echo + echo "Success File: $(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.OPS_SUCCESS_FILE }} ]; then echo "true"; else echo "false"; fi)" + echo "Failed File: $(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.OPS_FAILURE_FILE }} ]; then echo "true"; else echo "false"; fi)" + echo "Success Content: $(cat ${{ env.OUTPUT_DIR }}/${{ env.OPS_SUCCESS_FILE }} | sed 's/$/,/' | tr '\n' ' ')" + echo + echo "Failed Content: $(cat ${{ env.OUTPUT_DIR }}/${{ env.OPS_FAILURE_FILE }} | sed 's/$/,/' | tr '\n' ' ')" + - name: Slack Report update - Add info for UAT check - SUCCESS + if: | + steps.check_UAT_output_files.outputs.SUCCESS_EXISTS == 'true' + run: | + echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test UAT result: SUCCESS\nSuccessfully ran Concise Notebook on the following collections:\n${{ steps.check_UAT_output_files.outputs.SUCCESS_CONTENT }}\n" >> $GITHUB_ENV + - name: Slack Report update - Add info for UAT check - FAILURE + if: | + steps.check_UAT_output_files.outputs.FAIL_EXISTS == 'true' + run: | + echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test UAT result: FAILURE\nFailed to run Concise Notebook on the following collections:\n${{ steps.check_UAT_output_files.outputs.FAIL_CONTENT }}\n" >> $GITHUB_ENV + - name: Slack Report update - Add info for OPS check - SUCCESS + if: | + steps.check_OPS_output_files.outputs.SUCCESS_EXISTS == 'true' + run: | + echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test OPS result: SUCCESS\nSuccessfully ran Concise Notebook on the following collections:\n${{ steps.check_OPS_output_files.outputs.SUCCESS_CONTENT }}\n" >> $GITHUB_ENV + - name: Slack Report update - Add info for OPS check - FAILURE + if: | + steps.check_OPS_output_files.outputs.FAIL_EXISTS == 'true' + run: | + echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test OPS result: FAILURE\nFailed to run Concise Notebook on the following collections:\n${{ steps.check_OPS_output_files.outputs.FAIL_CONTENT }}\n" >> $GITHUB_ENV + - name: Slack Report update - Add action link on Failure + if: | + steps.check_UAT_output_files.outputs.FAIL_EXISTS == 'true' || + steps.check_OPS_output_files.outputs.FAIL_EXISTS == 'true' + run: | + echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\nExecution link:\ngithub.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_ENV + echo ${{ env.SLACK_REPORT_CONTENT }} + - name: Send Report to Slack + uses: slackapi/slack-github-action@v1.21.0 + if: | + env.SLACK_REPORT_CONTENT != '' + with: + payload: | + { + "status": "${{ env.SLACK_REPORT_CONTENT }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_BOT_WEBHOOK }} + - name: Remove UAT collections on FAIL + if: | + steps.check_UAT_output_files.outputs.FAIL_EXISTS == 'true' + run: | + python3 "remove_association.py" -p POCLOUD -n 'PODAAC Concise' -e uat -i '${{ env.OUTPUT_DIR }}/${{ env.UAT_FAILURE_FILE }}' --token ${{ secrets.LAUNCHPAD_TOKEN_UAT }} + - name: Remove OPS collections on FAIL + if: | + steps.check_OPS_output_files.outputs.FAIL_EXISTS == 'true' + run: | + python3 "remove_association.py" -p POCLOUD -n 'PODAAC Concise' -e ops -i '${{ env.OUTPUT_DIR }}/${{ env.OPS_FAILURE_FILE }}' --token ${{ secrets.LAUNCHPAD_TOKEN_OPS }} + - name: Update UAT collections on SUCCESS + if: | + steps.check_UAT_output_files.outputs.SUCCESS_EXISTS == 'true' + # Add a new line to the EOF if there isn't any, so the merging will start in a new line not after the last character + run: | + vi -escwq ./cmr/uat_associations.txt + cat ${{ env.OUTPUT_DIR }}/${{ env.UAT_SUCCESS_FILE }} >> ./cmr/uat_associations.txt + git config user.name "${GITHUB_ACTOR}" + git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" + git commit -am "Update uat_associations.txt with new collections" + git push + - name: Update OPS collections on SUCCESS + if: | + steps.check_OPS_output_files.outputs.SUCCESS_EXISTS == 'true' + # Add a new line to the EOF if there isn't any, so the merging will start in a new line not after the last character + run: | + vi -escwq ./cmr/ops_associations.txt + cat ${{ env.OUTPUT_DIR }}/${{ env.OPS_SUCCESS_FILE }} >> ./cmr/ops_associations.txt + git config user.name "${GITHUB_ACTOR}" + git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" + git commit -am "Update ops_associations.txt with new collections" + git push From 64ac817ebfcfcf27a490a3cf420cd38bbb173c95 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Mon, 28 Aug 2023 14:33:01 -0700 Subject: [PATCH 22/25] update old jupyter test --- .github/workflows/jupyter_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jupyter_test.yml b/.github/workflows/jupyter_test.yml index 7eefcace..7ac1b70e 100644 --- a/.github/workflows/jupyter_test.yml +++ b/.github/workflows/jupyter_test.yml @@ -1,5 +1,5 @@ # This is a test pipeline, that verifies and updates the associations in cmr -name: Add Collection Test +name: Add Collection Test OLD # Controls when the workflow will run on: # Allows you to run this workflow manually from the Actions tab From a65b86ffb115ac36ca747f51aedae3ae65acfbfb Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Mon, 28 Aug 2023 15:38:58 -0700 Subject: [PATCH 23/25] remove jupyter notebook references --- .github/workflows/jupyter_test.yml | 154 ------ .../harmony_concise_api_test.ipynb | 491 ------------------ 2 files changed, 645 deletions(-) delete mode 100644 .github/workflows/jupyter_test.yml delete mode 100644 jupyter_notebooks/harmony_concise_api_test.ipynb diff --git a/.github/workflows/jupyter_test.yml b/.github/workflows/jupyter_test.yml deleted file mode 100644 index 7ac1b70e..00000000 --- a/.github/workflows/jupyter_test.yml +++ /dev/null @@ -1,154 +0,0 @@ -# This is a test pipeline, that verifies and updates the associations in cmr -name: Add Collection Test OLD -# Controls when the workflow will run -on: - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -jobs: - # First job in the workflow installs and verifies the software - build: - name: Test Execution - # The type of runner that the job will run on - runs-on: ubuntu-latest - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - name: Set environment variables - run: | - echo "UAT_OUTPUT_FILE=jupyter_notebooks/output/uat_output_json.txt" >> $GITHUB_ENV - echo "OPS_OUTPUT_FILE=jupyter_notebooks/output/ops_output_json.txt" >> $GITHUB_ENV - echo "OUTPUT_DIR=jupyter_notebooks/output" >> $GITHUB_ENV - echo "UAT_SUCCESS_FILE=uat_success.txt" >> $GITHUB_ENV - echo "OPS_SUCCESS_FILE=ops_success.txt" >> $GITHUB_ENV - echo "UAT_FAILURE_FILE=uat_fail.txt" >> $GITHUB_ENV - echo "OPS_FAILURE_FILE=ops_fail.txt" >> $GITHUB_ENV - echo "SLACK_REPORT_CONTENT=" >> $GITHUB_ENV - - name: Set environment variables for notebook - run: | - echo "OPS_USERNAME=${{ secrets.EDL_USER }}" >> $GITHUB_ENV - echo "OPS_PASSWORD=${{ secrets.EDL_PASS }}" >> $GITHUB_ENV - echo "UAT_USERNAME=${{ secrets.EDL_USER }}" >> $GITHUB_ENV - echo "UAT_PASSWORD=${{ secrets.EDL_PASS }}" >> $GITHUB_ENV - - name: Create prerequisites - run: | - mkdir ${{ env.OUTPUT_DIR }} - realpath ${{ env.OUTPUT_DIR }} - - name: Install dependencies - run: | - pip3 install --upgrade pip - pip3 install black - pip3 install netCDF4 - pip3 install git+https://github.com/nasa/harmony-py.git - pip3 install git+https://github.com/podaac/cmr-umm-updater.git - pip3 install git+https://github.com/podaac/cmr-association-diff.git@6193079a14e36f4c9526aa426015c2b6be41f0e2 - pip3 install python-dateutil --upgrade - - name: Run CMR Association diff scripts - run: | - cmr_association_diff -e uat -t service -a "cmr/uat_associations.txt" -p POCLOUD -n 'PODAAC Concise' -o ${{ env.UAT_OUTPUT_FILE }} --token ${{ secrets.LAUNCHPAD_TOKEN_UAT }} - cmr_association_diff -e ops -t service -a "cmr/ops_associations.txt" -p POCLOUD -n 'PODAAC Concise' -o ${{ env.OPS_OUTPUT_FILE }} --token ${{ secrets.LAUNCHPAD_TOKEN_OPS }} - - name: Run Add Collection Test - run: | - python3 add_collection_test.py -e uat -i ${{ env.UAT_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} - python3 add_collection_test.py -e ops -i ${{ env.OPS_OUTPUT_FILE }} -o ${{ env.OUTPUT_DIR }} - - name: Check UAT files - id: check_UAT_output_files - run: | - echo "::set-output name=SUCCESS_EXISTS::$(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.UAT_SUCCESS_FILE }} ]; then echo "true"; else echo "false"; fi)" - echo "::set-output name=FAIL_EXISTS::$(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.UAT_FAILURE_FILE }} ]; then echo "true"; else echo "false"; fi)" - echo "::set-output name=SUCCESS_CONTENT::$(cat ${{ env.OUTPUT_DIR }}/${{ env.UAT_SUCCESS_FILE }} | sed 's/$/,/' | tr '\n' ' ')" - echo "::set-output name=FAIL_CONTENT::$(cat ${{ env.OUTPUT_DIR }}/${{ env.UAT_FAILURE_FILE }} | sed 's/$/,/' | tr '\n' ' ')" - echo - echo - echo "Success File: $(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.UAT_SUCCESS_FILE }} ]; then echo "true"; else echo "false"; fi)" - echo "Failed File: $(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.UAT_FAILURE_FILE }} ]; then echo "true"; else echo "false"; fi)" - echo "Success Content: $(cat ${{ env.OUTPUT_DIR }}/${{ env.UAT_SUCCESS_FILE }} | sed 's/$/,/' | tr '\n' ' ')" - echo - echo "Failed Content: $(cat ${{ env.OUTPUT_DIR }}/${{ env.UAT_FAILURE_FILE }} | sed 's/$/,/' | tr '\n' ' ')" - - name: Check OPS files - id: check_OPS_output_files - run: | - echo "::set-output name=SUCCESS_EXISTS::$(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.OPS_SUCCESS_FILE }} ]; then echo "true"; else echo "false"; fi)" - echo "::set-output name=FAIL_EXISTS::$(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.OPS_FAILURE_FILE }} ]; then echo "true"; else echo "false"; fi)" - echo "::set-output name=SUCCESS_CONTENT::$(cat ${{ env.OUTPUT_DIR }}/${{ env.OPS_SUCCESS_FILE }} | sed 's/$/,/' | tr '\n' ' ')" - echo "::set-output name=FAIL_CONTENT::$(cat ${{ env.OUTPUT_DIR }}/${{ env.OPS_FAILURE_FILE }} | sed 's/$/,/' | tr '\n' ' ')" - echo - echo - echo "Success File: $(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.OPS_SUCCESS_FILE }} ]; then echo "true"; else echo "false"; fi)" - echo "Failed File: $(if [ -f ${{ env.OUTPUT_DIR }}/${{ env.OPS_FAILURE_FILE }} ]; then echo "true"; else echo "false"; fi)" - echo "Success Content: $(cat ${{ env.OUTPUT_DIR }}/${{ env.OPS_SUCCESS_FILE }} | sed 's/$/,/' | tr '\n' ' ')" - echo - echo "Failed Content: $(cat ${{ env.OUTPUT_DIR }}/${{ env.OPS_FAILURE_FILE }} | sed 's/$/,/' | tr '\n' ' ')" - - name: Slack Report update - Add info for UAT check - SUCCESS - if: | - steps.check_UAT_output_files.outputs.SUCCESS_EXISTS == 'true' - run: | - echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test UAT result: SUCCESS\nSuccessfully ran Concise Notebook on the following collections:\n${{ steps.check_UAT_output_files.outputs.SUCCESS_CONTENT }}\n" >> $GITHUB_ENV - - name: Slack Report update - Add info for UAT check - FAILURE - if: | - steps.check_UAT_output_files.outputs.FAIL_EXISTS == 'true' - run: | - echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test UAT result: FAILURE\nFailed to run Concise Notebook on the following collections:\n${{ steps.check_UAT_output_files.outputs.FAIL_CONTENT }}\n" >> $GITHUB_ENV - - name: Slack Report update - Add info for OPS check - SUCCESS - if: | - steps.check_OPS_output_files.outputs.SUCCESS_EXISTS == 'true' - run: | - echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test OPS result: SUCCESS\nSuccessfully ran Concise Notebook on the following collections:\n${{ steps.check_OPS_output_files.outputs.SUCCESS_CONTENT }}\n" >> $GITHUB_ENV - - name: Slack Report update - Add info for OPS check - FAILURE - if: | - steps.check_OPS_output_files.outputs.FAIL_EXISTS == 'true' - run: | - echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\ncollection-test OPS result: FAILURE\nFailed to run Concise Notebook on the following collections:\n${{ steps.check_OPS_output_files.outputs.FAIL_CONTENT }}\n" >> $GITHUB_ENV - - name: Slack Report update - Add action link on Failure - if: | - steps.check_UAT_output_files.outputs.FAIL_EXISTS == 'true' || - steps.check_OPS_output_files.outputs.FAIL_EXISTS == 'true' - run: | - echo "SLACK_REPORT_CONTENT=${{ env.SLACK_REPORT_CONTENT }}\nExecution link:\ngithub.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_ENV - echo ${{ env.SLACK_REPORT_CONTENT }} - - name: Send Report to Slack - uses: slackapi/slack-github-action@v1.21.0 - if: | - env.SLACK_REPORT_CONTENT != '' - with: - payload: | - { - "status": "${{ env.SLACK_REPORT_CONTENT }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_BOT_WEBHOOK }} - - name: Remove UAT collections on FAIL - if: | - steps.check_UAT_output_files.outputs.FAIL_EXISTS == 'true' - run: | - python3 "remove_association.py" -p POCLOUD -n 'PODAAC Concise' -e uat -i '${{ env.OUTPUT_DIR }}/${{ env.UAT_FAILURE_FILE }}' --token ${{ secrets.LAUNCHPAD_TOKEN_UAT }} - - name: Remove OPS collections on FAIL - if: | - steps.check_OPS_output_files.outputs.FAIL_EXISTS == 'true' - run: | - python3 "remove_association.py" -p POCLOUD -n 'PODAAC Concise' -e ops -i '${{ env.OUTPUT_DIR }}/${{ env.OPS_FAILURE_FILE }}' --token ${{ secrets.LAUNCHPAD_TOKEN_OPS }} - - name: Update UAT collections on SUCCESS - if: | - steps.check_UAT_output_files.outputs.SUCCESS_EXISTS == 'true' - # Add a new line to the EOF if there isn't any, so the merging will start in a new line not after the last character - run: | - vi -escwq ./cmr/uat_associations.txt - cat ${{ env.OUTPUT_DIR }}/${{ env.UAT_SUCCESS_FILE }} >> ./cmr/uat_associations.txt - git config user.name "${GITHUB_ACTOR}" - git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" - git commit -am "Update uat_associations.txt with new collections" - git push - - name: Update OPS collections on SUCCESS - if: | - steps.check_OPS_output_files.outputs.SUCCESS_EXISTS == 'true' - # Add a new line to the EOF if there isn't any, so the merging will start in a new line not after the last character - run: | - vi -escwq ./cmr/ops_associations.txt - cat ${{ env.OUTPUT_DIR }}/${{ env.OPS_SUCCESS_FILE }} >> ./cmr/ops_associations.txt - git config user.name "${GITHUB_ACTOR}" - git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" - git commit -am "Update ops_associations.txt with new collections" - git push diff --git a/jupyter_notebooks/harmony_concise_api_test.ipynb b/jupyter_notebooks/harmony_concise_api_test.ipynb deleted file mode 100644 index f9a2de83..00000000 --- a/jupyter_notebooks/harmony_concise_api_test.ipynb +++ /dev/null @@ -1,491 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "910b7006", - "metadata": {}, - "source": [ - "# Harmony EOSS Concise API Tutorial" - ] - }, - { - "cell_type": "markdown", - "id": "3035e026", - "metadata": {}, - "source": [ - "\n", - "## What is Concise?\n", - "\n", - "Concise is a Harmony service developed by PODAAC that allows users to concatenate multiple L2 granules together into a single granule. This concatenation is done by adding a new subset_index dimension to the resulting granule.\n", - "\n", - "\n", - "## Before you start\n", - "\n", - "\n", - "Before you beginning this tutorial, make sure you have an account in the Earthdata Login UAT or Production environment, which will be used for this notebook by visiting https://uat.urs.earthdata.nasa.gov. These accounts, as all Earthdata Login accounts, are free to create and only take a moment to set up.\n", - "\n", - "Please setup the following environment variable for respective environment, setup in .bashrc file.\n", - "\n", - "OPS_USERNAME\n", - "OPS_PASSWORD\n", - "UAT_USERNAME\n", - "UAT_PASSWORD\n", - "\n", - "Set up libraries needed to run demo" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "id": "3c95100d", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "from harmony import BBox, Client, Collection, Request, Environment\n", - "import xarray as xr\n", - "import netCDF4 as nc\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "markdown", - "id": "caa60e99", - "metadata": {}, - "source": [ - "Set up collection to run concise and how many granules to concatenate" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "id": "0c9b70ea", - "metadata": { - "tags": [ - "parameters" - ] - }, - "outputs": [], - "source": [ - "collection_id = 'C2205121485-POCLOUD'\n", - "max_results = 2\n", - "venue = \"OPS\"" - ] - }, - { - "cell_type": "markdown", - "id": "86352d1e", - "metadata": {}, - "source": [ - "Retrieve credentials username and password for earthdata" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "id": "5ccd035f", - "metadata": {}, - "outputs": [], - "source": [ - "if venue == \"UAT\":\n", - " username = os.environ.get(\"UAT_USERNAME\")\n", - " password = os.environ.get(\"UAT_PASSWORD\")\n", - "elif venue == \"OPS\":\n", - " username = os.environ.get('OPS_USERNAME')\n", - " password = os.environ.get('OPS_PASSWORD')" - ] - }, - { - "cell_type": "markdown", - "id": "79b56b55", - "metadata": {}, - "source": [ - "Setup harmony client to make our harmony request with our username and password. \n", - "\n", - "Create our request with the collection we want to concatenate, set concatenate to true, how many granules we want to concatenate, set skip preview to true so job doesn't pause, and the format output we want.\n", - "\n", - "Check to make sure our harmony request is valid." - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "id": "b11675ac", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 41, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "if venue == \"UAT\":\n", - " harmony_client = Client(auth=(username, password), env=Environment.UAT)\n", - "elif venue == \"OPS\":\n", - " harmony_client = Client(auth=(username, password), env=Environment.PROD)\n", - "\n", - "collection = Collection(id=collection_id)\n", - "\n", - "request = Request(\n", - " collection = collection,\n", - " concatenate = True,\n", - " max_results = max_results,\n", - " skip_preview = True,\n", - " format=\"application/x-netcdf4\",\n", - ")\n", - "\n", - "request.is_valid()" - ] - }, - { - "cell_type": "markdown", - "id": "b4e5544d", - "metadata": {}, - "source": [ - "Now that we have a valid request we simply need to call the submit function using the client we created earlier and pass in the request as a parameter.\n", - "\n", - "Tip: if you want to see the request before submitting it, use the request_as_curl function on the client to get an equivalent curl command for the request that will be submitted." - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "id": "36ce8016", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "curl -X GET -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Authorization: *****' -H 'Connection: keep-alive' -H 'Cookie: urs_user_already_logged=yes; state=s%3A1c51c3d53a38e6af99f0366288cd18bf.p404RcPg%2BvidV0pdWb9gqeHVcz4Hld5s5Q5PexRzbXs; token=*****; _urs-gui_session=a61daf78fa6987f16d1ffc770d775b69' -H 'User-Agent: CPython/3.8.12 harmony-py/0.4.2 Darwin/22.6.0 python-requests/2.27.1' 'https://harmony.earthdata.nasa.gov/C2205121485-POCLOUD/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?forceAsync=true&format=application%2Fx-netcdf4&maxResults=2&concatenate=true&skipPreview=true'\n" - ] - } - ], - "source": [ - "print(harmony_client.request_as_curl(request))\n", - "\n", - "job1_id = harmony_client.submit(request)" - ] - }, - { - "cell_type": "markdown", - "id": "9d095bf3", - "metadata": {}, - "source": [ - "After submitting the request it is possible to retrieve the current processing status by using the job ID returned from the submission.\n", - "\n", - "If the request is still running, we can wait until the Harmony request has finished processing. This cell will wait until the request has finised." - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "id": "0d13a446", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "0790ef60-4c3b-4189-b9ac-d9dad2aafafe\n", - "{'status': 'running', 'message': 'CMR query identified 1308 granules, but the request has been limited to process only the first 2 granules because you requested 2 maxResults.', 'progress': 0, 'created_at': datetime.datetime(2023, 8, 16, 17, 32, 22, 669000, tzinfo=tzutc()), 'updated_at': datetime.datetime(2023, 8, 16, 17, 32, 22, 669000, tzinfo=tzutc()), 'created_at_local': '2023-08-16T10:32:22-07:00', 'updated_at_local': '2023-08-16T10:32:22-07:00', 'data_expiration': datetime.datetime(2023, 9, 15, 17, 32, 22, 669000, tzinfo=tzutc()), 'data_expiration_local': '2023-09-15T10:32:22-07:00', 'request': 'https://harmony.earthdata.nasa.gov/C2205121485-POCLOUD/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?forceAsync=true&format=application%2Fx-netcdf4&maxResults=2&concatenate=true&skipPreview=true', 'num_input_granules': 2}\n", - "\n", - "Waiting for the job to finish\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " [ Processing: 100% ] |###################################################| [|]\n" - ] - } - ], - "source": [ - "print(f'\\n{job1_id}')\n", - "\n", - "print(harmony_client.status(job1_id))\n", - "\n", - "print('\\nWaiting for the job to finish')\n", - "results = harmony_client.result_json(job1_id, show_progress=True)" - ] - }, - { - "cell_type": "markdown", - "id": "d47ecde0", - "metadata": {}, - "source": [ - "After the harmony job is finished we download the resulting concatenated granule file." - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "id": "168e7b11", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Downloading results:\n", - "\n", - "C2205121485-POCLOUD_merged.nc4\n", - "\n", - "Done downloading.\n" - ] - } - ], - "source": [ - "print('\\nDownloading results:')\n", - "filename = None\n", - "futures = harmony_client.download_all(job1_id, overwrite=True)\n", - "for f in futures:\n", - " print(f)\n", - " print(f.result()) # f.result() is a filename, in this case\n", - " filename = f.result()\n", - "print('\\nDone downloading.')" - ] - }, - { - "cell_type": "markdown", - "id": "c6f246ed", - "metadata": {}, - "source": [ - "With the output file downloaded, now we can open concatenated granule using xarray to inspect some of the metadata. \n", - "\n", - "Note:\n", - "In some of the collections the time variable has a time dimension and when we concatenate files we add a subset_index into the time dimension which causes the time variable have two dimension. Xarray doesn't allow the time variable have two dimensions so when using xarray to open concatenated files the time variable might need to be dropped. The file can be open with netcdf library" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "id": "04db3295", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "#some collections time variabe has a time dimension which can cause an exception when we concatenate and makes time two dimension\n", - "dt = nc.Dataset(filename,'r')\n", - "groups = list(dt.groups)\n", - "dt.close()\n", - " \n", - "drop_variables = [\n", - " 'time',\n", - " 'sample',\n", - " 'meas_ind',\n", - " 'wvf_ind',\n", - " 'ddm',\n", - " 'averaged_l1'\n", - "]\n", - "if len(groups) == 0:\n", - " groups = [None]" - ] - }, - { - "cell_type": "markdown", - "id": "e74cc045", - "metadata": {}, - "source": [ - "After opening the file we can use matplotlib to create a plot for each subindex where each subindex represents the data for the granule file. We will plot sea_surface_temperature for each granule using subset_index dimension." - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "id": "a733274d", - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['subset_files', 'ddm_source', 'spacecraft_id', 'spacecraft_num', 'prn_code', 'sv_num', 'antenna', 'sample_time', 'lat', 'lon', 'sc_lat', 'sc_lon', 'sc_alt', 'wind_speed', 'fds_nbrcs_wind_speed', 'fds_les_wind_speed', 'wind_speed_uncertainty', 'azimuth_angle', 'sc_roll', 'commanded_sc_roll', 'mean_square_slope', 'mean_square_slope_uncertainty', 'incidence_angle', 'nbrcs_mean', 'les_mean', 'range_corr_gain', 'fresnel_coeff', 'merra2_wind_speed', 'num_ddms_utilized', 'sample_flags', 'fds_sample_flags', 'sum_neg_brcs_value_used_for_nbrcs_flags', 'ddm_obs_utilized_flag', 'ddm_num_averaged_l1', 'ddm_channel', 'ddm_les', 'ddm_nbrcs', 'ddm_sample_index', 'ddm_averaged_l1_utilized_flag']\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "for group in groups:\n", - "\n", - " try:\n", - " ds = xr.open_dataset(filename, group=group, decode_times=False)\n", - " except xr.core.variable.MissingDimensionsError:\n", - " ds = xr.open_dataset(filename, group=group, decode_times=False, drop_variables=drop_variables)\n", - "\n", - " assert len(ds.coords['subset_index']) == max_results\n", - "\n", - " variable = None\n", - " variables = list(ds.variables)\n", - " print(variables)\n", - " \n", - " for v in variables:\n", - " if v not in ['subset_files', 'lat', 'lon', 'latitude', 'longitude', 'beam_clat', 'beam_clon']:\n", - " variable = v\n", - " break;\n", - "\n", - " if \"lon\" in variables:\n", - " x = \"lon\"\n", - " elif \"longitude\" in variables:\n", - " x = \"longitude\"\n", - " elif \"beam_clon\" in variables:\n", - " x = \"beam_clon\"\n", - " elif \"sp_lon\" in variables:\n", - " x = \"sp_lon\"\n", - " elif \"cellon\" in variables:\n", - " x = \"cellon\"\n", - " else:\n", - " x = None\n", - "\n", - " if \"lat\" in variables:\n", - " y = \"lon\"\n", - " elif \"latitude\" in variables:\n", - " y = \"longitude\"\n", - " elif \"beam_clat\" in variables:\n", - " y = \"beam_clat\"\n", - " elif \"sp_lat\" in variables:\n", - " y = \"sp_lat\"\n", - " elif \"cellat\" in variables:\n", - " y = \"cellat\"\n", - " else:\n", - " y = None\n", - " \n", - " if y is not None and x is not None:\n", - " break\n", - " \n", - " ds.close()\n", - "\n", - "if x is None or y is None:\n", - " raise Exception(\"Lon and Lat variables are not found\")\n", - " \n", - "for index in range(0, max_results):\n", - " \n", - " ds.isel(subset_index=index).plot.scatter(\n", - " y=y,\n", - " x=x,\n", - " hue=variable,\n", - " s=1,\n", - " levels=9,\n", - " cmap=\"jet\",\n", - " aspect=2.5,\n", - " size=9\n", - " )\n", - " \n", - " plt.xlim( 0., 360.)\n", - " plt.ylim(-90., 90.)\n", - " plt.show()" - ] - }, - { - "cell_type": "markdown", - "id": "696e3403", - "metadata": {}, - "source": [ - "We can also plot out the entire granule file which would plot all the data of the concatenated files." - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "id": "748cdb33", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "ds.plot.scatter(\n", - " y=y,\n", - " x=y,\n", - " hue=variable,\n", - " s=1,\n", - " levels=9,\n", - " cmap=\"jet\",\n", - " aspect=2.5,\n", - " size=9\n", - ")\n", - "\n", - "plt.xlim( 0., 360.)\n", - "plt.ylim(-90., 90.)\n", - "plt.show()\n", - "\n", - "ds.close()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cce2d481", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From 1dfec65fa0c54b0baffd64eeab21bf18d3ea3e12 Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Mon, 28 Aug 2023 15:44:02 -0700 Subject: [PATCH 24/25] reverting github actions name --- .github/workflows/add-collection-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/add-collection-test.yml b/.github/workflows/add-collection-test.yml index 96930112..a156eb6b 100644 --- a/.github/workflows/add-collection-test.yml +++ b/.github/workflows/add-collection-test.yml @@ -1,5 +1,5 @@ # This is a test pipeline, that verifies and updates the associations in cmr -name: Add Collection Test OLD +name: Add Collection Test # Controls when the workflow will run on: # Allows you to run this workflow manually from the Actions tab From 6699cc3304618705fdce121ac50cd37d6962121b Mon Sep 17 00:00:00 2001 From: Simon Liu Date: Mon, 28 Aug 2023 16:47:26 -0700 Subject: [PATCH 25/25] modify way we get a filename --- add_collection_test.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/add_collection_test.py b/add_collection_test.py index dc80d0d1..cd960de1 100644 --- a/add_collection_test.py +++ b/add_collection_test.py @@ -237,7 +237,12 @@ def test(collection_id, venue): for file in original_files: - file_name = file.rsplit(".", 1)[0] + # if the file name end in an alphabet so we know there is some extension + if file[-1].isalpha(): + file_name = file.rsplit(".", 1)[0] + else: + file_name = file + print(file_name) cmr_query = f"{cmr_base_url}{file_name}&collection_concept_id={collection_id}" print(cmr_query)