Source code for pvlib.iotools.merra2

import pandas as pd
import numpy as np
import requests
from io import StringIO


VARIABLE_MAP = {
    'SWGDN': 'ghi',
    'SWGDNCLR': 'ghi_clear',
    'ALBEDO': 'albedo',
    'LWGNT': 'longwave_net',
    'LWGAB': 'longwave_down',
    'T2M': 'temp_air',
    'PS': 'pressure',
    'TOTEXTTAU': 'aod550',
    'TQV': 'precipitable_water',
}


def _k_to_c(temp_k):
    return temp_k - 273.15


UNITS = {
    'T2M': _k_to_c,
}


[docs] def get_merra2(latitude, longitude, start, end, username, password, dataset, variables, map_variables=True): """ Retrieve MERRA-2 time-series irradiance and meteorological reanalysis data from NASA's GESDISC data archive. MERRA-2 [1]_ offers modeled data for many atmospheric quantities at hourly resolution on a 0.5° x 0.625° global grid. Access must be granted to the GESDISC data archive before EarthData credentials will work. See [2]_ for instructions. Parameters ---------- latitude : float In decimal degrees, north is positive (ISO 19115). longitude: float In decimal degrees, east is positive (ISO 19115). start : datetime like or str First timestamp of the requested period. If a timezone is not specified, UTC is assumed. end : datetime like or str Last timestamp of the requested period. If a timezone is not specified, UTC is assumed. Must be in the same year as ``start``. username : str NASA EarthData username. password : str NASA EarthData password. dataset : str or list of str Dataset name (with version), e.g. "M2T1NXRAD.5.12.4". If all variables are in the same dataset, this can be a single string. Otherwise, pass a list of dataset names corresponding to the list of requested variables. variables : list of str List of variable names to retrieve. See the documentation of the specific dataset you are accessing for options. map_variables : bool, default True When true, renames columns of the DataFrame to pvlib variable names where applicable. See variable :const:`VARIABLE_MAP`. Raises ------ ValueError If ``start`` and ``end`` are in different years, when converted to UTC. Returns ------- data : pd.DataFrame Time series data. The index corresponds to the middle of the interval. meta : dict Metadata. Notes ----- The following datasets provide quantities useful for PV modeling: +------------------------------------+-----------+--------------------+ | Dataset | Variable | pvlib name | +====================================+===========+====================+ | `M2T1NXRAD.5.12.4 <M2T1NXRAD_>`_ | SWGDN | ghi | | +-----------+--------------------+ | | SWGDNCLR | ghi_clear | | +-----------+--------------------+ | | ALBEDO | albedo | | +-----------+--------------------+ | | LWGNT | longwave_net | +------------------------------------+-----------+--------------------+ | `M2T1NXLFO.5.12.4 <M2T1NXLFO_>`_ | LWGAB | longwave_down | +------------------------------------+-----------+--------------------+ | `M2T1NXSLV.5.12.4 <M2T1NXSLV_>`_ | T2M | temp_air | | +-----------+--------------------+ | | U10M | n/a | | +-----------+--------------------+ | | V10M | n/a | | +-----------+--------------------+ | | PS | pressure | | +-----------+--------------------+ | | TO3 | n/a | | +-----------+--------------------+ | | TQV | precipitable_water | +------------------------------------+-----------+--------------------+ | `M2T1NXAER.5.12.4 <M2T1NXAER_>`_ | TOTEXTTAU | aod550 | | +-----------+--------------------+ | | TOTSCATAU | n/a | | +-----------+--------------------+ | | TOTANGSTR | n/a | +------------------------------------+-----------+--------------------+ .. _M2T1NXRAD: https://disc.gsfc.nasa.gov/datasets/M2T1NXRAD_5.12.4/summary .. _M2T1NXSLV: https://disc.gsfc.nasa.gov/datasets/M2T1NXSLV_5.12.4/summary .. _M2T1NXAER: https://disc.gsfc.nasa.gov/datasets/M2T1NXAER_5.12.4/summary .. _M2T1NXLFO: https://disc.gsfc.nasa.gov/datasets/M2T1NXLFO_5.12.4/summary A complete list of datasets and their documentation is available at [3]_. Note that MERRA2 does not currently provide DNI or DHI. References ---------- .. [1] https://gmao.gsfc.nasa.gov/gmao-products/merra-2/ .. [2] https://disc.gsfc.nasa.gov/earthdata-login .. [3] https://disc.gsfc.nasa.gov/datasets?project=MERRA-2 """ def _to_utc_dt_notz(dt): dt = pd.to_datetime(dt) if dt.tzinfo is not None: # convert to utc, then drop tz so that isoformat() is clean dt = dt.tz_convert("UTC").tz_localize(None) return dt start = _to_utc_dt_notz(start) end = _to_utc_dt_notz(end) # login login_url = "https://urs.earthdata.nasa.gov/api/users/find_or_create_token" response = requests.post( login_url, auth=(username, password), headers={"Accept": "application/json"}, timeout=10, ) response.raise_for_status() token = response.json()["access_token"] # data query if isinstance(dataset, str): datasets = [dataset] * len(variables) else: datasets = dataset data_url = "https://api.giovanni.earthdata.nasa.gov/timeseries" parameters = { "location": "[{},{}]".format(round(latitude, 4), round(longitude, 4)), "time": "{}/{}".format(start.isoformat(), end.isoformat()) } query_headers = { 'Authorization': f'Bearer {token}' } meta = {'dataset': dataset} data = {} for variable, dataset in zip(variables, datasets): name = dataset.replace(".", "_") + "_" + variable query_parameters = parameters.copy() query_parameters["data"] = name response = requests.get(data_url, params=query_parameters, headers=query_headers) response.raise_for_status() buffer = StringIO(response.text) var_meta = {} while (line := buffer.readline().rstrip()) != "": key, value = line.split(",", maxsplit=1) var_meta[key] = value meta[variable] = var_meta df = pd.read_csv(buffer, index_col=0, parse_dates=True) df = df.replace(float(var_meta["undef"]), np.nan) data[variable] = df["Data"] # copy lat/lon to the top level, for consistency # with other iotools functions meta["latitude"] = float(var_meta["lat"]) meta["longitude"] = float(var_meta["lon"]) df = pd.DataFrame(data) df.index = df.index.tz_localize("UTC") if map_variables: for col in df.columns: if col in UNITS: convert = UNITS[col] df[col] = convert(df[col]) df = df.rename(columns=VARIABLE_MAP) return df, meta