Create (or get if already exists) a provenance entity, store it in the database and get back a provenance ID.

    Arguments:
    :param dataset: Name of the data set.
    :param software_versions: (optional) Version of the software components used to get the data. It is a dictionary
    that accepts the following fields:
        - matlab_version
        - spm_version
        - spm_revision
        - fn_called
        - fn_version
        - others
    :param db_url: (optional) Database URL. If not defined, it looks for an Airflow configuration file.
    :return: Provenance ID.

def create_provenance(dataset, software_versions=None, db_url=None):
    """Create (or get if already exists) a provenance entity, store it in the database and get back a provenance ID.

    Arguments:
    :param dataset: Name of the data set.
    :param software_versions: (optional) Version of the software components used to get the data. It is a dictionary
    that accepts the following fields:
        - matlab_version
        - spm_version
        - spm_revision
        - fn_called
        - fn_version
        - others
    :param db_url: (optional) Database URL. If not defined, it looks for an Airflow configuration file.
    :return: Provenance ID.
    """
    logging.info("Connecting to database...")
    db_conn = connection.Connection(db_url)

    try:
        matlab_version = software_versions['matlab_version']
    except (KeyError, TypeError):
        matlab_version = None
    try:
        spm_version = software_versions['spm_version']
    except (KeyError, TypeError):
        spm_version = None
    try:
        spm_revision = software_versions['spm_revision']
    except (KeyError, TypeError):
        spm_revision = None
    try:
        fn_called = software_versions['fn_called']
    except (KeyError, TypeError):
        fn_called = None
    try:
        fn_version = software_versions['fn_version']
    except (KeyError, TypeError):
        fn_version = None
    try:
        others = software_versions['others']
    except (KeyError, TypeError):
        others = None

    provenance = db_conn.db_session.query(db_conn.Provenance).filter_by(
        dataset=dataset, matlab_version=matlab_version, spm_version=spm_version, spm_revision=spm_revision,
        fn_called=fn_called, fn_version=fn_version, others=others
    ).first()

    if not provenance:
        provenance = db_conn.Provenance(
            dataset=dataset, matlab_version=matlab_version, spm_version=spm_version, spm_revision=spm_revision,
            fn_called=fn_called, fn_version=fn_version, others=others
        )
        db_conn.db_session.merge(provenance)
        db_conn.db_session.commit()

        provenance = db_conn.db_session.query(db_conn.Provenance).filter_by(
            dataset=dataset, matlab_version=matlab_version, spm_version=spm_version, spm_revision=spm_revision,
            fn_called=fn_called, fn_version=fn_version, others=others
        ).first()

    provenance_id = provenance.id

    logging.info("Closing database connection...")
    db_conn.close()

    return provenance_id