diff --git a/docs/source/_autosummary/pvdeg.geospatial.plot_sparse_analysis_land.rst b/docs/source/_autosummary/pvdeg.geospatial.plot_sparse_analysis_land.rst new file mode 100644 index 0000000..16e8a98 --- /dev/null +++ b/docs/source/_autosummary/pvdeg.geospatial.plot_sparse_analysis_land.rst @@ -0,0 +1,6 @@ +pvdeg.geospatial.plot\_sparse\_analysis\_land +============================================= + +.. currentmodule:: pvdeg.geospatial + +.. autofunction:: plot_sparse_analysis_land \ No newline at end of file diff --git a/docs/source/_autosummary/pvdeg.geospatial.rst b/docs/source/_autosummary/pvdeg.geospatial.rst index 4524da2..159523f 100644 --- a/docs/source/_autosummary/pvdeg.geospatial.rst +++ b/docs/source/_autosummary/pvdeg.geospatial.rst @@ -34,6 +34,7 @@ pvdeg.geospatial pvdeg.geospatial.plot_Europe pvdeg.geospatial.plot_USA pvdeg.geospatial.plot_sparse_analysis + pvdeg.geospatial.plot_sparse_analysis_land pvdeg.geospatial.start_dask pvdeg.geospatial.template_parameters pvdeg.geospatial.zero_template @@ -157,6 +158,13 @@ pvdeg.geospatial .. minigallery:: pvdeg.geospatial.plot_sparse_analysis :add-heading: + .. autofunction:: plot_sparse_analysis_land + + .. _sphx_glr_backref_pvdeg.geospatial.plot_sparse_analysis_land: + + .. minigallery:: pvdeg.geospatial.plot_sparse_analysis_land + :add-heading: + .. autofunction:: start_dask .. _sphx_glr_backref_pvdeg.geospatial.start_dask: diff --git a/docs/source/_autosummary/pvdeg.utilities.display_json.rst b/docs/source/_autosummary/pvdeg.utilities.display_json.rst new file mode 100644 index 0000000..a59150c --- /dev/null +++ b/docs/source/_autosummary/pvdeg.utilities.display_json.rst @@ -0,0 +1,6 @@ +pvdeg.utilities.display\_json +============================= + +.. currentmodule:: pvdeg.utilities + +.. autofunction:: display_json \ No newline at end of file diff --git a/docs/source/_autosummary/pvdeg.utilities.linear_normalize.rst b/docs/source/_autosummary/pvdeg.utilities.linear_normalize.rst new file mode 100644 index 0000000..8fae071 --- /dev/null +++ b/docs/source/_autosummary/pvdeg.utilities.linear_normalize.rst @@ -0,0 +1,6 @@ +pvdeg.utilities.linear\_normalize +================================= + +.. currentmodule:: pvdeg.utilities + +.. autofunction:: linear_normalize \ No newline at end of file diff --git a/docs/source/_autosummary/pvdeg.utilities.merge_sparse.rst b/docs/source/_autosummary/pvdeg.utilities.merge_sparse.rst new file mode 100644 index 0000000..9da49b5 --- /dev/null +++ b/docs/source/_autosummary/pvdeg.utilities.merge_sparse.rst @@ -0,0 +1,6 @@ +pvdeg.utilities.merge\_sparse +============================= + +.. currentmodule:: pvdeg.utilities + +.. autofunction:: merge_sparse \ No newline at end of file diff --git a/docs/source/_autosummary/pvdeg.utilities.read_material.rst b/docs/source/_autosummary/pvdeg.utilities.read_material.rst new file mode 100644 index 0000000..875bb77 --- /dev/null +++ b/docs/source/_autosummary/pvdeg.utilities.read_material.rst @@ -0,0 +1,6 @@ +pvdeg.utilities.read\_material +============================== + +.. currentmodule:: pvdeg.utilities + +.. autofunction:: read_material \ No newline at end of file diff --git a/docs/source/_autosummary/pvdeg.utilities.rst b/docs/source/_autosummary/pvdeg.utilities.rst index fe0b340..95e47e5 100644 --- a/docs/source/_autosummary/pvdeg.utilities.rst +++ b/docs/source/_autosummary/pvdeg.utilities.rst @@ -21,17 +21,22 @@ pvdeg.utilities pvdeg.utilities.compare_templates pvdeg.utilities.convert_tmy + pvdeg.utilities.display_json pvdeg.utilities.fix_metadata pvdeg.utilities.geospatial_from_csv pvdeg.utilities.get_kinetics pvdeg.utilities.get_state_bbox pvdeg.utilities.gid_downsampling + pvdeg.utilities.linear_normalize + pvdeg.utilities.merge_sparse pvdeg.utilities.meta_as_dict pvdeg.utilities.new_id pvdeg.utilities.nrel_kestrel_check pvdeg.utilities.quantile_df + pvdeg.utilities.read_material pvdeg.utilities.remove_scenario_filetrees pvdeg.utilities.restore_gids + pvdeg.utilities.search_json pvdeg.utilities.strip_normalize_tmy pvdeg.utilities.tilt_azimuth_scan pvdeg.utilities.ts_gid_df @@ -65,6 +70,13 @@ pvdeg.utilities .. minigallery:: pvdeg.utilities.convert_tmy :add-heading: + .. autofunction:: display_json + + .. _sphx_glr_backref_pvdeg.utilities.display_json: + + .. minigallery:: pvdeg.utilities.display_json + :add-heading: + .. autofunction:: fix_metadata .. _sphx_glr_backref_pvdeg.utilities.fix_metadata: @@ -100,6 +112,20 @@ pvdeg.utilities .. minigallery:: pvdeg.utilities.gid_downsampling :add-heading: + .. autofunction:: linear_normalize + + .. _sphx_glr_backref_pvdeg.utilities.linear_normalize: + + .. minigallery:: pvdeg.utilities.linear_normalize + :add-heading: + + .. autofunction:: merge_sparse + + .. _sphx_glr_backref_pvdeg.utilities.merge_sparse: + + .. minigallery:: pvdeg.utilities.merge_sparse + :add-heading: + .. autofunction:: meta_as_dict .. _sphx_glr_backref_pvdeg.utilities.meta_as_dict: @@ -128,6 +154,13 @@ pvdeg.utilities .. minigallery:: pvdeg.utilities.quantile_df :add-heading: + .. autofunction:: read_material + + .. _sphx_glr_backref_pvdeg.utilities.read_material: + + .. minigallery:: pvdeg.utilities.read_material + :add-heading: + .. autofunction:: remove_scenario_filetrees .. _sphx_glr_backref_pvdeg.utilities.remove_scenario_filetrees: @@ -142,6 +175,13 @@ pvdeg.utilities .. minigallery:: pvdeg.utilities.restore_gids :add-heading: + .. autofunction:: search_json + + .. _sphx_glr_backref_pvdeg.utilities.search_json: + + .. minigallery:: pvdeg.utilities.search_json + :add-heading: + .. autofunction:: strip_normalize_tmy .. _sphx_glr_backref_pvdeg.utilities.strip_normalize_tmy: diff --git a/docs/source/_autosummary/pvdeg.utilities.search_json.rst b/docs/source/_autosummary/pvdeg.utilities.search_json.rst new file mode 100644 index 0000000..11f7324 --- /dev/null +++ b/docs/source/_autosummary/pvdeg.utilities.search_json.rst @@ -0,0 +1,6 @@ +pvdeg.utilities.search\_json +============================ + +.. currentmodule:: pvdeg.utilities + +.. autofunction:: search_json \ No newline at end of file diff --git a/docs/source/whatsnew/index.rst b/docs/source/whatsnew/index.rst index 78b3536..8298a18 100644 --- a/docs/source/whatsnew/index.rst +++ b/docs/source/whatsnew/index.rst @@ -4,7 +4,8 @@ What's New ========== PVDegradationTools (pvdeg) change log: - +.. include:: releases/v0.4.3.rst +.. include:: releases/v0.4.2.rst .. include:: releases/v0.4.1.rst .. include:: releases/v0.4.0.rst .. include:: releases/v0.3.3.rst diff --git a/docs/source/whatsnew/releases/v0.4.2.rst b/docs/source/whatsnew/releases/v0.4.2.rst index 597e551..d165d41 100644 --- a/docs/source/whatsnew/releases/v0.4.2.rst +++ b/docs/source/whatsnew/releases/v0.4.2.rst @@ -13,4 +13,4 @@ Tests Contributors ~~~~~~~~~~~~ * Martin Springer (:ghuser:`martin-springer`) -* Aidan Wesley (:ghuser:`AidanWesley``) +* Aidan Wesley (:ghuser:`AidanWesley``) \ No newline at end of file diff --git a/docs/source/whatsnew/releases/v0.4.3.rst b/docs/source/whatsnew/releases/v0.4.3.rst new file mode 100644 index 0000000..2b2691d --- /dev/null +++ b/docs/source/whatsnew/releases/v0.4.3.rst @@ -0,0 +1,14 @@ +v0.4.3 (2024-10-10) +=================== + +Enhancements +------------ +Suite of utility functions to facilitate accessing material parameter json files. + +* ``pvdeg.utilities.read_material`` creates a public api to replace the private ``pvdeg.untility._read_material`` function (to be deprecated soon) +* ``pvdeg.utilities.search_json`` to search jsons and identify keys for desired materials. +* ``pvdeg.utilities.display_json`` to view 2 level jsons in Jupyter Notebooks using HTML. + +Contributors +----------- +* Tobin Ford (:ghuser:`tobin-ford`) \ No newline at end of file diff --git a/pvdeg/temperature.py b/pvdeg/temperature.py index ba50047..0035268 100644 --- a/pvdeg/temperature.py +++ b/pvdeg/temperature.py @@ -196,7 +196,7 @@ def cell( Calculate the PV cell temperature using PVLIB Currently this only supports the SAPM temperature model. - Parameters: + Parameters ----------- weather_df : (pd.dataframe) Data Frame with minimum requirements of 'temp_air' and 'wind_speed' @@ -304,7 +304,7 @@ def temperature( Calculate the PV cell or module temperature using PVLIB Current supports the following temperature models: - Parameters: + Parameters ----------- cell_or_mod : (str) choose to calculate the cell or module temperature. Use @@ -347,12 +347,12 @@ def temperature( keyword argument dictionary used for the pvlib temperature model calculation. See https://pvlib-python.readthedocs.io/en/stable/reference/pv_modeling/temperature.html for more. - Return: + Return ------- temp_cell : pandas.DataFrame This is the temperature of the cell in a module at every time step.[°C] - References: + References ----------- R. Rabbani, M. Zeeshan, "Exploring the suitability of MERRA-2 reanalysis data for wind energy estimation, analysis of wind characteristics and energy potential assessment for selected diff --git a/pvdeg/utilities.py b/pvdeg/utilities.py index 3ed5cc5..c4413a5 100644 --- a/pvdeg/utilities.py +++ b/pvdeg/utilities.py @@ -13,6 +13,15 @@ from subprocess import run import cartopy.feature as cfeature + +# A mapping to simplify access to files stored in `pvdeg/data` +pvdeg_datafiles = { + "AApermeation": os.path.join(DATA_DIR, "AApermeation.json"), + "H2Opermeation": os.path.join(DATA_DIR, "H2Opermeation.json"), + "O2permeation": os.path.join(DATA_DIR, "O2permeation.json"), +} + + def gid_downsampling(meta, n): """ Downsample the NSRDB GID grid by a factor of n @@ -492,8 +501,7 @@ def convert_tmy(file_in, file_out="h5_from_tmy.h5"): ) -# previously: fname="materials.json" -# add control over what parameters (O2, H2, AA)? +### DEPRECATE ### def _read_material(name, fname="O2permeation.json"): """ read a material from materials.json and return the parameter dictionary @@ -1337,4 +1345,138 @@ def merge_sparse(files: list[str])->xr.Dataset: for var in ds.data_vars: merged_ds[var].values[np.ix_(lat_inds, lon_inds)] = ds[var].values - return merged_ds \ No newline at end of file + return merged_ds + +def display_json( + pvdeg_file: str = None, + fp: str = None, + ) -> None: + """ + Interactively view a 2 level JSON file in a JupyterNotebook + + Parameters: + ------------ + pvdeg_file: str + keyword for material json file in `pvdeg/data`. Options: + >>> "AApermeation", "H2Opermeation", "O2permeation" + fp: str + file path to material parameters json with same schema as material parameters json files in `pvdeg/data`. `pvdeg_file` will override `fp` if both are provided. + """ + from IPython.display import display, HTML + + if pvdeg_file: + try: + fp = pvdeg_datafiles[pvdeg_file] + except KeyError: + raise KeyError(f"{pvdeg_file} does not exist in pvdeg/data. Options are {pvdeg_datafiles.keys()}") + + with open(fp, 'r') as file: + data = json.load(file) + + def json_to_html(data): + json_str = json.dumps(data, indent=2) + for key in data.keys(): + json_str = json_str.replace(f'"{key}":', f'"{key}":') + + indented_html = '
'.join([' ' * 4 + line for line in json_str.splitlines()]) + return f'
{indented_html}
' + + html = f'

JSON Output at fp: {fp}

' + for key, value in data.items(): + html += ( + f'
' + f'{key}: ' + f'' + f'
{json_to_html(value)}
' + f'
' + ) + html += '
' + + # Display the HTML + display(HTML(html)) + + +def search_json( + pvdeg_file: str = None, + fp: str = None, + name_or_alias: str = None, + )-> str: + """ + Search through a 2 level JSON with arbitrary key names for subkeys with matching attributes of name or alias. + + Parameters + ------------ + pvdeg_file: str + keyword for material json file in `pvdeg/data`. Options: + >>> "AApermeation", "H2Opermeation", "O2permeation" + fp: str + file path to material parameters json with same schema as material parameters json files in `pvdeg/data`. `pvdeg_file` will override `fp` if both are provided. + name_or_alias: str + searches for matching subkey value in either `name` or `alias` attributes. exits on the first matching instance. + + Returns + --------- + jsonkey: str + arbitrary key from json that owns the matching subattribute of `name` or `alias`. + """ + + if pvdeg_file: + try: + fp = pvdeg_datafiles[pvdeg_file] + except KeyError: + raise KeyError(rf"{pvdeg_file} does not exist in pvdeg/data. Options are {pvdeg_datafiles.keys()}") + + with open(fp, "r") as file: + data = json.load(file) + + for key, subdict in data.items(): + if "name" in subdict and "alias" in subdict: + if (subdict["name"] == name_or_alias or subdict["alias"] == name_or_alias): + return key + + raise ValueError(rf"name_or_alias: {name_or_alias} not in JSON at {os.path(fp)}") + +def read_material( + pvdeg_file: str = None, + fp: str = None, + key: str = None, + parameters: list[str] = None, +)-> dict: + """ + Read material parameters from a `pvdeg/data` file or JSON file path. + + Parameters + ----------- + pvdeg_file: str + keyword for material json file in `pvdeg/data`. Options: + >>> "AApermeation", "H2Opermeation", "O2permeation" + fp: str + file path to material parameters json with same schema as material parameters json files in `pvdeg/data`. `pvdeg_file` will override `fp` if both are provided. + key: str + key corresponding to specific material in the file. In the pvdeg files these have arbitrary names. Inspect the files or use `display_json` or `search_json` to identify the key for desired material. + parameters: list[str] + parameters to grab from the file at index key. If none, will grab all items at index key. the elements in parameters must match the keys in the json exactly or the output value for the specific key/parameter in the retunred dict will be `None`. + + Returns + -------- + material: dict + dictionary of material parameters from the seleted file at the index key. + """ + + # these live in the `pvdeg/data` folder + if pvdeg_file: + try: + fp = pvdeg_datafiles[pvdeg_file] + except KeyError: + raise KeyError(f"{pvdeg_file} does not exist in pvdeg/data. Options are {pvdeg_datafiles.keys()}") + + with open(fp, "r") as file: + data = json.load(file) + + # take subdict from file + material_dict = data[key] + + if parameters: + material_dict = {k: material_dict.get(k, None) for k in parameters} + + return material_dict \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 6e9fc2d..0cfef44 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,6 +67,7 @@ docs = [ "nbsphinx", "sphinx_toggleprompt", "pydata_sphinx_theme", + "mistune==3.0.0", ] test = [ "pytest", diff --git a/tests/sandbox.ipynb b/tests/sandbox.ipynb index 0ec2d66..8a9ed66 100644 --- a/tests/sandbox.ipynb +++ b/tests/sandbox.ipynb @@ -419,7 +419,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -590,6 +590,7 @@ "from pvdeg.scenario import Scenario\n", "from pvdeg.standards import standoff\n", "from pvdeg import TEST_DATA_DIR\n", + "import pvdeg\n", "import json\n", "import pandas as pd\n", "import pytest\n", @@ -624,11 +625,304 @@ "\n", " assert a == restored" ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pvdeg" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pvdeg.utilities.pvdeg_datafiles" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "def test_read_material_special():\n", + "\n", + " template_material = pvdeg.utilities.read_material(pvdeg_file=\"AApermeation\", key=\"AA000\")\n", + "\n", + " assert len(template_material) == 1\n", + " assert \"comment\" in template_material\n", + "\n", + "test_read_material_special()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "template_material = pvdeg.utilities.read_material(pvdeg_file=\"AApermeation\", key=\"AA000\")\n", + "\n", + "[type(x) for x in template_material.values()][0]" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "def test_read_material_normal():\n", + "\n", + " res = {\n", + " 'name': 'ST504', \n", + " 'alias': 'PET1', \n", + " 'contributor': 'Michael Kempe', \n", + " 'source': 'unpublished measurements', \n", + " 'Fickian': True,\n", + " 'Ead': 47.603, \n", + " 'Do': 0.554153, \n", + " 'Eas': -11.5918, \n", + " 'So': 9.554366e-07, \n", + " 'Eap': 34.2011, \n", + " 'Po': 2128.8937\n", + " }\n", + "\n", + " template_material = pvdeg.utilities.read_material(pvdeg_file=\"O2permeation\", key=\"OX002\")\n", + "\n", + " assert template_material == res\n", + "\n", + "test_read_material_normal()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "def test_read_material_fewer_params():\n", + "\n", + " res = {\n", + " 'name': 'ST504', \n", + " 'Fickian': True,\n", + " }\n", + "\n", + " template_material = pvdeg.utilities.read_material(pvdeg_file=\"O2permeation\", key=\"OX002\", parameters=[\"name\", \"Fickian\"])\n", + "\n", + " assert template_material == res\n", + "\n", + "test_read_material_fewer_params()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "def test_read_material_extra_params():\n", + "\n", + " res = {\n", + " 'namenotindict1': None,\n", + " 'namenotindict2': None,\n", + " }\n", + "\n", + " template_material = pvdeg.utilities.read_material(pvdeg_file=\"O2permeation\", key=\"OX002\", parameters=[\"namenotindict1\", \"namenotindict2\"])\n", + "\n", + " assert template_material == res\n", + "\n", + "\n", + "test_read_material_extra_params()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def test_search_json():\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# pvdeg_file should override fp if both are provided\n", + "def test_read_material_fp_override():\n", + "\n", + " res = {\n", + " 'name': 'ST504', \n", + " 'alias': 'PET1', \n", + " 'contributor': 'Michael Kempe', \n", + " 'source': 'unpublished measurements', \n", + " 'Fickian': True,\n", + " 'Ead': 47.603, \n", + " 'Do': 0.554153, \n", + " 'Eas': -11.5918, \n", + " 'So': 9.554366e-07, \n", + " 'Eap': 34.2011, \n", + " 'Po': 2128.8937\n", + " }\n", + "\n", + " from pvdeg import DATA_DIR\n", + "\n", + " # pass pvdeg file and it gets overridden by the file path\n", + " template_material = pvdeg.utilities.read_material(\n", + " pvdeg_file=\"O2permeation\", \n", + " fp=os.path.join(DATA_DIR, \"AApermeation.json\"), \n", + " key=\"OX002\",\n", + " )\n", + "\n", + " assert template_material == res\n", + "\n", + "test_read_material_fp_override()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def test_search_json():\n", + "\n", + " name_res = pvdeg.utilities.search_json(pvdeg_file=\"H2Opermeation\", name_or_alias=\"Ethylene Vinyl Acetate\")\n", + " alias_res = pvdeg.utilities.search_json(pvdeg_file=\"H2Opermeation\", name_or_alias=\"EVA\")\n", + "\n", + " assert name_res == \"W001\"\n", + " assert alias_res == \"W001\"\n", + "\n", + "test_search_json()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "ename": "Failed", + "evalue": "Invalid regex pattern provided to 'match': incomplete escape \\U at position 46", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mFailed\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[3], line 10\u001b[0m\n\u001b[0;32m 4\u001b[0m invalid_name_or_alias \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnamenotindict\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 5\u001b[0m expected_error_message \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m 6\u001b[0m \u001b[38;5;124mrf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname_or_alias: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00minvalid_name_or_alias\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m not in JSON at \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 7\u001b[0m \u001b[38;5;124mrf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mos\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(DATA_DIR,\u001b[38;5;250m \u001b[39mpvdeg\u001b[38;5;241m.\u001b[39mutilities\u001b[38;5;241m.\u001b[39mpvdeg_datafiles[pvdeg_file])\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 8\u001b[0m )\n\u001b[1;32m---> 10\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mpytest\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraises\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;167;43;01mValueError\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmatch\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mexpected_error_message\u001b[49m\u001b[43m)\u001b[49m:\n\u001b[0;32m 11\u001b[0m pvdeg\u001b[38;5;241m.\u001b[39mutilities\u001b[38;5;241m.\u001b[39msearch_json(pvdeg_file\u001b[38;5;241m=\u001b[39mpvdeg_file, name_or_alias\u001b[38;5;241m=\u001b[39minvalid_name_or_alias)\n", + " \u001b[1;31m[... skipping hidden 1 frame]\u001b[0m\n", + "File \u001b[1;32mc:\\Users\\tford\\AppData\\Local\\miniconda3\\envs\\deg\\lib\\site-packages\\_pytest\\python_api.py:997\u001b[0m, in \u001b[0;36mRaisesContext.__init__\u001b[1;34m(self, expected_exception, message, match_expr)\u001b[0m\n\u001b[0;32m 995\u001b[0m re_error \u001b[38;5;241m=\u001b[39m e\n\u001b[0;32m 996\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m re_error \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m--> 997\u001b[0m \u001b[43mfail\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43mf\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mInvalid regex pattern provided to \u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mmatch\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m: \u001b[39;49m\u001b[38;5;132;43;01m{\u001b[39;49;00m\u001b[43mre_error\u001b[49m\u001b[38;5;132;43;01m}\u001b[39;49;00m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32mc:\\Users\\tford\\AppData\\Local\\miniconda3\\envs\\deg\\lib\\site-packages\\_pytest\\outcomes.py:178\u001b[0m, in \u001b[0;36mfail\u001b[1;34m(reason, pytrace)\u001b[0m\n\u001b[0;32m 165\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Explicitly fail an executing test with the given message.\u001b[39;00m\n\u001b[0;32m 166\u001b[0m \n\u001b[0;32m 167\u001b[0m \u001b[38;5;124;03m:param reason:\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 175\u001b[0m \u001b[38;5;124;03m The exception that is raised.\u001b[39;00m\n\u001b[0;32m 176\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 177\u001b[0m __tracebackhide__ \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m--> 178\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m Failed(msg\u001b[38;5;241m=\u001b[39mreason, pytrace\u001b[38;5;241m=\u001b[39mpytrace)\n", + "\u001b[1;31mFailed\u001b[0m: Invalid regex pattern provided to 'match': incomplete escape \\U at position 46" + ] + } + ], + "source": [ + "from pvdeg import DATA_DIR\n", + "\n", + "pvdeg_file = \"H2Opermeation\"\n", + "invalid_name_or_alias = \"namenotindict\"\n", + "expected_error_message = (\n", + " rf\"name_or_alias: {invalid_name_or_alias} not in JSON at \"\n", + " rf\"{os.path.join(DATA_DIR, pvdeg.utilities.pvdeg_datafiles[pvdeg_file])}\"\n", + ")\n", + "\n", + "with pytest.raises(ValueError, match=expected_error_message):\n", + " pvdeg.utilities.search_json(pvdeg_file=pvdeg_file, name_or_alias=invalid_name_or_alias)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'invalid_name_or_alias' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[2], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m expected_error_message \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m----> 2\u001b[0m \u001b[38;5;124mrf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname_or_alias: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00minvalid_name_or_alias\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m not in JSON at \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 3\u001b[0m \u001b[38;5;124mrf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mos\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(DATA_DIR,\u001b[38;5;250m \u001b[39mpvdeg\u001b[38;5;241m.\u001b[39mutilities\u001b[38;5;241m.\u001b[39mpvdeg_datafiles[pvdeg_file])\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 4\u001b[0m )\n", + "\u001b[1;31mNameError\u001b[0m: name 'invalid_name_or_alias' is not defined" + ] + } + ], + "source": [ + "\n", + "expected_error_message = (\n", + " rf\"name_or_alias: {invalid_name_or_alias} not in JSON at \"\n", + " rf\"{os.path.join(DATA_DIR, pvdeg.utilities.pvdeg_datafiles[pvdeg_file])}\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'name_or_alias: namenotindict not in JSON at C:\\\\Users\\\\tford\\\\dev\\\\PVDegradationTools\\\\pvdeg\\\\data\\\\H2Opermeation.json'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "expected_error_message" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'module' object is not callable", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[5], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mpvdeg\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mutilities\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msearch_json\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpvdeg_file\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpvdeg_file\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mname_or_alias\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minvalid_name_or_alias\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32m~\\dev\\PVDegradationTools\\pvdeg\\utilities.py:1437\u001b[0m, in \u001b[0;36msearch_json\u001b[1;34m(pvdeg_file, fp, name_or_alias)\u001b[0m\n\u001b[0;32m 1434\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (subdict[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m==\u001b[39m name_or_alias \u001b[38;5;129;01mor\u001b[39;00m subdict[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124malias\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m==\u001b[39m name_or_alias):\n\u001b[0;32m 1435\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m key\n\u001b[1;32m-> 1437\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mrf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname_or_alias: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mname_or_alias\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m not in JSON at \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mos\u001b[38;5;241m.\u001b[39mpath(fp)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[1;31mTypeError\u001b[0m: 'module' object is not callable" + ] + } + ], + "source": [ + "pvdeg.utilities.search_json(pvdeg_file=pvdeg_file, name_or_alias=invalid_name_or_alias)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "base", + "display_name": "deg", "language": "python", "name": "python3" }, @@ -642,7 +936,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.14" + "version": "3.9.19" }, "orig_nbformat": 4 }, diff --git a/tests/test_utilities.py b/tests/test_utilities.py index cd80552..2ef9bb3 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -80,6 +80,7 @@ def test_get_kinetics_bad(): assert res == desired_output +### DEPRECATE WITH THE OLD FUNCTION _read_material, replaced by read_material def test_read_material_bad(): # no name case fpath = os.path.join(DATA_DIR, "O2permeation.json") @@ -136,3 +137,98 @@ def test_nrel_kestrel_check_bad(): with pytest.raises(ConnectionError): pvdeg.utilities.nrel_kestrel_check() + + +# NEW MATERIAL UTIL FUNCTIONS +# These tests will likely fail if the associated materials are changed +# =========================== +def test_read_material_special(): + + template_material = pvdeg.utilities.read_material(pvdeg_file="AApermeation", key="AA000") + + assert len(template_material) == 1 + assert "comment" in template_material + +def test_read_material_normal(): + + res = { + 'name': 'ST504', + 'alias': 'PET1', + 'contributor': 'Michael Kempe', + 'source': 'unpublished measurements', + 'Fickian': True, + 'Ead': 47.603, + 'Do': 0.554153, + 'Eas': -11.5918, + 'So': 9.554366e-07, + 'Eap': 34.2011, + 'Po': 2128.8937 + } + + template_material = pvdeg.utilities.read_material(pvdeg_file="O2permeation", key="OX002") + + assert template_material == res + +def test_read_material_fewer_params(): + + res = { + 'name': 'ST504', + 'Fickian': True, + } + + template_material = pvdeg.utilities.read_material(pvdeg_file="O2permeation", key="OX002", parameters=["name", "Fickian"]) + + assert template_material == res + + + +def test_read_material_extra_params(): + + res = { + 'namenotindict1': None, + 'namenotindict2': None, + } + + template_material = pvdeg.utilities.read_material(pvdeg_file="O2permeation", key="OX002", parameters=["namenotindict1", "namenotindict2"]) + + assert template_material == res + +# pvdeg_file should override fp if both are provided +def test_read_material_fp_override(): + + res = { + 'name': 'ST504', + 'alias': 'PET1', + 'contributor': 'Michael Kempe', + 'source': 'unpublished measurements', + 'Fickian': True, + 'Ead': 47.603, + 'Do': 0.554153, + 'Eas': -11.5918, + 'So': 9.554366e-07, + 'Eap': 34.2011, + 'Po': 2128.8937 + } + + from pvdeg import DATA_DIR + + # fp gets overridden by pvdeg_file + template_material = pvdeg.utilities.read_material( + pvdeg_file="O2permeation", + fp=os.path.join(DATA_DIR, "AApermeation.json"), + key="OX002", + ) + + assert template_material == res + + +def test_search_json(): + name_res = pvdeg.utilities.search_json(pvdeg_file="H2Opermeation", name_or_alias="Ethylene Vinyl Acetate") + alias_res = pvdeg.utilities.search_json(pvdeg_file="H2Opermeation", name_or_alias="EVA") + + assert name_res == "W001" + assert alias_res == "W001" + + +# def test_search_json_bad(): +# ... \ No newline at end of file