    Find the indices of the boundary condition terms.
    This includes the assumption that relevant "proposal" values will begin with "bc".
    Bias factors are included if include_bias is set to True and "proposal" values are expected to start
    with "bias".

    Args:
        ds (xarray.Dataset) : output from the run_tdmcmc function
        include_bias (bool, optional) :
            Include any bias terms.
            Default = False.

    Returns:
        np.array : indices for boundary conditions within proposal / nIC / kICmax / NgridIC dimensions


    Find the indices of the fixed domains outside the sub-domain.
    This includes the assumption that relevant "proposal" values will begin with "fixed".

    Args:
        ds (xarray.Dataset) : output from the run_tdmcmc function

    Returns:
        np.array : indices for fixed regions within proposal / nIC / kICmax / NgridIC dimensions


    The prior_bc_outer function calculates the y prior boundary conditions for the edges of the whole
    domain.
    Bias factors are included if include_bias is set to True.

    Args:
        ds (xarray.Dataset) : output from the run_tdmcmc function
        include_bias (bool, optional) :
            Include any bias terms.
            Default = False.

    Returns:
        np.array : y prior boundary conditions for full domain


    The prior_bc_inner function calculates the y prior boundary conditions for the inner
    region.

    Args:
        ds (xarray.Dataset) : output from the run_tdmcmc function

    Returns:
        np.array : y prior inner boundary conditions


    The prior_mf function calculates the y prior mole fraction

    Args:
        ds (xarray.Dataset) : output from the run_tdmcmc function

    Returns:
        np.array : y prior mole fraction


    The post_bc_outer function calculates the y posterior boundary conditions for the whole domain
    region for each iteration and the mean.
    Bias factors are included if include_bias is set to True.

    Args:
        ds (xarray.Dataset) : output from the run_tdmcmc function
        include_bias (bool, optional) :
            Include any bias terms.
            Default = False.

    Returns:
        (np.array,np.array) : y posterior inner bc iterations, y posterior inner bc mean


    The post_bc_inner function calculates the y posterior boundary conditions for the inner
    region for each iteration and the mean.
    This combines mole fraction contributions for boundary conditions on the whole domain,
    any bias factors included and all fixed regions outside the inner region.

    Args:
        ds (xarray.Dataset) : output from the run_tdmcmc function

    Returns:
        (np.array,np.array) : y posterior inner bc iterations, y posterior inner bc mean


    The post_mf function calculates the y posterior mole fraction iterations and mean

    Args:
        ds (xarray.Dataset) : output from the run_tdmcmc function

    Returns:
        (np.array,np.array) : y posterior mole fraction iterations, y posterior mole fraction mean


    The combine_timeseries function takes a list of output datasets from a tdmcmc run and combines
    the parameters relevant to plotting a mole fraction timeseries.

    Current parameters copied from input and combined:
        "y_time","y_site","y","sigma_y_it","sites"

    Posterior boundary conditions (inner) and modelled mole fractions are calculated for each run and
    combined. Both mean and full iterations are included. Additional parameters within dataset:
        "bc_inner_post","bc_inner_post_it","mf_post","mf_post_it"

    If any

    Args:
        ds_mult (xarray.Dataset, xarray.Dataset, ...) :
            Any number of tdmcmc output datasets can be specified to be combined.
            All datasets will be combined.

    Returns:
        xarray.Dataset :
            Reduced, combined dataset from tdmcmc output.


    Plot a 2D histogram/density plot of where nuclei are located in inversion domain

    Requires x_ray dataset of outputs
    Currently in rainbow colour scheme - Eurgh! #endrainbow

    Specify an out_filename to write to disk


    Find tdmcmc output filenames based on naming convention:
        "directory"/output_"network"_"species"_"date".nc e.g. output_AGAGE_ch4_2008-01-01.nc
    Open as xarray.Dataset objects and return as a list.


    The create_output_param creates a dictionary containing the parameters to be passed to
    the write_outfile or append_outfile functions.


    The add_local_ratio function adds an additional "local_ratio" parameter to all xarray.Dataset objects
    within fp_data_H dictionary.

    Note: footprints_data_merge() function creates a dictionary of xarray.Dataset objects with one for each
    site. fp_sensivity() takes the output from footprints_data_merge() and adds sensivity matrix to each
    dataset in the dictionary.
    Each dataset should contain the following data variables:
        "mf"
        "fp"
        "release_lon"
        "release_lat"
        "sub_fp" (additional "sub_lon", "sub_lat" coords associated with this data variable)

    WARNING: Changes input object in place

    Args:
        fp_data_H (dict) :
            xarray.Dataset. Expects output from name.fp_sensitivity() function.
        return_release (bool) :
            Whether or not to also return the release_lats and release_lons
                                arrays.

    Returns:
        if return_release:
             tuple(dict (xarray Datasets and identifiers), np.array, np.array) :
                 fp_data_H with "local_ratio" data variable added, release_lons, release_lats
        else:
            dict (xarray Datasets and identifiers) : fp_data_H with "local_ratio" data variable added


    The average_period function resamples the input dataset along the specified dimension to the average
    period.

    Args:
        ds (xarray.Dataset) :
            Dataset containing time series dimension.
        av_period (str) :
            Averaging period to apply to timeseries dimension of dataset.
            E.g. "2H" (2 hours), "30min" or "30T" (30 minutes)
            See http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
            for list of all frequencies available.
        dim (str, optional) :
            Timeseries dimension within Dataset. Default = "time".

    Returns:
        xarray.Dataset:
            original dataset averaged along the specified dimension


    The average_period_fp function resamples all datasets within a footprints_data_merge() dictionary over
    the averaging periods.
    Note: av_period_site should contain the same number of entries as there are sites in fp_data_H

    WARNING: Datasets within dictionary are changed in place.

    Args:
        fp_data_H (dict) :
            Dictionary of datasets. Output from footprints_data_merge() function.
        av_period (list) :
            Averaging periods (str objects), one for each site.
            E.g. "2H" (2 hours), "30min" or "30T" (30 minutes)
        dim (str,optional) :
            Timeseries dimension within Dataset. Default = "time".

    Returns:
        dict:
            fp_data_H with datasets averaged along the specified dimension


    The reorder_dims function orders the dimensions to always have the first_dims before
    any other dimensions e.g. 'time'

    All other dimensions should retain their previous order as long as they are consistent
    between data variables e.g. if "height","lat" on one data variable and "lat","height" on
    another then one of these will be rearranged.

    Use ds.transpose() function.

    Args:
        fp_data_H (dict) :
            Dictionary of datasets. Output from footprints_data_merge() function.
        first_dims (list) :
            Dimensions to always include first.
            Default = ["time"]

    Returns:
        dict:
            fp_data_H with re-ordered dimensions


    The mcmc_param_type function defines the names of expected input parameters from the config file and
    the required Python object types.

    The mcmc_param_type output is currently based on an input template configuration file:
        $ACRG_PATH/acrg_config/templates/tdmcmc_template.ini

    WARNING: The description that follows may be subject to change, always check the template config file.
    The section headings are split into three section groups for the input parameters:
        'MEASUREMENTS' - details related to the measurements made
        'MCMC'         - parameters for running the mcmc model
        'TDMCMC'       - parameters for running the tdmcmc model (in addition to mcmc parameters needed)

    Returns:
        nested OrderedDict of sections and parameters within the configuration file

    e.g.
    OrderedDict([('MEASUREMENTS',
              OrderedDict([('sites', list),
                           ('species', str),
                           ('start_date', str),
                           ('end_date', str),
                           ('domain', str),
                           ('network', str)])),
             ('MCMC.MEASUREMENTS',
              OrderedDict([('meas_period', list), ('av_period', list),('max_level',int))])),
             ('MCMC.ITERATIONS',
              OrderedDict([('nIt', int), ('burn_in', int), ('nsub', int)])),
             ('MCMC.BASIS_FUNCTIONS',
              OrderedDict([('fp_basis_case', str), ('bc_basis_case', str)])),
             ('TDMCMC.SET_UP',
              OrderedDict([('reversible_jump', bool),
                           ('kmin', int),
                           ('kmax', int),
                           ('k_ap', int)])),
             ('MCMC.PDFS',
              OrderedDict([('x_pdf0', int),
                           ('pdf_param1_pdf0', int),
                           ('pdf_param2_pdf0', int),
                           ('sigma_model_pdf', int)])),
             ('MCMC.HYPERPARAMETERS',
              OrderedDict([('pdf_param10', float),
                           ('pdf_param20', float),
                           ('pdf_p1_hparam10', float),
                           ('pdf_p1_hparam20', int),
                           ('pdf_p2_hparam10', float),
                           ('pdf_p2_hparam20', int)])),
             ('MCMC.MODEL_UNCERTAINTY',
              OrderedDict([('sigma_model_ap', float),
                           ('sigma_model_hparams', numpy.ndarray),
                           ('bl_period', int),
                           ('bl_split', bool),
                           ('levels', int)])),
             ('MCMC.STEPSIZE',
              OrderedDict([('stepsize', float),
                           ('stepsize_pdf_p1', float),
                           ('stepsize_pdf_p2', float),
                           ('stepsize_sigma_y', float),
                           ('stepsize_clon', float),
                           ('stepsize_clat', float),
                           ('stepsize_bd', int)])),
             ('MCMC.COVARIANCE_MATRIX',
              OrderedDict([('inv_type', str),
                           ('tau_ap', float),
                           ('tau_hparams', numpy.ndarray),
                           ('tau_pdf', int),
                           ('stepsize_tau', float)])),
             ('MCMC.FILTERS', OrderedDict([('filters', list)])),
             ('MCMC.PARALLEL_TEMPERING',
              OrderedDict([('parallel_tempering', bool), ('nbeta', int)])),
             ('MCMC.OUTPUT',
              OrderedDict([('output_dir', str), ('unique_copy', bool)]))])


    The regenerate_config function regenerates the tdmcmc configuration file (usually named
    param.ini).

    WARNING: This will overwrite the original configuration file.

    Args:
        config_file (str):
            Name of configuration file to regenerate (overwrite).
            Default = $ACRG_PATH/acrg_tdmcmc/param.ini

    Returns
        None

        Writes to file.


    The essential_parameters function defines the set of parameters which need to be specified within the
    configuration file.

    TODO: Add any additional essential parameters to this function as the configuration set-up changes
    and expands.

    Args:
        section_group (str/None, optional):
            Allows selection of optional parameters for a particular section_group.
            Should be one of: "MEASUREMENTS","MCMC","TDMCMC"
            If None is specified, essential parameters for all section_groups will be returned

    Returns:
        list:
            Essential parameters for MCMC code


    The add_defaults function adds any default values if they have not been explictly specified within
    the input configuation file.

    The current defaults that can be added are:
        "network" (within MEASUREMENTS section group) - extracted from site_info.json file
        "unique_copy" (within MCMC section group)     - set to False as a default
        "lpdm" (within MCMC section group)            - set to 'name' if value is not specified
        "include_bias" (within MCMC section group)    - set to True if value is not specified
        "fix_bc" (within MCMC section group)          - set to False if value is not specified

    TODO: Add additional defaults as the configuration set-up changes and expands.

    Args:
        param (dict) :
            Dictionary of parameter names and values.
            Output from all_mcmc_param, measurements_param, mcmc_param, tdmcmc_param functions.
        section_group (str/None, optional):
            Only apply defaults for the particular section_group.
            Should be one of: "MEASUREMENTS","MCMC","TDMCMC"
            If None is specified, defaults will be added for all section_groups

    Returns:
        dict:
            param dictionary with default values added where necessary


    The check_inputs function checks combinations of input values to ensure everything needed
    has been specified.

    Args:
        param (dict) :
            Dictionary of parameter names and values.
            Output from all_mcmc_param, measurements_param, mcmc_param, tdmcmc_param functions.
        section_group (str/None, optional):
            Only applies check applicable to the specific section group
            Should be one of: "MEASUREMENTS","MCMC","TDMCMC"
            If None is specified, checks will be applied for all section_groups

    Returns:
        dict:
            param dictionary after checks have been made with some values removed if necessary.


    The measurements_param function extracts all parameters relevant to measurement details (see mcmc_param_type for full list)

    In addition to optional_param values, parameters from optional_parameters() function for section_group="MEASUREMENTS"
    are also treated as optional when reading the configuration file.

    Args:
        config_file (str) :
            Filename for input configuration file
        #optional_param (list, optional) :
        #    Additional parameters within configuration file which are optional. If the parameter cannot be found in input file,
        #    value will set to None.
        expected_param (list, optional) :
            Additional parameters within the configuration file which much be returned.
            An error will be raised if these parameters are not present.
            See essential_parameters() for other pre-defined parameter which must be present.

    Returns:
        OrderedDict:
            parameter names and values

        If any expected or essential measurement parameter cannot be found:
            Exception raised and program exited


    The mcmc_param function extracts all parameters for the MCMC run (see mcmc_param_type for full list)

    In addition to optional_param values, parameters from optional_parameters() function for section_group="MCMC" are
    also treated as optional when reading the configuration file.

    Args:
        config_file (str) :
            Filename for input configuration file
        #optional_param (list, optional) :
        #    Additional parameters within configuration file which are optional. If the parameter cannot be found in input file,
        #    value will set to None.
        expected_param (list, optional) :
            Additional parameters within the configuration file which much be returned.
            An error will be raised if these parameters are not present.
            See essential_parameters() for other pre-defined parameter which must be present.

    Returns:
        OrderedDict:
            parameter names and values

        If any expected or essential MCMC parameter cannot be found:
            Exception raised and program exited


    The tdmcmc_param function extracts all parameters for the MCMC run (see mcmc_param_type for full list)

    In addition to optional_param values, parameters from optional_parameters() function for section_group="TDMCMC" are
    also treated as optional when reading the configuration file.

    Args:
        config_file (str) :
            Filename for input configuration file
        #optional_param (list, optional) :
        #    Additional parameters within configuration file which are optional. If the parameter cannot be found in input file,
        #    value will set to None.
        expected_param (list, optional) :
            Additional parameters within the configuration file which much be returned.
            An error will be raised if these parameters are not present.
            See essential_parameters() for other pre-defined parameter which must be present.

    Returns:
        OrderedDict:
            parameter names and values

        If any expected or essential TDMCMC parameter cannot be found:
            Exception raised and program exited


    The all_mcmc_param function extracts all parameters related to running the tdmcmc code as defined in mcmc_param_type()

    In addition to optional_param values, parameters from optional_parameters() function are also treated as optional
    when reading the configuration file.

    Args:
        config_file (str) :
            Filename for input configuration file
        #optional_param (list, optional) :
        #    Additional parameters within configuration file which are optional. If the parameter cannot be found in input file,
        #    value will set to None.
        expected_param (list, optional) :
            Additional parameters within the configuration file which much be returned.
            An error will be raised if these parameters are not present.
            See essential_parameters() for other pre-defined parameter which must be present.

    Returns:
        OrderedDict:
            parameter names and values

        If any parameter defined in mcmc_param_type() cannot be found (not specified as an optional param):
            Exception raised and program exited


    The fill_param_defaults function fills in a set of names with defaults if the values
    are not specified.
    Relevant to tdmcmc_time.py script.


    The open_config function is used to open configuration files in the ini format.

    Args:
        config_file (str):
            Filename for input configuration file (str).

    Returns:
        configparser.ConfigParser object


    The generate_param_dict function creates a param_type nested dictionary from an input configuration
    file.
    This could be used on some fixed template config file to generate the parameter type dictionary which
    can then be applied to other configuration files of the same type.

    Args:
        config_file (str) :
            Filename for template configuration file (str).

    Returns:
        nested OrderedDict :
            Parameter type dictionary from configuration file input with sections as keys for parameters
            and value types.


    The generate_from_template function generates an example configuration file based on
    a template file. Template files are normally used to inform the expected format of any
    input configuration file.

    Args:
        template_file (str) :
            Input template file in expected .ini format.
        output_file (str) :
            Name of output file including path information.

    Returns
        None

    Writes output file.

    If output file is already present, the user will be asked whether the file should be
    overwritten. If the response is 'N' or 'no' or an unrecognised input an exception will
    be raised.


    The str_check function is used as part of checking the input from a configuration file.
    This function ensures the input remains as a string and removes any " or ' characters

    Args:
        string (str) :
            Value input from config file
        error (bool, optional) :
            Print error message if unable to evaluate (bool).

    Returns:
        string (formatted)


    The eval_check function evaluates the input string from a configuration file to a python object.
    For example:
        - '1' would evalute to an int object 1
        - '1.' or '1.0' would evaluate to float object 1.0
        - "[1,2,3]" would evalute to a list object [1,2,3]
        - "1,2,3" would evaluate to a tuple object (1,2,3)
    See eval() documentation for full list

    Args:
        string (str) :
            Value input from config file
        error (bool, optional) :
            Print error message if unable to evaluate.

    Returns:
        Python object

        If unable to convert string to python object:
            None


    The list_check function converts input string to a list.

    Args:
        string (str) :
            Value input from config file
        force_convert (bool, optional) :
            Specifies whether conversion to a list should be forced. (i.e. out = [out] if unable to
            evaluate any other way). Default = True
        error (bool, optional) :
            Print error message if unable to evaluate.

    Returns:
        List

        If unable to convert to list:
            None


    The convert function converts the input string to the specified value_type.
    If no value_type is stated, the function attempts to discern the appropriate type.

    Args:
        string (str) :
            Value input from config file
        value_type (str/None, optional) :
            Object type. Values accepted: "str","list"

    Returns:
        Python object of specified type

        If unable to convert to value_type:
            None
        If unable to find a suitable type when value_type is not specified:
            None


    The all_parameters_in_param_type function extracts all parameters (regardless of section/section_group) for a given
    param_type nested dictionary.

    Args:
        param_type (dict) :
            Nested dictionary of expected parameter names and types.
            Key for each parameter dictionary can be the section heading or the overall group (e.g. for [MCMC.MEASUREMENTS], section group should be 'MCMC').
            See module header for expected formats of param_type dictionary.

    Returns:
        list :
            list of all parameters in param_type dictionary


    The find_param_key function checks whether the keys within the param_type dictionary are for sections
    (e.g. 'MCMC.MEASUREMENTS') or groups (e.g. 'MCMC') and returns the relevant key(s).
    One of section or section_group should be specified.
    Returned key_type is one of 'section' or 'section_group'.

    Args:
        param_type (dict) :
            Nested dictionary of expected parameter names and types.
            Key for each parameter dictionary can be the section heading or the overall group (e.g. for [MCMC.MEASUREMENTS], section group should be 'MCMC').
            See module header for expected formats of param_type dictionary.
        section (str, optional) :
            Name of section in config file for the parameter
        section_group (str, optional) :
            Name of group in config file for the parameter

    Returns:
        list,str:
            keys, key_type


    The extract_params function extracts parameter names and values from a configuration file.
    The parameters which are extracted is dependent on whether the section, section_group and/or names
    variables are specified.
    A param_type dictionary can be defined to ensure variables are cast to the correct types.

    Args:
        config_file (str) :
            Filename for input configuration file.
        expected_param (list, optional) :
            Parameters within the configuration file which must be returned.
            An error will be raised if these parameters are not present.
        section (list/str/None, optional) :
            Extract parameters from section name(s).
        section_group (list/str/None, optional) :
            Extract parameters from all sections with this group (these groups).
            If section and section_group are both specified - section takes precedence.
        names (list, optional) :
            Parameter names to extract (within section or section_group, if specified)
        ignore_sections (list, optional) :
            Sections to ignore when reading in the configuration file (even if parameters are specified).
        ignore_section_groups (list, optional) :
            Sections groups to ignore when reading in the configuration file (even if parameters are specified).
        #optional_param (list, optional) :
        #    Parameters within configuration file which are optional. If the parameter cannot be found in input file,
        #    value will either be set to None or not included within the output dictionary (dependent on input for
        #    exclude_not_found option).
        #optional_section (list, optional) :
        #    If param_type is specified, all parameters within a section are treated as optional
        #    parameters.
        #    Note: if param_type dictionary is based on section groups and not sections, this
        #    input cannot be used to identify the optional parameters.
        #optional_section_group (list, optional) :
        #    If param_type is specified, all parameters within a section group are treated as
        #    optional parameters.
        exclude_not_found (bool, optional) :
            Whether to remove parameters which are not found in the input file or include them
            as None.
            Default = True.
        allow_new (bool, optional) :
            If a param_type is specified, whether to allow unrecognised parameters to be added
            without printing a warning.
            Default = False.   (i.e. Warning will be printed)
        param_type (dict, optional) :
            Nested dictionary of sections or groups and expected parameter names and types.
            See module header for expected formats of param_type dictionary.

    Returns:
        OrderedDict :
            Parameter names and values

        If parameter cannot be found (not specified as an optional param)
            Exception raised and program exited


    The all_param function extracts all parameters from a config file.
    If param_type specified will cast to the specified types, otherwise will attempt to discern the parameter types from the form of the values.

    Args:
        config_file (str) :
            Filename for input configuration file
        #optional_param (list, optional) :
        #    Parameters within configuration file which are optional. If the parameter cannot be found in input file,
        #    value will either be set to None or not included within the output dictionary (dependent on input for
        #    exclude_not_found option).
        expected_param (list, optional) :
            Parameters within the configuration file which must be returned.
            An error will be raised if these parameters are not present.
        param_type (dict, optional) :
            Nested dictionary of sections or groups and expected parameter names and types.
            See module header for expected formats of param_type dictionary.
        exclude_not_found (bool, optional) :
            Whether to remove parameters which are not found in the input file or include them as None.
        allow_new (bool, optional) :
            If a param_type is specified, whether to allow unrecognised parameters to be added
            without printing a warning.
            Default = False.   (i.e. Warning will be printed)

    Returns:
        OrderedDict:
            Parameter names and values


    Use git describe to return the latest tag (and git hash if applicable).

    Returns
    -------
    version : String defining the version of the code used, or "Unknown" if git is unavailable


Convert Julian dates (e.g. from IDL) to datetime


    Convert to hours

    Returns in the input provided, float or list of floats


Update data variables and coordinates of Dataset based on attributes dictionary.

    If `units` provided, data variables with "units" attribute will be rescaled by `units`. This is to convert e.g.
    from 1e-9 mol/mol to mol/mol.


Convert `time` coordinate of xarray Dataset or DataArray to number of "units" since
    1 Jan 1970 (the "UNIX epoch").


Compute the matrix "dot" of a tuple of DataArrays with sparse.COO values.

    This multiplies and sums over all common dimensions of the input DataArrays, and
    preserves the coordinates and dimensions that are not summed over.

    Common dimensions are automatically selected by name. The input arrays must  have at
    least one dimension in common. All matching dimensions will be used for multiplication.

    NOTE: this function shouldn't be necessary, but `da1 @ da2` doesn't work properly if the
    values of `da1` and `da2` are `sparse.COO` arrays.

    Args:
        da1, da2: xr.DataArrays to multiply and sum along common dimensions.
        debug: if true, will print the dimensions of the inputs to `sparse.tensordot`
            as well as the dimension of the result.
        along_dim: name

    Returns:
        xr.DataArray containing the result of matrix/tensor multiplication

    Raises:
        ValueError if the input DataArrays have no common dimensions to multiply.


Align lat/lon coordinates of sparse_da with lat/lon coordinates from other_array.

    NOTE: This is a work-around for an xarray Issue: https://github.com/pydata/xarray/issues/3445

    Args:
        sparse_da: xarray DataArray with sparse underlying array
        other_array: xarray Dataset or DataArray whose lat/lon coordinates should be used
            to replace the lat/lon coordinates in sparse_da

    Returns:
        copy of sparse_da with lat/lon coords from other_array


Calculate country stats.


Make flux output dataset


Returns dict to rename data vars and list of data vars to drop.


Create formatted PARIS emissions and concentrations datasets.

    Args:
        species: species used in inversion
        output_file_path: path to directory containing RHIME outputs
        country_files_root: path to directory containing country files
        avr_obs_period: the averaging period for measurements used in inversion
        n_files: number of output files to process. This is mainly to keep runs small for testing.
        return_concentrations: if False, only country and flux outputs are returned. (None is returned for concentrations.)
        report_mf_mode: if True, use mode for concentration prior/posterior predictives (i.e. for y and y BC)
        report_em_mode: if True, use mode for country and flux prior/posterior totals
        pol_from_obs: if True, this means that pollution_events_from_obs=True was specified

    Returns:
        emissions dataset and concentrations dataset


Calculate trace(s) for total country emissions.

        Args:
            species: name of species, e.g. "co2", "ch4", "sf6", etc.
            x_trace: xr.DataArray or xr.Dataset with coordinate dimensions ("draw", "nx").
                Note: "nx" be replaced with another name, as long as the same coordinate name
                was used in `get_x_to_country_matrix`.
            x_to_country: xr.DataArray with result from `get_x_to_country_mat`

        Returns:
            xr.DataArray with coordinate dimensions ("country", "draw")

        TODO: there is a "country unit" conversion in the old code, but it seems to always product
              1.0, based on how it is used in hbmcmc


Merge in another Countries object (in-place).

        Args:
            other: (list of) Countries object(s) to merge into this Country object.

        Returns:
            None (updates in-place)


Take raw RHIME output and rename/drop/create variables to get dataset ready for further processing.


Convert `nmeasure` dimension to multi-index over `site` and `time.`


Make InversionOutput object from RHIME output dataset.


Sample prior and posterior predictive distributions.

        This creates prior samples as a side-effect.


Extract y and mu_bc traces, calculate stats, and combine along time axis.


Adjust `time` coordinate of concentrations to represent half averaging "period".


    Parses all PyMC continuous distributions:
    https://docs.pymc.io/api/distributions/continuous.html

    Args:
        name:
          name of variable in the pymc model
        prior_params:
          dict of parameters for the distribution, including 'pdf' for the distribution to use.
          The value of `prior_params["pdf"]` must match the name of a PyMC continuous
          distribution: https://docs.pymc.io/api/distributions/continuous.html
        **kwargs: for instance, `shape` or `dims`

    Returns:
        continuous PyMC distribution

    For example:
    ```
    params = {"pdf": "uniform", "lower": 0.0, "upper": 1.0}
    parse_prior("x", params, shape=(20, 20))
    ```
    will create a 20 x 20 array of uniform random variables.

    Alternatively,
    ```
    params = {"pdf": "uniform", "lower": 0.0, "upper": 1.0}
    parse_prior("x", params, dims="nmeasure"))
    ```
    will create an array of uniform random variables with the same shape
    as the dimension coordinate `nmeasure`. This can be used if `pm.Model`
    is provided with coordinates.

    Note: calling `parse_prior` inside a `pm.Model` context (i.e. after `with pm.Model()`)
    has an important side-effect of registering the random variable with the model. Typically,
    `parse_prior` will be used in a `pm.Model` context, although it could be used to construct
    random variables for other purposes.


Create arviz InferenceData with posterior group created from RHIME output.


Merge prior, prior predictive, posterior, and posterior predictive samples into a single
    xr.Dataset.


Return xr.DataArray of quantiles computed over dimension `sample_dim`.

    NOTE: xarray has a .quantiles method built in, maybe we should use this.


Calculate the (KDE smoothed) mode of a data array containing MCMC
    samples.

    This can be parallelized if you chunk the DataArray first, e.g.

    da_chunked = da.chunk({"basis_region": 10})


Create lat and lon corner grids (for pcolormesh+xESMF etc) from geoData
    input
        geoData - dataframe from group "PRODUCT/SUPPORT_DATA/GEOLOCATIONS" of TROPOMI netCDF file

    return
        lat - 2d array of latitude grid corners
        lon - 2d array of longitude grid corners


Combine important information from different netCDF groups into a single data frame

    input
        filename - string of full filename for TROPOMI file

    return
        tropomi_data - dataframe containing mixing ratio, quality flags, grid data, and column data
                        the "qa_pass" flag variable is True for good measurements and False for bad measurements


    The gosat_add_coords function adds co-ordinates to a GOSAT dataset.
    This is valid for (at least) v6 of GOSAT CH4 Proxy Level 2 Data Product downloaded from the CCI Open Data Portal
    (e.g. filename of the form: ESACCI-GHG-L2-CH4-GOSAT-OCPR-20101231-fv6.nc)

    This assumes the input Dataset will be of the form:
        <xarray.Dataset>
        Dimensions:                           (m: 20, n: 1962)
        Dimensions without coordinates: m, n
        Data variables:
            xch4_quality_flag                 (n) int8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ...
            ch4_profile_apriori               (n, m) float32 1751.95 1751.95 1751.94 ...
            xch4                              (n) float32 1644.78 1657.72 1648.04 ...
            ...
        Attributes:
            title:                     ESA CCI GOSAT OCPR CH4
            institution:               University of Leicester (UoL), UK
            ...

    i.e. with no coordinates assigned for the two dimensions within the Dataset.
    This function redefines "m" as "time" and "n" as "level" and adds the associated values as coords.

    Args:
        ds (xarray.Dataset) :
            GOSAT CH4 Level 2 Data Product file opened with xarray as a Dataset.
        data_vars (list) :
            Data variables which will have the time and level (where appropriate) dataset coords added
            If data_vars if left blank ([] by default) coords will be added to all data variables within ds.

    Returns:
        ds (xarray.Dataset) :
            Dataset with time and level coordinates assigned
            (only includes specified data variables unless left blank)


    The add_history_attr adds or modifies the "history" attributes to include details of the modifications
    made to the original data.
    When history attribute is first created a timestamp is added of the current time.
    Note: Expect an additional attribute based on mod_attr has been added which contains details of the
    modification.

    Args:
        ds (xarray.Dataset) :
            Input Dataset.
        mod_attr (str) :
            Name of attribute which includes details of modification. This string will be added to the
            history attribute.
    Returns:
        xarray.Dataset:
            Input dataset with history attribute added or modified.


    The ds_check_internal_unique function checks whether an xarray.Dataset has repeat values on the "time" axis.
    Any time values which are repeated are modified by a small time increment to make the values unique.

    Args:
        ds (xarray.Dataset):
            Dataset with time axis.
        axis (str, optional):
            Name of time axis.
            Default = "time"

    Returns:
        xarray.Dataset:
            If no repeats are present:
                Original dataset is returned
            If repeats are present:
                The repeats of any time values are modified by applying a small random increment so the time values
                are not identical.


    The find_network function identifies the associated networks for a given site from the
    "acrg_site_info_2018.json" file.
    Args:
        site (str) :
            Site identifier. See "acrg_site_info_2018.json" for full list of options.
    Returns:
        list :
            List of networks for each site.


    The extract_dates function converts datetime objects into date strings for all values along a given dimension.
    Note: dimension should contain an array of np.datetime64 objects.

    Args:
        ds (xarray.Dataset) :
            Dataset which contains dimension specified by dim
        dim (str, optional):
            String of dimension containing datetime objects. Default = "time"
        dtype (str, optional):
            Specific dtype value to use to cast datetime object. Default = 'M8[D]'

    Returns:
        np.array (str) : dates as an array of strings


    The units function defines units for output variables.

    Data variable units defined within this function are:
        ch4_profile_apriori: ppb
        xch4: ppb
        xch4_uncertainty: ppb
        lat: degrees
        lon: degrees
        pressure_levels: hPa
        time: seconds since 1970-01-01 00:00:00
        pressure_weights: unitless
        xch4_averaging_kernel: unitless

    Args:
        name (str) :
            Name of output variable

    Returns:
        str :
            Unit of name (if present), None otherwise


    The gosat_split_output function creates a new dataset based on input index values along the
    split dimension (e.g. time).
    This is used to separate data points into subsets (usually to write out to file).

    If an ident column is specified the values within this column are also split out into a new "id" dimension.

    Note: units for each variable are set by the units() function (and so to include a unit must be
    defined there).

    Args:
        ds (xarray.Dataset) :
            Dataset with consistent dimension to split along.
        index (int/list) :
            Index value or values to use for the split.
        mapping (dict/OrderedDict, optional) :
            Mapping between the data variable names within ds and the output data variable names.
            If no mapping is specified this will use the same data variable names in input dataset
            for the output dataset.
        data_vars (list, optional) :
            Data variables within ds to include in output dataset. (list)
            If both mapping and data_vars are specified, mapping will supercede data_vars.
            If no mapping is included and data_vars if left blank ([] by default) all data variables will
            be copied.
        split_dim (str, optional) :
            Dimension to split along (i.e. that index is relevant to). Default = 'time' (str)
        ident (str, optional) :
            Data variable which includes identifier values for all data points within a bin e.g. "exposure_id".
            If ident is set then this data variable will be split out to contain an extra dimension ("id")
            The ident data variable is expected to contain some identifier for each data point separated
            by the ident_sep value (e.g. commas)
            e.g. ['2010123106380100271013,2010123106380100271014,2010123106380100271015']
        ident_sep (str, optional) :
            Separator value to use for identifier column.
            Default is a comma (','). Only used if ident is set.

    Returns:
        xarray.Dataset :
            Dataset containing values specified by indices along split_dim (e.g. time)
            Identifier column will be split into an extra dimension if ident is specified


    The write_netcdf function writes an xarray.Dataset to a netCDF file.
    The function will also checks whether the file exists and only overwrite if this option is set to True.

    Args:
        ds (xarray.Dataset) :
            Dataset to write to file
        filename (str) :
            Filename (including path information) for the output file
        overwrite (bool) :
            Whether to overwrite an existing file if present.
            Default = False

    Returns:
        None

        Writes dataset to file (filename)


    The gosat_output_filename function creates an output filename of the correct format for gosat based on the
    inputs.

    Filenames are of the form: "instrument"_gosat_"date (reformated)"-"num"_"species"-"inlet".nc
    e.g. /shared_data/air/shared/obs/GOSAT/GOSAT-INDIA/gosat-fts_gosat_20120920-09_ch4-column.nc

    Args:
        output_directory (str) :
            Top level for output directory e.g. "/shared_data/air/shared/obs/"
        network (str) :
            Which network is being considered e.g. "GOSAT/GOSAT-INDIA"
            This will be used to create the output path e.g. "/shared_data/air/shared/obs/GOSAT/GOSAT-INDIA/"
        instrument (str) :
            Instrument on satellite being used. e.g. "gosat-fts"
        date (str) :
            Date the measurements are relevant to e.g. "2010-01-01"
        species (str) :
            Species being considered e.g. "ch4". Should be defined within "openghg/supplementary data species_info.json" file
        inlet (str/None, optional) :
            Additional information to add to ch4 measurement e.g. column
        num (str/None, optional) :
            Number to append to the filename if gosat data is being written out as multiple files over one day.

     Returns:
         str:
             GOSAT observation filename with path information


    The gosat_output function creates output netCDF files each containing data related to one data point per file.
    The data variables within each netCDF file are:
        "ch4_profile_apriori","lat","lon","pressure_levels","pressure_weights","xch4","xch4_averaging_kernel",
        "xch4_uncertainty"
    Units for these values are set by the units() function.

    Args:
        ds (xarray.Dataset) :
            GOSAT CH4 Level 2 Data Product file as an xarray Dataset.
            Should have had co-ordinates and dimensions assigned with gosat_add_coords() function.
        site (str) :
            Specified sub-set defined for gosat e.g. GOSAT-INDIA (should be defined within site_info.json)
        species (str, optional) :
            Species of interest e.g. "ch4" (should be defined within species_info.json).
            Default = "ch4"
        file_per_day (bool, optional) :
            Output all results to one file per day rather than splitting out per time point. Default = False.
        output_directory (str, optional) :
            Top level directory to write output. Full path will be based on the "network" related to "site" .
            Default = obs_directory (defined at top of file).
        overwrite (bool, optional) :
            Whether to overwrite any files already present in the output_directory + network folder.
            Default = False.

    Returns:
        None

        Writes output to multiple .nc files (split on time axis).


    The gosat_output_name function creates a csv file in the correct format for input into NAME-III.
    Note: it is assumed input pressure values are in hPa values and so are converted to Pa for NAME (*100.)

    Args:
        ds (xarray.Dataset) :
            GOSAT CH4 Level 2 Data Product file as an xarray Dataset.
        site (str) :
            Specified sub-set defined for gosat e.g. GOSAT-INDIA. Should be defined within site_info.json.
            Note: at the moment this is just used in the filename and not in the folder structure
        max_level (int, optional) :
            Maximum level to include from input GOSAT data (up to 20).
            At the moment NAME footprints go up to 19km which corresponds to level 17 in GOSAT.
        use_name_pressure (bool, optional) :
            Whether to use the NAME surface pressure rather than the GOSAT surface pressure value for each data
            point.
        pressure_domain (str, optional) :
            Domain over which surface pressure values have been extracted (can be distinct from
            domain if pressure_domain contains area of domain).
            Must be included if use_name_pressure=True.
            Check $DATA_PATH/LPDM/surface_pressure folder to see which domains currently exist.
        pressure_base_dir (str, optional) :
            Base directory containing the NAME output files for the SurfacePressure run.
            Filename is assumed to be of the form "Pressure_C1_*.txt"
            See name_pressure_file() function for more details.
        pressure_max_days (int, optional) :
            Number of days tolerance to allow when using time stamp to find relevant NAME pressure values.
            Default = 31 (days).
        pressure_day_template (bool, optional) :
            Use nearest day as a template for the change of pressure over the course of the day and match
            to the nearest time on that day.
            E.g. if datetime is 2012-05-01 03:00:00, max_days is 31 and nearest day is 2012-01-01 then
            use entry from 2012-01-01 03:00:00 (rather than 2012-02-01 00:00:00, which would be the
            nearest entry).
            Default = True.
        name_directory (str, optional) :
            Top level directory to write files for NAME. Full path will be based on the "network" related to "site"
            Default defined at the top of this module.
        file_per_day (bool, optional) :
            Output all results to one file per day rather than splitting out per time point.
            Default=False.
        max_points (int/None, optional) :
            Only applicable if file_per_day is True.
            Maximum number of points to write if writing file per day. If number of points within the day
            exceeds max_points multiple files will be written out with a character after the date of "-A","-B",...
        overwrite (bool, optional) :
            Allow any files already present within the full path to name_directory to be overwritten.
            Default = False

    Returns:
        None

        Writes output to multiple .csv files (split on time axis).


    Calculate equivalent difference in latitude for a distance in km.

    Args:
        distance (int/float) :
            Distance in km.
        radius (int/float, optional)   :
            Radius of the Earth (default to 6371km)

    Returns:
        float :
            Latitude difference in degrees


    Calculate equivalent difference in longitude for a distance in km at a given latitude.

    Args:
        distance (int/float) :
            Distance in km.
        lat (int/float) :
            Latitude in degrees (between but not including -90 and +90. Note: max value = 89.995)
        radius (int/float) :
            Radius of the Earth (default to 6371km)

    Returns:
        float :
            Longitude difference in degrees


    The define_pressure_levels function scales the pressure_levels and dpressure values for input into NAME.
    Note: values to be output to obs/ files *should NOT* be run through this function.

    The pressure_levels provided with the GOSAT data (in particular) define instantaneous pressure points and not the boundaries or
    midpoints of each of the layers.
    The first pressure level (pressure_0) is treated as the surface pressure value.

    To create layers from these pressure levels the boundaries are defined as the midpoint between each level. If the levels are
    unevenly spaced the pressure levels themselves are then re-defined to be at the midpoint within each layer
    (or as the edge if set_as_edges=True). The top and bottom layer are treated as follows:
         - Bottom layer - Either whole or 1/2 difference between NAME or satellite surface pressure is used to define layer extent and
                          boundaries depending on if set_as_edges is True or False.
         - Top layer - set layer extent and as matching previous level value OR set layer extent and boundaries based on a minumum
                       pressure (set as 0 hPa), whichever dpressure is smaller.

    Args:
        ds (xarray.Dataset) :
            Dataset containg multiple data points with a set of pressure levels for each.
        pressure_domain (str/None, optional) :
            Domain over which surface pressure values have been extracted (can be distinct from
            domain if pressure_domain contains area of domain).
            Must be specified if pressure_NAME is not included explicitly.
            Check $DATA_PATH/LPDM/surface_pressure folder to see which domains currently exist.
        p_column (str, optional) :
            Name for the pressure_levels data (str). Default = "pressure_levels"
        set_as_edges (bool, optional) :
            Whether to treat the pressure levels as points at the edge of the layers rather than within the layers .
            Default = False.
            Note: level 0 will ALWAYS be treated as being the surface pressure (i.e. at the boundary) regardless
            of this parameter.
        include_bounds (bool, optional)   :
            Whether to output the boundary values for the layers as well as the pressure_levels and dpressure.
            Default = False.
        use_name_pressure (bool, optional) :
            If to use the NAME surface pressure rather than the GOSAT value included within the data.
            Default = False.
        pressure_NAME (numpy.array, optional) :
            This and the following parameters are only used when use_name_pressure=True.
            If pressure from NAME run has already been extracted, this can be specified with this parameter to
            save computing time.
            If not specified, columns from ds and pressure_base_dir and pressure_domain will be used to extract matching
            pressure values.
        columns (list, optional) :
            Names of data variables or co-ords within input Dataset for the latitude, longitude and time values
            (3 item list). Default = ["latitude","longitude","time"]
        pressure_dir (str, optional) :
            Base directory containing the NAME output files for the SurfacePressure run.
            Filename is assumed to be of the form "Pressure_C1_*.txt"
            See name_pressure_file() function for more details.
        max_days (int, optional) :
            Maximum number of days from time within ds to search for the relevant pressure data.
            Default = 31 (days).
        day_template (bool, optional) :
            Use nearest day as a template for the change of pressure over the course of the day and match
            to the nearest time on that day.
            E.g. if datetime is 2012-05-01 03:00:00, max_days is 31 and nearest day is 2012-01-01 then
            use entry from 2012-01-01 03:00:00 (rather than 2012-02-01 00:00:00, which would be the
            nearest entry).
            Default = True.

    Returns:
        if include_bounds == True:
            (np.array,np.array,np.array):
                pressure_levels,dpressure,pressure_bounds
        else:
            (np.array,np.array):
                pressure_levels,dpressure


    The name_pressure_match function finds the corresponding NAME surface pressure values based on a set of
    lat,lon and time values extracted from the input dataset.

    Args:
        ds (xarray.Dataset) :
            Dataset containing pressure values to match the NAME surface pressure values to. Within the
            dataset the pressure values should be related to latitude, longitude and time values.
        pressure_domain (str) :
            Domain over which surface pressure values have been extracted (can be distinct from
            domain if pressure_domain contains area of domain).
            Check $DATA_PATH/LPDM/surface_pressure folder to see which domains currently exist.
        columns (list, optional) :
            Names of data variables or co-ords within input Dataset for the latitude, longitude and time values.
            Default = ["latitude","longitude","time"]
        pressure_base_dir (str, optional) :
            Base directory containing the NAME output files for the SurfacePressure run.
            Filename is assumed to be of the form "Pressure_C1_*.txt"
            See name_pressure_file() function for more details.
        pressure_convert (float, optional) :
            If pressure values extracted from NAME are not in the required units, pressure_convert
            should be set to the scaling factor to convert these units.
            By default, we assume we want to convert to hPa from NAME input in Pa (pressure_covert=1/100.)
        max_days (int, optional) :
            Number of days tolerance to allow when using time stamp to find relevant NAME pressure values.
            Default = 31 (days).
        day_template (bool, optional) :
            Use nearest day as a template for the change of pressure over the course of the day and match
            to the nearest time on that day.
            E.g. if datetime is 2012-05-01 03:00:00, max_days is 31 and nearest day is 2012-01-01 then
            use entry from 2012-01-01 03:00:00 (rather than 2012-02-01 00:00:00, which would be the
            nearest entry).
            Note: Assumes NAME run for e.g. 2012-01-01 ends with datetime 2012-02-01 00:00:00.
            Default = True.

    Returns:
        numpy.array :
            Array of pressure values. One for each lat,lon,time value.


    The name_pressure function extracts the pressure values from a special NAME run to find surface pressure
    values across a given domain.
    These values will often be spread over multiple files and this function can take several files from a
    directory and create one dataset.

    Args:
        directory (str) :
            Directory containing the NAME output files for the SurfacePressure run.
        start_date (str, optional) :
            Start date range of interest for the pressure values.
        end_date (str, optional) :
            End date range of interest for the pressure values (optional)
        name (str, optional) :
            Name to use when creating new pressure data variables within output Dataset.
            Default = "surface_pressure"
        column_names (list, optional) :
            Names for co-ordinate axes within dataset. Should be a 3-item list for latitude, longitude and time.
            Default = ["latitude","longitude","time"]
        set_columns (list, optional) :
            Column names within input file which contain longitude, latitude and height (in that order).
            Function assumes these columns will be the first in the file and all other populated columns
            contain the surface pressure (or topography) values.
            Default = ["X (Lat-Long)","Y (Lat-Long)","Z (m agl)"] based on current BackRuns script.
        max_days (int, optional) :
            Number of days tolerance to allow when using time stamp to find relevant NAME pressure values.
            Default = 31 (days).

    Returns:
        xarray.Dataset :
            Surface pressure data covering at least start_date - end_date range (if specified)


    The ds_check_unique function checks for any repeats between two datasets on the dim_apply axis.
    Any repeats are removed from the first dataset (ds1) and returned.

    Args:
        ds1 (xarray.Dataset) :
            First Dataset with dim_apply dimension
        ds2 (xarray.Dataset) :
            Second Dataset with dim_apply dimension to compare to.
        dim_apply (str, optional) :
            Dimension to check for repeats (str). Default = "time"

    Returns:
        xarray.Dataset :
            ds1 with any matching values removed.


    The apply_filter function applies a filter array of indices to a dataset.
    All data variables with the dim_apply value as their first dimension will be filtered.

    Args:
        ds (xarray.Dataset) :
            Dataset to filter.
        filter_array (np.array) :
            Array of indices to keep within the dataset. All other indices will be removed.
        dim_apply (str, optional) :
            First order dimension to apply the filter to.
            This was almost always be "time" (default) but is included here for generality.

    Returns:
        xarray.Dataset :
            Copy of ds with data variables (data_vars) filtered.


    The coord_order function determines the order of the coordinates for the data variables.

    For example for the xarray.Dataset:
        <xarray.Dataset>
            Dimensions:                (level: 3, time: 10)
            Coordinates:
              * time                   (time) datetime64[ns] 2010-01-01T01:30:00 ...
              * level                  (level) int64 0 1 2
            Data variables:
                lat                    (time) float64 nan nan 30.67 31.0 31.33 31.67 ...
                xch4_averaging_kernel  (time, level) float64 nan nan nan nan nan nan 0.0 ...

    The two coordinate axes are "time" and "level". This function would determine that "time" is only ever a first
    order coordinate (only used for axis=0) and that "level" is a second order coordinate (only used for axis=1).

    Args:
        ds (xarray.Dataset) :
            Dataset
        data_vars (list, optional) :
            Which data variables within ds to check.
            If data_vars if left blank ([] by default) all data variables will be examined.
        check_consistent (bool, optional) :
            If True: checks that each coordinate is only ever used at one order (e.g. time is only
            ever used as a first order coordinate, level as a second order coordinate etc.)

    Returns:
        If check_consistent == False:
            dict : orders as a keys each with a list of relevant coordinate names
                    e.g. {1: ["time"], 2: ["level"]}
        If check_consistent == True:
            dict, bool : dictionary as described above, boolean flag for whether order is consistent


    The name_pressure_file function extracts the pressure values from one file of a special NAME run to find surface pressure
    values across a given domain.

    NOTE: This function can also be used to extract Topography information from the same NAME run
    To do this set the filename to a topography file (e.g. "Topog_C1_T1_201201010000.txt") and the name to e.g. "topography".
    The set_columns should be the same between pressure and topography files.

    Output from:
    - BackRuns_SurfaceField.scr (with SurfaceFieldOutputRequests.txt)

    Args:
        filename (str) :
            Pressure file produced by the appropriate BackRuns script including path information.
            Current script calls this: "Pressure_C1_'YYYYMMDD'_1d.txt" e.g. "Pressure_C1_20120101_15d.txt"
        name (str) :
            Name to use when creating new pressure (or topography) data variable within output Dataset.
            Default = "surface_pressure".
        column_names (list) :
            Names for co-ordinate axes within dataset. Should be a 3-item list for latitude, longitude and time.
            Default = ["latitude","longitude","time"]
        set_columns (list) :
            Column names within input file which contain longitude, latitude and height (in that order).
            Function assumes these columns will be the first in the file and all other populated columns
            contain the surface pressure (or topography) values.
            Default = ["X (Lat-Long)","Y (Lat-Long)","Z (m agl)"] based on current BackRuns script.
    Returns:
        xarray.Dataset :
            Dataset containing extracted information with dimensions of latitude,longitude,time


    The extract_files function extracts filenames from a directory based on a search_str and/or based on a start
    and end dates (if filename contains details of a datestamp).

    Note:
        By default if using start and end dates files of the form "*YYYYMMDD*" are expected e.g. filename_20111001.csv.
        A date_separator can also be specified between YYYY/MM and MM/DD.
        For example e.g. date_separator='-', will search for files of the form "*YYYY-MM-DD*".

    Args:
        directory (str) :
            Directory to search (str)
        search_str (str/None, optional) :
            String to use to search directory (using glob). If full filename is not specified this should
            contain at least one wildcard character ("*").
            If no search_str specified, all files from directory will be returned and filtered by any start
            and end criteria.
        start (str/None, optional) :
            Start date of the form "YYYY-MM-DD".
        end (str/None, optional) :
            End date of the form "YYYY-MM-DD". Date range is up to but not including this date.
            Either both or neither of start and end should be specified.
        date_separator (str) :
            Date separator string between year, month and day in filename.
            By default this is "", meaning dates of the form "YYYYMMDD" will be searched for.
        day (bool) :
            Expect day to be included in any date within the filename.
            If day is True expect dates of the form e.g. 20120101 or 2012-01-01.
            If day is False expect dates of the form e.g. 201201 or 2012-01

    Returns:
        list :
            Filenames as string s(full path information).


    The midpoint_bounds function uses midpoint between pressure points to define the boundaries. The pressure levels are
    then scaled to be at the centre of that boundary.

    Note:
        The assumption is made that first level represents the surface pressure (unless pressure_NAME is specified, where NAME
        surface pressure value replaces p_0).

    Args:
        pressure_levels (numpy.array) :
            Array containing pressure levels values for each data point (2D array)
        delta_pressure (numpy.array, optional) :
            Difference between the pressure levels.
        pressure_NAME (numpy.array, optional) :
            NAME surface pressure values which correspond to pressure_levels latitude, longitude and time coordinates.
            (1D numpy.array). These values can be extracted using the name_pressure_match() function.
            If this is specified, these NAME values will be used as the surface pressure values rather than the
            first level for each data point within the pressure_levels array.
        set_as_edges (bool, optional) :
            Whether to treat the pressure levels as points at the edge of the layers rather than within the layers.
            Default = False.
        calc_boundaries (bool, optional) :
            Whether to apply the necessary special conditions to calculate the bottom and top layers.
            Note: if this value is set to False, the pressure_levels and dpressure output arrays will not be the
            same length as the input pressure_levels array.
            Default = True.

    Returns:
        (np.array,np.array) :
            new_pressure_levels,dpressure


    The gosat_quality_filter function filters all data variables within a dataset by the "xch4_quality_flag" variable.
    The xch4_quality_flag equates to:
        - 0 indicates good_quality
        - 1 indicates potentially_bad_quality
    Note: the Dataset is filtered assuming all data variables have the same first dimension (will be true for GOSAT data
    but would need to check for other data)

    Args:
        ds (xarray.Dataset) :
            GOSAT CH4 Level 2 Data Product file opened with xarray as a Dataset.

    Returns:
        ds (xarray.Dataset) :
            Filtered Dataset with indices associated with xch4_quality_flag=1 removed.


    The gosat_mode_filter function filters all data variables within a dataset by the mode as determined by the "retr_flag" variable.
    Mode is either "land" or "glint" which corresponds to 0 and 1 within  "retr_flag" data variable.

    Args:
        ds (xarray.Dataset) :
            GOSAT CH4 Level 2 Data Product file opened with xarray as a Dataset.
        mode (str, optional) :
            Mode to include. Should be one of "land" or "glint". Default="land"

    Returns:
        ds (xarray.Dataset) :
            Filtered Dataset with indices relevant to specified mode remaining.


    The gosat_pressure_filter function removes all points which have at least one pressure_level undefined (-9999.99).
    Unable to use these points to calculate relevant pressure levels and difference between levels within the atmosphere.

    Args:
        ds (xarray.Dataset) :
            GOSAT CH4 Level 2 Data Product file opened with xarray as a Dataset.
            Should contain "pressure_levels" as a data variable.

    Returns:
       ds (xarray.Dataset) :
           Filtered Dataset with data points with undefined pressure levels removed.


    The latlon_filter function filters a Dataset by latitude and longitude bounds.
    The columns related to latitude and longitude should be data variables within the input Dataset.

    Args:
        ds (xarray.Dataset) :
            Dataset containing latitude and longitude data variables.
        lat_bounds (iterable) :
            Upper and lower bounds of latitude in degrees to include (two item tuple e.g. (6.0,33.5))
        lon_bounds (iterable) :
            Upper and lower bounds of longitude in degrees to include (two item tuple e.g. (23.0,71,4))
        columns (iterable, optional) :
            Data variable names for latitude and longitude (two item object ["latitude","longitude"] by default)

    Returns:
        ds (xarray.Dataset) :
            Filtered Dataset only including data between lat_bounds and lon_bounds


    The midpoint function calculates the midpoint between a set of dates. This can either be done between
    the earliest and latest dates within the list or taken recursively between each pair of dates.

    Args:
        datetimes (list/np.array) :
            Datetime array. Each element should be a numpy.datetime64 object.
        weight (bool) :
            If True: calculate the midpoint based on all elements in the list
            If False: calculate the midpoint based on the earliest and latest datetimes only.

    Return:
        numpy.datetime64 : midpoint


    The calc_mid function returns either the midpoint for a set of datetimes or the mean on the first order dimension
    (axis=0) of an array.

    Args:
        ds (xarray.Dataset) :
            Dataset containing name data variable .
        name (str) :
            Name of data variable within ds
        message (bool, optional) :
            If True, print a warning when the function is unable to find a mean based on the object type.
            Default = False

    Returns:
        mean or midpoint of ds[name] (same type as objects within ds[name] array)


    The associated_error_name function finds the name of a variable associated with an error from the name.
    Assumes name of variable and error is e.g. "xch4" and "xch4_uncertainty" where error_ident is the extra
    string added to the variable name.

    Args:
        ds (xarray.Dataset) :
            Dataset containing both error_name and associated variable
        error_name  (str) :
            Name of error data variable
        error_ident (str, optional) :
            string to be removed from error_name to extract data_variable.
            NOTE: Function assumes the original quantity with which the error is associated can be
            extracted by stripping off the error_ident (e.g. "uncertainty"). E.g. for "xch4_uncertainty"
            the name for the related quantity would be "xch4".
    Returns:
        str :
            Variable name

        If extracted variable is not found within the dataset or new variable name matches error_name:
            returns None


    The calc_mid_err function returns an error value appropriately scaled for multiple points.
    This uses the equation:
        (mean(error)**2 + std(variable)**2)**1/2

    Args:
        ds (xarray.Dataset) :
            Dataset. Note that dimensions must be used consistently for each data variable
            E.g. "time" should always be used as the first dimension, "level" as the second (if present)
        name (str) :
            Name of data variable for quantity related to error e.g. 'xch4'
        error_name (str) :
            Name of the data variable for the error quantity e.g. 'xch4_uncertainty'

    Returns:
        xarray.DataArray (1 entry):
            mean error of ds[name]


    The concat_str function concatenates the passed data variable as a string (arguments separated by "separator" e.g. ',').
    e.g. if name="exposure_id" then if the dataset contains:
    array(['2011101600560430371003', '2011101600560430372000',
       '2011101600560430372001'], dtype='|S22')
    then a string would be returned of the form
        '2011101600560430371003,2011101600560430372000,2011101600560430372001'

    Args:
        ds (xarray.Dataset) :
            Dataset containing data variable specified by name parameter.
        name (str) :
            data variable name within ds
        separator (str, optional) :
            Joining str for the string values when concatenated.
            Default = ','

    Returns:
        str :
            Values from name data variable as a string


    For a set of measurements to be averaged calculate the spread of latitude based on the maximum latitude difference
    between the points and the resolution (sounding) on each individual measurement.
        dlat = (sounding in degrees)*2 + (max(lat) - min(lat))

    Args:
        ds (xarray.Dataset) :
            Dataset which contains a data variable of latitudes (specified by lat_column)
        sounding (float, optional) :
            Footprint diameter for each individual measurement in km.
            Default = 10.5 km (this is the sounding for the GOSAT satellite)
        lat_column (str, optional) :
            Name of data variable containing latitude values within ds.
            Default = "latitude"

    Returns:
        float :
            dlat value


    For a set of measurements to be averaged calculate the spread of longitude based on the maximum longitude difference
    between the points and the resolution (sounding) on each individual measurement.
        dlon = (sounding in degrees at mean latitude)*2 + (max(lon) - min(lon))

    Args:
        ds (xarray.Dataset) :
            Dataset which contains data variables of latitude and longitude values (specified by columns)
        sounding (float, optional) :
            Footprint diameter for each individual measurement in km.
            Default = 10.5 km (this is the sounding for the GOSAT satellite)
        columns (list, optional) :
            Names of the latitude and longitude data variables (two item list).
            Default = ["latitude","longitude"]

    Returns:
        float :
            dlon value


    The mean_ds function reduces down a Dataset to the mean or midpoint of the contained data variables.
    Note: Function expects all data variables within the dataset to contain the same first dimension (axis=0).
    Note: The mean is taken over the first dimension only and any higher orders will be retained.
    Note: For datetime objects the midpoint between the earliest and latest date will be calculated.

    Args:
        ds (xarray.Dataset) :
            Dataset with consistent dimensions for each data variable. Only one first order dimension should be present.
            E.g. "time" should always be used as the first dimension, "level" as the second (if present)
        error_ident (list, optional) :
            Keywords to be used for calculting errors appropriately.
            NOTE: Function assumes the original quantity with which the error is associated can be
            extracted by stripping off the error_ident (e.g. "uncertainty"). E.g. for "xch4_uncertainty"
                        the name for the related quantity would be "xch4".
        ident (str, optional) :
            Data variable to keep as an identifier for each point within original dataset. This will be
            returned as a string concatention of the values.
                        Default = "exposure_id". If ident value is not present in dataset, no value will be used as identifier.
        dlat (str, optional) :
            Data variable to treat as latitude spread value. Default="dlat". If value is not present in dataset,
            no dlat value will be calcuated.
        dlon (str, optional) :
            Data variable to treat as longitude spread value. Default="dlon". If value is not present in dataset,
            no dlon value will be calcuated.
        coord_columns (list, optional) :
            Data variable names associated with latitude and longitude values. Used to calculate dlat and dlon.
            Default = ["latitude","longitude"].

    Returns:
        xarray.Dataset :
            Mean of all dataset values across first order dimension (axis=0)


    The create_zbin function adds an additional column to a dataset containing the midpoints of a specified lat-lon
    bin as a string. Each data point is assigned to a bin.
    The bin values will be of the form: "23.25,32.25" to indicate a position is within lat bin 23 - 23.5 and lon bin
    32 - 32.5. If a position is outside the latitude or longitude bounds the bin will contain "above" or "below"
    e.g. "above,32.25" to indicate this position is above the upper latitude bound but within lon bin 32 - 32.5.

    Adding this data variable allows the data to be easily grouped within each lat-lon bin.

    Note: if using imported GOSAT CH4 Proxy Level 2 Data Product (from the CCI Open Data Portal) you will need to
    have added the time and level coords using the gosat_add_coords() function before using this function.

    E.g. ds should be of the form:
        <xarray.Dataset>
        Dimensions:                           (level: 20, time: 1962)
        Coordinates:
          * level                             (level) int64 0 1 2 3 4 5 6 7 8 9 10 ...
          * time                              (time) datetime64[ns] 2010-12-31T00:31:51.000015 ...
        Data variables:
            xch4_quality_flag                 (time) int8 1 1 1 1 1 1 1 1 1 1 1 1 1 ...
            ch4_profile_apriori               (time, level) float32 1751.95 1751.95 ...
            xch4                              (time) float32 1644.78 1657.72 1648.04 ...
            longitude                         (time) float32 152.298 152.301 152.305 ...
            latitude                          (time) float32 -70.4105 -70.4111 ...
            ...
   i.e. with coords assigned (in this case time and level)

    Args:
        ds (xarray.Dataset) :
             Dataset with coordinates and dimensions assigned - see above.
        lat_bounds (list, optional) :
            Upper and lower bounds for latitude bins. Upper bound is included in range.
        lon_bounds (list, optional) :
            Upper and lower bounds for longitude bins. Upper bound is included in range.
        domain (str,optional) :
            Domain to take lat_bounds and lon_bounds from. This will supercede any lat_bounds and lon_bounds
            specified.
        columns (list, optional) :
            column names within ds containing the latitude and longitude positions as a two item list
            Default = ["latitude","longitude"].
        coord_bin (float/list, optional) :
            Size of each bin for latitude and longitude in degrees.
            To specify different bin sizes for latitude and longitude include a two item list
            (e.g. [0.234,0.356])
            Default = 0.5.

    Returns:
        ds (xarray.Dataset) :
            Dataset with additional "zbin" data variable


    The zbin_filter function uses the "zbin" column (added using create_zbin function) and removes any values which
    fall outside the latitude or longitude range set when creating the column (for the specified data variables or
    all if none are specified).

    See the create_zbin function for more information but a value is outside the range if the "zbin" column contains
    the word "above" or "below".

    Args:
        ds (xarray.Dataset) :
            Dataset which has "zbin" data variable created using create_zbin() function.
        dim_apply (str, time) :
            Dimension to apply filter to. Default = "time"

    Returns:
        ds (xarray.Dataset) :
            Dataset with data variables outside range removed


    The binned_mean function finds the mean within bins specified by outer latitude and longitude bounds and
    a given bin size for the input Dataset.

    Either lat_bounds AND lon_bounds OR domain must be specified.

    Args:
        ds (xarray.Dataset) :
            Dataset which contains latitude and longitude data variables (with names specified by columns).
        lat_bounds (list) :
            Upper and lower bounds for latitude bins.
        lon_bounds (list) :
            Upper and lower bounds for longitude bins.
            Either lat_bounds AND lon_bounds OR domain must be specified.
        domain (str) :
            Domain to take lat_bounds and lon_bounds from. This will supercede any lat_bounds and lon_bounds
            specified.
        coord_bin (float/list) :
            Size of each bin in degrees for latitude and longitude
            To specify different bin sizes for latitude and longitude include a two item list
            (e.g. [0.234,0.356])
            Default = 0.5
        columns (list, optional) :
            Column names within ds containing the latitude and longitude positions.
            Default = ["latitude","longitude"]
        add_spread (bool, optional) :
            Whether to add spread to dataset in the form of data variables called "dlat" and "dlon".
            Default=True

    Returns:
        xarray.Dataset :
            Dataset with mean values within each latitude and longitude bin


    The bin_check function uses a slower and simpler alternative method for binning (compared to xarray.Dataset.groupby function).
    This was built as a quick comparison method to check the output of method used in functions above.

    Args:
        filename (str) :
            Filename of GOSAT CH4 Level 2 Data Product file (str)
        lat_bounds (list, optional) :
            Upper and lower bounds for latitude. (tuple of values e.g. (6.0,36.5))
        lon_bounds (list, optional) :
            Upper and lower bounds for longitude. (tuple of values e.g. (70.0,90.5))
        domain (str, optional) :
            If lat_bounds and lon_bounds are not specified a domain can be specified instead.
        coord_bin (float/list) :
            Size of each bin in degrees (default = 0.5).

    Returns:
        np.array (3) : binned latitude, binned longitude, binned xch4 column


    The extract_files_dir_split function looks for files within sub-directories split by year.
    E.g. if directory="/data/shared/obs_raw/GOSAT/CH4_GOS_OCPR_v7.2/" then files for 2011 would be within
    "/data/shared/obs_raw/GOSAT/CH4_GOS_OCPR_v7.2/2011/"

    Args:
        directory (str) :
            Top level directory.
        search_str (str/None, optional) :
            String to use to search directory (using glob). If full filename is not specified this should
            contain at least one wildcard character ("*").
            If no search_str specified, all files from directory will be returned and filtered by any start
            and end criteria.
        start (str/None, optional) :
            Start date of the form "YYYY-MM-DD".
        end (str/None, optional) :
            End date of the form "YYYY-MM-DD". Date range is up to but not including this date.
            Either both or neither of start and end should be specified.
        date_separator (str, optional) :
            Date separator string between year, month and day in filename.
            By default this is "", meaning dates of the form "YYYYMMDD" will be searched for.

    Returns:
        list :
            Filenames as string s(full path information).


    The name_topog_match function finds the corresponding topography values based on a set of lat,lon coordinates.
    Note: expect lat,lon arrays are the same length and each set of axis corresponds to a pressure value at
    that lat,lon coord.
    Note: Uses first topography file found within relevant folder and does not check the date.

    Args:
        ds (xarray.Dataset) :
            Dataset containing latitude and longitude values values to match the NAME topography values to.
        pressure_domain (str) :
            Domain over which topography (and surface pressure) values have been extracted (can be
            distinct from domain if pressure_domain contains area of domain).
            Check $DATA_PATH/LPDM/surface_pressure folder to see which domains currently exist.
        columns (list, optional) :
            Names of data variables or co-ords within input Dataset for the latitude and longitude values.
            Default = ["latitude","longitude"]
        name (str, optional) :
            Name to use when creating new pressure data variables within output Dataset.
            Default = "topography"
        topog_base_dir (str, optional) :
            Base directory containing the NAME output files for the SurfacePressure run also
            containing topography information.
            Filename is assumed to be of the form "Topog_C1_T1_*.txt"
            See name_pressure_file() function for more details.

    Returns:
        numpy.array :
            Array of topography values. One for each lat,lon pair.


    The name_pressure_filter function removes any data points from a dataset which does not match the criteria set out
    by the filters parameter (and associated values).
    Filter options include:
        - cutoff based on a percentage difference between NAME and first pressure level
        - check NAME surface pressure is greater than (i.e. below in height) the second pressure level
        - check rough extent of the surface layer based on NAME pressure and second pressure level is in a certain range

    Note:
        Surface pressure level is (currently) defined as p0, where p0 is the first pressure level.
        This is correct for the GOSAT Level 2 Product based on the CCI GHG Documentation for level-based extraction:
            http://www.esa-ghg-cci.org/index.php?q=webfm_send/160

    Args:
        ds (xarray.Dataset) :
            Dataset containing pressure values with multiple pressure_levels defined for each data point.
        filters (list) :
            Which filters to apply based on NAME surface pressure
             - "cutoff": remove all points where surface pressure is outside a cutoff value compared to NAME
             - "level_order": remove all points where NAME surface pressure is less than pressure level 2
             - "dpressure_range": remove all points where NAME surface layer is outside a range of sizes.
        pressure_NAME (np.array, optional) :
            If pressure from NAME run has already been extracted, this can be specified explicitly to save
            computing time.
            If not specified, columns from ds and pressure_dir will be used to extract matching pressure values.
        columns (list, optional) :
            Names of the latitude, longitude, time and pressure variables to extract from input Dataset.
            This should be a 4-item list. Default = ["latitude","longitude","time","pressure_levels"]
            Note: Latitude, Longitude and Time are used to match to NAME pressure values.
        cutoff (float, optional) :
            Only used when "cutoff" is within filters. Percentage cutoff to apply from comparison between
            input pressure data and NAME pressure. Default = 5.0
        layer_range (list, optional) :
            Only used when "dpressure_range" is within filters. Range in metres the surface layer should have
            (will be converted to pressure units using barometric equation). (two-item list).
            Default = [50.,500.]
        pressure_dir (str, optional) :
            Base directory containing the NAME output files for the SurfacePressure run.
            Filename is assumed to be of the form "Pressure_C1_*.txt"
            See name_pressure_file() function for more details.
        pressure_domain (str/None,optional) :
            Domain over which surface pressure values have been extracted (can be distinct from
            domain if pressure_domain contains area of domain).
            * Must be specified if pressure_NAME has not been specified *
            Check $DATA_PATH/LPDM/surface_pressure folder to see which domains currently exist.
        max_days (int, optional) :
            Number of days tolerance to allow when using time stamp to find relevant NAME pressure values.
            Default = 31 (days).
        day_template (bool, optional) :
            Use nearest day as a template for the change of pressure over the course of the day and match
            to the nearest time on that day.
            E.g. if datetime is 2012-05-01 03:00:00, max_days is 31 and nearest day is 2012-01-01 then
            use entry from 2012-01-01 03:00:00 (rather than 2012-02-01 00:00:00, which would be the
            nearest entry).
            Default = True.
        pressure_convert (float, optional) :
            If pressure values extracted from NAME are not in the required units, pressure_convert
            should be set to the scaling factor to convert these units.
            By default, we assume we want to convert to hPa from NAME input in Pa (pressure_covert=1/100.)

    Returns:
        xarray.Dataset :
            Filtered Dataset with data points with pressure levels too different from the NAME values (based on
            the filters specified) removed.


    The gosat_process_file function processes input gosat data for one file, applying designated filters,
    binning and writing output as required.
    Binning is done based on latitude and longitude values in degrees.

    Filter criteria that can be applied include:
        - Latitude and longitude range - based on input bounds or specified domain
        - Start and end date range
        - Quality flag (xch4_quality_flag)
        - Bad pressure flag
        - Mode (land or glint)
        - Comparison from NAME surface pressure including a cutoff, comparing surface to the first level and the extent of the layer.

    Output can be written to:
        - netCDF files (.nc) based on suitable format for acrg repository. See gosat_output() and gosat_output_filename() functions.
        - text files  (.csv) suitable for input into NAME. See output_name() function.

    Args:
        filename (str) :
            Filename of GOSAT CH4 Level 2 Data Product file (str)
        site (str) :
            Specified sub-set defined for gosat e.g. GOSAT-INDIA. Should be defined within site_info.json
        species (str, optional) :
            Species of interest. Should be defined within species_info.json. Default = "ch4"
        lat_bounds (list, optional) :
            Upper and lower bounds for latitude. (two-item list e.g. [6.0,36.5])
        lon_bounds (list, optional) :
            Upper and lower bounds for longitude. (two-item list e.g. [70.0,90.5])
        domain (str, optional) :
            If lat_bounds and lon_bounds are not specified a domain can be specified instead.
            This must be a predetermined NAME domain and a footprint file must exist to extract the latitude
            and longitude bounds.
            If both domain and pair of lat_bounds and lon_bounds are specified, the explictly specified
            bounds will take precedence.
            This parameter will also be used to find folder containing surface pressure files (if
            applicable) if pressure_domain is not specified.
        coord_bin (float/list, optional) :
            If applying binning, this should be the size of each bin in degrees.
            To specify the same bin for latitude and longitude a single values (float) can be used.
            To specify different bins include a two item list (e.g. [0.234,0.356])
            Set to None if no binning is required.
        quality_filt (bool, optional) :
            Whether to remove data points using the quality filter flag (xch4_quality_flag)
            indicating possibly bad data (=1).
            Default = True.
        bad_pressure_filt (bool, optional) :
            Whether to remove data points where any pressure value = -9999.99 (seems to be a flag).
            Default = True.
        name_sp_filt (bool, optional) :
            Whether to remove data points based on the comparison between the GOSAT surface pressure value
            and the NAME surface pressure value.
            Exact conditions are specified by name_filters with associated values specified by cutoff
            and layer_range parameters if applicable.
            Default = False.
        mode (str, optional) :
            Which retrieval mode (retr_flag) to filter by (if any). Options: 'land' or 'glint'.
            Set to None if no filtering by mode is required.
        use_name_pressure (bool, optional) :
            Whether to use the NAME surface pressure rather than the input GOSAT surface pressure
            (first pressure_levels value for each time point) when creating the NAME csv file.
            Note:
                 - This is independent of the name_sp_filt and both or either can be applied.
                 - This does not affect the pressure_levels in the netCDF output.
            Default = False.
        name_filters (list) :
            If name_sp_filt=True, this is a list of which filters will be used.
            Options are: "cutoff", "level_order","dpressure_range".
            This value must be specified if name_sp_filt=True.
            See name_pressure_filter() function for details of these filters.
        cutoff (float, optional) :
            When applying the "cutoff" NAME filter, this is the percentage cutoff to apply from comparison
            between input pressure data and NAME pressure.
            Default = 5.0
        layer_range (list, optional) :
            When applying the "dpressure_range" NAME filter, this is the range in metres the surface layer
            should have (will be converted to pressure units using barometric equation). (two-item list).
            Default = [50.,500.]
        pressure_base_dir (str, optional) :
            Base directory containing the NAME output files for the SurfacePressure run.
            If pressure_domain (or domain) is specified this will be appended to the pressure_base_dir
            Default = "$DATA_PATH/LPDM/surface_pressure/"
        pressure_domain (str, optional) :
            Domain over which surface pressure has been created. Only needs to be specified if this is
            different (i.e. wider domain) than domain, or domain has not been explictly specified.
            Will be used to find full pressure_dir path to Pressure_*.txt files.
        pressure_max_days (int, optional) :
            Maximum number of days from time within ds to search for the relevant pressure data.
            Default = 31 (days).
        pressure_day_template (bool, optional) :
            Use nearest day as a template for the change of pressure over the course of the day and match
            to the nearest time on that day.
            E.g. if datetime is 2012-05-01 03:00:00, max_days is 31 and nearest day is 2012-01-01 then
            use entry from 2012-01-01 03:00:00 (rather than 2012-02-01 00:00:00, which would be the
            nearest entry).
            Default = True.
        write_nc (bool, optional) :
            Write output .nc files (one per bin along time axis by default)
            Default = False.
        output_directory (str, optional) :
            Top level directory to write output. Full path will be based on the "network" related to "site"
        write_name (bool, optional) :
            Write output .csv file for input into NAME (one per bin along time axis by default)
        name_directory (str, optional) :
            Top level directory to write files for NAME. Full path will be based on the "network" related to "site"
            Default defined at the top of this module.
        file_per_day (bool, optional) :
            Group together all points into create one output file per day rather than one per
            data point (bool).
            Default = False.
        max_name_level (int, optional) :
        	Maximum level to use when writing out NAME csv files.
        	Default = 17
        max_name_points (int/None, optional) :
            Only applicable if file_per_day is True.
            Maximum number of points to write to NAME csv file if writing file per day.
            If number of points within the day exceeds max_points multiple files will be written out with
            a character after the date of "-A","-B",...
            NOTE: This will not be applied to netCDF files even if number of points is greater than
            max_name_points, only to the NAME csv files. All points per day will be written to one file.
            A sensible number for this, if specified, would be 60.
            Default = None.
        overwrite (bool, optional) :
            Allow any files already present within the output_directory and name_directory to be overwritten.
            Default = False.
        verbose (bool, optional) :
            Print details of file processing to screen.
            Default = True.

    Returns:
        xarray.Dataset:
            processed GOSAT Dataset

        If write_nc is set to True:
            Set of .nc files will be written within path started by output_directory
        If write_name is set to True:
            Set of .csv files will be written to name_directory