diff --git a/doc/source/example_notebooks/IS2_data_variables.ipynb b/doc/source/example_notebooks/IS2_data_variables.ipynb index 90fa8500c..760657080 100644 --- a/doc/source/example_notebooks/IS2_data_variables.ipynb +++ b/doc/source/example_notebooks/IS2_data_variables.ipynb @@ -50,7 +50,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "scrolled": true + }, "outputs": [], "source": [ "import icepyx as ipx\n", @@ -319,7 +321,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -329,15 +331,15 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "# Uncomment and run the code in this cell to use the second variable subsetting suite of examples,\n", "# with the beam specifier containing \"profile\" instead of \"gt#l\"\n", "\n", - "# region_a = ipx.Query('ATL09',[-55, 68, -48, 71],['2019-02-22','2019-02-28'], \\\n", - "# start_time='00:00:00', end_time='23:59:59')" + "region_a = ipx.Query('ATL09',[-55, 68, -48, 71],['2019-02-22','2019-02-28'], \\\n", + " start_time='00:00:00', end_time='23:59:59')" ] }, { @@ -450,6 +452,7 @@ "1. Use a default list for the product (not yet fully implemented across all products. Have a default variable list for your field/product? Submit a pull request or post it as an issue on [GitHub](https://github.com/icesat2py/icepyx)!)\n", "2. Provide a list of variable names\n", "3. Provide a list of profiles/beams or other path keywords, where \"keywords\" are simply the unique subdirectory names contained in the full variable paths of the product. A full list of available keywords for the product is displayed in the error message upon entering `keyword_list=['']` into the `append` function (see below for an example) or by running `region_a.order_vars.avail(options=True)`, as above.\n", + "4. Providing a list of full variable path names from the H5 root path. icepyx will ensure that you are submitting valid variable paths.\n", "\n", "**Note: all products have a short list of \"mandatory\" variables/paths (containing spacecraft orientation and time information needed to convert the data's `delta_time` to a readable datetime) that are automatically added to any built list. If you have any recommendations for other variables that should always be included (e.g. uncertainty information), please let us know!**\n", "\n", @@ -724,7 +727,45 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Example 1.10: generate a default list for the rest of the tutorial\n", + "#### Example 1.10: `path_list`\n", + "Add a specific list of variable paths." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "too many values to unpack (expected 3)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[10], line 8\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# region_a.order_vars.remove(all=True)\u001b[39;00m\n\u001b[1;32m 2\u001b[0m path_list \u001b[38;5;241m=\u001b[39m [\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mgt1l/land_ice_segments/delta_time\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 3\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mgt1l/land_ice_segments/geophysical/bsnow_h\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 4\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mgt1l/land_ice_segments/geophysical/bsnow_conf\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 5\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mgt1l/land_ice_segments/fit_statistics/h_mean\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 6\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mgt1l/land_ice_segments/latitude\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 7\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mgt1l/land_ice_segments/longitude\u001b[39m\u001b[38;5;124m'\u001b[39m,]\n\u001b[0;32m----> 8\u001b[0m \u001b[43mregion_a\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43morder_vars\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mappend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath_list\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpath_list\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 9\u001b[0m pprint(region_a\u001b[38;5;241m.\u001b[39morder_vars\u001b[38;5;241m.\u001b[39mwanted)\n", + "File \u001b[0;32m~/computing/icepyx/github_repo/icepyx/icepyx/core/variables.py:530\u001b[0m, in \u001b[0;36mVariables.append\u001b[0;34m(self, defaults, var_list, beam_list, keyword_list, path_list)\u001b[0m\n\u001b[1;32m 527\u001b[0m final_vars \u001b[38;5;241m=\u001b[39m {}\n\u001b[1;32m 529\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m path_list:\n\u001b[0;32m--> 530\u001b[0m _, (beams, keywords, variables) \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparse_var_list(\n\u001b[1;32m 531\u001b[0m path_list, tiered_vars\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 532\u001b[0m )\n\u001b[1;32m 533\u001b[0m var_list \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(\u001b[38;5;28mset\u001b[39m(variables))\n\u001b[1;32m 534\u001b[0m beam_list \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(\u001b[38;5;28mset\u001b[39m(beams))\n", + "\u001b[0;31mValueError\u001b[0m: too many values to unpack (expected 3)" + ] + } + ], + "source": [ + "# region_a.order_vars.remove(all=True)\n", + "path_list = ['gt1l/land_ice_segments/delta_time',\n", + " 'gt1l/land_ice_segments/geophysical/bsnow_h',\n", + " 'gt1l/land_ice_segments/geophysical/bsnow_conf',\n", + " 'gt1l/land_ice_segments/fit_statistics/h_mean',\n", + " 'gt1l/land_ice_segments/latitude',\n", + " 'gt1l/land_ice_segments/longitude',]\n", + "region_a.order_vars.append(path_list=path_list)\n", + "pprint(region_a.order_vars.wanted)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Example 1.11: generate a default list for the rest of the tutorial\n", "Generate a reasonable variable list prior to download" ] }, @@ -912,7 +953,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "scrolled": true + }, "outputs": [], "source": [ "region_a.order_vars.remove(beam_list=['profile_1','profile_3'])\n", @@ -923,7 +966,31 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Example 2.10: generate a default list for the rest of the tutorial\n", + "#### Example 2.10: `path_list`\n", + "Add a specific list of variable paths." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region_a.order_vars.remove(all=True)\n", + "path_list = ['profile_2/high_rate/beam_elevation',\n", + " 'profile_2/high_rate/solar_elevation',\n", + " 'profile_2/high_rate/surface_conf',\n", + " 'profile_2/high_rate/surface_height'\n", + " ]\n", + "region_a.order_vars.append(path_list=path_list)\n", + "pprint(region_a.order_vars.wanted)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Example 2.11: generate a default list for the rest of the tutorial\n", "Generate a reasonable variable list prior to download" ] }, @@ -1063,9 +1130,9 @@ ], "metadata": { "kernelspec": { - "display_name": "icepyx-dev", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "icepyx-dev" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -1077,7 +1144,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/doc/source/user_guide/documentation/classes_dev_uml.svg b/doc/source/user_guide/documentation/classes_dev_uml.svg index 84fb2a450..422651c05 100644 --- a/doc/source/user_guide/documentation/classes_dev_uml.svg +++ b/doc/source/user_guide/documentation/classes_dev_uml.svg @@ -335,7 +335,7 @@ _get_sum_varlist(var_list, all_vars, defaults) _iter_paths(sum_varlist, req_vars, vgrp, beam_list, keyword_list) _iter_vars(sum_varlist, req_vars, vgrp) -append(defaults, var_list, beam_list, keyword_list) +append(defaults, var_list, beam_list, keyword_list, path_list) avail(options, internal) parse_var_list(varlist, tiered, tiered_vars) remove(all, var_list, beam_list, keyword_list) diff --git a/doc/source/user_guide/documentation/classes_user_uml.svg b/doc/source/user_guide/documentation/classes_user_uml.svg index 256cc1794..09d0d5702 100644 --- a/doc/source/user_guide/documentation/classes_user_uml.svg +++ b/doc/source/user_guide/documentation/classes_user_uml.svg @@ -4,11 +4,11 @@ - + classes_user_uml - + icepyx.core.auth.AuthenticationError @@ -111,37 +111,37 @@ icepyx.core.icesat2data.Icesat2Data - -Icesat2Data - - - + +Icesat2Data + + + icepyx.core.exceptions.NsidcQueryError - -NsidcQueryError - -errmsg -msgtxt : str - - + +NsidcQueryError + +errmsg +msgtxt : str + + icepyx.core.exceptions.QueryError - -QueryError - - - + +QueryError + + + icepyx.core.exceptions.NsidcQueryError->icepyx.core.exceptions.QueryError - - + + @@ -265,18 +265,18 @@ icepyx.core.variables.Variables - + Variables - + path product version wanted : NoneType, dict - -append(defaults, var_list, beam_list, keyword_list) -avail(options, internal) -parse_var_list(varlist, tiered, tiered_vars) -remove(all, var_list, beam_list, keyword_list) + +append(defaults, var_list, beam_list, keyword_list, path_list) +avail(options, internal) +parse_var_list(varlist, tiered, tiered_vars) +remove(all, var_list, beam_list, keyword_list) @@ -308,22 +308,22 @@ icepyx.core.visualization.Visualize - -Visualize - -bbox : list -cycles : NoneType -date_range : NoneType -product : NoneType, str -tracks : NoneType - -generate_OA_parameters(): list -grid_bbox(binsize): list -make_request(base_url, payload) -parallel_request_OA(): da.array -query_icesat2_filelist(): tuple -request_OA_data(paras): da.array -viz_elevation(): (hv.DynamicMap, hv.Layout) + +Visualize + +bbox : list +cycles : NoneType +date_range : NoneType +product : NoneType, str +tracks : NoneType + +generate_OA_parameters(): list +grid_bbox(binsize): list +make_request(base_url, payload) +parallel_request_OA(): da.array +query_icesat2_filelist(): tuple +request_OA_data(paras): da.array +viz_elevation(): (hv.DynamicMap, hv.Layout) diff --git a/icepyx/core/variables.py b/icepyx/core/variables.py index 15d5268e5..4d5d1e4b7 100644 --- a/icepyx/core/variables.py +++ b/icepyx/core/variables.py @@ -429,7 +429,14 @@ def _iter_paths(self, sum_varlist, req_vars, vgrp, beam_list, keyword_list): return req_vars # DevGoal: we can ultimately add an "interactive" trigger that will open the not-yet-made widget. Otherwise, it will use the var_list passed by the user/defaults - def append(self, defaults=False, var_list=None, beam_list=None, keyword_list=None): + def append( + self, + defaults=False, + var_list=None, + beam_list=None, + keyword_list=None, + path_list=None, + ): """ Add to the list of desired variables using user specified beams and variable list. A pregenerated default variable list can be used by setting defaults to True. @@ -457,6 +464,9 @@ def append(self, defaults=False, var_list=None, beam_list=None, keyword_list=Non the product that include that keyword in their path. A list of availble keywords can be obtained by entering `keyword_list=['']` into the function. + path_list : list of strings, default None + A list of variable path names given as the full path from the H5 root path. + Notes ----- See also the `IS2_data_access2-subsetting @@ -482,17 +492,48 @@ def append(self, defaults=False, var_list=None, beam_list=None, keyword_list=Non To add all variables and paths in ancillary_data >>> reg_a.order_vars.append(keyword_list=['ancillary_data']) # doctest: +SKIP + + To add variables as a list of explicit paths + + >>> path_list = ['gt1l/heights/delta_time', + ... 'gt1l/heights/dist_ph_across', + ... 'gt1l/heights/dist_ph_along', + ... 'gt1l/heights/h_ph', + ... 'gt1l/heights/lat_ph', + ... 'gt1l/heights/lon_ph'] + >>> region_a.order_vars.append(path_list=path_list) # doctest: +SKIP + """ - assert not ( - defaults == False - and var_list == None - and beam_list == None - and keyword_list == None - ), "You must enter parameters to add to a variable subset list. If you do not want to subset by variable, ensure your is2.subsetparams dictionary does not contain the key 'Coverage'." + # Check that at least one allowable combination of keywords are set + if ( + not defaults + and not (var_list or beam_list or keyword_list) + and not path_list + ): + raise ValueError( + "Either default or path_list, or at least one of var_list, " + "beam_list or keyword_list must be set." + ) + + # Check that only path_list, or only var_list, beam_list or keyword_list + # are set. + if (var_list or beam_list or keyword_list) and path_list: + raise ValueError( + "path_list cannot be set if var_list or " + "beam_list or keyword_list are set" + ) final_vars = {} + if path_list: + _, (beams, keywords, variables) = self.parse_var_list( + path_list, tiered_vars=True + ) + var_list = list(set(variables)) + beam_list = list(set(beams)) + keyword_list = list(set(keywords)) + vgrp, allpaths = self.avail(options=True, internal=True) self._check_valid_lists(vgrp, allpaths, var_list, beam_list, keyword_list) @@ -500,7 +541,7 @@ def append(self, defaults=False, var_list=None, beam_list=None, keyword_list=Non if not hasattr(self, "wanted") or self.wanted == None: self.wanted = {} - # DEVGOAL: add a secondary var list to include uncertainty/error information for lower level data if specific data variables have been specified... + # DEVGOAL: add a secondary var list to include uncertainty/error information for lower level data if specific data variables have been specified... # generate a list of variable names to include, depending on user input sum_varlist = self._get_sum_varlist(var_list, vgrp.keys(), defaults)