def log_to_DataFrame(execution_history_items, data_in_columns=[], data_out_columns=[], scoped_in_columns=[],
                     scoped_out_columns=[], semantic_data_columns=[], throw_on_pickle_error=True):
    """
    Returns all collapsed items in a table-like structure (pandas.DataFrame) with one row per executed 
    state and a set of properties resp. columns (e.g. state_name, outcome, run_id) for this state.
    The data flow (data_in/out, scoped_data_in/out, semantic_data) is omitted from this table
    representation by default, as the different states have different data in-/out-port, scoped_data-
    ports and semantic_data defined. However, you can ask specific data-/scoped_data-ports and semantic
    data to be exported as table column, given they are primitive-valued, by including the port / key
    names in the *_selected-parameters. These table-columns will obviously only be well-defined for
    states having this kind of port-name-/semantic-key and otherwise will contain a None-like value,
    indicating missing data.

    The available data per execution item (row in the table) can be printed using pandas.DataFrame.columns.
    """
    try:
        import pandas as pd
    except ImportError:
        raise ImportError("The Python package 'pandas' is required for log_to_DataFrame.")

    start, next_, concurrency, hierarchy, gitems = log_to_collapsed_structure(
        execution_history_items, throw_on_pickle_error=throw_on_pickle_error)
    gitems.pop(start['run_id'])
    if len(gitems) == 0:
        return pd.DataFrame()

    # remove columns which are not generic over all states (basically the
    # data flow stuff)
    df_keys = list(list(gitems.values())[0].keys())
    df_keys.remove('data_ins')
    df_keys.remove('data_outs')
    df_keys.remove('scoped_data_ins')
    df_keys.remove('scoped_data_outs')
    df_keys.remove('semantic_data')
    df_keys.sort()

    df_items = []

    for rid, item in gitems.items():
        row_data = [item[k] for k in df_keys]

        for key, selected_columns in [('data_ins', data_in_columns),
                                      ('data_outs', data_out_columns),
                                      ('scoped_data_ins', scoped_in_columns),
                                      ('scoped_data_outs', scoped_out_columns),
                                      ('semantic_data', semantic_data_columns)]:
            for column_key in selected_columns:
                row_data.append(item[key].get(column_key, None))
        df_items.append(row_data)

    for key, selected_columns in [('data_ins', data_in_columns),
                                  ('data_outs', data_out_columns),
                                  ('scoped_data_ins', scoped_in_columns),
                                  ('scoped_data_outs', scoped_out_columns),
                                  ('semantic_data', semantic_data_columns)]:
        df_keys.extend([key + '__' + s for s in selected_columns])
    df = pd.DataFrame(df_items, columns=df_keys)
    # convert epoch to datetime
    df.timestamp_call = pd.to_datetime(df.timestamp_call, unit='s')
    df.timestamp_return = pd.to_datetime(df.timestamp_return, unit='s')

    # use call timestamp as index
    df_timed = df.set_index(df.timestamp_call)
    df_timed.sort_index(inplace=True)

    return df_timed