Generate general statistics

    Output is an html page, rendered to 'plots_html_page.html' in the output directory.

def plots_html_page():
    """Generate general statistics

    Output is an html page, rendered to 'plots_html_page.html' in the output directory.
    """
    # page template
    template = jenv.get_template("plots_html_page.html")

    # container for template context
    context = dict()

    # a database client/session to run queries in
    cl = client.get_client()
    session = cl.create_session()

    # general styling
    seaborn.set_style('whitegrid')

    #
    #  plot: number of superheroes, by year of first appearance
    #

    # just query all character data, do analysis in pandas
    query = session.query(models.Character)
    character_data = cl.df_query(query)

    # plot character appearances per year
    fig = plt.figure(figsize=pixels_to_inches((400, 300)))
    plt.plot(character_data.groupby('first_apperance_year')['id'].count(), '-o', c=seaborn.color_palette()[0])
    # labels and title
    plt.xlabel('Year')
    plt.ylabel('Number of first appearances')
    plt.title('Number of first character appearances per year')
    # render to svg string, store in template context
    context['first_appearances_per_year_svg'] = fig_to_svg(fig)
    plt.close(fig)

    #
    #  plot: number of movies, by year of publication
    #

    # just query all movie data, do analysis in pandas
    query = session.query(models.Movie)
    movie_data = cl.df_query(query)

    # plot movie publications per year
    fig = plt.figure(figsize=pixels_to_inches((400, 300)))
    plt.plot(movie_data.groupby('year')['id'].count(), '-o', c=seaborn.color_palette()[1])
    plt.xlabel('Year')
    plt.ylabel('Number of movies')
    plt.title('Number of movies per year')
    context['movies_per_year_svg'] = fig_to_svg(fig)
    plt.close(fig)

    #
    #  plot: average character appearances per movie per year
    #

    # query number of character appearances for each movie, together with the movie year
    query = session.query(sa.func.count(models.MovieAppearance.character_id).label('n_characters'),
                          models.Movie.id,
                          models.Movie.year) \
        .join(models.Movie) \
        .group_by(models.Movie.id, models.Movie.year)
    appearance_counts = cl.df_query(query)

    fig = plt.figure(figsize=pixels_to_inches((400, 300)))
    plt.plot(appearance_counts.groupby('year')['n_characters'].mean(), '-o', c=seaborn.color_palette()[2])
    plt.xlabel('Year')
    plt.ylabel('Average number of characters')
    plt.title('Average number of characters in a movie, per year')
    context['average_appearances_per_movie_svg'] = fig_to_svg(fig)

    #
    #  plots: average movie budget per year, with and without inflation adjustment
    #

    fig = plt.figure(figsize=pixels_to_inches((400, 300)))
    plt.plot(movie_data.groupby('year')['budget'].mean() / 1e6, '-o', c=seaborn.color_palette()[3])
    plt.xlabel('Year')
    plt.ylabel('Average budget in Mio Euro')
    plt.title('Average movie budget per year')
    plt.xlim(1980, plt.xlim()[1])
    context['budget_per_year_svg'] = fig_to_svg(fig)
    plt.close(fig)

    fig = plt.figure(figsize=pixels_to_inches((400, 300)))
    plt.plot(movie_data.groupby('year')['budget_inflation_adjusted'].mean() / 1e6, '-o', c=seaborn.color_palette()[4])
    plt.xlabel('Year')
    plt.ylabel('Average budget in Mio Euro')
    plt.title('Average movie budget per year, adjusted for inflation')
    plt.xlim(1980, plt.xlim()[1])
    context['budget_adjusted_per_year_svg'] = fig_to_svg(fig)
    plt.close(fig)

    #
    # render template
    #

    # add additional context data:
    # - html code for list of imported universes
    # noinspection PyUnresolvedReferences
    context['universes_list'] = ', '.join(config.UNIVERSES)

    out_file = path.join(out_dir, "plots_html_page.html")
    html_content = template.render(**context)
    with open(out_file, 'w') as f:
        f.write(html_content)

    # done, clean up
    plt.close('all')
    session.close()