Skip to content

Commit

Permalink
feat(report,import): replace the barplot by a piechart
Browse files Browse the repository at this point in the history
  • Loading branch information
jacquesfize committed May 3, 2024
1 parent eaf5c2c commit 7b66d36
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 23 deletions.
95 changes: 80 additions & 15 deletions backend/geonature/core/gn_synthese/imports/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
from bokeh.models.layouts import Row
from bokeh.models import CustomJS, Select
from bokeh.embed import json_item
from bokeh.palettes import linear_palette, Turbo256, Plasma256
from bokeh.models import Range1d, AnnularWedge, ColumnDataSource, Legend, LegendItem

import numpy as np


def check_transient_data(task, logger, imprt):
Expand Down Expand Up @@ -386,34 +390,93 @@ def report_plot(imprt: TImports) -> Row:
TSources.name_source == f"Import(id={imprt.id_import})",
).one_or_none()

# Define the taxonomic categories to consider
# Define the taxonomic rank to consider
taxon_ranks = "regne phylum classe ordre famille sous_famille tribu group1_inpn group2_inpn group3_inpn".split()
figures = []

# Generate the plot for each rank
for rank in taxon_ranks:
# Generate the query to retrieve the count for each value taken by the rank
c_rank_taxref = getattr(Taxref, rank)
query = (
sa.select(
func.count(distinct(Synthese.cd_nom)).label("count"),
getattr(Taxref, rank).label("rank_value"),
c_rank_taxref.label("rank_value"),
)
.select_from(Synthese)
.outerjoin(Taxref, Taxref.cd_nom == Synthese.cd_nom)
.where(Synthese.id_dataset == imprt.id_dataset, Synthese.source == source)
.group_by(getattr(Taxref, rank))
.where(
Synthese.id_dataset == imprt.id_dataset,
Synthese.source == source,
)
.group_by(c_rank_taxref)
)
data = np.asarray(
[r if r[1] != "" else (r[0], "Non-assigné") for r in db.session.execute(query).all()]
)
results = db.session.execute(query).all()

# Extract the rank values and counts
rank_values = [r[1] for r in results]
count = [r[0] for r in results]
rank_values, counts = data[:, 1], data[:, 0].astype(int)

# Get angles (in radians) where start each section of the pie chart
angles = np.cumsum(
[2 * np.pi * (count / sum(counts)) for i, count in enumerate(counts)]
).tolist()

# Generate the color palette
palette = (
linear_palette(Turbo256, len(rank_values))
if len(rank_values) > 5
else linear_palette(Plasma256, len(rank_values))
)
colors = {value: palette[ix] for ix, value in enumerate(rank_values)}

# Store the data in a Bokeh data structure
browsers_source = ColumnDataSource(
dict(
start=[0] + angles[:-1],
end=angles,
colors=[colors[rank_value] for rank_value in rank_values],
countvalue=counts,
rankvalue=rank_values,
)
)
# Create the Figure object
fig = figure(
x_range=Range1d(start=-3, end=3),
y_range=Range1d(start=-3, end=3),
title=f"Distribution des taxons (selon le rang = {rank})",
tooltips=[("Number", "@countvalue"), (rank, "@rankvalue")],
width=600,
toolbar_location=None,
)
# Add the Pie chart
glyph = AnnularWedge(
x=0,
y=0,
inner_radius=0.9,
outer_radius=1.8,
start_angle="start",
end_angle="end",
line_color="white",
line_width=3,
fill_color="colors",
)
r = fig.add_glyph(browsers_source, glyph)

# Add the legend
legend = Legend(location="top_center")
for i, name in enumerate(colors):
legend.items.append(LegendItem(label=name, renderers=[r], index=i))
fig.add_layout(legend, "below")
fig.legend.ncols = 3 if len(colors) < 10 else 5

# Generate the bar plot
fig = figure(x_range=rank_values, title=f"Distribution des taxons (selon le rang = {rank})")
fig.vbar(x=rank_values, top=count, width=0.9)
# ERASE the grid and axis
fig.grid.visible = False
fig.axis.visible = False
fig.title.text_font_size = "16pt"

# Hide the plot for non-kingdom ranks
# Hide the unselected rank plot
if rank != "regne":
fig.visible = False

Expand All @@ -422,13 +485,15 @@ def report_plot(imprt: TImports) -> Row:

# Generate the layout with the plots and the rank selector
plot_area = column(figures)

select_plot = Select(
title="Rang",
value=(0, "regne"),
value=0, # Default is "regne"
options=[(ix, rank) for ix, rank in enumerate(taxon_ranks)],
width=fig.width,
)

# Update the visibility of the plots when the category selector changes
# Update the visibility of the plots when the taxonomic rank selector changes
select_plot.js_on_change(
"value",
CustomJS(
Expand All @@ -441,5 +506,5 @@ def report_plot(imprt: TImports) -> Row:
""",
),
)

return json_item(row(select_plot, plot_area, sizing_mode="stretch_width"))
column_fig = column(plot_area, select_plot, sizing_mode="scale_width")
return json_item(column_fig)
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ <h5 class="zone-geographique">Zone géographique</h5>
</div>
{% if data.chart is not none %}
<div id="chart" class="zone">
<p class="zone-geographique">Répartition taxonomique</p>
<img src="{{ data.chart }}">
<img src="{{ data.chart }}" alt="Répartition Taxonomique"/>
</div>
{% endif %}
</div>
Expand Down Expand Up @@ -151,13 +150,13 @@ <h5 class="zone-geographique">Zone géographique</h5>
<style>
/* Puts style here since I cannot make blueprint static files work...*/
.zone img {
max-width: 200px;
max-height: 100px;
width: 400px;
margin-left: auto;
margin-right: auto;
}

.zone {
max-width: 400px;
max-height: 100px;
width: 30%;
margin-left: 0px;
margin-top: 5px;
}
Expand Down Expand Up @@ -220,7 +219,7 @@ <h5 class="zone-geographique">Zone géographique</h5>
}

.left-block {
width: 700px;
width: 70%;
margin-left: 5px;
}
.description {
Expand Down
2 changes: 2 additions & 0 deletions backend/geonature/core/imports/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,11 @@ def update_transient_data_from_dataframe(imprt, entity, updated_cols, df):

def generate_pdf_from_template(template, data):
template_rendered = render_template(template, data=data)
open("test.html", "w").write(template_rendered)
html_file = HTML(
string=template_rendered,
base_url=current_app.config["API_ENDPOINT"],
encoding="utf-8",
)

return html_file.write_pdf()
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ <h5 class="card-title mt-1">Périmètre géographique des données importées</h
Afficher dans la synthèse
</button>
</div>
<div class="d-flex flex-column col-sm-6">
<div class="col-12">
<div id="chartreport"></div>
</div>
</div>
Expand Down

0 comments on commit 7b66d36

Please sign in to comment.