#!/usr/bin/env python
# -*- coding: utf-8 -*-

#WRITTEN BY DENE BOWDALO

###------------------------------------------------------------------------------------###
###IMPORT MODULES
###------------------------------------------------------------------------------------###

import numpy as np

###------------------------------------------------------------------------------------###
###------------------------------------------------------------------------------------###

#define and setup frameworks for storing standardised data for each data network    
def create_standardised_data_frame():

    #DATA
    #Refers to time and measured parameter variables, as well as variables which inform of the quality of each separate measurement. 
    data = {
    
    #TIME
    'time':                                             {'value':[], 'standard_name':'time',                                              'long_name':'time',                                              'units':'minutes since 0001-01-01 00:00:00', 'data_type':np.uint32,  'string_format':np.NaN,        'n_decimals':np.NaN, 'description':'Integer time in minutes since 0001-01-01 00:00 UTC. Time given refers to the start of the time window the measurement is representative of (temporal resolution).'},        
    
    #MEASUREMENT VALUES
    parameter_details['bsc_parameter_name']:            {'value':[], 'standard_name':parameter_details['long_parameter_name'],            'long_name':parameter_details['long_parameter_name'],            'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'description':'Measured value of surface %s for the stated temporal resolution.'%(parameter_details['long_parameter_name'])}, 
    
    #PARAMETERS INFORMING QUALITY OF MEASUREMENT 
    'temporal_resolution':                              {'value':[], 'standard_name':'temporal resolution',                               'long_name':'temporal measurement resolution',                   'units':'unitless',                          'data_type':np.object,  'string_format':'upper_short', 'n_decimals':np.NaN, 'description':'Temporal resolution that a specific measurement is representative of. Typically: H (hour), D (day), W, (week), M (month). If resolution is not one of these, reported as an integer string (in minutes). Highest time resolution possible is 1 minute.'}, 
    'reported_lower_limit_of_detection_per_measurement':{'value':[], 'standard_name':'reported lower limit of detection per measurement', 'long_name':'reported lower limit of detection per measurement', 'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'description':'Reported lower limit of detection of measurement methodology, for a specific measurement, in %s.'%(parameter_details['standard_units'])}, 
    'reported_upper_limit_of_detection_per_measurement':{'value':[], 'standard_name':'reported upper limit of detection per measurement', 'long_name':'reported upper limit of detection per measurement', 'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'description':'Reported upper limit of detection of measurement methodology, for a specific measurement, in %s.'%(parameter_details['standard_units'])}, 
    'reported_uncertainty_per_measurement':             {'value':[], 'standard_name':'reported measurement uncertainty per measurement',  'long_name':'reported measurement uncertainty per measurement',  'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'description':'Reported measurement uncertainty (±) of methodology, for a specific measurement. In principal this refers to the inherent uncertainty on every measurement as a function of the quadratic addition of the accuracy and precision metrics (at the same confidence interval), but is often reported incosistently e.g. being solely determined from random errors (i.e. just the measuremental precision). This is given in absolute terms in %s.'%(parameter_details['standard_units'])},
    'derived_uncertainty_per_measurement':              {'value':[], 'standard_name':'derived measurement uncertainty per measurement',   'long_name':'derived measurement uncertainty per measurement',   'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'description':'Derived measurement uncertainty (±) of methodology, for a specific measurement. This is calculated through the quadratic addition of reported (or if not available, documented) accuracy and precision metrics. This is given in absolute terms in %s.'%(parameter_details['standard_units'])},
    'flag':                                             {'value':[], 'standard_name':'flags',                                             'long_name':'data reporter provided standardised flags',         'units':'unitless',                          'data_type':np.object,  'string_format':'upper_short', 'n_decimals':np.NaN, 'description':'Data flag, indicating the data quality of a specific measurement, provided by the data reporter.'},
    'qa':                                               {'value':[], 'standard_name':'qa',                                                'long_name':'qa standardised data flags',                        'units':'unitless',                          'data_type':np.object,  'string_format':'upper_short', 'n_decimals':np.NaN, 'description':'Concatenated flag string, indicating scientific issues for each observation after being passed through multiple scientific quality control/assurance tests.'}}

    return data

#define and setup frameworks for storing standardised metadata for each data network, and from globally gridded datasets 
def create_standardised_metadata_frame():

    #METADATA
    #Refers to data which provides qualitative information about measurements, in general across large swatches of time, but can vary. 
    metadata = {    
    
    #VERSION OF GLOBALLY HARMONISED OBSERVATIONAL SURFACE TREATMENT (GHOST)
    'GHOST_version':{'value':[], 'standard_name':'GHOST version', 'long_name':'Globally Harmonised Observational Surface Treatment (GHOST)', 'units':'unitless', 'data_type':np.object, 'string_format':'upper_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Version of the Globally Harmonised Observational Surface Treatment (GHOST).'}, 
     
    #NETWORK STATION REFERENCE 
    'station_reference':{'value':[], 'standard_name':'station reference', 'long_name':'station reference identifier', 'units':'unitless', 'data_type':np.object, 'string_format':'upper_short', 'n_decimals':np.NaN, 'metadata_order':0, 'description':'reference ID for station.'}, 
    
    #NETWORK PROVIDED STATION INFORMATION
    'data_timezone':                   {'value':[], 'standard_name':'data timezone',                   'long_name':'reported data timezone',                   'units':'difference in hours to UTC', 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':16, 'description':'Timezone (relative to UTC) the data is reported in.'},
    'station_timezone':                {'value':[], 'standard_name':'station timezone',                'long_name':'station timezone',                         'units':'difference in hours to UTC', 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':17, 'description':'Actual timezone (relative to UTC in 2000-01-01 00:00) for the station'},
    'latitude':                        {'value':[], 'standard_name':'latitude',                        'long_name':'latitude',                                 'units':'decimal degrees North',      'data_type':np.float64, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':3,  'description':'Geodetic latitude of measuring instrument, in decimal degrees North.'},
    'longitude':                       {'value':[], 'standard_name':'longitude',                       'long_name':'longitude',                                'units':'decimal degrees East',       'data_type':np.float64, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':2,  'description':'Geodetic longitude of measuring instrument, in decimal degrees East.'},
    'altitude':                        {'value':[], 'standard_name':'altitude',                        'long_name':'altitude relative to mean sea level',      'units':'m',                          'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':4,  'description':'Altitude of the ground level at the station, relative to mean sea level, in metres.'},
    'sampling_height':                 {'value':[], 'standard_name':'sampling height',                 'long_name':'sampling height relative to ground',       'units':'m',                          'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':5,  'description':'Height above the ground of the inlet/instrument/sampler, in metres.'},
    'distance_to_building':            {'value':[], 'standard_name':'distance to building',            'long_name':'distance to the nearest building',         'units':'m',                          'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':18, 'description':'Distance to the nearest building of the inlet/instrument/sampler, in metres.'},
    'distance_to_kerb':                {'value':[], 'standard_name':'distance to kerb',                'long_name':'distance to the street kerb',              'units':'m',                          'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':19, 'description':'Distance to the street kerb of the inlet/instrument/sampler, in metres.'},
    'distance_to_junction':            {'value':[], 'standard_name':'distance to junction',            'long_name':'distance to the nearest road junction',    'units':'m',                          'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':20, 'description':'Distance to the nearest road junction of the inlet/instrument/sampler, in metres.'},
    'distance_to_source':              {'value':[], 'standard_name':'distance to source',              'long_name':'distance to the main emission source',     'units':'km',                         'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':21, 'description':'Distance to the main emission source (see variable: "main_emission_source") of the inlet/instrument/sampler, in kilometres.'},
    'street_width':                    {'value':[], 'standard_name':'street width',                    'long_name':'width of the street',                      'units':'m',                          'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':22, 'description':'Width of the street where measurements are being made (if applicable), in metres.'},
    'street_type':                     {'value':[], 'standard_name':'street type',                     'long_name':'type of street',                           'units':'unitless',                   'data_type':np.object,  'string_format':'title_short', 'n_decimals':np.NaN, 'metadata_order':23, 'description':'Type of street where measurements are being made (if applicable).'},
    'daytime_traffic_speed':           {'value':[], 'standard_name':'daytime traffic speed',           'long_name':'average daytime speed of passing traffic', 'units':'km hr-1',                    'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':24, 'description':'Average daytime speed of the passing traffic where measurements are being made (if applicable), in kilometres per hour.'},
    'daily_passing_vehicles':          {'value':[], 'standard_name':'daily passing vehicles',          'long_name':'average daily number of passing vehicles', 'units':'unitless',                   'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':25, 'description':'Average number of vehicles passing daily.'},
    'geodetic_datum':                  {'value':[], 'standard_name':'geodetic datum',                  'long_name':'geodetic datum',                           'units':'unitless',                   'data_type':np.object,  'string_format':'upper_short', 'n_decimals':np.NaN, 'metadata_order':11, 'description':'Name of the geodetic datum used as the reference point for the mapping of latitude/longitude coordinates.'}, 
    'projection':                      {'value':[], 'standard_name':'projection',                      'long_name':'projection',                               'units':'unitless',                   'data_type':np.object,  'string_format':'upper_short', 'n_decimals':np.NaN, 'metadata_order':12, 'description':'Name of the map projection used for the flattening of the elipsoidal Earth onto a 2D plane.'}, 
    'data_level':                      {'value':[], 'standard_name':'data level',                      'long_name':'data level',                               'units':'unitless',                   'data_type':np.object,  'string_format':'upper_short', 'n_decimals':np.NaN, 'metadata_order':14, 'description':'Data level of data reported. This varies with network.'},
    'climatology':                     {'value':[], 'standard_name':'climatology',                     'long_name':'climatology',                              'units':'unitless',                   'data_type':np.object,  'string_format':'upper_short', 'n_decimals':np.NaN, 'metadata_order':13, 'description':'Name of the climatology of which the observations pertain to.'},
    'station_name':                    {'value':[], 'standard_name':'station name',                    'long_name':'station name',                             'units':'unitless',                   'data_type':np.object,  'string_format':'title_short', 'n_decimals':np.NaN, 'metadata_order':6,  'description':'Name of station where the measurement was conducted.'},
    'city':                            {'value':[], 'standard_name':'province',                        'long_name':'province',                                 'units':'unitless',                   'data_type':np.object,  'string_format':'title_short', 'n_decimals':np.NaN, 'metadata_order':7,  'description':'Name of the city the station is located in.'},
    'province':                        {'value':[], 'standard_name':'province',                        'long_name':'province',                                 'units':'unitless',                   'data_type':np.object,  'string_format':'title_short', 'n_decimals':np.NaN, 'metadata_order':8,  'description':'Name of the province the station is located in.'},
    'county':                          {'value':[], 'standard_name':'county',                          'long_name':'county',                                   'units':'unitless',                   'data_type':np.object,  'string_format':'title_short', 'n_decimals':np.NaN, 'metadata_order':9,  'description':'Name of the county the station is located in.'},
    'country':                         {'value':[], 'standard_name':'country',                         'long_name':'country',                                  'units':'unitless',                   'data_type':np.object,  'string_format':'title_short', 'n_decimals':np.NaN, 'metadata_order':10, 'description':'Name of the country the station is located in.'},
    'population':                      {'value':[], 'standard_name':'population',                      'long_name':'population',                               'units':'unitless',                   'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':15, 'description':'Population size of the nearest urban settlement.'},
    'representative_radius':           {'value':[], 'standard_name':'representative_radius',           'long_name':'representative_radius',                    'units':'km',                         'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':27, 'description':'Radius of representativity of the measurements made (i.e. for what distance scale around the sampling point would the measurements be very similar?), given in kilometres.  A quantitative version of the "measurement_scale" classification.'},
    'network':                         {'value':[], 'standard_name':'network',                         'long_name':'data network',                             'units':'unitless',                   'data_type':np.object,  'string_format':'upper_short', 'n_decimals':np.NaN, 'metadata_order':1,  'description':'The name of the network which reports data for the specific station in question.'},
    'associated_networks':             {'value':[], 'standard_name':'other associated networks',       'long_name':'other associated networks',                'units':'unitless',                   'data_type':np.object,  'string_format':'upper_long',  'n_decimals':np.NaN, 'metadata_order':26, 'description':'String pair of associated network name and station reference. Format: network1:station_reference1;network2:station_reference2'},
    
    #NETWORK PROVIDED STANDARDISED CLASSIFICATIONS
    'standardised_network_provided_area_classification':   {'value':[], 'standard_name':'standardised network provided area classification',    'long_name':'standardised network provided area classification',    'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':28, 'description':'Standardised network provided classification, describing type of area a measurement station is situated in.'},                
    'standardised_network_provided_station_classification':{'value':[], 'standard_name':'standardised network provided station classification', 'long_name':'standardised network provided station classification', 'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':29, 'description':'Standardised network provided classification, categorising the type of air measured by a station.'},                
    'standardised_network_provided_main_emission_source':  {'value':[], 'standard_name':'standardised network provided main emission source',   'long_name':'standardised network provided main emission source',   'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':30, 'description':'Standardised network provided classification, describing the main emission source influencing air measured at a station.'},                
    'standardised_network_provided_land_use':              {'value':[], 'standard_name':'standardised network provided land use',               'long_name':'standardised network provided land use type',          'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':31, 'description':'Standardised network provided classification, describing the dominant land use in the area of the reporting station.'},                
    'standardised_network_provided_terrain':               {'value':[], 'standard_name':'standardised network provided terrain',                'long_name':'standardised network provided terrain type',           'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':32, 'description':'Standardised network provided classification, describing the dominant terrain in the area of the reporting station.'},                 
    'standardised_network_provided_measurement_scale':     {'value':[], 'standard_name':'standardised network provided measurement scale',      'long_name':'standardised network provided measurement scale',      'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':33, 'description':'Standardised network provided classification, a denotation of the geographic scope of the air quality measurements made.'},                         
    
    #GLOBALLY GRIDDED CLASSIFICATIONS
    #'ESDAC_Iwahashi_landform_classification':           {'value':[], 'standard_name':'ESDAC Iwahashi landform classification',            'long_name':'ESDAC Iwahashi landform classification',                      'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':34, 'description':'European Soil Data Centre (ESDAC) Iwahashi landform classification. The classification presents relief classes which are classified using an unsupervised nested-means algorithms and a three part geometric signature. Slope gradient, surface texture and local convexity are calculated based on the SRTM30 digital elevation model, within a given window size and classified according to the inherent data set properties. This is a dynamic landform classification method. Native resolution of 0.01 x 0.01 degrees.'},
    #'ESDAC_modal_Iwahashi_landform_classification_5km': {'value':[], 'standard_name':'ESDAC modal Iwahashi landform classification 5km',  'long_name':'ESDAC modal Iwahashi landform classification in 5km radius',  'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':35, 'description':'Modal European Soil Data Centre (ESDAC) Iwahashi landform classification in radius of 5km around station location.'},
    #'ESDAC_modal_Iwahashi_landform_classification_25km':{'value':[], 'standard_name':'ESDAC modal Iwahashi landform classification 25km', 'long_name':'ESDAC modal Iwahashi landform classification in 25km radius', 'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':36, 'description':'Modal European Soil Data Centre (ESDAC) Iwahashi landform classification in radius of 25km around station location.'},
    #'ESDAC_Meybeck_landform_classification':            {'value':[], 'standard_name':'ESDAC Meybeck landform classification',             'long_name':'ESDAC Meybeck landform classification',                       'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':37, 'description':'European Soil Data Centre (ESDAC) Meybeck landform classification. The classification presents relief classes which are calculated based on the relief roughness. Roughness and elevation are classified based on a digital elevation model according to static thresholds, with a given window size. This is a static landform classification method. Native resolution of 0.01 x 0.01 degrees.'},
    #'ESDAC_modal_Meybeck_landform_classification_5km':  {'value':[], 'standard_name':'ESDAC modal Meybeck landform classification 5km',   'long_name':'ESDAC modal Meybeck landform classification in 5km radius',   'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':38, 'description':'Modal European Soil Data Centre (ESDAC) Meybeck landform classification in radius of 5km around station location.'},
    #'ESDAC_modal_Meybeck_landform_classification_25km': {'value':[], 'standard_name':'ESDAC modal Meybeck landform classification 25km',  'long_name':'ESDAC modal Meybeck landform classification in 25km radius',  'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':39, 'description':'Modal European Soil Data Centre (ESDAC) Meybeck landform classification in radius of 25km around station location.'},
    #'Koppen-Geiger_WorldClim_classification':           {'value':[], 'standard_name':'Koppen-Geiger WorldClim classification',            'long_name':'Koppen-Geiger WorldClim classification',                      'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':40, 'description':'Koppen-Geiger WorldClim classification, classifying the five main climate groups, with each group being divided based on seasonal precipitation and temperature patterns. Follows the rules defined in Kriticos et al. (2012) as applied to the 5’ resolution WorldClim global climatology (www.worldclim.org; Version 1.4, release 3; Hijmans et al. 2005), were downloaded from the CliMond set of climate data products (www.climond.org; Kriticos et al. 2012). Native resolution of 0.0833 x 0.0833 degrees.'},
    #'MODIS_MCD12C1_v6_IGBP_land_use':                   {'value':[], 'standard_name':'MODIS MCD12C1 v6 IGBP land use',                    'long_name':'MODIS MCD12C1 v6 IGBP land use',                              'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':41, 'description':'Land use from the Moderate Resolution Imaging Spectroradiometer (MODIS) Land Cover Climate Modeling Grid (CMG) MCD12C1 version 6, using the International Geosphere-Biosphere Programme (IGBP) classification. Native resolution of 0.05 x 0.05 degrees.'},
    #'MODIS_MCD12C1_v6_IGBP_modal_land_use_25km':        {'value':[], 'standard_name':'MODIS MCD12C1 v6 IGBP modal land use 25km',         'long_name':'MODIS MCD12C1 v6 IGBP modal land use in 25km radius',         'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':42, 'description':'Modal land use in radius of 25km around the station location from the Moderate Resolution Imaging Spectroradiometer (MODIS) Land Cover Climate Modeling Grid (CMG) MCD12C1 version 6, using the International Geosphere-Biosphere Programme (IGBP) classification.'},
    #'TEOW_WWF_classification':                          {'value':[], 'standard_name':'TEOW WWF classification',                           'long_name':'TEOW WWF classification',                                     'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':43, 'description':'Terrestrial Ecoregions of the World (TEOW) World Wildlife Foundation (WWF) classification. There are 867 terrestrial ecoregions, classified into 14 different biomes such as forests, grasslands, or deserts. Ecoregions represent the original distribution of distinct assemblages of species and communities. See citation: Olson, D. M., Dinerstein, E., Wikramanayake, E. D., Burgess, N. D., Powell, G. V. N., Underwood, E. C., DAmico, J. A., Itoua, I., Strand, H. E., Morrison, J. C., Loucks, C. J., Allnutt, T. F., Ricketts, T. H., Kura, Y., Lamoreux, J. F., Wettengel, W. W., Hedao, P., Kassem, K. R. 2001. Terrestrial ecoregions of the world: a new map of life on Earth. Bioscience 51(11):933-938.'},
    #'WMO_region':                                       {'value':[], 'standard_name':'WMO region',                                        'long_name':'WMO region code',                                             'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':44, 'description':'World Meteorological Organization (WMO) region of station, as integer: 1 (Africa), 2 (Asia), 3 (South America), 4 (Northern America, Central America and the Caribbean), 5 (South-West Pacific), 6 (Europe), 7 (Antarctica).'},
    #'UMBC_anthrome_classification':                     {'value':[], 'standard_name':'UMBC anthrome classification',                      'long_name':'UMBC anthrome classification',                                'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':45, 'description':'University of Maryland Baltimore County (UMBC) anthrome classification, describing the anthropogenic land use. Native resolution of 0.0833 x 0.0833 degrees.'},
    #'UMBC_modal_anthrome_classification_25km':          {'value':[], 'standard_name':'UMBC modal anthrome classification 25km',           'long_name':'UMBC modal anthrome classification in 25km radius',           'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':46, 'description':'University of Maryland Baltimore County (UMBC) modal anthrome classification in radius of 25km around station location.'},
          
    #GLOBALLY GRIDDED PRODUCTS
    #'EDGAR_v4.3.2_annual_average_BC_emissions':                        {'value':[], 'standard_name':'EDGAR v4.3.2 annual average BC emissions',                         'long_name':'EDGAR v4.3.2 annual average black carbon emissions',                                                    'units':'kg m-2 s-1', 'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':47, 'description':'EDGAR v4.3.2 annual average BC emissions, in kilograms per squared metre per second. Native resolution of 0.1 x 0.1 degrees.'},         
    #'EDGAR_v4.3.2_annual_average_CO_emissions':                        {'value':[], 'standard_name':'EDGAR v4.3.2 annual average CO emissions',                         'long_name':'EDGAR v4.3.2 annual average carbon monoxide emissions',                                                 'units':'kg m-2 s-1', 'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':48, 'description':'EDGAR v4.3.2 annual average CO emissions, in kilograms per squared metre per second. Native resolution of 0.1 x 0.1 degrees.'},         
    #'EDGAR_v4.3.2_annual_average_NH3_emissions':                       {'value':[], 'standard_name':'EDGAR v4.3.2 annual average NH3 emissions',                        'long_name':'EDGAR v4.3.2 annual average ammonia emissions',                                                         'units':'kg m-2 s-1', 'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':49, 'description':'EDGAR v4.3.2 annual average NH3 emissions, in kilograms per squared metre per second. Native resolution of 0.1 x 0.1 degrees.'},         
    #'EDGAR_v4.3.2_annual_average_NMVOC_emissions':                     {'value':[], 'standard_name':'EDGAR v4.3.2 annual average NMVOC emissions',                      'long_name':'EDGAR v4.3.2 annual average non-methane volatile organic compound emissions',                           'units':'kg m-2 s-1', 'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':50, 'description':'EDGAR v4.3.2 annual average NMVOC emissions, in kilograms per squared metre per second. Native resolution of 0.1 x 0.1 degrees.'},         
    #'EDGAR_v4.3.2_annual_average_NOx_emissions':                       {'value':[], 'standard_name':'EDGAR v4.3.2 annual average NOx emissions',                        'long_name':'EDGAR v4.3.2 annual average emissions of nitrogen oxides',                                              'units':'kg m-2 s-1', 'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':51, 'description':'EDGAR v4.3.2 annual average NOx emissions, in kilograms per squared metre per second. Native resolution of 0.1 x 0.1 degrees.'},         
    #'EDGAR_v4.3.2_annual_average_OC_emissions':                        {'value':[], 'standard_name':'EDGAR v4.3.2 annual average OC emissions',                         'long_name':'EDGAR v4.3.2 annual average organic carbon emissions',                                                  'units':'kg m-2 s-1', 'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':52, 'description':'EDGAR v4.3.2 annual average OC emissions, in kilograms per squared metre per second. Native resolution of 0.1 x 0.1 degrees.'},         
    #'EDGAR_v4.3.2_annual_average_PM10_emissions':                      {'value':[], 'standard_name':'EDGAR v4.3.2 annual average PM10 emissions',                       'long_name':'EDGAR v4.3.2 annual average PM10 emissions',                                                            'units':'kg m-2 s-1', 'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':53, 'description':'EDGAR v4.3.2 annual average PM10 emissions, in kilograms per squared metre per second. Native resolution of 0.1 x 0.1 degrees.'},         
    #'EDGAR_v4.3.2_annual_average_biogenic_PM2.5_emissions':            {'value':[], 'standard_name':'EDGAR v4.3.2 annual average biogenic PM2.5 emissions',             'long_name':'EDGAR v4.3.2 annual average biogenic PM2.5 emissions',                                                  'units':'kg m-2 s-1', 'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':54, 'description':'EDGAR v4.3.2 annual average biogenic PM2.5 emissions, in kilograms per squared metre per second. Native resolution of 0.1 x 0.1 degrees.'},         
    #'EDGAR_v4.3.2_annual_average_fossilfuel_PM2.5_emissions':          {'value':[], 'standard_name':'EDGAR v4.3.2 annual average fossil fuel PM2.5 emissions',          'long_name':'EDGAR v4.3.2 annual average fossil fuel PM2.5 emissions',                                               'units':'kg m-2 s-1', 'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':55, 'description':'EDGAR v4.3.2 annual average fossil fuel PM2.5 emissions, in kilograms per squared metre per second. Native resolution of 0.1 x 0.1 degrees.'},         
    #'EDGAR_v4.3.2_annual_average_SO2_emissions':                       {'value':[], 'standard_name':'EDGAR v4.3.2 annual average SO2 emissions',                        'long_name':'EDGAR v4.3.2 annual average sulphur dioxide emissions',                                                 'units':'kg m-2 s-1', 'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':56, 'description':'EDGAR v4.3.2 annual average SO2 emissions, in kilograms per squared metre per second. Native resolution of 0.1 x 0.1 degrees.'},         
    #'ETOPO1_altitude':                                                 {'value':[], 'standard_name':'ETOPO1 altitude',                                                  'long_name':'ETOPO1 altitude, relative to sea level datum',                                                          'units':'m',          'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':57, 'description':'Altitude from ETOPO1 digital elevation model, relative to sea level datum, in metres. Native resolution of 0.0166 x 0.0166 degrees. A correction for coastal sites is made: if the derived altitude is <= -5 m, the maximum altitude of the neighboring grid boxes will be used instead. If all neighboring grid boxes have altitudes <= -5 m, the original value will be retained.'},         
    #'ETOPO1_max_altitude_difference_5km':                              {'value':[], 'standard_name':'ETOPO1 max altitude difference 5km',                               'long_name':'ETOPO1 maximum altitude difference between the ETOPO1_altitude and all ETOPO1 altitudes in 5km radius', 'units':'m',          'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':58, 'description':'Altitude difference between the ETOPO1_altitude, and the minimum ETOP1 altitude in a radius of 5 km around the station location, in metres. A correction for coastal sites is made: if the derived altitude is <= -5 m, the maximum altitude of the neighboring grid boxes will be used instead. If all neighboring grid boxes have altitudes <= -5 m, the original value will be retained.'},         
    #'GPW_population_density':                                          {'value':[], 'standard_name':'GPW population density',                                           'long_name':'GPW population density',                                                                                'units':'xx km–2',    'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':59, 'description':'Gridded Population of the World (GPW), population density, in populus per squared kilometre, from either version 3 and 4 of the provided gridded datasets, dependent on the data year: v3 (1990-2000), v4 (2000-2015). Native resolution of 0.0416 x 0.0416 degrees.'},         
    #'GPW_average_population_density_5km':                              {'value':[], 'standard_name':'GPW average population density 5km',                               'long_name':'GPW average population density in 5km radius',                                                          'units':'xx km–2',    'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':60, 'description':'Gridded Population of the World (GPW), average population density in a radius of 5 km around the station location.'},         
    #'GPW_average_population_density_25km':                             {'value':[], 'standard_name':'GPW average population density 25km',                              'long_name':'GPW average population density in 25km radius',                                                         'units':'xx km–2',    'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':61, 'description':'Gridded Population of the World (GPW), average population density in a radius of 25 km around the station location.'},         
    #'GPW_max_population_density_5km':                                  {'value':[], 'standard_name':'GPW max population density 5km',                                   'long_name':'GPW average population density in 5km radius',                                                          'units':'xx km–2',    'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':62, 'description':'Gridded Population of the World (GPW), maximum population density in a radius of 5 km around the station location.'},         
    #'GPW_max_population_density_25km':                                 {'value':[], 'standard_name':'GPW max population density 25km',                                  'long_name':'GPW average population density in 25km radius',                                                         'units':'xx km–2',    'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':63, 'description':'Gridded Population of the World (GPW), maximum population density in a radius of 25 km around the station location.'},         
    #'NOAA-DMSP-OLS_v4_nighttime_stable_lights':                        {'value':[], 'standard_name':'NOAA-DMSP-OLS v4 nighttime stable lights',                         'long_name':'NOAA DMSP-OLS version 4 nighttime stable lights',                                                       'units':'unitless',   'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':64, 'description':'National Oceanic and Atmospheric Administration (NOAA), Defense Meteorological Satellite Program - Operational Linescane System (DMSP-OLS) version 4 nighttime stable lights. Native resolution of 0.0083 x 0.0083 degrees. The values represent a brightness index ranging from 0 to 63. The sensor saturates at a value of 63.'},         
    #'NOAA-DMSP-OLS_v4_average_nighttime_stable_lights_5km':            {'value':[], 'standard_name':'NOAA-DMSP-OLS v4 average nighttime stable lights 5km',             'long_name':'NOAA DMSP-OLS version 4 average nighttime stable lights in 5km radius',                                 'units':'unitless',   'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':65, 'description':'National Oceanic and Atmospheric Administration (NOAA), Defense Meteorological Satellite Program - Operational Linescane System (DMSP-OLS) version 4 average nighttime stable lights in 5km radius of measurement station. The values represent a brightness index ranging from 0 to 63. The sensor saturates at a value of 63.'},         
    #'NOAA-DMSP-OLS_v4_average_nighttime_stable_lights_25km':           {'value':[], 'standard_name':'NOAA-DMSP-OLS v4 average nighttime stable lights 25km',            'long_name':'NOAA DMSP-OLS version 4 average nighttime stable lights in 25km radius',                                'units':'unitless',   'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':66, 'description':'National Oceanic and Atmospheric Administration (NOAA), Defense Meteorological Satellite Program - Operational Linescane System (DMSP-OLS) version 4 average nighttime stable lights in 25km radius of measurement station. The values represent a brightness index ranging from 0 to 63. The sensor saturates at a value of 63.'},         
    #'NOAA-DMSP-OLS_v4_max_nighttime_stable_lights_5km':                {'value':[], 'standard_name':'NOAA-DMSP-OLS v4 max nighttime stable lights 5km',                 'long_name':'NOAA DMSP-OLS version 4 maximum nighttime stable lights in 5km radius',                                 'units':'unitless',   'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':67, 'description':'National Oceanic and Atmospheric Administration (NOAA), Defense Meteorological Satellite Program - Operational Linescane System (DMSP-OLS) version 4 maximum nighttime stable lights in 5km radius of measurement station. The values represent a brightness index ranging from 0 to 63. The sensor saturates at a value of 63.'},         
    #'NOAA-DMSP-OLS_v4_max_nighttime_stable_lights_25km':               {'value':[], 'standard_name':'NOAA-DMSP-OLS v4 max nighttime stable lights 25km',                'long_name':'NOAA DMSP-OLS version 4 maximum nighttime stable lights in 25km radius',                                'units':'unitless',   'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':68, 'description':'National Oceanic and Atmospheric Administration (NOAA), Defense Meteorological Satellite Program - Operational Linescane System (DMSP-OLS) version 4 maximum nighttime stable lights in 25km radius of measurement station. The values represent a brightness index ranging from 0 to 63. The sensor saturates at a value of 63.'},         
    #'OMI_level3_tropospheric_column_annual_average_NO2':               {'value':[], 'standard_name':'OMI level3 tropospheric column annual average NO2',                'long_name':'OMI level3 tropospheric column annual average nitrogen dioxide',                                        'units':'xx m-2',     'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':69, 'description':'AURA Ozone monitoring instrument (OMI) level3 tropospheric column annual average NO2, in molecules per squared metres. Native resolution of 0.25 x 0.25 degrees.'},         
    #'OMI_level3_tropospheric_column_cloud_screened_annual_average_NO2':{'value':[], 'standard_name':'OMI level3 tropospheric column cloud screened annual average NO2', 'long_name':'OMI level3 tropospheric column cloud screened annual average nitrogen dioxide',                         'units':'xx m-2',     'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':70, 'description':'AURA Ozone monitoring instrument (OMI) level3 tropospheric column cloud screened (where cloud fraction is less than 30 percent) annual average NO2, in molecules per squared metres. Native resolution of 0.25 x 0.25 degrees.'},         
    #'GSFC_coastline_proximity':                                        {'value':[], 'standard_name':'GSFC coastline proximity',                                         'long_name':'GSFC proximity to the coastline',                                                                       'units':'km',         'data_type':np.float32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':71, 'description':'Proximity to the coastline provided by the NASA Goddard Space Flight Center (GSFC) Ocean Color Group, in kilometres, produced using the Generic Mapping Tools package. Native resolution of 0.01 x 0.01 degrees. Negative distances represent locations over land (including land-locked bodies of water), while positive distances represent the ocean. There is an uncertainty of up to 1 km in the computed distance at any given point.'},         

    #MEASUREMENT INFORMATION
    'primary_sampling_instrument_name':                        {'value':[], 'standard_name':'primary sampling instrument name',                         'long_name':'standardised primary sampling instrument name',                         'units':'unitless',                          'data_type':np.object,  'string_format':'short',       'n_decimals':np.NaN, 'metadata_order':72,     'description':'Standardised name of the primary sampling instrument (if no specific instrument is used, or known, this is the standardised primary sampling type).'},  
    'primary_sampling_type':                                   {'value':[], 'standard_name':'primary sampling type',                                    'long_name':'standardised primary sampling type',                                    'units':'unitless',                          'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':73,     'description':'Standardised primary sampling type.'},
    'primary_sampling_instrument_documented_flow_rate':        {'value':[], 'standard_name':'primary sampling instrument documented flow rate',         'long_name':'primary sampling instrument documented sampling flow rate',             'units':'l min-1',                           'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Volume (litres) of fluid which passes to the primary sampling instrument, per unit time (minutes), as given in instrumental manual/documentation. Can be a range: e.g. 1.0-3.0.'},  
    'primary_sampling_instrument_reported_flow_rate':          {'value':[], 'standard_name':'primary sampling instrument reported flow rate',           'long_name':'primary sampling instrument reported sampling flow rate',               'units':'l min-1',                           'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Volume (litres) of fluid which passes to the primary sampling instrument, per unit time (minutes), as given in metadata. Can be a range: e.g. 1.0-3.0.'},
    'primary_sampling_process_details':                        {'value':[], 'standard_name':'primary sampling process details',                         'long_name':'primary sampling process details',                                      'units':'unitless',                          'data_type':np.object,  'string_format':'lower_long',  'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Miscellaneous details regarding assumptions made in the standardisation of the primary sampling instrument/type.'},
    'primary_sampling_instrument_manual':                      {'value':[], 'standard_name':'primary sampling instrument manual',                       'long_name':'primary sampling instrument manual',                                    'units':'unitless',                          'data_type':np.object,  'string_format':'short',       'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Path to the location in the esarchive of the manual for the specific primary sampling instrument.'},
    'primary_sampling_further_details':                        {'value':[], 'standard_name':'primary sampling further details',                         'long_name':'primary sampling further details',                                      'units':'unitless',                          'data_type':np.object,  'string_format':'lower_long',  'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Further associated details regarding the specifics of the primary sampling instrument/type.'},
    'sample_preparation_methodology_names':                    {'value':[], 'standard_name':'sample preparation methodology names',                     'long_name':'standardised names of the sample preparation methodologies',            'units':'unitless',                          'data_type':np.object,  'string_format':'short',       'n_decimals':np.NaN, 'metadata_order':74,     'description':'Standardised names of all the sample preparation methodologies utilised in the measurement process. Mutiple names are separated by ";" (if no specific sample preparation method names are known/given, these are the standardised sample preparation method types).'},               
    'sample_preparation_methodology_types':                    {'value':[], 'standard_name':'sample preparation methodology types',                     'long_name':'standardised types of the sample preparation methodologies',            'units':'unitless',                          'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':75,     'description':'Standardised types of all the sample preparation methodologies utilised in the measurement process. Mutiple types are separated by ";".'},               
    'sample_preparation_process_details':                      {'value':[], 'standard_name':'sample preparation process details',                       'long_name':'sample preparation process details',                                    'units':'unitless',                          'data_type':np.object,  'string_format':'lower_long',  'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Miscellaneous details regarding assumptions made in the standardisation of the sample preparation methodologies. Multiple details regarding different methodologies are are separated by ";".'},
    'sample_preparation_further_details':                      {'value':[], 'standard_name':'sample preparation further details',                       'long_name':'sample preparation further details',                                    'units':'unitless',                          'data_type':np.object,  'string_format':'lower_long',  'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Further associated details regarding the specifics of the sample preparation methodologies. Multiple details regarding different methodologies are are separated by ";".'},
    'measuring_instrument_name':                               {'value':[], 'standard_name':'measuring instrument name',                                'long_name':'standardised measuring instrument name',                                'units':'unitless',                          'data_type':np.object,  'string_format':'short',       'n_decimals':np.NaN, 'metadata_order':76,     'description':'Standardised name of the measuring instrument (if no specific instrument is used, or known, this is the standardised measurement methodology).'},  
    'measurement_methodology':                                 {'value':[], 'standard_name':'measurement methodology',                                  'long_name':'standardised measurement methodology',                                  'units':'unitless',                          'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':77,     'description':'Standardised name of the measurement methodology.'},               
    'measuring_instrument_sampling_type':                      {'value':[], 'standard_name':'measuring instrument sampling type',                       'long_name':'standardised sampling type of the measuring instrument',                'units':'unitless',                          'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':78,     'description':'Standardised name of the measuring instrument sampling type.'},     
    'measuring_instrument_documented_flow_rate':               {'value':[], 'standard_name':'measuring instrument documented flow rate',                'long_name':'measuring instrument documented flow rate',                             'units':'l min-1',                           'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Volume (litres) of fluid which passes to the measuring instrument, per unit time (minutes), as given in instrumental manual/documentation. Can be a range: e.g. 1.0-3.0.'}, 
    'measuring_instrument_reported_flow_rate':                 {'value':[], 'standard_name':'measuring instrument reported flow rate',                  'long_name':'measuring instrument reported flow rate',                               'units':'l min-1',                           'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Volume (litres) of fluid which passes to the measuring instrument, per unit time (minutes), as given in metadata. Can be a range: e.g. 1.0-3.0.'},  
    'measuring_instrument_process_details':                    {'value':[], 'standard_name':'measuring instrument process details',                     'long_name':'primary sampling process details',                                      'units':'unitless',                          'data_type':np.object,  'string_format':'lower_long',  'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Miscellaneous details regarding assumptions made in the standardisation of the measuring instrument.'},
    'measuring_instrument_manual_name':                        {'value':[], 'standard_name':'measuring instrument manual',                              'long_name':'measuring instrument manual',                                           'units':'unitless',                          'data_type':np.object,  'string_format':'short',       'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Path to the location in the esarchive of the manual for the specific measuring instrument.'},
    'measuring_instrument_further_details':                    {'value':[], 'standard_name':'measuring instrument further details',                     'long_name':'measuring instrument further details',                                  'units':'unitless',                          'data_type':np.object,  'string_format':'lower_long',  'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Further associated details regarding the specifics of the measuring instrument.'},
    'measuring_instrument_reported_units':                     {'value':[], 'standard_name':'measuring instrument reported units',                      'long_name':'measuring instrument reported measurement units',                       'units':'unitless',                          'data_type':np.object,  'string_format':'short',       'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Units that the measured parameter are natively reported in.'}, 
    'measuring_instrument_reported_lower_limit_of_detection':  {'value':[], 'standard_name':'measuring instrument reported lower limit of detection',   'long_name':'measuring instrument reported lower limit of detection',                'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Lower limit of detection of measurement methodology, as given in metadata.'},
    'measuring_instrument_documented_lower_limit_of_detection':{'value':[], 'standard_name':'measuring instrument documented lower limit of detection', 'long_name':'measuring instrument documented lower limit of detection',              'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Lower limit of detection of measurement methodology, as given in the instrumental manual/documentation.'}, 
    'measuring_instrument_reported_upper_limit_of_detection':  {'value':[], 'standard_name':'measuring instrument reported upper limit of detection',   'long_name':'measuring instrument reported upper limit of detection',                'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Upper limit of detection of measurement methodology, as given in metadata.'},
    'measuring_instrument_documented_upper_limit_of_detection':{'value':[], 'standard_name':'measuring instrument documented upper limit of detection', 'long_name':'measuring instrument documented upper limit of detection',              'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Upper limit of detection of measurement methodology, as given in the instrumental manual/documentation.'}, 
    'measuring_instrument_reported_uncertainty':               {'value':[], 'standard_name':'measuring instrument reported measurement uncertainty',    'long_name':'measuring instrument reported measurement uncertainty',                 'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Measurement uncertainty (±), as given in metadata. In principal this refers to the inherent uncertainty on every measurement as a function of the quadratic addition of the accuracy and precision metrics (at the same confidence interval), but is often reported incosistently e.g. being solely determined from random errors (i.e. just the measuremental precision). It can be given in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%); or a percentage quantity after a fixed limit (i.e. 0.5%>=50).'},
    'measuring_instrument_documented_uncertainty':             {'value':[], 'standard_name':'measuring instrument documented measurement uncertainty',  'long_name':'measuring instrument documented measurement uncertainty',               'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Measurement uncertainty (±), as given in the instrumental manual/documentation. In principal this refers to the inherent uncertainty on every measurement as a function of the quadratic addition of the accuracy and precision metrics (at the same confidence interval), but is often reported incosistently e.g. being solely determined from random errors (i.e. just the measuremental precision). This can be given in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%); or a percentage quantity after a fixed limit (i.e. 0.5%>=50).'},
    'measuring_instrument_reported_accuracy':                  {'value':[], 'standard_name':'measuring instrument reported measurement accuracy',       'long_name':'measuring instrument reported measurement accuracy',                    'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Measurement accuracy (±), as given in metadata. Accuracy describes the difference between the measurement and the actual value of the part that is measured. It includes: Bias (a measure of the difference between the true value and the observed value of a part -- If the “true” value is unknown, it can be calculated by averaging several measurements with the most accurate measuring equipment available) and Linearity (a measure of how the size of the part affects the bias of a measurement system -- It is the difference in the observed bias values through the expected range of measurement). This can be given as in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%); or a percentage quantity after a fixed limit (i.e. 0.5%>=50).'}, 
    'measuring_instrument_documented_accuracy':                {'value':[], 'standard_name':'measuring instrument documented measurement accuracy',     'long_name':'measuring instrument documented measurement accuracy',                  'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Measurement accuracy (±), as given in the instrumental manual/documentation. Accuracy describes the difference between the measurement and the actual value of the part that is measured. It includes: Bias (a measure of the difference between the true value and the observed value of a part -- If the “true” value is unknown, it can be calculated by averaging several measurements with the most accurate measuring equipment available) and Linearity (a measure of how the size of the part affects the bias of a measurement system -- It is the difference in the observed bias values through the expected range of measurement). This can be given as in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%); or a percentage quantity after a fixed limit (i.e. 0.5%>=50).'}, 
    'measuring_instrument_reported_precision':                 {'value':[], 'standard_name':'measuring instrument reported measurement precision',      'long_name':'measuring instrument reported measurement precision',                   'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Measurement precision (±), as given in metadata. Precision describes the variation you see when you measure the same part repeatedly with the same device. It includes the following two types of variation: Repeatability (variation due to the measuring device -- it is the variation observed when the same operator measures the same part repeatedly with the same device) and Reproducibility (variation due to the operators and the interaction between operator and part -- It is the variation of the bias observed when different operators measure the same parts using the same device). This can be given as in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%); or a percentage quantity after a fixed limit (i.e. 0.5%>=50).'}, 
    'measuring_instrument_documented_precision':               {'value':[], 'standard_name':'measuring instrument documented measurement precision',    'long_name':'measuring instrument documented measurement precision',                 'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Measurement precision (±), as given in instrumental manual/documentation. Precision describes the variation you see when you measure the same part repeatedly with the same device. It includes the following two types of variation: Repeatability (variation due to the measuring device -- it is the variation observed when the same operator measures the same part repeatedly with the same device) and Reproducibility (variation due to the operators and the interaction between operator and part -- It is the variation of the bias observed when different operators measure the same parts using the same device). This can be given as in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%); or a percentage quantity after a fixed limit (i.e. 0.5%>=50).'}, 
    'measuring_instrument_reported_zero_drift':                {'value':[], 'standard_name':'measuring instrument reported zero drift',                 'long_name':'measuring instrument reported zero drift',                              'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Zero drift of measuring instrument per unit of time, as given in metadata. Zero drift (or baseline drift) refers to the shifting of the whole calibration by the same amount caused by slippage or due to undue warming up of the electronic circuits. It is reported as the maximum possible drift per unit of time in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%/day); or a percentage quantity after a fixed limit (i.e. 0.5%>=50/day).'}, 
    'measuring_instrument_documented_zero_drift':              {'value':[], 'standard_name':'measuring instrument documented zero drift',               'long_name':'measuring instrument documented zero drift',                            'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Zero drift of measuring instrument per unit of time, as given in instrumental manual/documentation. Zero drift (or baseline drift) refers to the shifting of the whole calibration by the same amount caused by slippage or due to undue warming up of the electronic circuits. It is reported as the maximum possible drift per unit of time in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%/day); or a percentage quantity after a fixed limit (i.e. 0.5%>=50/day).'}, 
    'measuring_instrument_reported_span_drift':                {'value':[], 'standard_name':'measuring instrument reported span drift',                 'long_name':'measuring instrument reported span drift',                              'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Span drift of measuring instrument per unit of time, as given in metadata. Span drift (or sensitivity drift) refers to when there is proportional change in the indication of an instrument all along the upward scale, hence higher calibrations end up being shifted more than lower calibrations. It is reported as the maximum possible drift per unit of time in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%/day); or a percentage quantity after a fixed limit (i.e. 0.5%>=50/day).'}, 
    'measuring_instrument_documented_span_drift':              {'value':[], 'standard_name':'measuring instrument documented span drift',               'long_name':'measuring instrument documented span drift',                            'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Span drift of measuring instrument per unit of time, as given in instrumental manual/documentation. Span drift (or sensitivity drift) refers to when there is proportional change in the indication of an instrument all along the upward scale, hence higher calibrations end up being shifted more than lower calibrations. It is reported as the maximum possible drift per unit of time in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%/day); or a percentage quantity after a fixed limit (i.e. 0.5%>=50/day).'}, 
    'measuring_instrument_reported_zonal_drift':               {'value':[], 'standard_name':'measuring instrument reported zonal drift',                'long_name':'measuring instrument reported zonal drift',                             'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Zonal drift of measuring instrument per unit of time, as given in metadata. Zonal drift refers to when drift occurs only over a portion of the full scale or span of an instrument, while the remaining portion of the scale remains unaffected. It is reported as the maximum possible drift per unit of time in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%/day); or a percentage quantity after a fixed limit (i.e. 0.5%>=50/day).'}, 
    'measuring_instrument_documented_zonal_drift':             {'value':[], 'standard_name':'measuring instrument documented zonal drift',              'long_name':'measuring instrument documented zonal drift',                           'units':parameter_details['standard_units'], 'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Zonal drift of measuring instrument per unit of time, as given in instrumental manual/documentation. Zonal drift refers to when drift occurs only over a portion of the full scale or span of an instrument, while the remaining portion of the scale remains unaffected. It is reported as the maximum possible drift per unit of time in absolute terms; as a percentage; the greater of either an absolute value or percentage (i.e. 25.0/0.5%/day); or a percentage quantity after a fixed limit (i.e. 0.5%>=50/day).'}, 
    'measuring_instrument_reported_measurement_resolution':    {'value':[], 'standard_name':'measuring instrument reported measurement resolution',     'long_name':'measuring instrument reported measurement resolution',                  'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Measurement resolution, as given in metadata. The measurement resolution is defined as the smallest change or increment in the measured quantity that the instrument can detect. However it is often reported inconsistently, often being simply the number of digits an instrument can display, which does not relate to the actual physical resolution of the instrument.'}, 
    'measuring_instrument_documented_measurement_resolution':  {'value':[], 'standard_name':'measuring instrument documented measurement resolution',   'long_name':'measuring instrument documented measurement resolution',                'units':parameter_details['standard_units'], 'data_type':np.float32, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Measurement resolution, as given in instrumental manual/documentation. The measurement resolution is defined as the smallest change or increment in the measured quantity that the instrument can detect. However it is often reported inconsistently, often being simply the number of digits an instrument can display, which does not relate to the actual physical resolution of the instrument.'}, 
    'measuring_instrument_reported_absorption_cross_section':  {'value':[], 'standard_name':'measuring instrument reported absorption cross section',   'long_name':'measuring instrument reported absorption cross section',                'units':'cm2',                               'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Assumed molecule cross-section for parameter being measured (in cm2/molecule), as given in metadata. This field is only used for parameters being measured using optical methods, where a molecule cross section is assumed for processing the measurement values. Physically it is the effective area of the molecule that photon needs to traverse in order to be absorbed. The larger the absorption cross section, the easier it is to photoexcite the molecule. Can be a range: e.g. 1e-15-1.5e-15.'}, 
    'measuring_instrument_documented_absorption_cross_section':{'value':[], 'standard_name':'measuring instrument documented absorption cross section', 'long_name':'measuring instrument documented absorption cross section',              'units':'cm2',                               'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Assumed molecule cross-section for parameter being measured (in cm2/molecule), as given in instrumental manual/documentation. This field is only used for parameters being measured using optical methods, where a molecule cross section is assumed for processing the measurement values. Physically it is the effective area of the molecule that photon needs to traverse in order to be absorbed. The larger the absorption cross section, the easier it is to photoexcite the molecule. Can be a range: e.g. 1e-15-1.5e-15.'}, 
    'measuring_instrument_inlet_information':                  {'value':[], 'standard_name':'measuring instrument inlet information',                   'long_name':'measuring instrument measurement inlet information',                    'units':'unitless',                          'data_type':np.object,  'string_format':'lower_long',  'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Description of sampling inlet of the measuring instrument.'}, 
    'measuring_instrument_volume_standard_temperature':        {'value':[], 'standard_name':'measuring instrument volume standard temperature',         'long_name':'measuring instrument volume standard temperature',                      'units':'K',                                 'data_type':np.float64, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':79,     'description':'The temperature (in Kelvin) which has been used for normalising gas volume concentrations. This temperature refers to the bench temperature of the measuring instrument at time of measurement. Normalisation is typically done in-instrument to a fixed standard temperature and pressure. If this is not reported by the data provider, then this is assumed to be the known network standard temperature.'},  
    'measuring_instrument_volume_standard_pressure':           {'value':[], 'standard_name':'measuring instrument volume standard pressure',            'long_name':'measuring instrument volume standard pressure ',                        'units':'hPa',                               'data_type':np.float64, 'string_format':np.NaN,        'n_decimals':np.NaN, 'metadata_order':80,     'description':'The pressure (in hPa) which has been used for normalising gas volume concentrations. This pressure refers to the internal pressure of the measuring instrument at time of measurement. Normalisation is typically done in-instrument to a fixed standard temperature and pressure. If this is not reported by the data provider, then this is assumed to be the known network standard pressure.'},  
    'measuring_instrument_calibration_scale':                  {'value':[], 'standard_name':'measuring instrument calibration scale',                   'long_name':'measuring instrument calibration scale name',                           'units':'unitless',                          'data_type':np.object,  'string_format':'upper_short', 'n_decimals':np.NaN, 'metadata_order':81,     'description':'Name of calibration scale used for the calibration of the measuring instrument'},
    #'measuring_instrument_europe_reference_equivalence_status':{'value':[], 'standard_name':'measuring instrument Europe reference equivalence status', 'long_name':'standardised measuring instrument Europe reference equivalence status', 'units':'unitless',                          'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Standardised status that shows if the the utilised measuring instrument has been proven to produce equivalent measurements as the reference measurement methodology as defined by the European Parliament. The reference methods are defined in the European directives here: https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:32008L0050&from=en and here: https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:32004L0107&from=EN . This can be 1 of 5 standardised options (or NaN if measurement method unknown): reference (the methodology used is excatly that of the reference), equivalent (the methodology has been proven to be equivalent to the reference), not_equivalent (the methodology has not been proven, or attempted, to be equivalent to the reference), no_reference (there exists no reference method for the parameter measured), testing (the methodology is currently been tested to see if it is equivalent to the reference).'},
    #'measuring_instrument_us_reference_equivalence_status':    {'value':[], 'standard_name':'measuring instrument US reference equivalence status',     'long_name':'standardised measuring instrument US reference equivalence status',     'units':'unitless',                          'data_type':np.object,  'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Standardised status that shows if the the utilised measuring instrument has been proven to produce equivalent measurements as the reference measurement methodology as defined by the United States government. The list of designated reference and equilalent methods is given here: https://www.epa.gov/sites/production/files/2018-01/documents/amtic_list_dec_2017_update_1-20-2018_0.pdf .This can be 1 of 7 standardised options (or NaN if measurement method unknown): reference (the methodology used is excatly that of the reference), equivalent (the methodology has been proven to be equivalent to the reference), not_equivalent (the methodology has not been proven, or attempted, to be equivalent to the reference), no_reference (there exists no reference method for the parameter measured), testing (the methodology is currently been tested to see if it is equivalent to the reference), assume_equivalent (no information is found about the specific instrument regarding its reference equivalence status, common sense suggests the method it uses is reference equivalent), assume_not_equivalent (no information is found about the specific instrument regarding its reference equivalence status, common sense suggests the method it uses is not reference equivalent), assume_reference (no information is found about the specific instrument regarding its reference equivalence status, common sense suggests the method it uses is equal to the reference method'},
    
    #CONTACT INFORMATION
    'principal_investigator_name':         {'value':[], 'standard_name':'principal investigator name',          'long_name':'principal investigator name',          'units':'unitless', 'data_type':np.object, 'string_format':'title_short', 'n_decimals':np.NaN, 'metadata_order':82, 'description':'Full name of the principal scientific investigator for the specific reported data.'}, 
    'principal_investigator_institution':  {'value':[], 'standard_name':'principal investigator institution',   'long_name':'principal investigator institution',   'units':'unitless', 'data_type':np.object, 'string_format':'title_short', 'n_decimals':np.NaN, 'metadata_order':83, 'description':'Institution of the principal scientific investigator for the specific reported data.'}, 
    'principal_investigator_email_address':{'value':[], 'standard_name':'principal investigator email address', 'long_name':'principal investigator email address', 'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':84, 'description':'Email address of the principal scientific investigator for the specific reported data.'}, 
    'contact_name':                        {'value':[], 'standard_name':'contact name',                         'long_name':'contact name',                         'units':'unitless', 'data_type':np.object, 'string_format':'title_short', 'n_decimals':np.NaN, 'metadata_order':85, 'description':'Full name of the principal data contact for the specific reported data.'}, 
    'contact_institution':                 {'value':[], 'standard_name':'contact institution',                  'long_name':'contact institution',                  'units':'unitless', 'data_type':np.object, 'string_format':'title_short', 'n_decimals':np.NaN, 'metadata_order':86, 'description':'Institution of the principal data contact for the specific reported data.'}, 
    'contact_email_address':               {'value':[], 'standard_name':'contact email address',                'long_name':'contact email address',                'units':'unitless', 'data_type':np.object, 'string_format':'lower_short', 'n_decimals':np.NaN, 'metadata_order':87, 'description':'Email address of the principal data contact for the specific reported data.'}, 
    
    #TIMESTAMPS
    'meta_update_stamp':  {'value':[], 'standard_name':'metdata update timestamp', 'long_name':'metdata update timestamp', 'units':'unitless', 'data_type':np.uint32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Time stamp of metadata updates in integer minutes from 0001-01-01 00:00 UTC.'}, 
    'data_download_stamp':{'value':[], 'standard_name':'data download timestamp',  'long_name':'data download timestamp',  'units':'unitless', 'data_type':np.uint32, 'string_format':np.NaN, 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Time stamp of date/time of data download in integer minutes from 0001-01-01 00:00 UTC.'}, 
    
    #FURTHER DETAIL
    'network_sampling_details':     {'value':[], 'standard_name':'network sampling details',      'long_name':'network sampling details',      'units':'unitless', 'data_type':np.object, 'string_format':'lower_long', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Extra details provided by the reporting network about the sampling methods employed.'},
    'network_uncertainty_details':  {'value':[], 'standard_name':'network uncertainty details',   'long_name':'network uncertainty details',   'units':'unitless', 'data_type':np.object, 'string_format':'lower_long', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Extra details provided by the reporting network about the uncertainties involved with the measurement methods employed.'},
    'network_maintenance_details':  {'value':[], 'standard_name':'network maintenance details',   'long_name':'network maintenance details',   'units':'unitless', 'data_type':np.object, 'string_format':'lower_long', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Extra details provided by the reporting network about the operational maintenance done at the station.'},
    'network_qa_details':           {'value':[], 'standard_name':'network qa details',            'long_name':'network qa details',            'units':'unitless', 'data_type':np.object, 'string_format':'lower_long', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Extra details provided by the reporting network about the in-network quality assurance of measurements.'},
    'network_miscellaneous_details':{'value':[], 'standard_name':'network miscellaneous details', 'long_name':'network miscellaneous details', 'units':'unitless', 'data_type':np.object, 'string_format':'lower_long', 'n_decimals':np.NaN, 'metadata_order':np.NaN, 'description':'Extra miscellanous details provided by the reporting network.'}}

    return metadata

###------------------------------------------------------------------------------------###
#takes multiple types of reported site classifications from multiple networks and produces standardised classifications across all networks 

def mapping_network_classifications(native_classifications):

    #iterate through values in native_classifications dictionary and make sure all values are lower-cased and all white spaces are stripped.
    for key in native_classifications.keys():
        native_classifications[key] = native_classifications[key].replace(" ", "").lower()

#STANDARD CLASSIFICATION DEFINITIONS:
#----------------------------------------------------

#AREA_CLASSIFICATION: Describes type of area a measurement station is situated in
            
#rural: All areas, that do not fulfil the criteria for an urban area are defined as "rural" 
        #3 subdivisions to indicate the distance to the nearest built-up urban area
#------near_city: area within 10 km from the border of an urban or suburban area.
#------regional: 10-50 km from major sources/source areas.
#------remote: > 50 km from major sources/source areas.


#urban: All areas with some level of urban influence are defined as "urban"
        #2 subdivisions to separate between urban centres and suburban areas:
#------centre: Continuously built-up urban area meaning complete (or at least highly predominant) building-up of the street front side by buildings with at least two floors or large detached buildings with at least two floors.
               #With the exception of city parks, the built-up area is not mixed with non-urbanised areas.     
#------suburban: Largely built-up urban area. ‘Largely built-up’ means contiguous settlement of detached buildings of any size with a building density less than for ‘continuously built-up’ area.
                #The built-up area is mixed with non-urbanised areas (e.g. agricultural, lakes, woods).
                #It must also be noted that ‘suburban’ as defined here has a different meaning than in every day English i.e. ‘an outlying part of a city or town’ suggesting that a suburban area is always associated to an urban area.
                #A suburban area can be suburban on its own without any urban part.
            

#----------------------------------------------------
#STATION_CLASSIFICATION: Categorises the dominant type of air measured by a station

#background : Located such that its pollution levels are representative of the average exposure of the general population within the type of area under assessment. The pollution level should not be dominated by a single source type (e.g. traffic), unless that source type is typical within the area
             #under assessment. The station should usually be representative of a wider area of at least several square kilometers.

#point_source: Measurements influenced by a major stationary emissions source (i.e power plant),
              #or influenced by traffic, off-road vehicles and engines, rail, marine, or aviation sources.
              #Subdivisions of 'industrial' & 'traffic' given to allow for greater speciation given by AIRBASE & EIONET)
#--------industrial: Located in close proximity to single industrial sources or industrial areas, in a location that should represent the highest concentrations to which the population within the zone are exposed to. 
                    #A wide range of industrial sources can be considered here, including: a) thermal power generation, b) district heating plants, c) refineries, d) waste incineration/treatment plants, dump sites, e) mining, including gravel, oil, natural gas, f) airports or g) ports.
#--------traffic: Located in close proximity to a road, in a location that should represent the highest concentrations to which the population are exposed to within the zone.
                  #Located such that the pollution level for the specific pollutant is determined predominantly by the emissions from road traffic (i.e. not ship, railway, airplane, off-road) on distinct major roads.

#----------------------------------------------------
#MAIN_EMISSION_SOURCE: Describes the main source of the emissions influencing air at a station.   
                     #*Note - this describes the main source of emissions, but does not necessarily mean these emissions dominate the type of air measured at a station (given by STATION_CLASSIFICATION). 

#agriculture: emissions associated with agriculture

#commercial_and_residential_combustion: emissions associated with commercial and residential combustion

#extraction_of_fossil_fuels: emissions associated with the extraction of fossil fuels 

#industrial_combustion: emissions associated with industrial combustion

#natural: emissions from natural sources (e.g terpenes from trees)

#other_mobile_sources_and_machinery: emissions from all other mobile sources than traffic, and from off-road vehicles and engines 

#production_processes: emissions from processes associated with production and assembly

#power_production: emissions from processes associated with the generation of power

#road_transport: emissions associated with emissions from traffic

#solvents: emissions associated with use of solvents

#waste_treatment_and_disposal: emissions associated with waste treatment and disposal

#----------------------------------------------------
#LAND_USE: Dominant land use in the area of the reporting station 
          #categories broadly follow IGBP land cover classification system, followed by MODIS/VIIRS land use maps
          #source: http://www.eomf.ou.edu/static/IGBP.pdf

#barren: Lands with exposed soil, sand or rocks and never have more than 10% vegetated cover during any time of the year.
#--------beach: landform alongside a body of water which consists of loose particles. The particles composing a beach are typically made from rock, such as sand, gravel, shingle, pebbles, or cobblestones.
#--------desert: a barren area of landscape where little precipitation occurs and consequently living conditions are hostile for plant and animal life. 
                #The lack of vegetation exposes the unprotected surface of the ground to the processes of denudation.
#--------rock: characterised by areas of bedrock exposure, scarps, talus, slides, volcanic material, rock glaciers, and other accumulations of rock without vegetative cove 
#--------soil: thin soil, without vegetation

#forest: Lands dominated by woody vegetation or trees, with a percent cover >60% and height exceeding 2 m. 
        #Includes all evergreen needleleaf, evergreen broadleaf, deciduous needleleaf, deciduous broadleaf types

#open: Lands with herbaceous, other understory systems or woody vegetation less than 2 m tall
#--------grassland: Lands with herbaceous types of cover. Tree and shrub cover is less than 10%.
#--------savanna: Lands with herbaceous and other understory systems, and with forest canopy cover between 10% and 60%. The forest cover height exceeds 2 m.
#--------shrubland: Lands with woody vegetation less than 2 m tall and with shrub canopy cover > 10%. The shrub foliage can be either evergreen or deciduous.

#snow: Lands under snow/ice cover throughout the year.

#urban: Land covered by buildings and other man-made structures.
#--------agricultural: Lands covered with temporary crops followed by harvest and a bare soil period (e.g., single and multiple cropping systems).
                      #Also includes lands used for farming and raising of livestock
                      #It is important to note that also agricultural is classed under urban, this class also includes naturally occuring crops.
                      #**Sites with agricultural land_use can have an AREA_CLASSIFICATION of 'rural'. 
                      #**They are defined as 'urban' under LAND_USE as they would not be there without human activity, but can be located extremely far from urban areas, with no major emission sources nearby (with the exception of pesticides)
#--------blighted: A blighted area is defined as: by reason of deterioration, faulty planning, inadequate or improper facilities, deleterious land use or the existence of unsafe structures, 
                  #or any combination of these factors, are detrimental to the safety, health or welfare of the community.
#--------commercial: A commercial area is real estate intended for use by for-profit businesses, such as office complexes, shopping malls, service stations and restaurants. 
                    #It may be purchased outright by a developer for future projects or leased through a real estate broker.
#--------industrial: Industrial land use is the use of a piece of land for industrial purposes, eg. manufacturing.
#--------military: Land used for solely military purposes
#--------park: A large public garden or area of land used for recreation.
#--------residential: A residential area is a land used in which housing predominates, as opposed to industrial and commercial areas. Housing may vary significantly between, and through, residential areas.
                     #These include single-family housing, multi-family residential, or mobile homes.
#--------transportation: All types of land use used for human transportation. This includes airports, roads, railway lines and shipping ports.
#**possibly some overlap between between 'industrial' and 'transportation' classes, as some networks may class things such as airports as industrial (e.g AIRBASE), and others not

#water: Oceans, seas, lakes, reservoirs, and rivers. Can be either fresh or salt- water bodies.

#wetland: Lands with a permanent mixture of water and herbaceous or woody vegetation. The vegetation can be present either in salt, brackish, or fresh water.


#----------------------------------------------------
#TERRAIN: Dominant terrain in the area of the reporting station 

#coastal: A coastal area is where land meets the sea or ocean.

#complex: A region having irregular topography (not including mountains or coastal). 
         #Complex terrain can include variations in land use, such as urban, irrigated, and unirrigated.

#flat: Open terrain, open country or open ground is terrain which is mostly flat and free of obstructions such as trees and buildings. 
      #Examples include farmland, grassland and specially cleared areas such as an airport.

#mountain: A mountain is a large landform that stretches above the surrounding land in a limited area, usually in the form of a peak.

#rolling: Terrain where the natural slopes consistently rise and fall across a horizontal plane 


#----------------------------------------------------
#MEASUREMENT_SCALE: A denotation of the geographic scope of the air quality measurements made by the monitor. 
                   #The implication is that the same measurement made elsewhere within the measurement scale 
                   #would produce an equivalent result to that produced at the monitoring site
                   #**Neighbourhood and City scales have potential to overlap in applications that concern secondarily formed or homogeneously distributed air pollutants
                    
#micro: representative for: several metres - ~100m

#middle: representative for: ~100m - 0.5km, several city blocks

#neighbourhood: representative for: 0.5km - 4km, some extended area of city that has relatively uniform land use

#city: representative for: 4km - 50km, city like dimensions. 

#regional: representative for: 50km - 100s km, rural area of reasonably homogeneous geography, without large sources

#------------------------------------------------
#NOW MAP INDIVIDUAL NATIVE NETWORK CLASSIFICATIONS TO STANDARD CLASSIFICATIONS 
#------------------------------------------------
#AIRBASE

#AIRBASE NATIVE CLASSIFICATIONS = AREA_CLASSIFICATION, STATION_CLASSIFICATION, MAIN_EMISSION_SOURCE, LAND_USE, AREA_CLASSIFICATION_RURAL_SUBDIVISION, REPRESENTATIVE_RADIUS

#AREA_CLASSIFICATION = suburban, urban, rural 
#STATION_CLASSIFICATION = background, industrial, traffic
#MAIN_EMISSION_SOURCE = agriculture, "commercial, institutional and residential combustion", "extraction and distribution of fossil fuels", "industrial combustion", nature, other, "other mobile sources and machinery (specify)", "production processes", "public power, co-generation and district heating", "road transport", "use of solvents", "waste treatment and disposal"
#LAND_USE = agricultural, commercial, industrial, natural, residential
#AREA_CLASSIFICATION_RURAL_SUBDIVISION = nearcity, remote, regional
#REPRESENTATIVE_RADIUS = representative radius of measurements in kilometres

    if run_details['network'] == 'AIRBASE':

        #AREA CLASSIFICATION 
        mapping_area_classification = {'urban':'urban','suburban':'urban','rural':'rural','unknown':'','':''}
        mapping_area_classification_urban_subdivision = {'urban':'centre','suburban':'suburban'}
        mapping_area_classification_rural_subdivision = {'nearcity':'near_city','regional':'regional','remote':'remote'}

        area_classification = mapping_area_classification[native_classifications['area_classification']] 
    
        if area_classification == 'urban':
            area_classification_urban_subdivision = mapping_area_classification_urban_subdivision[native_classifications['area_classification']]
            area_classification = '%s-%s'%(area_classification,area_classification_urban_subdivision) 
        if area_classification == 'rural':
            area_classification_rural_subdivision = mapping_area_classification_rural_subdivision[native_classifications['area_classification_rural_subdivision']]
            area_classification = '%s-%s'%(area_classification,area_classification_rural_subdivision) 
        

        #STATION CLASSIFICATION
        mapping_station_classification = {'background':'background','industrial':'point_source','traffic':'point_source','unknown':'','':''}
    
        station_classification = mapping_station_classification[native_classifications['station_classification']]
    
        if native_classifications['station_classification'] == 'industrial':
            station_classification_point_source_subdivision = 'industrial'
            station_classification = '%s-%s'%(station_classification,station_classification_point_source_subdivision) 
        if native_classifications['station_classification'] == 'traffic':
            station_classification_point_source_subdivision = 'traffic'
            station_classification = '%s-%s'%(station_classification,station_classification_point_source_subdivision) 
    
        #MAIN_EMISSION_SOURCE
        mapping_main_emission_source_classification = {'agriculture':'agriculture', 'commercial,institutionalandresidentialcombustion':'commercial_and_residential_combustion', 'extractionanddistributionoffossilfuels':'extraction_of_fossil_fuels', 'industrialcombustion':'industrial_combustion', 'nature':'natural', 'other':'', 'othermobilesourcesandmachinery(specify)':'other_mobile_sources_and_machinery', 'productionprocesses':'production_processes', 'publicpower,co-generationanddistrictheating':'power_production', 'roadtransport':'road_transport', 'useofsolvents':'solvents', 'wastetreatmentanddisposal':'waste_treatment_and_disposal', 'unknown':'', '':''}
        main_emission_source = mapping_main_emission_source_classification[native_classifications['main_emission_source']]
    
    
        #LAND USE - mixed land uses are sometimes given - process all into one standardised string separated by '/'
                   #'natural' land use is too vague to map to a land use (without given details) - do not use
        
        mapping_land_use = {'agricultural':'urban','commercial':'urban','industrial':'urban','residential':'urban','natural':'','mountain':'barren-rock','unknown':'','':''}
        mapping_land_use_urban_subdivision = {'agricultural':'agricultural','commercial':'commercial','industrial':'industrial','residential':'residential'}
    
        native_land_use = native_classifications['land_use'].split('/')
    
        land_use = ''
        if native_land_use != ['']:
            for nlu in native_land_use:
                if land_use != '':
                    land_use = land_use+'/'
                iter_land_use = mapping_land_use[nlu]
                if iter_land_use == 'urban':
                    iter_land_use_urban_subdivision = mapping_land_use_urban_subdivision[nlu]
                    iter_land_use = '%s-%s'%(iter_land_use,iter_land_use_urban_subdivision)
                land_use = land_use + iter_land_use
   
        #TERRAIN - if the land_use is 'barren-rock' this is because the raw provided land use is mountain, therefore give terrain this classification
        if land_use == 'barren-rock':
            terrain = 'mountain'
        #else if the AREA_CLASSIFICATION is "urban" or "suburban", then assume the terrain is "complex"
        elif ('urban' in area_classification) or ('suburban' in area_classification):
            terrain = 'complex'
        else:
            terrain = ''
          
        #MEASUREMENT SCALE - use REPRESENTATIVE_RADIUS to determine standardised measurement scale
        if (native_classifications['representative_radius'] != '') & (native_classifications['representative_radius'] != 'unknown'):
            if float(native_classifications['representative_radius']) < 0.1:
                measurement_scale = 'micro'
            elif (float(native_classifications['representative_radius']) >= 0.1) & (float(native_classifications['representative_radius']) < 0.5):
                measurement_scale = 'middle'
            elif (float(native_classifications['representative_radius']) >= 0.5) & (float(native_classifications['representative_radius']) < 4.0):
                measurement_scale = 'neighbourhood'
            elif (float(native_classifications['representative_radiuss']) >= 4.0) & (float(native_classifications['representative_radius']) < 50.0):
                measurement_scale = 'city'
            elif float(native_classifications['representative_radius']) >= 50.0:
                measurement_scale = 'regional'
        else:
            measurement_scale = ''
    
#------------------------------------------------
#AQS

#AQS NATIVE CLASSIFICATIONS = AREA_CLASSIFICATION, LAND_USE, MEASUREMENT_SCALE

#AREA_CLASSIFICATION = urbanandcentercity, suburban, rural
#LAND_USE = agricultural, blightedareas, commercial, desert, forest, industrial, militaryreservation, mobile, residential
#MEASUREMENT_SCALE = microscale, middlescale, neighborhood, urbanscale, regionalscale 

    elif run_details['network'] == 'AQS':

        #AREA CLASSIFICATION 
        mapping_area_classification = {'urbanandcentercity':'urban','suburban':'urban','rural':'rural','unknown':'','':''}
        mapping_area_classification_urban_subdivision = {'urbanandcentercity':'centre','suburban':'suburban'}

        area_classification = mapping_area_classification[native_classifications['area_classification']] 
    
        if area_classification == 'urban':
            area_classification_urban_subdivision = mapping_area_classification_urban_subdivision[native_classifications['area_classification']]
            area_classification = '%s-%s'%(area_classification,area_classification_urban_subdivision) 


        #STATION CLASSIFICATION - no direct category that gives this, but can derive it
                                 #where measurement_scale is 'micro' or 'middle', assume this point source dominated (<0.5km)
                                 #other larger scales (>0.5km) are assumed to be representative of background  
    
        mapping_station_classification = {'microscale':'point_source','middlescale':'point_source','neighborhood':'background','urbanscale':'background','regionalscale':'background','unknown':'','':''}
        station_classification = mapping_station_classification[native_classifications['measurement_scale']]
    
        #MAIN_EMISSION_SOURCE - No information
        main_emission_source = ''
    
        #LAND USE
        mapping_land_use = {'agricultural':'urban','blightedareas':'urban','commercial':'urban','desert':'barren','forest':'forest','industrial':'urban','militaryreservation':'urban','mobile':'urban','residential':'urban','unknown':'','':''}
        mapping_land_use_barren_subdivision = {'desert':'desert'}
        mapping_land_use_urban_subdivision = {'agricultural':'agricultural','blightedareas':'blighted','commercial':'commercial','industrial':'industrial','militaryreservation':'military','mobile':'transportation','residential':'residential'}

        land_use = mapping_land_use[native_classifications['land_use']]
    
        if land_use == 'barren':
            land_use_barren_subdivision = mapping_land_use_barren_subdivision[native_classifications['land_use']]
            land_use = '%s-%s'%(land_use,land_use_barren_subdivision) 
        if land_use == 'urban':
            land_use_urban_subdivision = mapping_land_use_urban_subdivision[native_classifications['land_use']]
            land_use = '%s-%s'%(land_use,land_use_urban_subdivision) 
        
        #TERRAIN - If the AREA_CLASSIFICATION is "urban" or "suburban", then assume the terrain is "complex"
        if ('urban' in area_classification) or ('suburban' in area_classification):
            terrain = 'complex'
        else:
            terrain = ''
    
        #MEASUREMENT SCALE 
        mapping_measurement_scale = {'microscale':'micro','middlescale':'middle','neighborhood':'neighbourhood','urbanscale':'city','regionalscale':'regional','unknown':'','':''}
        measurement_scale = mapping_measurement_scale[native_classifications['measurement_scale']]

#------------------------------------------------
#CAPMON

#CAPMON NATIVE CLASSIFICATIONS = AREA_CLASSIFICATION

#AREA_CLASSIFICATION = rural
    
    elif run_details['network'] == 'CAPMON':
    
        #AREA CLASSIFICATION
        if native_classifications['area_classification'] == 'rural':
            area_classification = 'rural'
        else:
            area_classification = ''    
        
        #STATION CLASSIFICATION - Derive from area classification, if class is 'rural', then assume it is 'background' representative
    
        if area_classification == 'rural':
            station_classification = 'background'
        else:
            station_classification = ''
            
        #MAIN_EMISSION_SOURCE - No information
        main_emission_source = ''
        
        #LAND USE - No information
        land_use = ''
        
        #TERRAIN - If the AREA_CLASSIFICATION is "urban" or "suburban", then assume the terrain is "complex"
        if ('urban' in area_classification) or ('suburban' in area_classification):
            terrain = 'complex'
        else:
            terrain = ''
        
        #MEASUREMENT SCALE - No information
        measurement_scale = ''

#------------------------------------------------
#CASTNET 

#CASTNET NATIVE CLASSIFICATIONS = LAND_USE, TERRAIN

#LAND_USE = agric, arid, coastal, coastal/marsh, desert, forest, forest/arid, forest/marsh, forest/tropical, marsh, prairie, range, tropical, urban, urban/agric
#TERRAIN = coastal, complex, flat, flat/water, mountaintop, rolling, water

    elif run_details['network'] == 'CASTNET':
    
        #AREA CLASSIFICATION - derive from certain LAND_USE cateogories. 
                              #Specifically the 'urban', 'urban/agric' are classed as 'urban'
                              #The rest are assumed to be 'rural'
    
        mapping_area_classification = {'agric':'rural','arid':'rural','coastal':'rural','coastal/marsh':'rural','desert':'rural','forest':'rural','forest/arid':'rural','forest/marsh':'rural','forest/tropical':'rural','marsh':'rural','prairie':'rural','range':'rural','tropical':'rural','urban':'urban','urban/agric':'urban','unknown':'','':''}
        area_classification = mapping_area_classification[native_classifications['land_use']]
    
        #STATION CLASSIFICATION - Derive from area classification, if class is 'rural', then assume it is 'background' representative
                                 #No not have enough detail to assume representativeness of 'urban' sites' 
        
        if area_classification == 'rural':
            station_classification = 'background'
        else:
            station_classification = ''
        
        #MAIN_EMISSION_SOURCE - No information
        main_emission_source = ''
            
        #LAND USE - mixed land uses are sometimes given, put these mixed values into just category (unlike done with AIRBASE), as way classifications are reported lends itself to this 
                    #i.e. they are are mixture of biome and land covers, and often these merge naturally into 1 category
                    #make assumption for 'range', that lands grazed by animals are naturally occurring -->, 'open'. Can also be lands grazed by domestic animals --> 'agriculture', but this is not accounted for 
                   
        mapping_land_use = {'agric':'urban','arid':'barren','coastal':'wetland','coastal/marsh':'wetland','desert':'barren','forest':'forest','forest/arid':'forest','forest/marsh':'forest','forest/tropical':'forest','marsh':'wetland','prairie':'open','range':'open','tropical':'forest','urban':'urban','urban/agric':'urban','unknown':'','':''}
        land_use = mapping_land_use[native_classifications['land_use']]
        
        if native_classifications['land_use'] == 'desert':
            land_use_barren_subdivision = 'desert'
            land_use = '%s-%s'%(land_use,land_use_barren_subdivision) 
            
        if native_classifications['land_use'] == 'prairie':
            land_use_open_subdivision = 'grassland'
            land_use = '%s-%s'%(land_use,land_use_open_subdivision) 
        
        if (native_classifications['land_use'] == 'agric') or (native_classifications['land_use'] == 'urban/agric'):
            land_use_urban_subdivision = 'agricultural'
            land_use = '%s-%s'%(land_use,land_use_urban_subdivision) 
            
        #TERRAIN - first use given 'terrain' classification
        mapping_terrain_classification = {'coastal':'coastal','complex':'complex','flat':'flat','flat/water':'flat','mountaintop':'mountain','rolling':'rolling','water':'','unknown':'','':''}
        terrain = mapping_terrain_classification[native_classifications['terrain']]
        #if terrain is empty string still, If the AREA_CLASSIFICATION is "urban" or "suburban", then assume the terrain is "complex"
        if terrain == '':
            if ('urban' in area_classification) or ('suburban' in area_classification):
                terrain = 'complex'

        #MEASUREMENT SCALE - No information
        measurement_scale = ''

#------------------------------------------------
#EANET

#EANET NATIVE CLASSIFICATIONS = AREA_CLASSIFICATION

#AREA_CLASSIFICATION = urban, rural, remote
    
    elif run_details['network'] == 'EANET':
    
        #AREA CLASSIFICATION - Enough detail reported in data manuals to subdivide rural classes
                               #'rural' class defined as more than 20km from large emission sources --> 'regional' 
                               #'remote' class defined as more than 50km from large emission sources --> 'remote' 
                               
        mapping_area_classification = {'urban':'urban','rural':'rural','remote':'rural','unknown':'','':''}
        mapping_area_classification_rural_subdivision = {'rural':'regional','remote':'remote'}
        
        area_classification = mapping_area_classification[native_classifications['area_classification']]
        
        if area_classification == 'rural':
            area_classification_rural_subdivision = mapping_area_classification_rural_subdivision[native_classifications['area_classification']]
            area_classification = '%s-%s'%(area_classification,area_classification_rural_subdivision)  
        
        #STATION CLASSIFICATION - Derive from area classification, if class is 'rural', then assume it is 'background' representative
                                 #No not have enough detail to assume representativeness of 'urban' sites' 
        
        if area_classification == 'rural':
            station_classification = 'background'
        else:
            station_classification = ''
        
        #MAIN_EMISSION_SOURCE - No information
        main_emission_source = ''
        
        #LAND USE - No information
        land_use = ''
        
        #TERRAIN - If the AREA_CLASSIFICATION is "urban" or "suburban", then assume the terrain is "complex"
        if ('urban' in area_classification) or ('suburban' in area_classification):
            terrain = 'complex'
        else:
            terrain = ''
        
        #MEASUREMENT SCALE - No information
        measurement_scale = ''

#------------------------------------------------
#EBAS

#EMEP NATIVE CLASSIFICATIONS = AREA_CLASSIFICATION, LAND_USE

#AREA_CLASSIFICATION = mountain, polar, coastal, rural, suburban, urbanandcentercity, other
#LAND_USE = agricultural, airport, blightedarea, commercial, desert, forest, grassland,
#gravelandstone, industrial, militaryreservation, remotepark, residential, singlepointsourcearea,
#snowfield, urbanpark, wetland, other


    elif run_details['network'] == 'EBAS':

        #AREA CLASSIFICATION 
        mapping_area_classification = {'mountain':'rural','polar':'rural','coastal':'rural','rural':'rural','suburban':'urban','urbanandcentercity':'urban','other':'','notavailable':'','unknown':'','':''}
        mapping_area_classification_urban_subdivision = {'urbanandcentercity':'centre','suburban':'suburban'}

        area_classification = mapping_area_classification[native_classifications['area_classification']] 
        if area_classification == 'urban':
            area_classification_urban_subdivision = mapping_area_classification_urban_subdivision[native_classifications['area_classification']]
            area_classification = '%s-%s'%(area_classification,area_classification_urban_subdivision)     


        #STATION CLASSIFICATION - Derive this class from mixture of AREA CLASSIFICATION AND LAND_USE
                                #Where land use is 'singlepointsourcearea', the station is classed as 'point_source'
                                #Where land use is 'airport', the station is classed as 'point_source-industrial'
                                #Otherwise, if area_classification is 'rural', then set class as 'background'
        
        #if land use is 'singlepointsourcearea' then classify station as 'point_source'
        if (native_classifications['land_use'] == 'singlepointsourcearea'):
            station_classification = 'point_source'
         #if land use is 'airport' then classify as 'point_source-industrial'
        elif (native_classifications['land_use'] == 'airport'):
            station_classification = 'point_source-industrial'
        #otherwise if area classification is 'rural', make assumption the station is a 'background' site
        elif area_classification == 'rural':
            station_classification = 'background'
        #can't be sure of station classification - set as blank
        else:
            station_classification = ''
            
        #MAIN_EMISSION_SOURCE - No information
        main_emission_source = ''
            
        #LAND USE - Only use 'grassland' to classify land_use as 'open', know from experience it is used to describe both 'shrublands' and 'grasslands'
        mapping_land_use = {'agricultural':'urban','airport':'urban','blightedarea':'urban','commercial':'urban','desert':'barren','forest':'forest','grassland':'open','gravelandstone':'barren','industrial':'urban','militaryreservation':'urban','remotepark':'urban','residential':'urban','singlepointsourcearea':'urban','snowfield':'snow','urbanpark':'urban','wetland':'wetland','other':'','notavailable':'','unknown':'','':''}
        mapping_land_use_barren_subdivision = {'desert':'desert','gravelandstone':'rock'}
        mapping_land_use_urban_subdivision = {'agricultural':'agricultural','airport':'transportation','blightedarea':'blighted','commercial':'commercial','industrial':'industrial','militaryreservation':'military','remotepark':'park','residential':'residential','singlepointsourcearea':'','urbanpark':'park'}

        land_use = mapping_land_use[native_classifications['land_use']]
        
        if land_use == 'barren':
            land_use_barren_subdivision = mapping_land_use_barren_subdivision[native_classifications['land_use']]
            land_use = '%s-%s'%(land_use,land_use_barren_subdivision) 
        if land_use == 'urban':
            land_use_urban_subdivision = mapping_land_use_urban_subdivision[native_classifications['land_use']]
            #take care not to needlessly append empty string associated with 'singlepointsourcearea', too vague to give specific land use
            if land_use_urban_subdivision != '':
                land_use = '%s-%s'%(land_use,land_use_urban_subdivision) 
    
        #TERRAIN 
        terrain = ''
        if native_classifications['area_classification'] == 'mountain':
            terrain = 'mountain'
        elif native_classifications['area_classification'] == 'coastal':
            terrain = 'coastal'
        
        #if terrain is empty string still, If the AREA_CLASSIFICATION is "urban" or "suburban", then assume the terrain is "complex"
        if terrain == '':    
            if ('urban' in area_classification) or ('suburban' in area_classification):
                terrain = 'complex'

        #MEASUREMENT SCALE - No information
        measurement_scale = ''

#------------------------------------------------
#EIONET

#EIONET NATIVE CLASSIFICATIONS = AREA_CLASSIFICATION (EIONET OR AIRBASE), STATION_CLASSIFICATION (EIONET OR AIRBASE), MAIN_EMISSION_SOURCE (AIRBASE), LAND_USE (AIRBASE), AREA_CLASSIFICATION_RURAL_SUBDIVISION (AIRBASE), REPRESENTATIVE_RADIUS (AIRBASE)

#AREA_CLASSIFICATION = suburban, urban, rural, rural-nearcity, rural-regional, rural-remote 
#STATION_CLASSIFICATION = background, industrial, traffic
#MAIN_EMISSION_SOURCE = agriculture, "commercial, institutional and residential combustion", "extraction and distribution of fossil fuels", "industrial combustion", nature, other, "other mobile sources and machinery (specify)", "production processes", "public power, co-generation and district heating", "road transport", "use of solvents", "waste treatment and disposal"
#LAND_USE = agricultural, commercial, industrial, natural, residential
#AREA_CLASSIFICATION_RURAL_SUBDIVISION = nearcity, remote, regional
#REPRESENTATIVE_RADIUS = representative radius of measurements in kilometres

    elif run_details['network'] == 'EIONET':

        #AREA CLASSIFICATION 
        mapping_area_classification = {'urban':'urban','suburban':'urban','rural':'rural','rural-nearcity':'rural','rural-near_city':'rural','rural-regional':'rural','rural-remote':'rural','unknown':'','':''}
        mapping_area_classification_urban_subdivision = {'urban':'centre','suburban':'suburban'}
        mapping_area_classification_rural_subdivision = {'rural-nearcity':'near_city','rural-near_city':'near_city','rural-regional':'regional','rural-remote':'remote','rural':''}

        area_classification = mapping_area_classification[native_classifications['area_classification']] 
    
        if area_classification == 'urban':
            area_classification_urban_subdivision = mapping_area_classification_urban_subdivision[native_classifications['area_classification']]
            area_classification = '%s-%s'%(area_classification,area_classification_urban_subdivision) 
        if area_classification == 'rural':
            area_classification_rural_subdivision = mapping_area_classification_rural_subdivision[native_classifications['area_classification']]
            if area_classification_rural_subdivision != '':
                area_classification = '%s-%s'%(area_classification,area_classification_rural_subdivision) 
            #if do not have rural subdivisions, then try use AIRBASE only available AREA_CLASSIFICATION_RURAL_SUBDIVISION
            #check AREA_CLASSIFICATION_RURAL_SUBDIVISION not empty string or 'unknown'
            elif (native_classifications['area_classification_rural_subdivision'] != '') & (native_classifications['area_classification_rural_subdivision'] != 'unknown'):
                mapping_area_classification_rural_subdivision = {'nearcity':'near_city','regional':'regional','remote':'remote'}
                area_classification_rural_subdivision = mapping_area_classification_rural_subdivision[native_classifications['area_classification_rural_subdivision']]
                area_classification = '%s-%s'%(area_classification,area_classification_rural_subdivision) 
        
        #STATION CLASSIFICATION
        mapping_station_classification = {'background':'background','industrial':'point_source','traffic':'point_source','unknown':'','':''}
    
        station_classification = mapping_station_classification[native_classifications['station_classification']]
    
        if native_classifications['station_classification'] == 'traffic':
            station_classification_point_source_subdivision = 'traffic'
            station_classification = '%s-%s'%(station_classification,station_classification_point_source_subdivision)
            
        if native_classifications['station_classification'] == 'industrial':
            station_classification_point_source_subdivision = 'industrial'
            station_classification = '%s-%s'%(station_classification,station_classification_point_source_subdivision)  

        #MAIN_EMISSION_SOURCE
        mapping_main_emission_source_classification = {'agriculture':'agriculture', 'commercial,institutionalandresidentialcombustion':'commercial_and_residential_combustion', 'extractionanddistributionoffossilfuels':'extraction_of_fossil_fuels', 'industrialcombustion':'industrial_combustion', 'nature':'natural', 'other':'', 'othermobilesourcesandmachinery(specify)':'other_mobile_sources_and_machinery', 'productionprocesses':'production_processes', 'publicpower,co-generationanddistrictheating':'power_production', 'roadtransport':'road_transport', 'useofsolvents':'solvents', 'wastetreatmentanddisposal':'waste_treatment_and_disposal', 'unknown':'', '':''}
        main_emission_source = mapping_main_emission_source_classification[native_classifications['main_emission_source']]
    
    
        #LAND USE - mixed land uses are sometimes given - process all into one standardised string separated by '/'
                   #'natural' land use is too vague to map to a land use (without given details) - do not use
        
        mapping_land_use = {'agricultural':'urban','commercial':'urban','industrial':'urban','residential':'urban','natural':'','mountain':'barren-rock','unknown':'','':''}
        mapping_land_use_urban_subdivision = {'agricultural':'agricultural','commercial':'commercial','industrial':'industrial','residential':'residential'}
    
        native_land_use = native_classifications['land_use'].split('/')
    
        land_use = ''
        if native_land_use != ['']:
            for nlu in native_land_use:
                if land_use != '':
                    land_use = land_use+'/'
                iter_land_use = mapping_land_use[nlu]
                if iter_land_use == 'urban':
                    iter_land_use_urban_subdivision = mapping_land_use_urban_subdivision[nlu]
                    iter_land_use = '%s-%s'%(iter_land_use,iter_land_use_urban_subdivision)
                land_use = land_use + iter_land_use

        #TERRAIN - if the land_use is 'barren-rock' this is because the raw provided land use is mountain, therefore give terrain this classification
        if land_use == 'barren-rock':
            terrain = 'mountain'
        #else if the AREA_CLASSIFICATION is "urban" or "suburban", then assume the terrain is "complex"
        elif ('urban' in area_classification) or ('suburban' in area_classification):
            terrain = 'complex'
        else:
            terrain = ''

        #MEASUREMENT SCALE - use REPRESENTATIVE_RADIUS to determine standardised measurement scale
        if (native_classifications['representative_radius'] != '') & (native_classifications['representative_radius'] != 'unknown'):
            if float(native_classifications['representative_radius']) < 0.1:
                measurement_scale = 'micro'
            elif (float(native_classifications['representative_radius']) >= 0.1) & (float(native_classifications['representative_radius']) < 0.5):
                measurement_scale = 'middle'
            elif (float(native_classifications['representative_radius']) >= 0.5) & (float(native_classifications['representative_radius']) < 4.0):
                measurement_scale = 'neighbourhood'
            elif (float(native_classifications['representative_radius']) >= 4.0) & (float(native_classifications['representative_radius']) < 50.0):
                measurement_scale = 'city'
            elif float(native_classifications['representative_radius']) >= 50.0:
                measurement_scale = 'regional'
        else:
            measurement_scale = ''
    

#------------------------------------------------
#GAW 

#GAW NATIVE CLASSIFICATIONS = NONE

    elif run_details['network'] == 'GAW':
    
        #AREA CLASSIFICATION - No information
        area_classification = ''
        
        #STATION CLASSIFICATION - No information
        station_classification = ''
        
        #MAIN_EMISSION_SOURCE - No information
        main_emission_source = ''
        
        #LAND USE - No information
        land_use = ''
        
        #TERRAIN - If the AREA_CLASSIFICATION is "urban" or "suburban", then assume the terrain is "complex"
        if ('urban' in area_classification) or ('suburban' in area_classification):
            terrain = 'complex'
        else:
            terrain = ''
        
        #MEASUREMENT SCALE - No information
        measurement_scale = ''
        
#------------------------------------------------
#NAPS

#NAPS NATIVE CLASSIFICATIONS = STATION_CLASSIFICATION, LAND_USE, MEASUREMENT_SCALE

#STATION_CLASSIFICATION = pe (General Population Exposure), rb (Regional Background), t (Transportation Source Influenced), ps (Point Source Influenced)
#LAND_USE = a (Agricultural), c (Commercial), f (Forested), i (Industrial), o (Open), p (Parks), r (Residential), w (Water)
#MEASUREMENT_SCALE = mi (Micro), md (Middle), ne (Neighbourhood), sr (Sub-Regional), r (Regional)

    elif run_details['network'] == 'NAPS':
    
        #AREA CLASSIFICATION - not given directly, but derive it from station_classification
                              #all 'General Population Exposure', 'Transportation Source Influenced' and 'Point Source Influenced' classes defined as being within 'urban' area
                              #'Regional background' is defined as being outside 'urban' area --> 'rural' 
        
        mapping_area_classification = {'pe':'urban','t':'urban','ps':'urban','rb':'rural','unknown':'','na':'','':''}
        area_classification = mapping_area_classification[native_classifications['station_classification']]
        
        #STATION CLASSIFICATION
        mapping_station_classification = {'pe':'background','rb':'background','t':'point_source','ps':'point_source','unknown':'','na':'','':''}
        station_classification = mapping_station_classification[native_classifications['station_classification']]

        #MAIN_EMISSION_SOURCE - No information
        main_emission_source = ''

        #LAND USE
        mapping_land_use = {'a':'urban','c':'urban','f':'forest','i':'urban','o':'open','p':'urban','r':'urban','w':'water','unknown':'','na':'','':''}
        mapping_land_use_urban_subdivision = {'a':'agricultural','c':'commercial','i':'industrial','p':'park','r':'residential'}
        
        land_use = mapping_land_use[native_classifications['land_use']]
        
        if land_use == 'urban':
            land_use_urban_subdivision = mapping_land_use_urban_subdivision[native_classifications['land_use']]
            land_use = '%s-%s'%(land_use,land_use_urban_subdivision) 
            
        #TERRAIN - If the AREA_CLASSIFICATION is "urban" or "suburban", then assume the terrain is "complex"
        if ('urban' in area_classification) or ('suburban' in area_classification):
            terrain = 'complex'
        else:
            terrain = ''
        
        #MEASUREMENT SCALE 
        mapping_measurement_scale = {'mi':'micro','md':'middle','ne':'neighbourhood','sr':'city','r':'regional','unknown':'','na':'','':''}
        measurement_scale = mapping_measurement_scale[native_classifications['measurement_scale']]

#------------------------------------------------
#SEARCH

#SEARCH NATIVE CLASSIFICATIONS = AREA_CLASSIFICATION

#AREA_CLASSIFICATION = urban, suburban, rural
    
    elif run_details['network'] == 'SEARCH':
    
        #AREA CLASSIFICATION
        mapping_area_classification = {'urban':'urban','suburban':'urban','rural':'rural','unknown':'','':''}
        mapping_area_classification_urban_subdivision = {'urban':'centre','suburban':'suburban'}
        
        area_classification = mapping_area_classification[native_classifications['area_classification']]
        
        if area_classification == 'urban':
            area_classification_urban_subdivision = mapping_area_classification_urban_subdivision[native_classifications['area_classification']]
            area_classification = '%s-%s'%(area_classification,area_classification_urban_subdivision) 
        
        #STATION CLASSIFICATION - Derive from area classification, if class is 'rural', then assume it is 'background' representative
                                 #No not have enough detail to assume background nature of 'urban' sites' 
        
        if area_classification == 'rural':
            station_classification = 'background'
        else:
            station_classification = ''
        
        #MAIN_EMISSION_SOURCE - No information
        main_emission_source = ''
        
        #LAND USE - No information
        land_use = ''
        
        #TERRAIN - If the AREA_CLASSIFICATION is "urban" or "suburban", then assume the terrain is "complex"
        if ('urban' in area_classification) or ('suburban' in area_classification):
            terrain = 'complex'
        else:
            terrain = ''
        
        #MEASUREMENT SCALE - No information
        measurement_scale = ''
        
#------------------------------------------------
#IF ANY OF STANDARD CLASSIFICATIONS ARE EMPTY STRINGS --> CONVERT TO NaN
    classes = [area_classification,station_classification,main_emission_source,land_use,terrain,measurement_scale]
    for x, cl in enumerate(classes):
        if cl == '':
            classes[x] = np.NaN

    return classes[0], classes[1], classes[2], classes[3], classes[4], classes[5]

###------------------------------------------------------------------------------------###
#STANDARDISED FLAGS

#Indicate the data quality of a specific measurement, provided by the data reporter.

#**Note: These flags refer specifically to information/or lack of information provided by the data provider 
#and not to post-processing/quality control of observations (given separately by the ‘qa’ field).

def standard_flags():

    #--------------------------------------------------------------
    #Validity
    #V = Valid, I = Invalid

    #--------------------------------------------------------------
    #Standard Flag types
    
    #A = Unspecified Aggregation/Representation issue
    #A1 = Data completeness less than 90%
    #A2 = Data completeness less than 75%
    #A3 = Data completeness less than 66%
    #A4 = Data completeness less than 50%
    #A5 = Data completeness less than 25%
    #A6 =  More than 75% of the measurements are below detection limit
    #A7 =  More than 50% of the measurements are below detection limit
    
    #C = Unspecified Chemical issue
    
    #D = Unspecified data formatting/processing issue
    #D1 = Unspecified corrected data formatting/processing issue

    #E = Estimated data - unspecified reason    
    #E1 - Below detection limit
    #E2 - Above detection limit
    #E3 - Value substituted from secondary monitor 
    
    #L = Unspecified Local Contamination
    #L1 = Agricultural Contamination
    #L2 = Bird-dropping Contamination
    #L3 = Construction Contamination
    #L4 = Dust Contamination
    #L5 = Fire/Wood Burning Contamination
    #L6 = Industrial Contamination
    #L7 = Internal laboratory/instrument Contamination
    #L8 = Insect Contamination
    #L9 = Pollen/leaf Contamination
    #L10 = Sea-salt Contamination
    #L11 = Traffic Contamination
    
    #I = Unspecified Measurement issue
    #I1 = Bad operation procedures
    #I2 = Calibration/Precision Issues
    #I3 = Below Detection Limit
    #I4 = Invalid Flow Rate
    #I5 = Extreme Internal meteorological conditions
    #I6 = Physical Issue with filter
    #I7 = Mechanical issue/non-operational equipment
    #I8 = Power Fail
    #I9 = Low Data Capture
    #I10 = Erroneous sampling 
    #I11 = No Technician 
    #I12 = Unmeasured key meteorological parameter
    #I13 = Sample diluted for analysis
    #I14 = External meteorological conditions significantly impact upon instrumental operation
    #I15 = Matrix effect
    
    #J = Un-specified operational checks 
    #J1 = Calibration/blank check
    #J2 = Precision check
    #J3 = Zero-span check
    
    #M = Missing data - No stated reason why
    
    #N = Un-flagged data
    
    #P = Preliminary data
    
    #U = Unspecified issue
    
    #V = Valid data
    
    #W = Unspecified Exceptional Event
    #W1 = Asian Dust Event
    #W2 = Station inside cloud
    #W3 = Demolition
    #W4 = Seismic activity
    #W5 = Fireworks
    #W6 = Hurricane
    #W7 = Chemical Spill/Industrial Accident 
    #W8 = Infrequent Large Gathering
    #W9 = Stratospheric Ozone Intrusion
    #W10 = Heavy rain/snowfall shower (squall)
    #W11 = Sahara Dust Event
    #W12 = Terrorist Act
    #W13 = Cleanup After a Major Disaster
    #W14 = Volcanic Eruptions
    #W15 = High Winds
    #W16 = Wildfire

    #X = Unspecified extreme/inconsistent/irregular/suspect data
    #X1 = Irregular data manually screened and accepted 
    #X2 = Irregular data manually screened and rejected 
    #X3 = Close to detection limit
    #X4 = Extremely high value
    #X5 = Extremely low value
    #X6 = Negative values
    #X7 = Inconsistent with other measurements
    #X8 = Data does not meet quality control criteria
    #X9 = Reconstructed/recalculated/reanalysed data
    #X10 = High variability
    
    #--------------------------------------------------------------
    
    if run_details['network'] == 'AIRBASE':
        flags ={        
        #Unspecified issues
        '0':{'flag_type':'U', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid'},
        #Valid
        '1':{'flag_type':'V', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Valid'}}
        
    #--------------------------------------------------------------
    elif run_details['network'] == 'AQS':
        flags ={  
        #Missing data
        'ND':{  'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'No Value Detected, Zero Reported '},
        'AF':{  'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Scheduled but not Collected (Legacy=9972)'},
        '9972':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Scheduled but not Collected'},
        'BG':{  'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Missing ozone data not likely to exceed level of standard (Legacy=9966)'},
        '9966':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Missing ozone data not likely to exceed level of standard'},
        'AM ':{ 'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Miscellaneous Void (Legacy=9979)'},
        '9979':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Miscellaneous Void'},
        'AU':{  'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Monitoring Waived (Legacy=9987)'},
        '9987':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Monitoring Waived'},
        #Estimated data
        'BR':{'flag_type':'E1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sample Value Below Acceptable Range'},
        'EH':{'flag_type':'E2', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Estimated; Exceeds Upper Range'},
        'MS':{'flag_type':'E1', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Value reported is 1/2 MDL substituted.'},
        'SS':{'flag_type':'E3', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Value substituted from secondary monitor'},
        'DN':{'flag_type':'E',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'DNPH peak less than NATTS TAD requirement, reported value should be considered an estimate'},
        'LJ':{'flag_type':'E',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Identification Of Analyte Is Acceptable; Reported Value Is An Estimate'},
        #Measurement issues
        '3':{   'flag_type':'I1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Field Issue'},
        '4':{   'flag_type':'I1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Lab Issue'},
        '7':{   'flag_type':'I2',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Below Lowest Calibration Level'},
        'FX':{  'flag_type':'I6',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Filter Integrity Issue'},
        'MD':{  'flag_type':'I3',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Value less than MDL'},
        'AV':{  'flag_type':'I8',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Power Failure (Legacy=9988)'},
        '9988':{'flag_type':'I8',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Power Failure'},
        'AN':{  'flag_type':'I7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Machine Malfunction (Legacy=9980)'},
        '9980':{'flag_type':'I7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Machine Malfunction'},
        'AJ':{  'flag_type':'I6',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Filter Damage (Legacy=9976)'},
        '9976':{'flag_type':'I6',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Filter Damage'},
        'AK':{  'flag_type':'I6',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Filter Leak (Legacy=9977)'},
        '9977':{'flag_type':'I6',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Filter Leak'},
        'AR':{  'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Lab Error (Legacy=9984)'},
        '9984':{'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Lab Error'},
        'AA':{  'flag_type':'I5',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sample Pressure out of Limits (Legacy=9967)'},
        '9967':{'flag_type':'I5',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sample Pressure out of Limits'},
        'HT':{  'flag_type':'I10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Sample pick-up hold time exceeded'},
        'AH':{  'flag_type':'I4',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sample Flow Rate or CV out of Limits (Legacy=9974)'},
        '9974':{'flag_type':'I4',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sample Flow Rate or CV out of Limits'},
        'SC':{  'flag_type':'I10', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sampler Contamination (Legacy=9948)'},
        '9948':{'flag_type':'I10', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sampler Contamination'},
        'QP':{  'flag_type':'I7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Pressure Sensor Questionable'},
        'QT':{  'flag_type':'I7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Temperature Sensor Questionable'},
        'W':{   'flag_type':'I4',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Flow Rate Average out of Spec.'},
        'X':{   'flag_type':'I5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Filter Temperature Difference or Average out of Spec.'},
        'AQ':{  'flag_type':'I9',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Collection Error (Legacy=9983)'},
        '9983':{'flag_type':'I9',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Collection Error'},
        'BK':{  'flag_type':'I7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Site computer/data logger down (Legacy=9962)'},
        '9962':{'flag_type':'I7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Site computer/data logger down'},
        'AB':{  'flag_type':'I11', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Technician Unavailable (Legacy=9968)'},
        '9968':{'flag_type':'I11', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Technician Unavailable'},
        'BB':{  'flag_type':'I11', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Unable to Reach Site (Legacy=9994)'},
        '9994':{'flag_type':'I11', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Unable to Reach Site'},
        'AE':{  'flag_type':'I14', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Shelter Temperature Outside Limits (Legacy=9971)'},
        '9971':{'flag_type':'I14', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Shelter Temperature Outside Limits'},
        'TS':{  'flag_type':'I5',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Holding Time Or Transport Temperature Is Out Of Specs. (Legacy=9956)'},
        '9956':{'flag_type':'I5',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Holding Time Or Transport Temperature Is Out Of Specs.'},
        'BJ':{  'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Operator Error (Legacy=9963)'},
        '9963':{'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Operator Error'},
        'AG':{  'flag_type':'I10', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sample Time out of Limits (Legacy=9973)'},
        '9973':{'flag_type':'I10', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sample Time out of Limits'},
        'AI':{  'flag_type':'I9',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Insufficient Data (cannot calculate) (Legacy=9975)'},
        '9975':{'flag_type':'I9',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Insufficient Data (cannot calculate)'},
        'AP':{  'flag_type':'I7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Vandalism (Legacy=9982)'},
        '9982':{'flag_type':'I7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Vandalism'},
        'BH':{  'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Interference/co-elution/misidentification (Legacy=9965)'},
        '9965':{'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Interference/co-elution/misidentification'},
        'MC':{  'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Module End Cap Missing (Legacy=9958)'},
        '9958':{'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Module End Cap Missing'},
        'BI':{  'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Lost or damaged in transit (Legacy=9964)'},
        '9964':{'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Lost or damaged in transit'},
        'SV':{  'flag_type':'I5',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sample Volume out of limits'},
        'DI':{  'flag_type':'I13', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Sample was diluted for analysis'},
        'FB':{  'flag_type':'I2',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Field Blank Value Above Acceptable Limit'},
        'LB':{  'flag_type':'I2',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Lab blank value above acceptable limit'},
        'TB':{  'flag_type':'I2',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Trip Blank Value Above Acceptable Limit'},
        'TT':{  'flag_type':'I5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Transport Temperaure is Out of Specs.'},
        'Y':{   'flag_type':'I10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Elapsed Sample Time out of Spec.'},
        'MX':{  'flag_type':'I15', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Matrix Effect'},
        '2':{   'flag_type':'I1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Operational Deviation'},
        #Operational checks
        'AT':{  'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Calibration (Legacy=9986)'},
        '9986':{'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Calibration'},
        'AY':{  'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Q C Control Points (zero/span) (Legacy=9991)'},
        '9991':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Q C Control Points (zero/span)'},
        'AX':{  'flag_type':'J2', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Precision Check (Legacy=9990)'},
        '9990':{'flag_type':'J2', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Precision Check'},
        'AZ':{  'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Q C Audit (Legacy=9992)'},
        '9992':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Q C Audit'},
        'BA':{  'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Maintenance/Routine Repairs (Legacy=9993)'},
        '9993':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Maintenance/Routine Repairs'},
        'BC':{  'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Multi-point Calibration (Legacy=9995)'},
        '9995':{'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Multi-point Calibration'},
        'BD':{  'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Auto Calibration (Legacy=9996)'},
        '9996':{'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Auto Calibration'},
        'BF':{  'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Precision/Zero/Span (Legacy=9998)'},
        '9998':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Precision/Zero/Span'},
        'BL':{  'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'QA Audit (Legacy=9961)'},
        '9961':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'QA Audit'},
        'BM':{  'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Accuracy check (Legacy=9960)'},
        '9960':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Accuracy check'},
        'CS':{  'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Laboratory Calibration Standard (Legacy=9953)'},
        '9953':{'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Laboratory Calibration Standard'},
        'ST':{  'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Calibration Verification Standard (Legacy=9954)'},
        '9954':{'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Calibration Verification Standard'},
        'TC':{  'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Component Check & Retention Time Standard (Legacy=9952)'},
        '9952':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Component Check & Retention Time Standard'},
        'FI':{  'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Filter Inspection Flag (Legacy=9959)'},
        '9959':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Filter Inspection Flag'},
        'DL':{  'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Detection Limit Analyses (Legacy=9949)'},
        '9949':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Detection Limit Analyses'},
        'MB':{  'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Method Blank (Analytical) (Legacy=9955)'},
        '9955':{'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Method Blank (Analytical)'},
        'QV':{  'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Quality Control Multi-point Verification'},
        #Possible Local Contamination
        'RF':{  'flag_type':'L5',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Fire - Canadian '},
        'RF':{  'flag_type':'L5',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Fire - Canadian'},
        'RG':{  'flag_type':'L5',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Fire - Mexico/Central America '},
        'IG':{  'flag_type':'L5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Fire - Mexico/Central America'},
        'RM':{  'flag_type':'L5',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Prescribed Fire'},
        'IM':{  'flag_type':'L5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Prescribed Fire'},
        'Q':{   'flag_type':'L5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Prescribed Burning (Not Active)'},
        'RP':{  'flag_type':'L5',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Structural Fire'},
        'IP':{  'flag_type':'L5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Structural Fire'},
        'F':{   'flag_type':'L5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Structural Fire (Not Active)'},
        'J':{   'flag_type':'L3',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Construction'},
        'L':{   'flag_type':'L3',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Highway Construction (Not Active)'},
        'P':{   'flag_type':'L3',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Roofing Operations (Not Active)'},
        'D':{   'flag_type':'L6',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Sandblasting (Not Active)'},
        'N':{   'flag_type':'L6',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Sanding/Salting of Streets (Not Active)'},
        'RI':{  'flag_type':'L9',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'High Pollen Count '},
        'II':{  'flag_type':'L9',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'High Pollen Count '},
        'G':{   'flag_type':'L9',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'High Pollen Count (Not Active)'},
        'RR':{  'flag_type':'L11', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Unique Traffic Disruption'},
        'IR':{  'flag_type':'L11', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Unique Traffic Disruption'},
        'I':{   'flag_type':'L11', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Unusual Traffic Congestion (Not Active)'},
        'M':{   'flag_type':'L11', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Rerouting of Traffic (Not Active)'},
        'K':{   'flag_type':'L1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Agricultural Tilling (Not Active)'},
        'AC':{  'flag_type':'L3',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Construction/Repairs in Area (Legacy=9969)'},
        '9969':{'flag_type':'L3',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Construction/Repairs in Area'},
        'NS':{  'flag_type':'L',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Influenced by nearby source'},
        'BE':{  'flag_type':'L3',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Building/Site Repair (Legacy=9997)'},
        '9997':{'flag_type':'L3',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Building/Site Repair'},
        'CC':{  'flag_type':'L7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Clean Canister Residue'},
         #Extreme/Inconsistent/Irregular/Suspect data
        'PQ':{  'flag_type':'X3', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Values Between PQL And MDL (Not Active)'},
        'SQ':{  'flag_type':'X3', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Values Between SQL and MDL '},
        '1':{   'flag_type':'X8', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Deviation from a CFR/Critical Criteria Requirement'},
        '1V':{  'flag_type':'X1', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Data reviewed and validated'},
        '5':{   'flag_type':'X',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Outlier'},
        '9':{   'flag_type':'X6', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Negative value detected - zero reported'},
        'LK':{  'flag_type':'X',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Analyte Identified; Reported Value May Be Biased High'},
        'LL':{  'flag_type':'X',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Analyte Identified; Reported Value May Be Biased Low'},
        'QX':{  'flag_type':'X8', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Does not meet QC criteria'},
        '6':{   'flag_type':'X8', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'QAPP Issue'},
        'V':{   'flag_type':'X1', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Validated Value'},
        '1C':{  'flag_type':'X8', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'A 1-Point QC check exceeds acceptance criteria but there is compelling evidence that the analyzer data is valid.'},
        'VB':{  'flag_type':'X1', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Value below normal; no reason to invalidate'},
        'EC':{  'flag_type':'X8', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Exceeds Critical Criteria'},
        'CL':{  'flag_type':'X8', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Surrogate Recoveries Outside Control Limits'},
        'CB':{  'flag_type':'X9', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Values have been Blank Corrected'},
        'SX':{  'flag_type':'X8', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Does Not Meet Siting Criteria'},
        'AS':{  'flag_type':'X8', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Poor Quality Assurance Results (Legacy=9985)'},
        '9985':{'flag_type':'X8', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Poor Quality Assurance Results'},
        'AL':{  'flag_type':'X2', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Voided by Operator (Legacy=9978)'},
        '9978':{'flag_type':'X2', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Voided by Operator'},
        'DA':{  'flag_type':'X',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Aberrant Data (Corrupt Files, Aberrant Chromatography, Spikes, Shifts) (Legacy=9951)'},
        '9951':{'flag_type':'X',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Aberrant Data (Corrupt Files, Aberrant Chromatography, Spikes, Shifts)'},
        'BN':{  'flag_type':'X8', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sample Value Exceeds Media Limit (Legacy=9947)'},
        '9947':{'flag_type':'X8', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sample Value Exceeds Media Limit'},
        #Exceptional Events
        'RA':{  'flag_type':'W11', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'African Dust'},
        'IA':{  'flag_type':'W11', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'African Dust'},
        'U':{   'flag_type':'W11', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Sahara Dust (Not Active)'},
        'RB':{  'flag_type':'W1',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Asian Dust'},
        'IB':{  'flag_type':'W1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Asian Dust'},
        'RC':{  'flag_type':'W7',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Chem. Spills & Indust. Accidents'},
        'IC':{  'flag_type':'W7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Chem. Spills & Indust Accidents'},
        'H':{   'flag_type':'W7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Chem. Spills & Indust. Accidents (Not Active)'},
        'RD':{  'flag_type':'W13', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Cleanup After a Major Disaster'},
        'ID':{  'flag_type':'W13', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Cleanup After a Major Disaster'},
        'R':{   'flag_type':'W13', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Cleanup After a Major Disaster (Not Active)'},
        'RE':{  'flag_type':'W3',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Demolition'},
        'IE':{  'flag_type':'W3',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Demolition'},
        'RH':{  'flag_type':'W5',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Fireworks'},
        'IH':{  'flag_type':'W5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Fireworks'},
        'RJ':{  'flag_type':'W15', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'High Winds'},
        'IJ':{  'flag_type':'W15', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'High Winds'},
        'A':{   'flag_type':'W15', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'High Winds (Not Active)'},
        'RK':{  'flag_type':'W8',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Infrequent Large Gatherings'},
        'IK':{  'flag_type':'W8',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Infrequent Large Gatherings'},
        'O':{   'flag_type':'W8',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Infrequent Large Gatherings (Not Active)'},
        'RL':{  'flag_type':'W',   'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Other'},
        'IL':{  'flag_type':'W',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Other'},
        'Z':{   'flag_type':'W',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Other event (Not Active)'},
        'RN':{  'flag_type':'W4',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Seismic Activity'},
        'IN':{  'flag_type':'W4',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Seismic Activity'},
        'S':{   'flag_type':'W4',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Seismic Activity (Not Active)'},
        'RO':{  'flag_type':'W9',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Stratospheric Ozone Intrusion'},
        'IO':{  'flag_type':'W9',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Stratospheric Ozone Intrusion'},
        'B':{   'flag_type':'W9',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Stratospheric Ozone Intrusion (Not Active)'},
        'RQ':{  'flag_type':'W12', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Terrorist Act'},
        'IQ':{  'flag_type':'W12', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Terrorist Act'},
        'RS':{  'flag_type':'W14', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Volcanic Eruptions'},
        'IS':{  'flag_type':'W14', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Volcanic Eruptions'},
        'C':{   'flag_type':'W14', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Volcanic Eruption (Not Active)'},
        'RT':{  'flag_type':'W16', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Wildfire-USA'},
        'IT':{  'flag_type':'W16', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Wildfire-USA'},
        'E':{   'flag_type':'W16', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Forest Fire (Not Active)'},
        'RU':{  'flag_type':'W16', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Wildland Fire Use Fire-USA (Not Active)'},
        'IU':{  'flag_type':'W16', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Wildland Fire Use Fire-USA (Not Active)'},
        'AO':{  'flag_type':'W10', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Bad Weather (Legacy=9981)'},
        '9981':{'flag_type':'W10', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Bad Weather'},
        'AD':{  'flag_type':'W6',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Shelter Storm Damage (Legacy=9970)'},
        '9970':{'flag_type':'W6',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Shelter Storm Damage'},
        'AW':{  'flag_type':'W16', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Wildlife Damage (Legacy=9989)'},
        '9989':{'flag_type':'W16', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Wildlife Damage'},
        'SA':{  'flag_type':'W6',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Storm Approaching (Legacy=9957)'},
        '9957':{'flag_type':'W6',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Storm Approaching'},
        #Preliminary data
        'XX':{  'flag_type':'P', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Experimental Data (Legacy=9950)'},
        '9950':{'flag_type':'P', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Experimental Data'},
        #Un-flagged data
        '8':{'flag_type':'N', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'QA/QC Unknown (Not Active)'},  
        #Multiple Data Flags
        'T':{'flag_type':'N', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Multiple PM2.5 Validity Flags (Not Active)'},
        #Valid
        '':{'flag_type':'V', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Valid value'}}

    #--------------------------------------------------------------
    elif run_details['network'] == 'CAPMON':
        flags ={        
        #Missing data
        'M1':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'No value was reported by the field or laboratory instrument (e.g. instrument failure, lost sample).'},
        #Estimated data
        'V7':{'flag_type':'E1', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'The reported value is below the analytical or method or instrument detection limit and has been substituted by the detection limit or lowest measurable value as described in the EXPLANATION OF REPORTED DETECTION LIMIT VALUES.'},
        #Measurement issues
        'V1':{'flag_type':'I3', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'The reported value is below the analytical or method or instrument detection limit. Values may be positive, zero or negative.'},
        #Extreme/Inconsistent/Irregular/Suspect data
        'V2':{'flag_type':'X1', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'The reported value is unusual (e.g., an outlier) but assessed by the Principal investigator who determined that it was valid or there was insufficient evidence for invalidation. Principal investigators may have included a textual comment to indicate possible causes for the unusual value (e.g. forest fire, volcano, dust storm).'},
        'M2':{'flag_type':'X2', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'invalidated by Principal Investigator'},
        #Valid
        'V0':{'flag_type':'V', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Valid measurement'}}

    #--------------------------------------------------------------
    elif run_details['network'] == 'CASTNET':
        flags ={
        #Missing Data
        'M':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Field data missing'},
        #Measurement issues
        'F':{'flag_type':'I8',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Field instrument power failure'},
        'K':{'flag_type':'I4',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Non-nominal flow value identified during automated screening'},
        'N':{'flag_type':'I10', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Sampling time inadequate to calculate hourly average'},
        'U':{'flag_type':'I3',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Concentration below reporting limit for analyzer'},
        'Z':{'flag_type':'I3',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'< and U flags apply'},
        #Operational checks
        'C':{'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid data due to field calibration of instrument'},
        #Possible Local Contamination
        'A':{'flag_type':'L', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Anomalous value resulting from local anthropogenic activity'},
        #Extreme/Inconsistent/Irregular/Suspect data
        'P':{'flag_type':'X2', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Potential problem identified during automated screening requiring further investigation'},
        'R':{'flag_type':'X2', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Indicates that the QC check is valid but that associated ambient measurements are not valid and the check should not be submitted as a 1-point QC check to AQS.'},
        '^':{'flag_type':'X4', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Alarm high -- ozone > 120'},
        '_':{'flag_type':'X6', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Field reading less than zero'},
        'S':{'flag_type':'X9', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Field instrument out of DQO at time of 2nd calibration'},
        #Exceptional Events
        'E':{'flag_type':'W', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Exceptional event designation requested by state agency'},
        #Unspecified issues
        'I':{'flag_type':'U', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid reading'},
        #Aggregation/representation issues
        '<':{'flag_type':'A1', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Missing < 25% of hourly sampling period'},
        'B':{'flag_type':'A5', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Field instrument channel down for > 75% of hourly sampling period'},
        'D':{'flag_type':'A2', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Field instrument channel down for 25% to 75% of hourly sampling period'},
        #Valid
        '':{'flag_type':'V',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Valid data'}}
         
    #--------------------------------------------------------------   
    elif run_details['network'] == 'EANET':
        flags ={}

    #--------------------------------------------------------------
    elif run_details['network'] == 'EBAS':
        flags ={
        #Missing data 
        '999':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Missing measurement, unspecified reason'},
        '990':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Precipitation not measured due to snow-fall. Needed for historic data, should not be needed for new data'},
        '899':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Measurement undefined, unspecified reason'},
        '890':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Concentration in precipitation undefined, no precipitation'},
        '783':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Low precipitation, concentration unknown'},
        '750':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'H+ not measured in alkaline sample'},
        #Estimated data
        '799':{'flag_type':'E',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Measurement missing (unspecified reason), data element contains estimated value'},
        '798':{'flag_type':'E',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Measurement missing (unspecified reason), data element contains estimated value. Considered valid.'},
        '797':{'flag_type':'E3', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Data element taken from co-located instrument'},
        '784':{'flag_type':'E',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Low precipitation, concentration estimated'},
        '782':{'flag_type':'E',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Low precipitation, concentration estimated'},
        '781':{'flag_type':'E1', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Value below detection limit, data element contains detection limit'},
        '771':{'flag_type':'E2', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Value above range, data element contains upper range limit'},
        '770':{'flag_type':'E2', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Value above range, data element contains estimated value'},
        '760':{'flag_type':'E',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Value estimated by summing up the constituents measured'},
        '741':{'flag_type':'E',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':"Non refractory AMS concentrations. Don't include compounds that volatalises above 600 deg C"},
        '740':{'flag_type':'E',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Probably biased gas/particle ratio'},
        '655':{'flag_type':'E',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Estimated value created by averaging or splitting samples'},
        #Measurement issues
        '780':{'flag_type':'I3',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Value below detection or quantification limit, data element contains estimated or measured value. Use of flag 147 is encouraged.'},
        '699':{'flag_type':'I7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Mechanical problem, unspecified reason'},
        '685':{'flag_type':'I2',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid due to secondary standard gas measurement. Used for Level 0.'},
        '681':{'flag_type':'I9',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Low data capture'},
        '680':{'flag_type':'I12', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Undefined wind direction'},
        '677':{'flag_type':'I14', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Icing or hoar frost in the intake'},
        '675':{'flag_type':'I12', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'no visibility data available'},
        '674':{'flag_type':'I14', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Icing or hoar frost in the intake, considered valid'},
        '670':{'flag_type':'I9',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Incomplete data acquisition for multi-component data sets'},
        '669':{'flag_type':'I6',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Moist or wet filter, invalid'},
        '668':{'flag_type':'I6',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Moist or wet filter, valid'},
        '666':{'flag_type':'I6',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Filter damaged, invalid'},
        '665':{'flag_type':'I6',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Filter damaged, valid'},
        '664':{'flag_type':'I4',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Instrument flow(s) too far off target value, considered invalid'},
        '663':{'flag_type':'I4',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Too high sampling flow, data considered invalid'},
        '662':{'flag_type':'I4',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Too high sampling flow, data considered valid'},
        '660':{'flag_type':'I10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Unspecified sampling anomaly, considered valid'},
        '659':{'flag_type':'I10', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Unspecified sampling anomaly'},
        '658':{'flag_type':'I5',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Too small air volume'},
        '656':{'flag_type':'I7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Wet-only collector failure, operated as bulk collector'},
        '654':{'flag_type':'I10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Sampling period longer than normal, considered representative. Observed values reported'},
        '653':{'flag_type':'I10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Sampling period shorter than normal, considered representative. Observed values reported'},
        '650':{'flag_type':'I7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Precipitation collector failure'},
        '649':{'flag_type':'I8',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Temporary power fail has affected sampler operation'},
        '644':{'flag_type':'I2',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Low instrument precision and/or calibration issues'},
        '641':{'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Aerosol filters installed incorrectly'},
        '640':{'flag_type':'I5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Instrument internal relative humidity above 40%'},
        '635':{'flag_type':'I5',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Internal temperatures too far off target value, considered invalid'},
        '632':{'flag_type':'I1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Lid of polyurethane foam (PUF) sampler not closed'},
        '63O':{'flag_type':'I1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'POP concentration from the polyurethane foam (PUF) only'},
        '533':{'flag_type':'I1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Filters mixed up; incorrect analysis'},
        '532':{'flag_type':'I2',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Data less accurate than normal due to high field blank value'},
        '531':{'flag_type':'I9',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Low recovery, analysis inaccurate'},
        '147':{'flag_type':'I3',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Below theoretical detection limit or formal Q/A limit, but a value has been measured and reported and is considered valid'},
        '101':{'flag_type':'I9',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Denuder capture efficiency < 75%. Valid measurement'},
        #Operational checks
        '980':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Missing due to calibration or zero/span check'},
        '684':{'flag_type':'J3', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid due to zero/span check. Used for Level 0.'},
        '683':{'flag_type':'J1', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid due to calibration. Used for Level 0.'},
        '682':{'flag_type':'J',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid due to calibration or zero/span check. Used for Level 0.'},
        #Chemical issues
        '549':{'flag_type':'C', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Impure chemicals'},
        '541':{'flag_type':'C', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Gold trap passiviated by unknown compound'},
        '540':{'flag_type':'C', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Spectral interference in laboratory analysis'},
        '534':{'flag_type':'C', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Wrong coated denuder used'},
        '530':{'flag_type':'C', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid due to too low or too high recovery'},
        '521':{'flag_type':'C', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Bactericide was added to sample for storage under warm climate. Considered valid'},
        #Possible Local Contamination
        '652':{'flag_type':'L3',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Construction/acitivity nearby'},
        '651':{'flag_type':'L1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Agricultural activity nearby'},
        '647':{'flag_type':'L5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Fire/wood burning nearby'},
        '646':{'flag_type':'L11', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Exceptional traffic nearby'},
        '645':{'flag_type':'L11', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Exceptional traffic nearby'},
        '599':{'flag_type':'L',   'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Unspecified contamination or local influence'},
        '593':{'flag_type':'L6',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Industrial contamination, considered invalid'},
        '591':{'flag_type':'L1',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Agricultural contamination, considered invalid'},
        '578':{'flag_type':'L10', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Large sea salt contribution (ratio between marine and excess sulphate is larger than 2.0). Used for old data only. For newer data use 451/450.'},
        '568':{'flag_type':'L4',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Dust contamination, considered invalid'},
        '567':{'flag_type':'L8',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Insect contamination, considered invalid'},
        '566':{'flag_type':'L2',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Bird droppings, considered invalid'},
        '565':{'flag_type':'L9',  'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Pollen and/or leaf contamination, considered invalid'},
        '559':{'flag_type':'L',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Unspecified contamination or local influence, but considered valid'},
        '558':{'flag_type':'L4',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Dust contamination, but considered valid'},
        '557':{'flag_type':'L8',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Insect contamination, but considered valid'},
        '556':{'flag_type':'L2',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Bird droppings, but considered valid'},
        '555':{'flag_type':'L9',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Pollen and/or leaf contamination, but considered valid'},
        '460':{'flag_type':'L',   'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Contamination suspected'},
        '451':{'flag_type':'L10', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Invalid due to large sea salt contribution'},
        '450':{'flag_type':'L10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Considerable sea salt contribution, but considered valid'},
        '260':{'flag_type':'L',   'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Contamination suspected'},
        '251':{'flag_type':'L10', 'network_decreed_validity':'I', 'self_decreed_validity':'V', 'decription':'Invalid due to large sea salt contribution'},
        '250':{'flag_type':'L10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Considerable sea salt contribution, but considered valid'},
        '189':{'flag_type':'L',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Possible local contamination indicated by wind from contaminated sector (auto)'},
        '188':{'flag_type':'L',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Possible local contamination indicated by low wind speed (auto)'},
        '187':{'flag_type':'L',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Possible local contamination indicated by occurence of new particles (auto)'},
        '186':{'flag_type':'L',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Possible local contamination indicated by single scattering albedo (auto)'},
        '185':{'flag_type':'L',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Possible local contamination indicated by wind direction or velocity'},
        #Extreme/Inconsistent/Irregular/Suspect data
        '900':{'flag_type':'X2',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Hidden and invalidated by data originator'},
        '701':{'flag_type':'X',   'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Less accurate than usual, unspecified reason. (Used only with old data, for new data see groups 6 and 5)'},
        '499':{'flag_type':'X7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Inconsistent with another unspecified measurement'},
        '498':{'flag_type':'X7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Gold trap inconsistency in mercury monitor'},
        '478':{'flag_type':'X7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid due to inconsistency discovered through ion balance calculations'},
        '477':{'flag_type':'X7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid due to inconsistency between measured and estimated conductivity'},
        '476':{'flag_type':'X7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Inconsistency discovered through ion balance calculations, but considered valid'},
        '475':{'flag_type':'X7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Inconsistency between measured and estimated conductivity, but considered valid'},
        '471':{'flag_type':'X7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Particulate mass concentration higher than parallell mass concentration measurement with higher cut off i.e PM1_mass > PM25_mass and PM25_mass > PM10_mass. Considered invalid.'},
        '470':{'flag_type':'X7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Particulate mass concentration higher than parallell mass concentration measurement with higher cut off i.e PM1_mass > PM25_mass and PM25_mass > PM10_mass'},
        '459':{'flag_type':'X',   'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Extreme value, unspecified error'},
        '458':{'flag_type':'X4',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Extremely high value, outside four times standard deviation in a lognormal distribution'},
        '457':{'flag_type':'X5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Extremely low value, outside four times standard deviation in a lognormal distribution'},
        '456':{'flag_type':'X2',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalidated by data originator'},
        '452':{'flag_type':'X8',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid due to large uncertainty'},
        '440':{'flag_type':'X9',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Reconstructed or recalculated data'},
        '299':{'flag_type':'X7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Inconsistent with another unspecified measurement'},
        '298':{'flag_type':'X7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Gold trap inconsistency in mercury monitor'},
        '278':{'flag_type':'X7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid due to inconsistency discovered through ion balance calculations'},
        '277':{'flag_type':'X7',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalid due to inconsistency between measured and estimated conductivity'},
        '276':{'flag_type':'X7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Inconsistency discovered through ion balance calculations, but considered valid'},
        '275':{'flag_type':'X7',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Inconsistency between measured and estimated conductivity, but considered valid'},
        '258':{'flag_type':'X4',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Extremely high value, outside four times standard deviation in a log-normal distribution'},
        '257':{'flag_type':'X5',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Extremely low value, outside four times standard deviation in a log-normal'},
        '256':{'flag_type':'X2',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Invalidated by database co-ordinator'},
        '211':{'flag_type':'X1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Irregular data checked and accepted by database co-ordinator. Valid measurement'},
        '210':{'flag_type':'X1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Episode data checked and accepted by database co-ordinator. Valid measurement'},
        '120':{'flag_type':'X9',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Sample reanalysed with similar results. Valid measurement'},
        '111':{'flag_type':'X1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Irregular data checked and accepted by data originator. Valid measurement'},
        '110':{'flag_type':'X1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Episode data checked and accepted by data originator. Valid measurement'},        
        '103':{'flag_type':'X10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'CV of replicate ALPHA samplers > 15 %;. Valid measurement'},
        '102':{'flag_type':'X10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'CV of replicate diffusion tubes > 30 %. Valid measurement'},
        '100':{'flag_type':'X1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Checked by data originator. Valid measurement, overrides any invalid flags'},
        #Exceptional Events
        '679':{'flag_type':'W',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Unspecified meteorological condition'},
        '678':{'flag_type':'W6',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Hurricane'},
        '676':{'flag_type':'W2',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'station inside cloud (visibility < 1000 m)'},
        '657':{'flag_type':'W10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Precipitation collector overflow. Heavy snowfall/rain shower (squall)'},
        '648':{'flag_type':'W10', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Snow sampler'},
        '410':{'flag_type':'W11', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Sahara dust event'},
        #Unspecified issues
        '259':{'flag_type':'U', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Unspecified error expected'},
         #Preliminary data
        '420':{'flag_type':'P', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Preliminary data'},
        '220':{'flag_type':'P', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Preliminary data'},
        #Aggregation/representation issues
        '395':{'flag_type':'A1',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Data completeness less than 90%'},
        '394':{'flag_type':'A1',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Data completeness less than 90%'},
        '393':{'flag_type':'A2',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Data completeness less than 75%'},
        '392':{'flag_type':'A2',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Data completeness less than 75%'},
        '391':{'flag_type':'A4',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Data completeness less than 50%'},
        '390':{'flag_type':'A4',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Data completeness less than 50%'},
        '389':{'flag_type':'A3',  'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Data completeness less than 66%'},
        '388':{'flag_type':'A3',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Data completeness less than 66%'},
        '382':{'flag_type':'A6',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'More than 75% of the measurements are below detection limit'},
        '380':{'flag_type':'A7',  'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'More than 50% of the measurements are below detection limit'},
        '370':{'flag_type':'A',   'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'For monthly averages with samples partly in two months, the number of days in each month is used for weighing the sample'},
        #Formatting/processing issues
        '249':{'flag_type':'D1', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Apparent typing error corrected. Valid measurement'},
        '248':{'flag_type':'D1', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Illegal flag was removed by the database co-ordinator. Lost flag information (used for historic data only).'},
        '247':{'flag_type':'D1', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Overlapping sample interval was corrected by the database co-ordinator. Possible wrong sample time (used for historic data only)'},
        '191':{'flag_type':'D1', 'network_decreed_validity':'V', 'self_decreed_validity':'V','decription':'Data not truncation corrected - Valid measurement'},
        '190':{'flag_type':'D',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Not corrected for cross-sensitivity to particle scattering'},
        #Valid
        '000':{'flag_type':'V',  'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Valid Measurement'}}
    
    #--------------------------------------------------------------
    elif run_details['network'] == 'EIONET':
        flags ={
        ##Estimated data
        '2':{'flag_type':'E1', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Data considered valid by the data provider for its related reporting purposes. However, the value has been measured below the detection limit and the value reported is the detection limit (only used for primary data).'},
        '3':{'flag_type':'E1', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Data considered valid by the data provider for its related reporting purposes. However, the value has been measured below the detection limit and the value reported is half of this detection limit (only used for primary data).'},
        #Operational checks
        '-99':{'flag_type':'J', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Data is considered to be invalid due to the regular calibration or the normal maintenance of the instrumentation (only used for primary data).'},        
        #Unspecified issues
        '-1':{'flag_type':'U', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'For primary data, data is considered to be invalid due to other circumstances or data is simply missing. For aggregated data, data is not valid because of insufficient data capture following rules set out in Directive and Guidance.'},
        #Valid
        '1':{'flag_type':'V', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Primary data considered valid by the data provider for its related reporting purposes. Aggregated data is valid following rules set out in Directive and Guidance'}}
    
    #--------------------------------------------------------------
    elif run_details['network'] == 'GAW':
        flags ={}
    
    #--------------------------------------------------------------
    elif run_details['network'] == 'NAPS':
        flags ={
        #Missing Data
        'M1':{'flag_type':'M', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Missing value - no value available'},
        #Measurement issues
        'V1':{'flag_type':'I3', 'network_decreed_validity':'V', 'self_decreed_validity':'I', 'decription':'Valid value - below detection limit'},
        #Extreme/Inconsistent/Irregular/Suspect data
        'V2':{'flag_type':'X1', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'extreme or unusual value assessed and considered valid'},
        'M2':{'flag_type':'X2', 'network_decreed_validity':'I', 'self_decreed_validity':'I', 'decription':'Missing value - invalidated'},
        #Un-flagged data
        'H1':{'flag_type':'N', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Historical data that have not been assessed or validated (data prior to 2015)'},
        #Valid
        'V0':{'flag_type':'V', 'network_decreed_validity':'V', 'self_decreed_validity':'V', 'decription':'Valid value'}}

    #--------------------------------------------------------------
    elif run_details['network'] == 'SEARCH':
        flags ={}
   
   #--------------------------------------------------------------
   
    return flags
    
###------------------------------------------------------------------------------------###

#return qa flag associated with a specific data quality assurance check or classifications

def get_standard_qa_flag(flag_type):
    
    standard_qa_flags = {

    #Basic QA checks
    #-----------------------------------------------------
    #Missing Measurement
    #Measurement is missing (i.e. NaN)
    'Missing Measurement':'A1',
    
    #Infinite Value
    #Value is infinite -- happens when values are outside of the range that the float32 data type can handle (-3.4E+38 to +3.4E+38)
    'Infinite Value':'A2',
    
    #Negative Measurement
    #Measurement is negative in absolute terms.
    'Negative Measurement':'A3',
    
    #Zero Measurement
    #Have measurement equal to zero
    'Zero Measurement':'A4',
    
    #No Key Metadata
    #One of the key metadata fields (latitude, longitude) is absent
    'No Key Metadata':'A5',
    
    #No Altitude Metadata
    #Altitude metadata field is absent, altitude is estimated using the ETOPO1 1 arc-minute global relief model
    'No Altitude Metadata':'A6',
    
    #Assumed Gas Volume
    #Have assumed gas volume when converting between mass density and volume mixing ratio. (Do not have either temperature or pressure, or both).  
    'Assumed Gas Volume':'A7',
    
    #Local timezone has been determined to be non-integer for time of measurement, relative to UTC.
    'Non-Integer Local Timezone (relative to UTC)':'A8',
    #-----------------------------------------------------
    
        
    #Duplicate / Overlapping Time Flags
    #-----------------------------------------------------
    #Duplicate Time - First Value Kept
    #Multiple measurements reported for the same temporal window - the first time is kept preferentially.
    'Duplicate Time - First Value Kept':'B1',
    
    #Overlapping Time - First Value Kept
    #Measurements reported with overlapping temporal windows - these windows have the same temporal resolutions (e.g. all hourly), therefore the first time is preferentially kept.
    'Overlapping Time - First Value Kept':'B2',
    
    #Overlapping Time - Finest Temporal Resolution Kept
    #Measurements reported with overlapping temporal windows - at least 2 of the overlapping windows have different temporal resolutions. Preferentially the finest temporal resolutions are kept. If have more than 1 windows of the same finest resolution, the first time is preferentially kept.
    'Overlapping Time - Finest Temporal Resolution Kept':'B3',
    #-----------------------------------------------------
    
    
    #Station Classifications
    #-----------------------------------------------------
    #High Altitude - Metadata Altitude
    #Station has an altitude >= 1500 metres relative to mean sea level, altitude taken from network provided metadata 
    'High Altitude - Metadata Altitude':'C1',
    
    #High Altitude - Metadata Derived
    #Station determined to be a 'mountain' station, derived from standardised 'terrain' network provided metadata
    'High Altitude - Metadata Derived':'C2',
    
    #High Altitude - ETOPO1 
    #Station determined to have an altitude >= 1500 metres relative to sea level datum, altitude taken from ETOPO1 digital elevation model
    'High Altitude - ETOPO1':'C3',
    
    #High Altitude - Iwahashi Global Landform Classification 
    #Stations determined to be high altitudes, derived from the European Soil Data Centre Iwahashi Global Landform Classification. 
    'High Altitude - Iwahashi Global Landform Classification':'C4',
    
    #High Altitude - Meybeck Global Landform Classification 
    #Stations determined to be high altitudes, derived from the European Soil Data Centre Meybeck Global Landform Classification. 
    'High Altitude - Meybeck Global Landform Classification':'C5',
    
    #Near Coast - Metadata Derived
    #Station is located near the coast - derived from standardised 'terrain' network provided metadata 
    'Near Coast - Metadata Derived':'C6',
    
    #Near Coast - GSFC
    #Stations located within 50km of the coast - using GSFC nearest to coastline dataset (0.01 degree grid)
    'Near Coast - GSFC':'C7',
    
    #Rural Station - Lenient Metadata Derived
    #Station has been determined to be rural, using standardised network provided metadata, following lenient classifications. 
    'Rural Station - Lenient Metadata Derived':'C8',
    
    #Urban Station - Lenient Metadata Derived
    #Station has been determined to be urban, using standardised network provided metadata, following lenient classifications. 
    'Urban Station - Lenient Metadata Derived':'C9',
    
    #Unclassified Station - Lenient Metadata Derived
    #Station has been determined to be unclassified, using standardised network provided metadata, following lenient classifications.
    'Unclassified Station - Lenient Metadata Derived':'C10',
    
    #Rural Station - Strict Metadata Derived
    #Station has been determined to be rural, using standardised network provided metadata, following strict classifications. 
    'Rural Station - Strict Metadata Derived':'C11',
    
    #Urban Station - Strict Metadata Derived
    #Station has been determined to be urban, using standardised network provided metadata, following strict classifications. 
    'Urban Station - Strict Metadata Derived':'C12',
    
    #Unclassified Station - Strict Metadata Derived
    #Station has been determined to be unclassified, using standardised network provided metadata, following strict classifications.
    'Unclassified Station - Strict Metadata Derived':'C13',
    
    #Rural Station - Anthrome
    #Rural station as defined by using the UMBC Anthrome gridded classification dataset
    'Rural Station - Anthrome':'C14',
    
    #Urban Station - Anthrome
    #Urban station as defined by using the UMBC Anthrome gridded classification dataset
    'Urban Station - Anthrome':'C15',
    
    #Rural Station - TOAR
    #Rural station as defined by using a TOAR approach to classification (Tropospheric Ozone Assessment Report).
    'Rural Station - TOAR':'C16',
    
    #Urban Station - TOAR
    #Urban station as defined by using a TOAR approach to classification (Tropospheric Ozone Assessment Report).
    'Urban Station - TOAR':'C17',
    
    #Unclassified Station - TOAR
    #Unclassified station as defined using a TOAR approach to classification (Tropospheric Ozone Assessment Report).
    'Unclassified Station - TOAR':'C18',
    
    #Rural Station - Joly-Peuch 
    #Rural station as defined using a Joly-Peuch approach to classification
    'Rural Station - Joly-Peuch':'C19',
    
    #Unclassified Station - Joly-Peuch 
    #Unclassified station as defined using a Joly-Peuch approach to classification
    'Unclassified Station - Joly-Peuch':'C20',
    #-----------------------------------------------------
    
    
    #Duplicate station
    #-----------------------------------------------------
    #Station has been decreed to be a duplicate (i.e. reporting the same data as from another network, but the data from another network has been preferred)   
    'Duplicate Station':'D',
    #-----------------------------------------------------
    
    
    #Extreme Data Flags
    #-----------------------------------------------------
    #Extreme Data - Scientifically Non-Feasible
    #Data is greater than a scientifically feasible limit (variable by parameter).
    'Extreme Data - Scientifically Non-Feasible':'E1',
    
    #Extreme Data - Distributional Outlier
    #Data is screened through adjusted boxplot to determine distributional outliers
    'Extreme Data - Distributional Outlier':'E2',
    
    #Extreme Data - Manually Decreed
    #Data has been found and decreed manually to be extreme, a select section of data is flagged
    'Extreme Data - Manually Decreed':'E3',
    #-----------------------------------------------------
    
    
    #Invalid Data Provider Flags
    #-----------------------------------------------------
    #Invalid Data Provider Flags - Scientifically Decreed
    #Measurements are associated with data quality flags given by the data provider which have been scientifically decreed to suggest the measurements are associated with substantial uncertainty/bias
    'Invalid Data Provider Flags - Scientifically Decreed':'F1',
    
    #Invalid Data Provider Flags - Network Decreed
    #Measurements are associated with data quality flags given by the data provider which have been decreed by the reporting network to suggest the measurements are associated with substantial uncertainty/bias 
    'Invalid Data Provider Flags - Network Decreed':'F2',
    #-----------------------------------------------------
    
    
    #Recurring Value
    #-----------------------------------------------------
    #Do check for persistently recurring values. check is done by using a moving window of 12 measurements. If 11/12 of values in the window are valid.
    'Recurring Value':'G',
    #-----------------------------------------------------
    
    
    #Hitting LOD
    #-----------------------------------------------------
    #More than 25% of station data (per month) is below/above exactly on the LOD, therefore significantly biasing the remaining distribution of data 
    'Hitting LOD':'H',
    #-----------------------------------------------------
    
    
    #Insufficient Measurement Resolution Flags
    #-----------------------------------------------------
    #Insufficient Measurement Resolution - Reported
    #The reported resolution of measurement is coarser than a set limit (variable by measured parameter)
    'Insufficient Measurement Resolution - Reported':'I1',
    
    #Insufficient Measurement Resolution - Empirical
    #The resolution of measurement is analysed month by month. If the minimum difference between observations is coarser than a set limit (variable by measured parameter), measurements are flagged.
    'Insufficient Measurement Resolution - Empirical':'I2',
    #-----------------------------------------------------
    
    
    #Limit of Detection Flags
    #-----------------------------------------------------
    #Below Documented Lower Limit of Detection
    #Measurement is below or equal to the instrumental documented lower limit of detection 
    'Below Documented Lower Limit of Detection':'L1',
    
    #Below Reported Lower Limit of Detection
    #Measurement is below or equal to the network reported lower limit of detection 
    'Below Reported Lower Limit of Detection':'L2',
    
    #Above Documented Upper Limit of Detection
    #Measurement is above or equal to the instrumental documented upper limit of detection 
    'Above Documented Upper Limit of Detection':'L3',
    
    #Above Reported Upper Limit of Detection
    #Measurement is above or equal to the network reported upper limit of detection 
    'Above Reported Upper Limit of Detection':'L4',
    #-----------------------------------------------------
    
    
    #Measurement Methodology Flags
    #-----------------------------------------------------
    #Methodology Not Mapped
    #The measurement methodology used has not yet been mapped to standardised dictionaries of measurement methodologies
    'Methodology Not Mapped':'M1',
    
    #Assumed Primary Sampling
    #A level of assumption has been made in determining the primary sampling type
    'Assumed Primary Sampling':'M2',
    
    #Assumed Sample Preparation
    #A level of assumption has been made in determining the sample preparation
    'Assumed Sample Preparation':'M3',
    
    #Assumed Measurement Methodology
    #A level of assumption has been made in determining the measurement methodology 
    'Assumed Measurement Methodology':'M4',
    
    #Unknown Primary Sampling Instrument
    #The specific name of the primary sampling instrument is unknown
    'Unknown Primary Sampling Instrument':'M5',
    
    #Unknown Measuring Instrument
    #The specific name of measuring instrument is unknown 
    'Unknown Measuring Instrument':'M6',
    
    #Erroneous Primary Sampling
    #The primary sampling is not appropriate to prepare the specific parameter for subsequent measurement.
    'Erroneous Primary Sampling':'M7',
    
    #Erroneous Sample Preparation
    #The sample preparation is not appropriate to prepare the specific parameter for subsequent measurement.
    'Erroneous Sample Preparation':'M8',
    
    #Erroneous Measurement Method
    #The measurement methodology used is not known to be able to measure the specific parameter. Only do check when known (or have assumed method).
    'Erroneous Measurement Methodology':'M9',
    
    #Invalid QA Measurement Method 
    #The specific measurement methodology has been decreed not to conform to QA standards as the method is not sufficiently proven/ subject to substantial biases/uncertainty. Only do check when known (or have assumed method).
    'Invalid QA Measurement Methodology':'M10',
    #-----------------------------------------------------
    
    
    #Temporal Period Flags - for classifying periods of time measurements are made within 
    #-----------------------------------------------------
    #Daytime
    #Time of measurement is daytime. Done by calculating the solar elevation angle for a latitude/longitude/measurement height at a certain timestamp.
    'Daytime':'P1',
    
    #Nightime
    #Time of measurement is nighttime. Done by calculating the solar elevation angle for a latitude/longitude/measurement height at a certain timestamp.
    'Nighttime':'P2',
    
    #Weekday
    #Time of measurement is weekday.
    'Weekday':'P3',
    
    #Weekend
    #Time of measurement is weekend.
    'Weekend':'P4',
    #-----------------------------------------------------


    #Temporal Representation Flags
    #-----------------------------------------------------
    #Periods are decreed not representative if <50% of period is not represented with valid measurements (after screening by key QA flags), or a data gap exists which is >15% of total length of period
    
    #Not Hourly Representative
    'Not Hourly Representative':'R1',
    
    #Not Diurnally Representative
    'Not Diurnally Representative':'R2',
    
    #Not Weekly Representative
    'Not Weekly Representative':'R3',
    
    #Not Monthly Representative
    'Not Monthly Representative':'R4',
    
    #Not Annually Representative
    'Not Annually Representative':'R5',
    #-----------------------------------------------------
    
    
    }
    
    return standard_qa_flags[flag_type]
