Get a list of ids which describe which class they get mapped to.

    Parameters
    ----------
    symbol_yml_file : string
        Path to a YAML file.
    metadata : dict
        Metainformation of symbols, like the id on write-math.com.
        Has keys 'symbols', 'tags', 'tags2symbols'.

    Returns
    -------
    list of dictionaries : Each dictionary represents one output class and has
        to have the keys 'id' (which is an id on write-math.com) and
        'mappings' (which is a list of ids on write-math.com). The mappings
        list should at least contain the id itself, but can contain more.

    Examples
    --------
    >>> get_symbol_ids('symbols.yml')
    [{'id': 42, 'mappings': [1, 42, 456, 1337]}, {'id': 2, 'mappings': [2]}]

    The yml file has to be of the structure

    ```
    - {latex: 'A'}
    - {latex: 'B'}
    - {latex: 'O',
       mappings: ['0', 'o']}
    - {latex: 'C'}
    - {latex: '::REJECT::',
       mappings: ['::ALL_FREE::']}
    - {latex: '::ARROW::',
       mappings: ['::TAG/arrow::'],
       exclude: ['\rightarrow']}
    ```

def get_symbol_ids(symbol_yml_file, metadata):
    """
    Get a list of ids which describe which class they get mapped to.

    Parameters
    ----------
    symbol_yml_file : string
        Path to a YAML file.
    metadata : dict
        Metainformation of symbols, like the id on write-math.com.
        Has keys 'symbols', 'tags', 'tags2symbols'.

    Returns
    -------
    list of dictionaries : Each dictionary represents one output class and has
        to have the keys 'id' (which is an id on write-math.com) and
        'mappings' (which is a list of ids on write-math.com). The mappings
        list should at least contain the id itself, but can contain more.

    Examples
    --------
    >>> get_symbol_ids('symbols.yml')
    [{'id': 42, 'mappings': [1, 42, 456, 1337]}, {'id': 2, 'mappings': [2]}]

    The yml file has to be of the structure

    ```
    - {latex: 'A'}
    - {latex: 'B'}
    - {latex: 'O',
       mappings: ['0', 'o']}
    - {latex: 'C'}
    - {latex: '::REJECT::',
       mappings: ['::ALL_FREE::']}
    - {latex: '::ARROW::',
       mappings: ['::TAG/arrow::'],
       exclude: ['\rightarrow']}
    ```
    """
    with open(symbol_yml_file, 'r') as stream:
        symbol_cfg = yaml.load(stream)
    symbol_ids = []
    symbol_ids_set = set()

    for symbol in symbol_cfg:
        if 'latex' not in symbol:
            logging.error("Key 'latex' not found for a symbol in %s (%s)",
                          symbol_yml_file,
                          symbol)
            sys.exit(-1)
        results = [el for el in metadata['symbols']
                   if el['formula_in_latex'] == symbol['latex']]
        if len(results) != 1:
            logging.warning("Found %i results for %s: %s",
                            len(results),
                            symbol['latex'],
                            results)
            if len(results) > 1:
                results = sorted(results, key=lambda n: n['id'])
            else:
                sys.exit(-1)
        mapping_ids = [results[0]['id']]
        if 'mappings' in symbol:
            for msymbol in symbol['mappings']:
                filtered = [el for el in metadata['symbols']
                            if el['formula_in_latex'] == msymbol['latex']]
                if len(filtered) != 1:
                    logging.error("Found %i results for %s: %s",
                                  len(filtered),
                                  msymbol,
                                  filtered)
                    if len(filtered) > 1:
                        filtered = natsorted(filtered, key=lambda n: n['id'])
                    else:
                        sys.exit(-1)
                mapping_ids.append(filtered[0]['id'])
        symbol_ids.append({'id': int(results[0]['id']),
                           'formula_in_latex': results[0]['formula_in_latex'],
                           'mappings': mapping_ids})
        for id_tmp in mapping_ids:
            if id_tmp not in symbol_ids_set:
                symbol_ids_set.add(id_tmp)
            else:
                for symbol_tmp in symbol_ids:
                    if id_tmp in symbol_tmp['mappings']:
                        break
                logging.error('Symbol id %s is already used: %s',
                              id_tmp,
                              symbol_tmp)
                sys.exit(-1)

    # print(metadata.keys())
    # for el in metadata:
    #    print(metadata[el][0].keys())
    # TODO: assert no double mappings
    # TODO: Support for
    # - ::ALL_FREE:: - meaning the rest of all ids which are not assigned to
    #                  any other class get assigned to this class
    # - ::TAG/arrow:: - meaning all ids of the tag arrow get assigned here
    # - exclude
    logging.info('%i base classes and %i write-math ids.',
                 len(symbol_ids),
                 len(symbol_ids_set))
    return symbol_ids