diff --git a/hydropandas/extensions/plots.py b/hydropandas/extensions/plots.py index e06e2489..c743d249 100644 --- a/hydropandas/extensions/plots.py +++ b/hydropandas/extensions/plots.py @@ -378,6 +378,7 @@ def section_plot( - limit y-axis of section plot to observations only - remove the checking (if obs are near bottom) from this function - moving the legend outside the plot + - set xlim of observation plot more tight when tmin is not specified """ # prepare column for x location in section plot @@ -555,6 +556,8 @@ def section_plot( else: ax_section.set_xlabel(section_label_x) + ax_obs.set_xlim(left=tmin, right=tmax) + # rotate labels on observation axis ax_obs.set_xticks( ax_obs.get_xticks(), diff --git a/hydropandas/io/bro.py b/hydropandas/io/bro.py index d81dfb1e..e33b7a46 100644 --- a/hydropandas/io/bro.py +++ b/hydropandas/io/bro.py @@ -16,7 +16,7 @@ def get_obs_list_from_gmn(bro_id, ObsClass, only_metadata=False, keep_all_obs=True): - """ + """get a list of observation from a groundwater monitoring network. Parameters ---------- @@ -60,7 +60,8 @@ class of the observations, so far only GroundwaterObs is supported gmn = tree.find(".//xmlns:GMN_PO", ns) gmws = gmn.findall("xmlns:measuringPoint", ns) - logger.info(f"{len(gmws)} groundwater monitoring wells within groundwater meetnet") + logger.info( + f"{len(gmws)} groundwater monitoring wells within groundwater meetnet") obs_list = [] for gmw in tqdm(gmws): @@ -130,26 +131,37 @@ def get_bro_groundwater(bro_id, tube_nr=None, only_metadata=False, **kwargs): elif bro_id.startswith("GMW"): if tube_nr is None: - raise ValueError("if bro_id is GMW a filternumber should be specified") + raise ValueError( + "if bro_id is GMW a filternumber should be specified") meta = get_metadata_from_gmw(bro_id, tube_nr) - gld_id = get_gld_id_from_gmw(bro_id, tube_nr) + gld_ids = get_gld_ids_from_gmw(bro_id, tube_nr) - if gld_id is None: + if gld_ids is None: meta["name"] = f"{bro_id}_{tube_nr}" only_metadata = True # cannot get time series without gld id else: - meta["name"] = gld_id + meta["name"] = f"{bro_id}_{tube_nr}" + meta["gld_ids"] = gld_ids if only_metadata: empty_df = pd.DataFrame() return empty_df, meta - return measurements_from_gld(gld_id, **kwargs) + for i, gld_id in enumerate(gld_ids): + if i == 0: + df, meta_new = measurements_from_gld(gld_id, **kwargs) + meta.update(meta_new) + else: + df_new, meta_new = measurements_from_gld(gld_id, **kwargs) + df = pd.concat([df, df_new], axis=1) + meta.update(meta_new) + + return df, meta -def get_gld_id_from_gmw(bro_id, tube_nr, quality_regime="IMBRO/A"): - """get bro_id of a grondwterstandendossier (gld) from a bro_id of a +def get_gld_ids_from_gmw(bro_id, tube_nr): + """get bro_ids of multiple grondwaterstandendossier (gld) from a bro_id of a grondwatermonitoringsput (gmw). Parameters @@ -158,8 +170,6 @@ def get_gld_id_from_gmw(bro_id, tube_nr, quality_regime="IMBRO/A"): starts with 'GLD' or 'GMW' e.g. 'GMW000000036287'. tube_nr : int tube number. - quality_regime : str - either choose 'IMBRO/A' or 'IMBRO'. Raises ------ @@ -170,8 +180,8 @@ def get_gld_id_from_gmw(bro_id, tube_nr, quality_regime="IMBRO/A"): Returns ------- - str - bro_id of a grondwaterstandonderzoek (gld). + list of str or None + bro_ids of a grondwaterstandonderzoek (gld). """ if not bro_id.startswith("GMW"): @@ -193,37 +203,14 @@ def get_gld_id_from_gmw(bro_id, tube_nr, quality_regime="IMBRO/A"): for tube in d["monitoringTubeReferences"]: if tube["tubeNumber"] == tube_nr: - if len(tube["gldReferences"]) == 1: - return tube["gldReferences"][0]["broId"] - elif len(tube["gldReferences"]) == 0: + if len(tube["gldReferences"]) == 0: logger.info( f"no groundwater level dossier for {bro_id} and tube number" f"{tube_nr}" ) return None - elif len(tube["gldReferences"]) == 2: - logger.info( - f"two gld references found for GMW {bro_id} and tube nr" - f"{tube_nr}, using {quality_regime} quality regime" - ) - for gldref in tube["gldReferences"]: - url2 = gldref["url"] - req2 = requests.get(url2) - ns = { - "ns11": "http://www.broservices.nl/xsd/dsgld/1.0", - "brocom": "http://www.broservices.nl/xsd/brocommon/3.0", - } - tree = xml.etree.ElementTree.fromstring(req2.text) - gld = tree.findall(".//ns11:GLD_O", ns)[0] - qualityRegime = gld.find("brocom:qualityRegime", ns).text - if qualityRegime == quality_regime: - return gldref["broId"] - logger.info( - f"no gld reference with quality regime {quality_regime} was found" - ) - return None else: - raise RuntimeError("unexpected number of gld references") + return [gldref["broId"] for gldref in tube["gldReferences"]] def measurements_from_gld( @@ -295,11 +282,13 @@ def measurements_from_gld( raise (Exception("Only one gld supported")) gld = glds[0] - meta = {"name": bro_id, "source": "BRO"} - meta["monitoring_well"] = gld.find("ns11:monitoringPoint//gldcommon:broId", ns).text + meta = {"source": "BRO"} + meta["monitoring_well"] = gld.find( + "ns11:monitoringPoint//gldcommon:broId", ns).text meta["tube_nr"] = int( gld.find("ns11:monitoringPoint//gldcommon:tubeNumber", ns).text ) + meta["name"] = f"{meta['monitoring_well']}_{meta['tube_nr']}" gmn = gld.find("ns11:groundwaterMonitoringNet//gldcommon:broId", ns) if gmn is None: meta["monitoringsnet"] = None @@ -313,7 +302,8 @@ def measurements_from_gld( np.nan if value.text is None else float(value.text) for value in gld.findall(f"{msts}//waterml:value", ns) ] - qualifiers = [q.text for q in gld.findall(f"{msts}//swe:Category//swe:value", ns)] + qualifiers = [q.text for q in gld.findall( + f"{msts}//swe:Category//swe:value", ns)] # to dataframe df = pd.DataFrame( @@ -574,6 +564,13 @@ class of the observations, e.g. GroundwaterObs or WaterlvlObs DESCRIPTION. """ + + if only_metadata and not keep_all_obs: + logger.error( + "you will get an empty ObsCollection with only_metadata is True and" + "keep_all_obs is False" + ) + url = "https://publiek.broservices.nl/gm/gmw/v1/characteristics/searches?" data = {} @@ -615,7 +612,7 @@ class of the observations, e.g. GroundwaterObs or WaterlvlObs [gmw.text for gmw in tree.findall(".//dsgmw:GMW_C//brocom:broId", ns)] ) - if len(gmws_ids) > 1000: + if len(gmws_ids) > 1000 and not ignore_max_obs: ans = input( f"You requested to download {len(gmws_ids)} observations, this can" "take a while. Are you sure you want to continue [Y/n]? " diff --git a/hydropandas/io/fews.py b/hydropandas/io/fews.py index c494bdad..f5293566 100644 --- a/hydropandas/io/fews.py +++ b/hydropandas/io/fews.py @@ -184,8 +184,7 @@ class of the observations, e.g. GroundwaterObs or WaterlvlObs loc = h_attr.text if loc not in locationIds: element.clear() - logger.info( - f" ... skipping '{loc}', not in locationIds") + logger.info(f" ... skipping '{loc}', not in locationIds") continue if filterdict is not None: @@ -508,8 +507,7 @@ class of the observations, e.g. GroundwaterObs or WaterlvlObs source="FEWS", ) else: - o = ObsClass(ts, x=x, y=y, unit=unit, meta=header, - name=name, source="FEWS") + o = ObsClass(ts, x=x, y=y, unit=unit, meta=header, name=name, source="FEWS") return o, header @@ -581,8 +579,7 @@ def write_pi_xml(obs_coll, fname, timezone=1.0, version="1.24"): tag=htag, date=hdate, time=htime ) elif htag.endswith("timeStep"): - hline = '<{tag} unit="{unit}"/>\n'.format( - tag=htag, unit=hval) + hline = '<{tag} unit="{unit}"/>\n'.format(tag=htag, unit=hval) else: hline = paramline.format(tag=htag, param=hval) hlines.append(3 * "\t" + hline) diff --git a/hydropandas/io/menyanthes.py b/hydropandas/io/menyanthes.py index cf9ecc9f..32ddd3c2 100644 --- a/hydropandas/io/menyanthes.py +++ b/hydropandas/io/menyanthes.py @@ -1,24 +1,70 @@ -# -*- coding: utf-8 -*- -"""Created on Thu Oct 10 11:01:22 2019. - -@author: oebbe -""" - import logging import os import numpy as np -from pandas import DataFrame, Series +from pandas import DataFrame, Series, Timedelta, Timestamp from scipy.io import loadmat from ..observation import GroundwaterObs, WaterlvlObs -from ..util import matlab2datetime logger = logging.getLogger(__name__) +def matlab2datetime(tindex): + """ + Transform a MATLAB serial date number to a Python datetime object, rounded + to seconds. + + Parameters + ---------- + tindex : float + The MATLAB serial date number to convert. + + Returns + ------- + datetime : datetime.datetime + The equivalent datetime object in Python. + + Notes + ----- + MATLAB serial date numbers represent the number of days elapsed since + January 1, 0000 (the proleptic Gregorian calendar), with January 1, 0000 as + day 1. Fractions of a day can be represented as a decimal. + + The returned datetime object is rounded to the nearest second. + + Examples + -------- + >>> matlab2datetime(719529.496527778) + datetime.datetime(2019, 1, 1, 11, 55, 2) + + """ + day = Timestamp.fromordinal(int(tindex)) + dayfrac = Timedelta(days=float(tindex) % 1) - Timedelta(days=366) + return day + dayfrac + + def read_file(fname, ObsClass, load_oseries=True, load_stresses=True): - """This method is used to read the file.""" + """ + Read data from a Menyanthes file and create observation objects. + + Parameters + ---------- + fname : str + Name of the Menyanthes file to read. + ObsClass : GroundwaterObs or WaterlvlObs + Class of observation object to create. + load_oseries : bool, optional + Flag indicating whether to load observation series or not, by default + True. + load_stresses : bool, optional + Flag indicating whether to load stresses or not, by default True. + + Returns + ------- + obs_list : list + List of observation objects created from the Menyanthes file. + """ logger.info(f"reading menyanthes file {fname}") @@ -117,7 +163,38 @@ def read_file(fname, ObsClass, load_oseries=True, load_stresses=True): def read_oseries(mat): - """Read the oseries from a mat file from menyanthes.""" + """Read the oseries from a mat file from menyanthes. + + Parameters + ---------- + mat : dict + A dictionary object containing the Menyanthes file data. + + Returns + ------- + dict + A dictionary containing oseries data, with oseries names as keys and + their corresponding metadata and values as values. + + Notes + ----- + This function reads the oseries data from a Menyanthes file in .mat format + and returns it in a dictionary format. The oseries data contains the + following metadata: + - name: The name of the oseries. + - x: The x-coordinate of the oseries location. + - y: The y-coordinate of the oseries location. + - source: The data source. + - unit: The unit of measurement. + + In addition to the metadata, the oseries data also contains a pandas Series + object named 'values', which contains the time series data for the oseries. + + Examples + -------- + >>> mat = loadmat('menyanthes_file.mat') + >>> d_h = read_oseries(mat) + """ d_h = {} # Check if more then one time series model is present @@ -158,12 +235,20 @@ def read_oseries(mat): def read_stresses(mat): + """Reads the stresses from a mat file from menyanthes. + + Parameters + ---------- + mat : dict + A dictionary object containing the mat file. + + Returns + ------- + dict + A dictionary object containing the stresses data. + """ d_in = {} - # Check if more then one time series is present - # if not isinstance(mat["IN"], np.ndarray): - # mat["IN"] = [mat["IN"]] - # Read all the time series for i, IN in enumerate(mat["IN"]): if not hasattr(IN, "Name") and not hasattr(IN, "name"): diff --git a/hydropandas/io/wiski.py b/hydropandas/io/wiski.py index edbe6546..3f580c30 100644 --- a/hydropandas/io/wiski.py +++ b/hydropandas/io/wiski.py @@ -41,6 +41,41 @@ def read_wiski_file( unit="", **kwargs, ): + """ + Read data from a WISKI file. + + Parameters: + ----------- + fname : str + The name of the file to be read. + sep : str, optional (default=";") + The delimiter used to separate fields in the file. + header_sep : str, optional (default=None) + The delimiter used to separate fields in the header. If None, the + function will try to automatically detect the separator. + header_identifier : str, optional (default="#") + The character used to identify header lines. + read_series : bool, optional (default=True) + Whether to read the time series data from the file. + infer_datetime_format : bool, optional (default=True) + Whether to infer the datetime format of the timestamp column. + translate_dic : dict, optional (default=None) + A dictionary mapping header field names to the desired output names. + tz_localize : bool, optional (default=True) + Whether to localize the datetime index to the machine's timezone. + unit : str, optional (default="") + The unit of measurement of the data. + **kwargs : keyword arguments + Additional arguments to pass to the pandas `read_csv` function. + + Returns: + -------- + data : pandas.DataFrame or None + A dataframe containing the time series data from the file. Returns None + if `read_series` is False. + metadata : dict + A dictionary containing metadata about the data in the file. + """ logger.info("reading -> {}".format(os.path.split(fname)[-1])) if translate_dic is None: @@ -133,6 +168,46 @@ def read_wiski_dir( keep_all_obs=True, **kwargs, ): + """ + Reads WISKI CSV files from a directory and returns a list of observation + objects. + + Parameters + ---------- + dirname : str + The path of the directory containing the WISKI CSV files. + ObsClass : object, optional + The observation class to use for creating observation objects. Default + is None. + suffix : str, optional + The file extension of the WISKI CSV files. Default is ".csv". + unpackdir : str, optional + The directory to which the files should be unpacked. Default is None. + force_unpack : bool, optional + If True, forces the files to be unpacked even if they are already in the + target directory. Default is False. + preserve_datetime : bool, optional + If True, preserves the original modification times of the files when + unpacking them. Default is False. + keep_all_obs : bool, optional + If True, keeps all observation objects even if they have no metadata + available. Default is True. + **kwargs + Additional keyword arguments to pass to the `from_wiski` method of the + `ObsClass` object. + + Returns + ------- + list + A list of observation objects created from the WISKI CSV files in the + directory. + + Raises + ------ + FileNotFoundError + If no WISKI CSV files are found in the directory. + + """ # get files dirname, unzip_fnames = get_files( dirname, diff --git a/hydropandas/obs_collection.py b/hydropandas/obs_collection.py index cf028674..5779f43d 100644 --- a/hydropandas/obs_collection.py +++ b/hydropandas/obs_collection.py @@ -27,7 +27,7 @@ def read_bro( tmin=None, tmax=None, only_metadata=False, - keep_all_obs=False, + keep_all_obs=True, epsg=28992, ignore_max_obs=False, ): @@ -726,7 +726,8 @@ def _set_metadata_value(self, iname, att_name, value, add_to_meta=False): if add_to_meta: o.meta.update({att_name: value}) - logger.debug(f"add {att_name} of {iname} with value {value} to meta") + logger.debug( + f"add {att_name} of {iname} with value {value} to meta") def _is_consistent(self, check_individual_obs=True): """check if an observation collection is consistent. An observation @@ -753,12 +754,17 @@ def _is_consistent(self, check_individual_obs=True): """ # check unique index if not self.index.is_unique: - logger.warning(f"index of observation collection -> {self.name} not unique") + logger.warning( + f""""index of observation collection -> {self.name} + not unique. non unique indices are:""" + ) + logger.warning(" ".join(self.index[self.index.duplicated()])) return False # check nan values in observations if self.obs.isna().any(): - logger.warning(f"missing observation object in collection -> {self.name} ") + logger.warning( + f"missing observation object in collection -> {self.name} ") return False # check oc data with individual object attributes @@ -847,7 +853,8 @@ def add_observation(self, o, check_consistency=True, **kwargs): raise RuntimeError("inconsistent observation collection") if not isinstance(o, obs.Obs): - raise TypeError("Observation should be of type hydropandas.observation.Obs") + raise TypeError( + "Observation should be of type hydropandas.observation.Obs") # add new observation to collection if o.name not in self.index: @@ -1036,7 +1043,8 @@ def from_dataframe(cls, df, obs_list=None, ObsClass=obs.GroundwaterObs): obs_list = [ObsClass() for i in range(len(df))] df["obs"] = obs_list else: - raise TypeError(f"df should be type pandas.DataFrame not {type(df)}") + raise TypeError( + f"df should be type pandas.DataFrame not {type(df)}") return cls(df) @@ -1312,7 +1320,8 @@ class of the observations, e.g. GroundwaterObs or WaterlvlObs return cls(obs_df, name=name, meta=meta) else: - raise ValueError("either specify variables file_or_dir or xmlstring") + raise ValueError( + "either specify variables file_or_dir or xmlstring") @classmethod def from_imod( @@ -1527,7 +1536,8 @@ class of the observations, can be PrecipitationObs, EvaporationObs elif isinstance(ObsClasses, type): if issubclass( - ObsClasses, (obs.PrecipitationObs, obs.EvaporationObs, obs.MeteoObs) + ObsClasses, (obs.PrecipitationObs, + obs.EvaporationObs, obs.MeteoObs) ): ObsClasses = [ObsClasses] * len(meteo_vars) else: @@ -1988,7 +1998,8 @@ def interpolate( # add all metadata that is equal for all observations kwargs = {} - meta_att = set(otype._metadata) - set(["x", "y", "name", "source", "meta"]) + meta_att = set(otype._metadata) - \ + set(["x", "y", "name", "source", "meta"]) for att in meta_att: if (self.loc[:, att] == self.iloc[0].loc[att]).all(): kwargs[att] = self.iloc[0].loc[att] @@ -2001,7 +2012,8 @@ def interpolate( y=xy[i][1], name=col, source=f"interpolation {self.name}", - meta={"interpolation_kernel": kernel, "interpolation_epsilon": epsilon}, + meta={"interpolation_kernel": kernel, + "interpolation_epsilon": epsilon}, **kwargs, ) obs_list.append(o) diff --git a/hydropandas/observation.py b/hydropandas/observation.py index 9aa7b136..b5b75ea1 100644 --- a/hydropandas/observation.py +++ b/hydropandas/observation.py @@ -1,4 +1,4 @@ -"""Module with a number of observation classes. +"""Module with observation classes. The Obs class is a subclass of a pandas DataFrame with additional attributes and methods. The specific classes (GroundwaterObs, @@ -32,19 +32,14 @@ class Obs(pd.DataFrame): Unless specified explicitly the first numeric column in the observation is used for analysis and plotting. - An Obs object is a subclass of a pandas.DataFrame and allows for additional - attributes and methods. More information about subclassing pandas - DataFrames pandas can be found here: - http://pandas.pydata.org/pandas-docs/stable/development/extending.html#extending-subclassing-pandas - Parameters ---------- + name : str + name x : int or float x coordinate of observation point y : int or float y coordinate of observation point - name : str - name meta : dictionary metadata filename : str @@ -608,17 +603,32 @@ def from_artdino_file(cls, fname=None, **kwargs): @classmethod def from_wiski(cls, fname, **kwargs): - """read wiski file - - Parameters - ---------- - fname : [type] - [description] + """ + Read data from a WISKI file. - Returns - ------- - [type] - [description] + Parameters: + ----------- + fname : str + The name of the file to be read. + sep : str, optional (default=";") + The delimiter used to separate fields in the file. + header_sep : str, optional (default=None) + The delimiter used to separate fields in the header. If None, the + function will try to automatically detect the separator. + header_identifier : str, optional (default="#") + The character used to identify header lines. + read_series : bool, optional (default=True) + Whether to read the time series data from the file. + infer_datetime_format : bool, optional (default=True) + Whether to infer the datetime format of the timestamp column. + translate_dic : dict, optional (default=None) + A dictionary mapping header field names to the desired output names. + tz_localize : bool, optional (default=True) + Whether to localize the datetime index to the machine's timezone. + unit : str, optional (default="") + The unit of measurement of the data. + **kwargs : keyword arguments + Additional arguments to pass to the pandas `read_csv` function. """ from .io import wiski @@ -1378,7 +1388,7 @@ def from_knmi( ) @classmethod - def from_xy( + def from_nearest_xy( cls, xy, et_type="EV24", diff --git a/hydropandas/util.py b/hydropandas/util.py index 58aed5e4..4afca7c4 100644 --- a/hydropandas/util.py +++ b/hydropandas/util.py @@ -14,7 +14,7 @@ from colorama import Back, Fore, Style from numpy import unique -from pandas import DataFrame, DatetimeIndex, Timedelta, Timestamp +from pandas import DataFrame, DatetimeIndex from scipy.interpolate import RBFInterpolator logger = logging.getLogger(__name__) @@ -87,43 +87,6 @@ def unzip_file(src, dst, force=False, preserve_datetime=False): return 1 -def unzip_changed_files(zipname, pathname, check_time=True, check_size=False): - # Extract each file in a zip-file only when the properties are different - # With the default arguments this method only checks the modification time - with zipfile.ZipFile(zipname) as zf: - infolist = zf.infolist() - for info in infolist: - fname = os.path.join(pathname, info.filename) - extract = False - if os.path.exists(fname): - if check_time: - tz = time.mktime(info.date_time + (0, 0, -1)) - tf = os.path.getmtime(fname) - if tz != tf: - extract = True - if check_size: - sz = info.file_size - sf = os.path.getsize(fname) - if sz != sf: - extract = True - else: - extract = True - if extract: - logging.info("extracting {}".format(info.filename)) - zf.extract(info.filename, pathname) - # set the correct modification time - # (which is the time of extraction by default) - tz = time.mktime(info.date_time + (0, 0, -1)) - os.utime(os.path.join(pathname, info.filename), (tz, tz)) - - -def matlab2datetime(tindex): - """Transform a matlab time to a datetime, rounded to seconds.""" - day = Timestamp.fromordinal(int(tindex)) - dayfrac = Timedelta(days=float(tindex) % 1) - Timedelta(days=366) - return day + dayfrac - - def get_files( file_or_dir, ext, unpackdir=None, force_unpack=False, preserve_datetime=False ): diff --git a/hydropandas/version.py b/hydropandas/version.py index bc8c296f..4910b9ec 100644 --- a/hydropandas/version.py +++ b/hydropandas/version.py @@ -1 +1 @@ -__version__ = "0.7.2" +__version__ = "0.7.3" diff --git a/tests/test_004_gwobs.py b/tests/test_004_gwobs.py index d9bcdb60..6252d537 100644 --- a/tests/test_004_gwobs.py +++ b/tests/test_004_gwobs.py @@ -57,11 +57,13 @@ def test_get_modellayers_mf6_structured(): # Create the Flopy simulation object model_name = "test_mf6_structured" - sim = flopy.mf6.MFSimulation(sim_name=model_name, exe_name="mf6", version="mf6") + sim = flopy.mf6.MFSimulation( + sim_name=model_name, exe_name="mf6", version="mf6") # Create the Flopy groundwater flow (gwf) model object model_nam_file = "{}.nam".format(model_name) - gwf = flopy.mf6.ModflowGwf(sim, modelname=model_name, model_nam_file=model_nam_file) + gwf = flopy.mf6.ModflowGwf( + sim, modelname=model_name, model_nam_file=model_nam_file) Lx = 300000.0 Ly = 400000.0 ztop = 50.0 diff --git a/tests/test_011_bro.py b/tests/test_011_bro.py index c399f2a9..16ed8b08 100644 --- a/tests/test_011_bro.py +++ b/tests/test_011_bro.py @@ -53,25 +53,13 @@ def test_groundwater_observations2(): return -def test_get_gld_id_from_gmw(): +def test_get_gld_ids_from_gmw(): bro_id = "GMW000000036287" bro_id = "GMW000000055372" bro_id = "GMW000000059186" - bro.get_gld_id_from_gmw(bro_id, tube_nr=1) - - return - - -def test_get_gld_id_from_gmw_quality_regime(): - # bro id with two gld's with a different quality regime - # both gld's have no measurements 13-3-2023 - bro_id = "GMW000000063853" - gld1 = bro.get_gld_id_from_gmw(bro_id, tube_nr=1, quality_regime="IMBRO/A") - - gld2 = bro.get_gld_id_from_gmw(bro_id, tube_nr=1, quality_regime="IMBRO") - assert ( - gld1 != gld2 - ), "different quality regimes should return different gld id's for this gmw id" + bro_id = "GMW000000063853" # two gld ids + bro_id = "GMW000000030953" # three gld ids + bro.get_gld_ids_from_gmw(bro_id, tube_nr=1) return