respond to Tom's comments
MODIFY
docs/api.md
docs/api.md
:show-inheritance:
```
+```{eval-rst}
+.. autoclass:: pangeo_forge.recipe.NetCDFtoZarrMultiVarSequentialRecipe
+ :show-inheritance:
+```
+
## Patterns
```{eval-rst}

MODIFY
docs/tutorials/multi_variable_recipe.ipynb
docs/tutorials/multi_variable_recipe.ipynb
"- There is a time sequence (month) to the files.\n",
"- Different variables live in different files.\n",
"\n",
- "Because our dataset is spread over muliple files, we will have to use a {class}`pangeo_forge.recipe.NetCDFtoZarrMultiVarSequentialRecipe` class (rather than the simpler {class}`pangeo_forge.recipe.NetCDFtoZarrMultiVarSequentialRecipe`).\n",
+ "Because our dataset is spread over muliple files, we will have to use a {class}`pangeo_forge.recipe.NetCDFtoZarrMultiVarSequentialRecipe` class (rather than the simpler {class}`pangeo_forge.recipe.NetCDFtoZarrSequentialRecipe`).\n",
"\n",
"## Step 1: Get to know your source data\n",
"\n",
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": 2,
"metadata": {},
"outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Exception reporting mode: Plain\n"
+ ]
+ },
{
"ename": "ValueError",
"evalue": "unable to decode time units 'months since 1955-01-01 00:00:00' with 'the default calendar'. Try opening your dataset with decode_times=False or installing cftime if it is not installed.",
"output_type": "error",
"traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m~/Code/xarray/xarray/coding/times.py\u001b[0m in \u001b[0;36mdecode_cf_datetime\u001b[0;34m(num_dates, units, calendar, use_cftime)\u001b[0m\n\u001b[1;32m 193\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 194\u001b[0;31m \u001b[0mdates\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_decode_datetime_with_pandas\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mflat_num_dates\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcalendar\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 195\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mKeyError\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mOutOfBoundsDatetime\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mOverflowError\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Code/xarray/xarray/coding/times.py\u001b[0m in \u001b[0;36m_decode_datetime_with_pandas\u001b[0;34m(flat_num_dates, units, calendar)\u001b[0m\n\u001b[1;32m 145\u001b[0m \u001b[0mdelta\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mref_date\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_unpack_netcdf_time_units\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0munits\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 146\u001b[0;31m \u001b[0mdelta\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_netcdf_to_numpy_timeunit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdelta\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 147\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Code/xarray/xarray/coding/times.py\u001b[0m in \u001b[0;36m_netcdf_to_numpy_timeunit\u001b[0;34m(units)\u001b[0m\n\u001b[1;32m 45\u001b[0m \u001b[0munits\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"%ss\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 46\u001b[0;31m return {\n\u001b[0m\u001b[1;32m 47\u001b[0m \u001b[0;34m\"microseconds\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;34m\"us\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mKeyError\u001b[0m: 'months'",
+ "Traceback \u001b[0;36m(most recent call last)\u001b[0m:\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/coding/times.py\"\u001b[0m, line \u001b[1;32m194\u001b[0m, in \u001b[1;35mdecode_cf_datetime\u001b[0m\n dates = _decode_datetime_with_pandas(flat_num_dates, units, calendar)\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/coding/times.py\"\u001b[0m, line \u001b[1;32m146\u001b[0m, in \u001b[1;35m_decode_datetime_with_pandas\u001b[0m\n delta = _netcdf_to_numpy_timeunit(delta)\n",
+ "\u001b[0;36m File \u001b[0;32m\"/Users/rpa/Code/xarray/xarray/coding/times.py\"\u001b[0;36m, line \u001b[0;32m46\u001b[0;36m, in \u001b[0;35m_netcdf_to_numpy_timeunit\u001b[0;36m\u001b[0m\n\u001b[0;31m return {\u001b[0m\n",
+ "\u001b[0;31mKeyError\u001b[0m\u001b[0;31m:\u001b[0m 'months'\n",
"\nDuring handling of the above exception, another exception occurred:\n",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m~/Code/xarray/xarray/coding/times.py\u001b[0m in \u001b[0;36m_decode_cf_datetime_dtype\u001b[0;34m(data, units, calendar, use_cftime)\u001b[0m\n\u001b[1;32m 112\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 113\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdecode_cf_datetime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexample_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcalendar\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0muse_cftime\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 114\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Code/xarray/xarray/coding/times.py\u001b[0m in \u001b[0;36mdecode_cf_datetime\u001b[0;34m(num_dates, units, calendar, use_cftime)\u001b[0m\n\u001b[1;32m 195\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mKeyError\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mOutOfBoundsDatetime\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mOverflowError\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 196\u001b[0;31m dates = _decode_datetime_with_cftime(\n\u001b[0m\u001b[1;32m 197\u001b[0m \u001b[0mflat_num_dates\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfloat\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcalendar\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Code/xarray/xarray/coding/times.py\u001b[0m in \u001b[0;36m_decode_datetime_with_cftime\u001b[0;34m(num_dates, units, calendar)\u001b[0m\n\u001b[1;32m 133\u001b[0m return np.asarray(\n\u001b[0;32m--> 134\u001b[0;31m \u001b[0mcftime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum2date\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnum_dates\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcalendar\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0monly_use_cftime_datetimes\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 135\u001b[0m )\n",
- "\u001b[0;32mcftime/_cftime.pyx\u001b[0m in \u001b[0;36mcftime._cftime.num2date\u001b[0;34m()\u001b[0m\n",
- "\u001b[0;32mcftime/_cftime.pyx\u001b[0m in \u001b[0;36mcftime._cftime._dateparse\u001b[0;34m()\u001b[0m\n",
- "\u001b[0;31mValueError\u001b[0m: 'months since' units only allowed for '360_day' calendar",
+ "Traceback \u001b[0;36m(most recent call last)\u001b[0m:\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/coding/times.py\"\u001b[0m, line \u001b[1;32m113\u001b[0m, in \u001b[1;35m_decode_cf_datetime_dtype\u001b[0m\n result = decode_cf_datetime(example_value, units, calendar, use_cftime)\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/coding/times.py\"\u001b[0m, line \u001b[1;32m196\u001b[0m, in \u001b[1;35mdecode_cf_datetime\u001b[0m\n dates = _decode_datetime_with_cftime(\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/coding/times.py\"\u001b[0m, line \u001b[1;32m134\u001b[0m, in \u001b[1;35m_decode_datetime_with_cftime\u001b[0m\n cftime.num2date(num_dates, units, calendar, only_use_cftime_datetimes=True)\n",
+ " File \u001b[1;32m\"cftime/_cftime.pyx\"\u001b[0m, line \u001b[1;32m461\u001b[0m, in \u001b[1;35mcftime._cftime.num2date\u001b[0m\n",
+ "\u001b[0;36m File \u001b[0;32m\"cftime/_cftime.pyx\"\u001b[0;36m, line \u001b[0;32m133\u001b[0;36m, in \u001b[0;35mcftime._cftime._dateparse\u001b[0;36m\u001b[0m\n",
+ "\u001b[0;31mValueError\u001b[0m\u001b[0;31m:\u001b[0m 'months since' units only allowed for '360_day' calendar\n",
"\nDuring handling of the above exception, another exception occurred:\n",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-3-da61c62763d1>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mxarray\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mxr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mds\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mxr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mopen_dataset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"woa18_decav_t01_5d.nc\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m~/Code/xarray/xarray/backends/api.py\u001b[0m in \u001b[0;36mopen_dataset\u001b[0;34m(filename_or_obj, group, decode_cf, mask_and_scale, decode_times, autoclose, concat_characters, decode_coords, engine, chunks, lock, cache, drop_variables, backend_kwargs, use_cftime, decode_timedelta)\u001b[0m\n\u001b[1;32m 573\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 574\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mclose_on_error\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstore\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 575\u001b[0;31m \u001b[0mds\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmaybe_decode_store\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstore\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchunks\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 576\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 577\u001b[0m \u001b[0;31m# Ensure source filename always stored in dataset object (GH issue #2550)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Code/xarray/xarray/backends/api.py\u001b[0m in \u001b[0;36mmaybe_decode_store\u001b[0;34m(store, chunks)\u001b[0m\n\u001b[1;32m 469\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 470\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmaybe_decode_store\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstore\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchunks\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 471\u001b[0;31m ds = conventions.decode_cf(\n\u001b[0m\u001b[1;32m 472\u001b[0m \u001b[0mstore\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 473\u001b[0m \u001b[0mmask_and_scale\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmask_and_scale\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Code/xarray/xarray/conventions.py\u001b[0m in \u001b[0;36mdecode_cf\u001b[0;34m(obj, concat_characters, mask_and_scale, decode_times, decode_coords, drop_variables, use_cftime, decode_timedelta)\u001b[0m\n\u001b[1;32m 587\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"can only decode Dataset or DataStore objects\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 588\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 589\u001b[0;31m vars, attrs, coord_names = decode_cf_variables(\n\u001b[0m\u001b[1;32m 590\u001b[0m \u001b[0mvars\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 591\u001b[0m \u001b[0mattrs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Code/xarray/xarray/conventions.py\u001b[0m in \u001b[0;36mdecode_cf_variables\u001b[0;34m(variables, attributes, concat_characters, mask_and_scale, decode_times, decode_coords, drop_variables, use_cftime, decode_timedelta)\u001b[0m\n\u001b[1;32m 490\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mstackable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdims\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 491\u001b[0m )\n\u001b[0;32m--> 492\u001b[0;31m new_vars[k] = decode_cf_variable(\n\u001b[0m\u001b[1;32m 493\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 494\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Code/xarray/xarray/conventions.py\u001b[0m in \u001b[0;36mdecode_cf_variable\u001b[0;34m(name, var, concat_characters, mask_and_scale, decode_times, decode_endianness, stack_char_dim, use_cftime, decode_timedelta)\u001b[0m\n\u001b[1;32m 338\u001b[0m \u001b[0mvar\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtimes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCFTimedeltaCoder\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvar\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 339\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mdecode_times\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 340\u001b[0;31m \u001b[0mvar\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtimes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCFDatetimeCoder\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0muse_cftime\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0muse_cftime\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvar\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 341\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 342\u001b[0m \u001b[0mdimensions\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mattributes\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mencoding\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvariables\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0munpack_for_decoding\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvar\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Code/xarray/xarray/coding/times.py\u001b[0m in \u001b[0;36mdecode\u001b[0;34m(self, variable, name)\u001b[0m\n\u001b[1;32m 461\u001b[0m \u001b[0munits\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpop_to\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mattrs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mencoding\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"units\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 462\u001b[0m \u001b[0mcalendar\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpop_to\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mattrs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mencoding\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"calendar\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 463\u001b[0;31m \u001b[0mdtype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_decode_cf_datetime_dtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcalendar\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0muse_cftime\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 464\u001b[0m transform = partial(\n\u001b[1;32m 465\u001b[0m \u001b[0mdecode_cf_datetime\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Code/xarray/xarray/coding/times.py\u001b[0m in \u001b[0;36m_decode_cf_datetime_dtype\u001b[0;34m(data, units, calendar, use_cftime)\u001b[0m\n\u001b[1;32m 121\u001b[0m \u001b[0;34m\"if it is not installed.\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 122\u001b[0m )\n\u001b[0;32m--> 123\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 124\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 125\u001b[0m \u001b[0mdtype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"dtype\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"object\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mValueError\u001b[0m: unable to decode time units 'months since 1955-01-01 00:00:00' with 'the default calendar'. Try opening your dataset with decode_times=False or installing cftime if it is not installed."
+ "Traceback \u001b[0;36m(most recent call last)\u001b[0m:\n",
+ " File \u001b[1;32m\"<ipython-input-2-7cf168336cd7>\"\u001b[0m, line \u001b[1;32m3\u001b[0m, in \u001b[1;35m<module>\u001b[0m\n ds = xr.open_dataset(\"woa18_decav_t01_5d.nc\")\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/backends/api.py\"\u001b[0m, line \u001b[1;32m575\u001b[0m, in \u001b[1;35mopen_dataset\u001b[0m\n ds = maybe_decode_store(store, chunks)\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/backends/api.py\"\u001b[0m, line \u001b[1;32m471\u001b[0m, in \u001b[1;35mmaybe_decode_store\u001b[0m\n ds = conventions.decode_cf(\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/conventions.py\"\u001b[0m, line \u001b[1;32m589\u001b[0m, in \u001b[1;35mdecode_cf\u001b[0m\n vars, attrs, coord_names = decode_cf_variables(\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/conventions.py\"\u001b[0m, line \u001b[1;32m492\u001b[0m, in \u001b[1;35mdecode_cf_variables\u001b[0m\n new_vars[k] = decode_cf_variable(\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/conventions.py\"\u001b[0m, line \u001b[1;32m340\u001b[0m, in \u001b[1;35mdecode_cf_variable\u001b[0m\n var = times.CFDatetimeCoder(use_cftime=use_cftime).decode(var, name=name)\n",
+ " File \u001b[1;32m\"/Users/rpa/Code/xarray/xarray/coding/times.py\"\u001b[0m, line \u001b[1;32m463\u001b[0m, in \u001b[1;35mdecode\u001b[0m\n dtype = _decode_cf_datetime_dtype(data, units, calendar, self.use_cftime)\n",
+ "\u001b[0;36m File \u001b[0;32m\"/Users/rpa/Code/xarray/xarray/coding/times.py\"\u001b[0;36m, line \u001b[0;32m123\u001b[0;36m, in \u001b[0;35m_decode_cf_datetime_dtype\u001b[0;36m\u001b[0m\n\u001b[0;31m raise ValueError(msg)\u001b[0m\n",
+ "\u001b[0;31mValueError\u001b[0m\u001b[0;31m:\u001b[0m unable to decode time units 'months since 1955-01-01 00:00:00' with 'the default calendar'. Try opening your dataset with decode_times=False or installing cftime if it is not installed.\n"
]
}
],
"source": [
+ "%xmode plain\n",
"import xarray as xr\n",
"ds = xr.open_dataset(\"woa18_decav_t01_5d.nc\")"
]

MODIFY
pangeo_forge/recipe.py
pangeo_forge/recipe.py
@@ -125,15 +125,10 @@ class BaseRecipe(ABC):
@dataclass
class NetCDFtoZarrRecipe(BaseRecipe):
"""This class represents a dataset composed of many individual NetCDF files.
- The files are arraged in a sequence along a single dimension, called the
- `sequence_dim`. Each file may contain multiple variables.
+ This class uses Xarray to read and write data and writes its output to Zarr.
+ The files are assumed to be arranged in a sequence along dimension ``sequence_dim``
+ (commonly "time".)
- The dataset is assembled by concatenating all of these files along `sequence_dim`.
- The target is written in Zarr format.
-
- This class uses Xarray to read and write data.
-
- :param input_urls: The inputs used to generate the dataset.
:param sequence_dim: The dimension name along which the inputs will be concatenated.
:param inputs_per_chunk: The number of inputs to use in each chunk.
:param nitems_per_input: The length of each input along the `sequence_dim` dimension.
@@ -156,7 +151,7 @@ class NetCDFtoZarrRecipe(BaseRecipe):
:param target_chunks: Desired chunk structure for the targret dataset.
"""
- sequence_dim: str = ""
+ sequence_dim: Optional[str] = None
inputs_per_chunk: int = 1
nitems_per_input: int = 1
target: Optional[AbstractTarget] = field(default_factory=UninitializedTarget)
@@ -387,6 +382,12 @@ class NetCDFtoZarrRecipe(BaseRecipe):
@dataclass
class NetCDFtoZarrSequentialRecipe(NetCDFtoZarrRecipe):
+ """There is only one sequence of input files. Each file can contain
+ many variables.
+
+ :param input_urls: The inputs used to generate the dataset.
+ """
+
input_urls: Iterable[str] = field(repr=False, default_factory=list)
def __post_init__(self):
@@ -409,6 +410,12 @@ class NetCDFtoZarrSequentialRecipe(NetCDFtoZarrRecipe):
@dataclass
class NetCDFtoZarrMultiVarSequentialRecipe(NetCDFtoZarrRecipe):
+ """There are muliples sequences of input files (but all along the same dimension.)
+ Different variables live in different files.
+
+ :param input_pattern: An pattern used to generate the input file names.
+ """
+
input_pattern: VariableSequencePattern = field(default_factory=VariableSequencePattern)
def __post_init__(self):

respond to Tom's comments