Groundwater Analysis Report (GAR)

import matplotlib.pyplot as plt
import brodata

Download a GroundwaterAnalysisReport using GroundwaterAnalysisReport.from_bro_id(bro_id). The object contains the data from the BRO XML file.

gar = brodata.gar.GroundwaterAnalysisReport.from_bro_id("GAR000000019636")
gar
GroundwaterAnalysisReport(broId='GAR000000019636')

Measurements are stored in the laboratoryAnalysis attribute (a pandas DataFrame).

gar.laboratoryAnalysis
analyticalTechnique valuationMethod parameter analysisMeasurementValue uom qualityControlStatus limitSymbol
analysisDate
1982-02-12 None None 3548 126.55 mS/m goedgekeurd NaN
1982-02-12 None None 1398 7.00 1 goedgekeurd NaN
1982-02-12 None None 374 345.00 mg/l goedgekeurd NaN
1982-02-12 None None 289 0.54 mg/l goedgekeurd NaN
1982-02-12 None None 447 145.00 mg/l goedgekeurd NaN
1982-02-12 None None 508 165.00 mg/l goedgekeurd NaN
1982-02-12 None None 4188 0.22 mg/l goedgekeurd NaN
1982-02-12 None None 920 2.00 mg/l goedgekeurd NaN
1982-02-12 None None 1318 5.00 mg/l goedgekeurd NaN
1982-02-12 None None 1125 14.00 mg/l goedgekeurd NaN
1982-02-12 None None 1262 95.00 mg/l goedgekeurd NaN
1982-02-12 None None 1270 0.10 mg/l goedgekeurd LT
1982-02-12 None None 1508 95.00 mg/l goedgekeurd NaN

Use to_dict() to view the remaining contents of the GroundwaterAnalysisReport.

gar_data = gar.to_dict()
gar_data.pop("laboratoryAnalysis")
gar_data
{'broId': 'GAR000000019636',
 'corrected': 'ja',
 'deliveryAccountableParty': '30276683',
 'deregistered': 'nee',
 'fieldObservation': {'abnormalityInCooling': 'nee',
  'abnormalityInDevice': 'nee',
  'pollutedByEngine': 'nee',
  'filterAerated': 'onbekend',
  'groundWaterLevelDroppedTooMuch': 'onbekend',
  'abnormalFilter': 'nee',
  'sampleAerated': 'onbekend',
  'hoseReused': 'ja',
  'temperatureDifficultToMeasure': 'nee'},
 'fieldResearch': Empty DataFrame
 Columns: []
 Index: [],
 'groundwaterMonitoringNet': 'GMN000000000523',
 'groundwaterMonitoringWell': 'GMW000000038534',
 'id': 'BRO_0003',
 'latestCorrectionTime': '2026-02-20T14:16:45+01:00',
 'objectRegistrationTime': '2023-01-10T20:05:19+01:00',
 'qualityControlMethod': 'onbekend',
 'qualityRegime': 'IMBRO/A',
 'registrationCompletionTime': '2023-01-10T20:05:19+01:00',
 'registrationStatus': 'voltooid',
 'reregistered': 'nee',
 'tubeNumber': 1,
 'underReview': 'nee'}

Multiple objects

All measurements of one tube

gmw_id = "GMW000000017707"
tube_number = 1
df = brodata.gmw.get_tube_observations(gmw_id, tube_number, kind="gar")
df
analyticalTechnique valuationMethod parameter analysisMeasurementValue uom qualityControlStatus limitSymbol reportingLimit
analysisDate
1991-07-01 AAS CIW 284 620.00 ug/l goedgekeurd NaN NaN
1991-07-01 AAS CIW 374 13.00 mg/l goedgekeurd NaN NaN
1991-07-01 AAS CIW 1270 1.08 mg/l goedgekeurd NaN NaN
1991-07-01 AAS CIW 1508 71.00 mg/l goedgekeurd NaN NaN
1991-07-01 AAS CIW 4188 0.01 mg/l goedgekeurd LT NaN
... ... ... ... ... ... ... ... ...
2024-03-15 AAS CIW 1334 0.01 mg/l goedgekeurd NaN 0.01
2024-03-15 AAS CIW 3654 0.02 ug/l goedgekeurd LT 0.02
2024-03-15 AAS CIW 108 0.02 ug/l goedgekeurd LT 0.02
2024-03-15 AAS CIW 2450 0.10 ug/l goedgekeurd LT 0.10
2024-03-15 AAS CIW 1898 0.03 ug/l goedgekeurd LT 0.03

2974 rows × 8 columns

parameter_list = brodata.gar.get_parameter_list()
parameter_list
description aquoCode aspect casNumber id unit
code
10 1,1-dichloorpropaan 11DClC3a NVT 78-99-9 10 ug/l
100 2,4,5-trichlooraniline 245TClAn NVT 636-30-6 100 ug/l
101 2,4,5-trichloorfenol 245TClFol NVT 95-95-4 101 ug/l
102 2,4,5-trichloorfenoxyazijnzuur 245T NVT 93-76-5 102 ug/l
103 2,4,5-trichloorfenoxypropionzuur 245TP NVT 93-72-1 103 ug/l
... ... ... ... ... ... ...
921 Kaliumpermanganaat verbruik PMV NVT NVT 921 mg/l
93 2,3-dichlooraniline 23DClAn NVT 608-27-5 93 ug/l
94 2,3-dichloorfenol 23DClFol NVT 576-24-9 94 ug/l
967 koolstofdisulfide CS2 NVT 75-15-0 967 ug/l
971 koper Cu nf 7440-50-8 971 ug/l

1086 rows × 6 columns

# add the parameter description
df["parameter_description"] = parameter_list.loc[df["parameter"], "description"].values
# show all the unique parameters and the number of measurements
parameter_description_counts = df["parameter_description"].value_counts()
parameter_description_counts
parameter_description
aluminium                                                                  22
waterstofcarbonaat                                                         22
nitraat                                                                    22
sulfaat                                                                    22
fosfor totaal                                                              22
                                                                           ..
som 10 polycyclische aromatische koolwaterstoffen (VROM)                    1
som monocyclische aromatische koolwaterstoffen (BTEX)                       1
perfluorbutaansulfonamide                                                   1
som 4- en 5-methyl-1H-benzotriazool                                         1
VERVALLEN; perfluoroctaanzuur, ammoniumzout >> gebruik voortaan ID 4443     1
Name: count, Length: 728, dtype: int64
parameter_description = "sulfaat"
parameter_code = brodata.gar.get_parameter_code(parameter_description, parameter_list=parameter_list)
mask = df["parameter"] == parameter_code
ax = df.loc[mask, "analysisMeasurementValue"].plot(marker=".")
uom = df.loc[mask, "uom"].unique()
assert len(uom) == 1
ax.set_ylabel(uom[0])
ax.set_title(f"{parameter_description} {gmw_id}_{tube_number}");
../_images/fdfcfaf73a5525f8973fb4228caad2e7f78d49a65155b67923dd1073960690a8.png

All measurements within an extent

As with Groundwater Level Dossiers, you can download GAR data within an extent via brodata.gm.get_data_in_extent or brodata.gmw.get_data_in_extent. Both return a GeoDataFrame where laboratoryAnalysis contains measurement data and groundwaterAnalysisReport lists GAR BRO IDs for each tube.

For simplicity we use brodata.gm.get_data_in_extent (see the GLD example).

extent = [115000, 120000, 438000, 441000]
gdf = brodata.gm.get_data_in_extent(extent=extent, kind="gar", combine=True)
gdf.T
gmw_bro_id GMW000000038534 GMW000000040467
tube_number 1 2 1 3
geometry POINT (115429.97423841307 438779.949886862) POINT (115429.97423841307 438779.949886862) POINT (115429.97423841307 438779.949886862) POINT (115429.97423841307 438779.949886862)
gm_gmw_monitoringtube_pk 38840 38841 42394 42395
gm_gmw.href https://api.pdok.nl/tno/bro-grondwatermonitori... https://api.pdok.nl/tno/bro-grondwatermonitori... https://api.pdok.nl/tno/bro-grondwatermonitori... https://api.pdok.nl/tno/bro-grondwatermonitori...
gm_gmw_fk 29773 29773 31606 31606
tube_status onbekend onbekend onbekend onbekend
tube_in_use ja ja ja ja
tube_top_diameter NaN NaN NaN NaN
screen_top_position -15.16 -23.26 -12.96 -23.96
screen_bottom_position -17.16 -25.26 -14.96 -25.96
electrode_top_position None None None None
electrode_bottom_position None None None None
laboratoryAnalysis analyticalTechnique valuationMeth... analyticalTechnique valuationMeth... analyticalTechnique valuationMeth... analyticalTechnique valuationMeth...
groundwaterAnalysisReport [GAR000000019636, GAR000000019637, GAR00000001... [GAR000000019646, GAR000000019647, GAR00000001... [GAR000000038330, GAR000000038331, GAR00000003... [GAR000000038290, GAR000000038291, GAR00000003...

Plot the GeoDataFrame to inspect locations; some monitoring wells may overlap.

f, ax = plt.subplots()
ax.axis("scaled")
ax.axis(extent)
gdf.plot(ax=ax);
../_images/92a18091aeb4ab27265cd92cc412f5f01c67eab767512171087ab593cb83b39c.png

Plot measurement series for the tubes in a single figure.

f, ax = plt.subplots()
parameter_description = "sulfaat"
parameter_code = brodata.gar.get_parameter_code(parameter_description, parameter_list=parameter_list)
uom = "mg/l"
for index in gdf.index:
    df = gdf.at[index, "laboratoryAnalysis"]
    mask = df["parameter"] == parameter_code
    if not mask.any():
        continue
    assert (df.loc[mask, "uom"] == uom).all()
    ax = df.loc[mask, "analysisMeasurementValue"].plot(marker=".", ax=ax, label=index)
ax.set_ylabel(uom)
ax.set_title(parameter_description)
ax.legend();
../_images/78f6b5bf446cf1662b4e96460f0b20436ff1341094b4008fb3bdbaa901b6a39d.png