diff --git a/Example.ipynb b/Example.ipynb
index ec50dd4..0ad1858 100644
--- a/Example.ipynb
+++ b/Example.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 1,
"id": "53bc9780",
"metadata": {},
"outputs": [],
@@ -14,7 +14,7 @@
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": 2,
"id": "1f3871fc",
"metadata": {},
"outputs": [],
@@ -24,7 +24,7 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 3,
"id": "6fd7e7f9",
"metadata": {},
"outputs": [
@@ -50,7 +50,7 @@
"}"
]
},
- "execution_count": 2,
+ "execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
@@ -62,252 +62,128 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "3dd386bd",
+ "execution_count": 6,
+ "id": "b77ff62c",
"metadata": {},
"outputs": [
{
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "131\n"
- ]
- },
- {
- "ename": "IndexError",
- "evalue": "positional indexers are out-of-bounds",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/indexing.py:1714\u001b[0m, in \u001b[0;36m_iLocIndexer._get_list_axis\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1713\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1714\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mobj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_take_with_is_copy\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1715\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mIndexError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m 1716\u001b[0m \u001b[38;5;66;03m# re-raise with different error message, e.g. test_getitem_ndarray_3d\u001b[39;00m\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/generic.py:4153\u001b[0m, in \u001b[0;36mNDFrame._take_with_is_copy\u001b[0;34m(self, indices, axis)\u001b[0m\n\u001b[1;32m 4144\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 4145\u001b[0m \u001b[38;5;124;03mInternal version of the `take` method that sets the `_is_copy`\u001b[39;00m\n\u001b[1;32m 4146\u001b[0m \u001b[38;5;124;03mattribute to keep track of the parent dataframe (using in indexing\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 4151\u001b[0m \u001b[38;5;124;03mSee the docstring of `take` for full explanation of the parameters.\u001b[39;00m\n\u001b[1;32m 4152\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m-> 4153\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtake\u001b[49m\u001b[43m(\u001b[49m\u001b[43mindices\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mindices\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4154\u001b[0m \u001b[38;5;66;03m# Maybe set copy if we didn't actually change the index.\u001b[39;00m\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/generic.py:4133\u001b[0m, in \u001b[0;36mNDFrame.take\u001b[0;34m(self, indices, axis, **kwargs)\u001b[0m\n\u001b[1;32m 4129\u001b[0m indices \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39marange(\n\u001b[1;32m 4130\u001b[0m indices\u001b[38;5;241m.\u001b[39mstart, indices\u001b[38;5;241m.\u001b[39mstop, indices\u001b[38;5;241m.\u001b[39mstep, dtype\u001b[38;5;241m=\u001b[39mnp\u001b[38;5;241m.\u001b[39mintp\n\u001b[1;32m 4131\u001b[0m )\n\u001b[0;32m-> 4133\u001b[0m new_data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_mgr\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtake\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 4134\u001b[0m \u001b[43m \u001b[49m\u001b[43mindices\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4135\u001b[0m \u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_block_manager_axis\u001b[49m\u001b[43m(\u001b[49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4136\u001b[0m \u001b[43m \u001b[49m\u001b[43mverify\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 4137\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4138\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_constructor_from_mgr(new_data, axes\u001b[38;5;241m=\u001b[39mnew_data\u001b[38;5;241m.\u001b[39maxes)\u001b[38;5;241m.\u001b[39m__finalize__(\n\u001b[1;32m 4139\u001b[0m \u001b[38;5;28mself\u001b[39m, method\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtake\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 4140\u001b[0m )\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/internals/managers.py:891\u001b[0m, in \u001b[0;36mBaseBlockManager.take\u001b[0;34m(self, indexer, axis, verify)\u001b[0m\n\u001b[1;32m 890\u001b[0m n \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mshape[axis]\n\u001b[0;32m--> 891\u001b[0m indexer \u001b[38;5;241m=\u001b[39m \u001b[43mmaybe_convert_indices\u001b[49m\u001b[43m(\u001b[49m\u001b[43mindexer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mn\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mverify\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mverify\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 893\u001b[0m new_labels \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39maxes[axis]\u001b[38;5;241m.\u001b[39mtake(indexer)\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/indexers/utils.py:282\u001b[0m, in \u001b[0;36mmaybe_convert_indices\u001b[0;34m(indices, n, verify)\u001b[0m\n\u001b[1;32m 281\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m mask\u001b[38;5;241m.\u001b[39many():\n\u001b[0;32m--> 282\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mIndexError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mindices are out-of-bounds\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 283\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m indices\n",
- "\u001b[0;31mIndexError\u001b[0m: indices are out-of-bounds",
- "\nThe above exception was the direct cause of the following exception:\n",
- "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)",
- "Cell \u001b[0;32mIn[3], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m Ta_C \u001b[38;5;241m=\u001b[39m \u001b[43mforecast_Ta_C\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[43m \u001b[49m\u001b[43mtime_UTC\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m2025-05-22 21:11:22.358885\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3\u001b[0m \u001b[43m \u001b[49m\u001b[43mgeometry\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgeometry\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[43m)\u001b[49m\n\u001b[1;32m 6\u001b[0m Ta_C\n",
- "File \u001b[0;32m~/Projects/global-forecasting-system/global_forecasting_system/global_forecasting_system.py:275\u001b[0m, in \u001b[0;36mforecast_Ta_C\u001b[0;34m(time_UTC, geometry, resampling, directory, listing)\u001b[0m\n\u001b[1;32m 269\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mforecast_Ta_C\u001b[39m(\n\u001b[1;32m 270\u001b[0m time_UTC: datetime,\n\u001b[1;32m 271\u001b[0m geometry: rt\u001b[38;5;241m.\u001b[39mRasterGeometry \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 272\u001b[0m resampling: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcubic\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 273\u001b[0m directory: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 274\u001b[0m listing: pd\u001b[38;5;241m.\u001b[39mDataFrame \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m rt\u001b[38;5;241m.\u001b[39mRaster:\n\u001b[0;32m--> 275\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mforecast_Ta_K\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtime_UTC\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtime_UTC\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgeometry\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgeometry\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mresampling\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mresampling\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdirectory\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdirectory\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlisting\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlisting\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m273.15\u001b[39m\n",
- "File \u001b[0;32m~/Projects/global-forecasting-system/global_forecasting_system/global_forecasting_system.py:267\u001b[0m, in \u001b[0;36mforecast_Ta_K\u001b[0;34m(time_UTC, geometry, resampling, directory, listing)\u001b[0m\n\u001b[1;32m 261\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mforecast_Ta_K\u001b[39m(\n\u001b[1;32m 262\u001b[0m time_UTC: datetime,\n\u001b[1;32m 263\u001b[0m geometry: rt\u001b[38;5;241m.\u001b[39mRasterGeometry \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 264\u001b[0m resampling: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcubic\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 265\u001b[0m directory: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 266\u001b[0m listing: pd\u001b[38;5;241m.\u001b[39mDataFrame \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m rt\u001b[38;5;241m.\u001b[39mRaster:\n\u001b[0;32m--> 267\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mGFS_interpolate\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmessage\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mGFS_TA_MESSAGE\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtime_UTC\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtime_UTC\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgeometry\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgeometry\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mresampling\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mresampling\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdirectory\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdirectory\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlisting\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlisting\u001b[49m\u001b[43m)\u001b[49m\n",
- "File \u001b[0;32m~/Projects/global-forecasting-system/global_forecasting_system/global_forecasting_system.py:225\u001b[0m, in \u001b[0;36mGFS_interpolate\u001b[0;34m(message, time_UTC, geometry, resampling, directory, listing)\u001b[0m\n\u001b[1;32m 218\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mGFS_interpolate\u001b[39m(\n\u001b[1;32m 219\u001b[0m message: \u001b[38;5;28mint\u001b[39m,\n\u001b[1;32m 220\u001b[0m time_UTC: datetime,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 223\u001b[0m directory: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 224\u001b[0m listing: pd\u001b[38;5;241m.\u001b[39mDataFrame \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m rt\u001b[38;5;241m.\u001b[39mRaster:\n\u001b[0;32m--> 225\u001b[0m before_after \u001b[38;5;241m=\u001b[39m \u001b[43mGFS_before_after_addresses\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtime_UTC\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlisting\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlisting\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 227\u001b[0m before_address \u001b[38;5;241m=\u001b[39m before_after\u001b[38;5;241m.\u001b[39miloc[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39maddress\n\u001b[1;32m 228\u001b[0m logger\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbefore URL: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcolored_logging\u001b[38;5;241m.\u001b[39mURL(before_address)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n",
- "File \u001b[0;32m~/Projects/global-forecasting-system/global_forecasting_system/global_forecasting_system.py:164\u001b[0m, in \u001b[0;36mGFS_before_after_addresses\u001b[0;34m(time_UTC, listing)\u001b[0m\n\u001b[1;32m 155\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mzero-length GFS listing at time \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtime_UTC\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m UTC\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 157\u001b[0m \u001b[38;5;66;03m# min_time = min(listing.forecast_time_UTC)\u001b[39;00m\n\u001b[1;32m 158\u001b[0m \u001b[38;5;66;03m# max_time = max(listing.forecast_time_UTC)\u001b[39;00m\n\u001b[1;32m 159\u001b[0m \n\u001b[1;32m 160\u001b[0m \u001b[38;5;66;03m# logger.info(f\"selecting GFS files for time {time_UTC} UTC between {min_time} UTC and {max_time} UTC\")\u001b[39;00m\n\u001b[1;32m 161\u001b[0m \n\u001b[1;32m 162\u001b[0m \u001b[38;5;66;03m# before = listing[listing.forecast_time_UTC <= time_UTC].iloc[[-1]]\u001b[39;00m\n\u001b[0;32m--> 164\u001b[0m before \u001b[38;5;241m=\u001b[39m \u001b[43mlisting\u001b[49m\u001b[43m[\u001b[49m\u001b[43mlisting\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mforecast_time_UTC\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mapply\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43;01mlambda\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mforecast_time_UTC\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mforecast_time_UTC\u001b[49m\u001b[43m)\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m<\u001b[39;49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mtime_UTC\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miloc\u001b[49m\u001b[43m[\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m]\u001b[49m\n\u001b[1;32m 165\u001b[0m after \u001b[38;5;241m=\u001b[39m listing[listing\u001b[38;5;241m.\u001b[39mforecast_time_UTC\u001b[38;5;241m.\u001b[39mapply(\u001b[38;5;28;01mlambda\u001b[39;00m forecast_time_UTC: \u001b[38;5;28mstr\u001b[39m(forecast_time_UTC) \u001b[38;5;241m>\u001b[39m \u001b[38;5;28mstr\u001b[39m(time_UTC))]\u001b[38;5;241m.\u001b[39miloc[[\u001b[38;5;241m0\u001b[39m]]\n\u001b[1;32m 166\u001b[0m before_after \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mconcat([before, after])\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/indexing.py:1191\u001b[0m, in \u001b[0;36m_LocationIndexer.__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 1189\u001b[0m maybe_callable \u001b[38;5;241m=\u001b[39m com\u001b[38;5;241m.\u001b[39mapply_if_callable(key, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj)\n\u001b[1;32m 1190\u001b[0m maybe_callable \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_check_deprecated_callable_usage(key, maybe_callable)\n\u001b[0;32m-> 1191\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_getitem_axis\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmaybe_callable\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/indexing.py:1743\u001b[0m, in \u001b[0;36m_iLocIndexer._getitem_axis\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1741\u001b[0m \u001b[38;5;66;03m# a list of integers\u001b[39;00m\n\u001b[1;32m 1742\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m is_list_like_indexer(key):\n\u001b[0;32m-> 1743\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_list_axis\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1745\u001b[0m \u001b[38;5;66;03m# a single integer\u001b[39;00m\n\u001b[1;32m 1746\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1747\u001b[0m key \u001b[38;5;241m=\u001b[39m item_from_zerodim(key)\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/indexing.py:1717\u001b[0m, in \u001b[0;36m_iLocIndexer._get_list_axis\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1714\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39m_take_with_is_copy(key, axis\u001b[38;5;241m=\u001b[39maxis)\n\u001b[1;32m 1715\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mIndexError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m 1716\u001b[0m \u001b[38;5;66;03m# re-raise with different error message, e.g. test_getitem_ndarray_3d\u001b[39;00m\n\u001b[0;32m-> 1717\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mIndexError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpositional indexers are out-of-bounds\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01merr\u001b[39;00m\n",
- "\u001b[0;31mIndexError\u001b[0m: positional indexers are out-of-bounds"
- ]
+ "data": {
+ "text/plain": [
+ "Timestamp('2025-05-28 00:00:00')"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
}
],
"source": [
- "Ta_C = forecast_Ta_C(\n",
- " time_UTC=time_UTC,\n",
- " geometry=geometry,\n",
- ")\n",
+ "from global_forecasting_system import earliest_time_UTC\n",
"\n",
- "Ta_C"
+ "earliest = earliest_time_UTC()\n",
+ "earliest"
]
},
{
"cell_type": "code",
- "execution_count": 5,
- "id": "31e6c9fc",
+ "execution_count": 9,
+ "id": "4f2aec61",
"metadata": {},
"outputs": [
{
"data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " forecast_time_UTC | \n",
- " address | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " | 0 | \n",
- " 2025-05-28 00:00:00 | \n",
- " https://www.ncei.noaa.gov/data/global-forecast... | \n",
- "
\n",
- " \n",
- " | 1 | \n",
- " 2025-05-28 03:00:00 | \n",
- " https://www.ncei.noaa.gov/data/global-forecast... | \n",
- "
\n",
- " \n",
- " | 129 | \n",
- " 2025-05-28 06:00:00 | \n",
- " https://www.ncei.noaa.gov/data/global-forecast... | \n",
- "
\n",
- " \n",
- " | 130 | \n",
- " 2025-05-28 09:00:00 | \n",
- " https://www.ncei.noaa.gov/data/global-forecast... | \n",
- "
\n",
- " \n",
- " | 131 | \n",
- " 2025-05-28 12:00:00 | \n",
- " https://www.ncei.noaa.gov/data/global-forecast... | \n",
- "
\n",
- " \n",
- " | ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " | 253 | \n",
- " 2025-06-12 18:00:00 | \n",
- " https://www.ncei.noaa.gov/data/global-forecast... | \n",
- "
\n",
- " \n",
- " | 254 | \n",
- " 2025-06-12 21:00:00 | \n",
- " https://www.ncei.noaa.gov/data/global-forecast... | \n",
- "
\n",
- " \n",
- " | 255 | \n",
- " 2025-06-13 00:00:00 | \n",
- " https://www.ncei.noaa.gov/data/global-forecast... | \n",
- "
\n",
- " \n",
- " | 256 | \n",
- " 2025-06-13 03:00:00 | \n",
- " https://www.ncei.noaa.gov/data/global-forecast... | \n",
- "
\n",
- " \n",
- " | 257 | \n",
- " 2025-06-13 06:00:00 | \n",
- " https://www.ncei.noaa.gov/data/global-forecast... | \n",
- "
\n",
- " \n",
- "
\n",
- "
131 rows × 2 columns
\n",
- "
"
- ],
"text/plain": [
- " forecast_time_UTC address\n",
- "0 2025-05-28 00:00:00 https://www.ncei.noaa.gov/data/global-forecast...\n",
- "1 2025-05-28 03:00:00 https://www.ncei.noaa.gov/data/global-forecast...\n",
- "129 2025-05-28 06:00:00 https://www.ncei.noaa.gov/data/global-forecast...\n",
- "130 2025-05-28 09:00:00 https://www.ncei.noaa.gov/data/global-forecast...\n",
- "131 2025-05-28 12:00:00 https://www.ncei.noaa.gov/data/global-forecast...\n",
- ".. ... ...\n",
- "253 2025-06-12 18:00:00 https://www.ncei.noaa.gov/data/global-forecast...\n",
- "254 2025-06-12 21:00:00 https://www.ncei.noaa.gov/data/global-forecast...\n",
- "255 2025-06-13 00:00:00 https://www.ncei.noaa.gov/data/global-forecast...\n",
- "256 2025-06-13 03:00:00 https://www.ncei.noaa.gov/data/global-forecast...\n",
- "257 2025-06-13 06:00:00 https://www.ncei.noaa.gov/data/global-forecast...\n",
- "\n",
- "[131 rows x 2 columns]"
+ "datetime.date(2025, 5, 28)"
]
},
- "execution_count": 5,
+ "execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "listing = global_forecasting_system.get_GFS_listing()\n",
- "listing"
+ "earliest.to_pydatetime().date()"
]
},
{
"cell_type": "code",
- "execution_count": 10,
- "id": "99726c21",
+ "execution_count": 7,
+ "id": "229d091f",
"metadata": {},
"outputs": [
{
"data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " forecast_time_UTC | \n",
- " address | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- "
\n",
- "
"
- ],
"text/plain": [
- "Empty DataFrame\n",
- "Columns: [forecast_time_UTC, address]\n",
- "Index: []"
+ "pandas._libs.tslibs.timestamps.Timestamp"
]
},
- "execution_count": 10,
+ "execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "listing[listing.forecast_time_UTC.apply(lambda forecast_time_UTC: str(forecast_time_UTC) <= str(time_UTC))]"
+ "type(earliest)"
]
},
{
"cell_type": "code",
- "execution_count": 8,
- "id": "d9e02cc4",
+ "execution_count": 4,
+ "id": "3dd386bd",
"metadata": {},
"outputs": [
{
- "ename": "IndexError",
- "evalue": "positional indexers are out-of-bounds",
+ "ename": "ValueError",
+ "evalue": "no GFS files found before time 2025-05-22 21:11:22.358885 UTC",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/indexing.py:1714\u001b[0m, in \u001b[0;36m_iLocIndexer._get_list_axis\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1713\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1714\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mobj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_take_with_is_copy\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1715\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mIndexError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m 1716\u001b[0m \u001b[38;5;66;03m# re-raise with different error message, e.g. test_getitem_ndarray_3d\u001b[39;00m\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/generic.py:4153\u001b[0m, in \u001b[0;36mNDFrame._take_with_is_copy\u001b[0;34m(self, indices, axis)\u001b[0m\n\u001b[1;32m 4144\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 4145\u001b[0m \u001b[38;5;124;03mInternal version of the `take` method that sets the `_is_copy`\u001b[39;00m\n\u001b[1;32m 4146\u001b[0m \u001b[38;5;124;03mattribute to keep track of the parent dataframe (using in indexing\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 4151\u001b[0m \u001b[38;5;124;03mSee the docstring of `take` for full explanation of the parameters.\u001b[39;00m\n\u001b[1;32m 4152\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m-> 4153\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtake\u001b[49m\u001b[43m(\u001b[49m\u001b[43mindices\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mindices\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4154\u001b[0m \u001b[38;5;66;03m# Maybe set copy if we didn't actually change the index.\u001b[39;00m\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/generic.py:4133\u001b[0m, in \u001b[0;36mNDFrame.take\u001b[0;34m(self, indices, axis, **kwargs)\u001b[0m\n\u001b[1;32m 4129\u001b[0m indices \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39marange(\n\u001b[1;32m 4130\u001b[0m indices\u001b[38;5;241m.\u001b[39mstart, indices\u001b[38;5;241m.\u001b[39mstop, indices\u001b[38;5;241m.\u001b[39mstep, dtype\u001b[38;5;241m=\u001b[39mnp\u001b[38;5;241m.\u001b[39mintp\n\u001b[1;32m 4131\u001b[0m )\n\u001b[0;32m-> 4133\u001b[0m new_data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_mgr\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtake\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 4134\u001b[0m \u001b[43m \u001b[49m\u001b[43mindices\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4135\u001b[0m \u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_block_manager_axis\u001b[49m\u001b[43m(\u001b[49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4136\u001b[0m \u001b[43m \u001b[49m\u001b[43mverify\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 4137\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4138\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_constructor_from_mgr(new_data, axes\u001b[38;5;241m=\u001b[39mnew_data\u001b[38;5;241m.\u001b[39maxes)\u001b[38;5;241m.\u001b[39m__finalize__(\n\u001b[1;32m 4139\u001b[0m \u001b[38;5;28mself\u001b[39m, method\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtake\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 4140\u001b[0m )\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/internals/managers.py:891\u001b[0m, in \u001b[0;36mBaseBlockManager.take\u001b[0;34m(self, indexer, axis, verify)\u001b[0m\n\u001b[1;32m 890\u001b[0m n \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mshape[axis]\n\u001b[0;32m--> 891\u001b[0m indexer \u001b[38;5;241m=\u001b[39m \u001b[43mmaybe_convert_indices\u001b[49m\u001b[43m(\u001b[49m\u001b[43mindexer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mn\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mverify\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mverify\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 893\u001b[0m new_labels \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39maxes[axis]\u001b[38;5;241m.\u001b[39mtake(indexer)\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/indexers/utils.py:282\u001b[0m, in \u001b[0;36mmaybe_convert_indices\u001b[0;34m(indices, n, verify)\u001b[0m\n\u001b[1;32m 281\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m mask\u001b[38;5;241m.\u001b[39many():\n\u001b[0;32m--> 282\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mIndexError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mindices are out-of-bounds\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 283\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m indices\n",
- "\u001b[0;31mIndexError\u001b[0m: indices are out-of-bounds",
- "\nThe above exception was the direct cause of the following exception:\n",
- "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)",
- "Cell \u001b[0;32mIn[8], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m before \u001b[38;5;241m=\u001b[39m \u001b[43mlisting\u001b[49m\u001b[43m[\u001b[49m\u001b[43mlisting\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mforecast_time_UTC\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mapply\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43;01mlambda\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mforecast_time_UTC\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mforecast_time_UTC\u001b[49m\u001b[43m)\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m<\u001b[39;49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mtime_UTC\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miloc\u001b[49m\u001b[43m[\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m]\u001b[49m\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/indexing.py:1191\u001b[0m, in \u001b[0;36m_LocationIndexer.__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 1189\u001b[0m maybe_callable \u001b[38;5;241m=\u001b[39m com\u001b[38;5;241m.\u001b[39mapply_if_callable(key, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj)\n\u001b[1;32m 1190\u001b[0m maybe_callable \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_check_deprecated_callable_usage(key, maybe_callable)\n\u001b[0;32m-> 1191\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_getitem_axis\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmaybe_callable\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/indexing.py:1743\u001b[0m, in \u001b[0;36m_iLocIndexer._getitem_axis\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1741\u001b[0m \u001b[38;5;66;03m# a list of integers\u001b[39;00m\n\u001b[1;32m 1742\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m is_list_like_indexer(key):\n\u001b[0;32m-> 1743\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_list_axis\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1745\u001b[0m \u001b[38;5;66;03m# a single integer\u001b[39;00m\n\u001b[1;32m 1746\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1747\u001b[0m key \u001b[38;5;241m=\u001b[39m item_from_zerodim(key)\n",
- "File \u001b[0;32m/opt/homebrew/Caskroom/miniforge/base/envs/global-forecasting-system/lib/python3.10/site-packages/pandas/core/indexing.py:1717\u001b[0m, in \u001b[0;36m_iLocIndexer._get_list_axis\u001b[0;34m(self, key, axis)\u001b[0m\n\u001b[1;32m 1714\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mobj\u001b[38;5;241m.\u001b[39m_take_with_is_copy(key, axis\u001b[38;5;241m=\u001b[39maxis)\n\u001b[1;32m 1715\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mIndexError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m 1716\u001b[0m \u001b[38;5;66;03m# re-raise with different error message, e.g. test_getitem_ndarray_3d\u001b[39;00m\n\u001b[0;32m-> 1717\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mIndexError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpositional indexers are out-of-bounds\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01merr\u001b[39;00m\n",
- "\u001b[0;31mIndexError\u001b[0m: positional indexers are out-of-bounds"
+ "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[0;32mIn[4], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m Ta_C \u001b[38;5;241m=\u001b[39m \u001b[43mforecast_Ta_C\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[43m \u001b[49m\u001b[43mtime_UTC\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtime_UTC\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3\u001b[0m \u001b[43m \u001b[49m\u001b[43mgeometry\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgeometry\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[43m)\u001b[49m\n\u001b[1;32m 6\u001b[0m Ta_C\n",
+ "File \u001b[0;32m~/Projects/global-forecasting-system/global_forecasting_system/global_forecasting_system.py:297\u001b[0m, in \u001b[0;36mforecast_Ta_C\u001b[0;34m(time_UTC, geometry, resampling, directory, listing)\u001b[0m\n\u001b[1;32m 291\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mforecast_Ta_C\u001b[39m(\n\u001b[1;32m 292\u001b[0m time_UTC: datetime,\n\u001b[1;32m 293\u001b[0m geometry: rt\u001b[38;5;241m.\u001b[39mRasterGeometry \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 294\u001b[0m resampling: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcubic\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 295\u001b[0m directory: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 296\u001b[0m listing: pd\u001b[38;5;241m.\u001b[39mDataFrame \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m rt\u001b[38;5;241m.\u001b[39mRaster:\n\u001b[0;32m--> 297\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mforecast_Ta_K\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtime_UTC\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtime_UTC\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgeometry\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgeometry\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mresampling\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mresampling\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdirectory\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdirectory\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlisting\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlisting\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m273.15\u001b[39m\n",
+ "File \u001b[0;32m~/Projects/global-forecasting-system/global_forecasting_system/global_forecasting_system.py:289\u001b[0m, in \u001b[0;36mforecast_Ta_K\u001b[0;34m(time_UTC, geometry, resampling, directory, listing)\u001b[0m\n\u001b[1;32m 283\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mforecast_Ta_K\u001b[39m(\n\u001b[1;32m 284\u001b[0m time_UTC: datetime,\n\u001b[1;32m 285\u001b[0m geometry: rt\u001b[38;5;241m.\u001b[39mRasterGeometry \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 286\u001b[0m resampling: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcubic\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 287\u001b[0m directory: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 288\u001b[0m listing: pd\u001b[38;5;241m.\u001b[39mDataFrame \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m rt\u001b[38;5;241m.\u001b[39mRaster:\n\u001b[0;32m--> 289\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mGFS_interpolate\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmessage\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mGFS_TA_MESSAGE\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtime_UTC\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtime_UTC\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgeometry\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgeometry\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mresampling\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mresampling\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdirectory\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdirectory\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlisting\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlisting\u001b[49m\u001b[43m)\u001b[49m\n",
+ "File \u001b[0;32m~/Projects/global-forecasting-system/global_forecasting_system/global_forecasting_system.py:247\u001b[0m, in \u001b[0;36mGFS_interpolate\u001b[0;34m(message, time_UTC, geometry, resampling, directory, listing)\u001b[0m\n\u001b[1;32m 240\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mGFS_interpolate\u001b[39m(\n\u001b[1;32m 241\u001b[0m message: \u001b[38;5;28mint\u001b[39m,\n\u001b[1;32m 242\u001b[0m time_UTC: datetime,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 245\u001b[0m directory: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 246\u001b[0m listing: pd\u001b[38;5;241m.\u001b[39mDataFrame \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m rt\u001b[38;5;241m.\u001b[39mRaster:\n\u001b[0;32m--> 247\u001b[0m before_after \u001b[38;5;241m=\u001b[39m \u001b[43mGFS_before_after_addresses\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtime_UTC\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlisting\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlisting\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 249\u001b[0m before_address \u001b[38;5;241m=\u001b[39m before_after\u001b[38;5;241m.\u001b[39miloc[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39maddress\n\u001b[1;32m 250\u001b[0m logger\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mbefore URL: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcolored_logging\u001b[38;5;241m.\u001b[39mURL(before_address)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n",
+ "File \u001b[0;32m~/Projects/global-forecasting-system/global_forecasting_system/global_forecasting_system.py:177\u001b[0m, in \u001b[0;36mGFS_before_after_addresses\u001b[0;34m(time_UTC, listing)\u001b[0m\n\u001b[1;32m 174\u001b[0m before_rows \u001b[38;5;241m=\u001b[39m listing[listing\u001b[38;5;241m.\u001b[39mforecast_time_UTC\u001b[38;5;241m.\u001b[39mapply(\u001b[38;5;28;01mlambda\u001b[39;00m forecast_time_UTC: \u001b[38;5;28mstr\u001b[39m(forecast_time_UTC) \u001b[38;5;241m<\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(time_UTC))]\n\u001b[1;32m 176\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(before_rows) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[0;32m--> 177\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mno GFS files found before time \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtime_UTC\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m UTC\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 179\u001b[0m before \u001b[38;5;241m=\u001b[39m before_rows\u001b[38;5;241m.\u001b[39miloc[[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m]]\n\u001b[1;32m 181\u001b[0m after_rows \u001b[38;5;241m=\u001b[39m listing[listing\u001b[38;5;241m.\u001b[39mforecast_time_UTC\u001b[38;5;241m.\u001b[39mapply(\u001b[38;5;28;01mlambda\u001b[39;00m forecast_time_UTC: \u001b[38;5;28mstr\u001b[39m(forecast_time_UTC) \u001b[38;5;241m>\u001b[39m \u001b[38;5;28mstr\u001b[39m(time_UTC))]\n",
+ "\u001b[0;31mValueError\u001b[0m: no GFS files found before time 2025-05-22 21:11:22.358885 UTC"
]
}
],
+ "source": [
+ "Ta_C = forecast_Ta_C(\n",
+ " time_UTC=time_UTC,\n",
+ " geometry=geometry,\n",
+ ")\n",
+ "\n",
+ "Ta_C"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "31e6c9fc",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "listing = global_forecasting_system.get_GFS_listing()\n",
+ "listing"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "99726c21",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "listing[listing.forecast_time_UTC.apply(lambda forecast_time_UTC: str(forecast_time_UTC) <= str(time_UTC))]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d9e02cc4",
+ "metadata": {},
+ "outputs": [],
"source": [
"before = listing[listing.forecast_time_UTC.apply(lambda forecast_time_UTC: str(forecast_time_UTC) <= str(time_UTC))].iloc[[-1]]"
]
@@ -319,6 +195,14 @@
"metadata": {},
"outputs": [],
"source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8ca59e87",
+ "metadata": {},
+ "outputs": [],
+ "source": []
}
],
"metadata": {
diff --git a/global_forecasting_system/__init__.py b/global_forecasting_system/__init__.py
index 479d2e5..23ccd71 100644
--- a/global_forecasting_system/__init__.py
+++ b/global_forecasting_system/__init__.py
@@ -1,3 +1,3 @@
from .global_forecasting_system import *
-__version__ = "1.1.1"
+__version__ = "1.2.0"
diff --git a/global_forecasting_system/global_forecasting_system.py b/global_forecasting_system/global_forecasting_system.py
index c85a046..d482da9 100644
--- a/global_forecasting_system/global_forecasting_system.py
+++ b/global_forecasting_system/global_forecasting_system.py
@@ -142,6 +142,20 @@ def get_GFS_listing(date_URL: str = None) -> pd.DataFrame:
return address_df
+def earliest_time_UTC(listing: pd.DataFrame = None) -> datetime:
+ if listing is None:
+ listing = get_GFS_listing()
+
+ if len(listing) == 0:
+ raise ValueError("zero-length GFS listing")
+
+ earliest_time = min(listing.forecast_time_UTC).to_pydatetime()
+
+ return earliest_time
+
+def earliest_date_UTC(listing: pd.DataFrame = None) -> date:
+ return earliest_date_UTC(listing=listing).date()
+
def GFS_before_after_addresses(time_UTC: datetime, listing: pd.DataFrame = None) -> pd.DataFrame:
if not isinstance(time_UTC, datetime):
time_UTC = parser.parse(time_UTC)
diff --git a/pyproject.toml b/pyproject.toml
index ee3819d..d209c86 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "global-forecasting-system"
-version = "1.1.1"
+version = "1.2.0"
description = "Global Forecasting System (GFS) Search & Download Utility"
readme = "README.md"
authors = [