You've already forked etude_lego_jurassic_world
Ajoute la richesse chromatique par set
This commit is contained in:
196
tests/test_color_richness.py
Normal file
196
tests/test_color_richness.py
Normal file
@@ -0,0 +1,196 @@
|
||||
"""Tests des métriques de richesse chromatique."""
|
||||
|
||||
import csv
|
||||
from pathlib import Path
|
||||
|
||||
from lib.rebrickable.color_richness import (
|
||||
build_richness_by_set,
|
||||
build_richness_by_year,
|
||||
write_richness_by_set,
|
||||
write_richness_by_year,
|
||||
)
|
||||
|
||||
|
||||
def write_csv(path: Path, headers: list[str], rows: list[list[str]]) -> None:
|
||||
"""Écrit un CSV simple pour les besoins de tests."""
|
||||
with path.open("w", newline="") as csv_file:
|
||||
writer = csv.writer(csv_file)
|
||||
writer.writerow(headers)
|
||||
writer.writerows(rows)
|
||||
|
||||
|
||||
def test_build_richness_by_set_computes_shares_and_counts(tmp_path: Path) -> None:
|
||||
"""Calcule les partages de couleurs principales et les dénombrements."""
|
||||
colors_by_set = tmp_path / "colors_by_set.csv"
|
||||
write_csv(
|
||||
colors_by_set,
|
||||
[
|
||||
"set_num",
|
||||
"set_id",
|
||||
"year",
|
||||
"color_rgb",
|
||||
"is_translucent",
|
||||
"color_name",
|
||||
"quantity_total",
|
||||
"quantity_non_spare",
|
||||
"quantity_minifig",
|
||||
"quantity_non_minifig",
|
||||
],
|
||||
[
|
||||
["1000-1", "1000", "2020", "AAAAAA", "false", "Gray", "10", "10", "0", "10"],
|
||||
["1000-1", "1000", "2020", "BBBBBB", "false", "Blue", "5", "5", "5", "0"],
|
||||
["2000-1", "2000", "2021", "CCCCCC", "true", "Trans", "3", "3", "0", "3"],
|
||||
],
|
||||
)
|
||||
sets_enriched = tmp_path / "sets_enriched.csv"
|
||||
write_csv(
|
||||
sets_enriched,
|
||||
["set_num", "set_id", "name", "year", "in_collection"],
|
||||
[
|
||||
["1000-1", "1000", "Set A", "2020", "true"],
|
||||
["2000-1", "2000", "Set B", "2021", "false"],
|
||||
],
|
||||
)
|
||||
|
||||
richness = build_richness_by_set(colors_by_set, sets_enriched)
|
||||
|
||||
assert richness == [
|
||||
{
|
||||
"set_num": "1000-1",
|
||||
"set_id": "1000",
|
||||
"name": "Set A",
|
||||
"year": "2020",
|
||||
"in_collection": "true",
|
||||
"colors_distinct": "2",
|
||||
"colors_minifig": "1",
|
||||
"colors_non_minifig": "1",
|
||||
"total_parts_non_spare": "15",
|
||||
"top_color_name": "Gray",
|
||||
"top_color_share": "0.6667",
|
||||
"top3_share": "1.0000",
|
||||
},
|
||||
{
|
||||
"set_num": "2000-1",
|
||||
"set_id": "2000",
|
||||
"name": "Set B",
|
||||
"year": "2021",
|
||||
"in_collection": "false",
|
||||
"colors_distinct": "1",
|
||||
"colors_minifig": "0",
|
||||
"colors_non_minifig": "1",
|
||||
"total_parts_non_spare": "3",
|
||||
"top_color_name": "Trans",
|
||||
"top_color_share": "1.0000",
|
||||
"top3_share": "1.0000",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def test_build_richness_by_year_aggregates_metrics(tmp_path: Path) -> None:
|
||||
"""Agrège les métriques par année."""
|
||||
richness_rows = [
|
||||
{
|
||||
"set_num": "s1",
|
||||
"set_id": "1",
|
||||
"name": "A",
|
||||
"year": "2020",
|
||||
"in_collection": "true",
|
||||
"colors_distinct": "4",
|
||||
"colors_minifig": "1",
|
||||
"colors_non_minifig": "3",
|
||||
"total_parts_non_spare": "10",
|
||||
"top_color_name": "Red",
|
||||
"top_color_share": "0.5000",
|
||||
"top3_share": "0.9000",
|
||||
},
|
||||
{
|
||||
"set_num": "s2",
|
||||
"set_id": "2",
|
||||
"name": "B",
|
||||
"year": "2020",
|
||||
"in_collection": "false",
|
||||
"colors_distinct": "2",
|
||||
"colors_minifig": "0",
|
||||
"colors_non_minifig": "2",
|
||||
"total_parts_non_spare": "5",
|
||||
"top_color_name": "Blue",
|
||||
"top_color_share": "0.6000",
|
||||
"top3_share": "1.0000",
|
||||
},
|
||||
{
|
||||
"set_num": "s3",
|
||||
"set_id": "3",
|
||||
"name": "C",
|
||||
"year": "2021",
|
||||
"in_collection": "true",
|
||||
"colors_distinct": "3",
|
||||
"colors_minifig": "1",
|
||||
"colors_non_minifig": "3",
|
||||
"total_parts_non_spare": "7",
|
||||
"top_color_name": "Green",
|
||||
"top_color_share": "0.5714",
|
||||
"top3_share": "1.0000",
|
||||
},
|
||||
]
|
||||
|
||||
yearly = build_richness_by_year(richness_rows)
|
||||
|
||||
assert yearly == [
|
||||
{
|
||||
"year": "2020",
|
||||
"average_colors_distinct": "3.00",
|
||||
"median_colors_distinct": "3.00",
|
||||
"max_colors_distinct": "4",
|
||||
"min_colors_distinct": "2",
|
||||
"average_top3_share": "0.9500",
|
||||
"median_top3_share": "0.9500",
|
||||
},
|
||||
{
|
||||
"year": "2021",
|
||||
"average_colors_distinct": "3.00",
|
||||
"median_colors_distinct": "3.00",
|
||||
"max_colors_distinct": "3",
|
||||
"min_colors_distinct": "3",
|
||||
"average_top3_share": "1.0000",
|
||||
"median_top3_share": "1.0000",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def test_write_richness_outputs_csv(tmp_path: Path) -> None:
|
||||
"""Sérialise les métriques par set et par année."""
|
||||
by_set_path = tmp_path / "color_richness_by_set.csv"
|
||||
by_year_path = tmp_path / "color_richness_by_year.csv"
|
||||
sample_set_rows = [
|
||||
{
|
||||
"set_num": "s1",
|
||||
"set_id": "1",
|
||||
"name": "A",
|
||||
"year": "2020",
|
||||
"in_collection": "true",
|
||||
"colors_distinct": "1",
|
||||
"colors_minifig": "1",
|
||||
"colors_non_minifig": "1",
|
||||
"total_parts_non_spare": "5",
|
||||
"top_color_name": "Red",
|
||||
"top_color_share": "1.0000",
|
||||
"top3_share": "1.0000",
|
||||
}
|
||||
]
|
||||
sample_year_rows = [
|
||||
{
|
||||
"year": "2020",
|
||||
"average_colors_distinct": "1.00",
|
||||
"median_colors_distinct": "1.00",
|
||||
"max_colors_distinct": "1",
|
||||
"min_colors_distinct": "1",
|
||||
"average_top3_share": "1.0000",
|
||||
"median_top3_share": "1.0000",
|
||||
}
|
||||
]
|
||||
|
||||
write_richness_by_set(by_set_path, sample_set_rows)
|
||||
write_richness_by_year(by_year_path, sample_year_rows)
|
||||
|
||||
assert by_set_path.exists()
|
||||
assert by_year_path.exists()
|
||||
38
tests/test_color_richness_plot.py
Normal file
38
tests/test_color_richness_plot.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""Tests des visuels de richesse chromatique."""
|
||||
|
||||
import matplotlib
|
||||
from pathlib import Path
|
||||
|
||||
from lib.plots.color_richness import (
|
||||
plot_concentration_scatter,
|
||||
plot_richness_boxplot,
|
||||
plot_richness_top_sets,
|
||||
)
|
||||
|
||||
|
||||
matplotlib.use("Agg")
|
||||
|
||||
|
||||
def test_plot_richness_outputs_images(tmp_path: Path) -> None:
|
||||
"""Génère les trois graphiques principaux."""
|
||||
richness_path = tmp_path / "color_richness_by_set.csv"
|
||||
richness_path.write_text(
|
||||
"set_num,set_id,name,year,in_collection,colors_distinct,colors_minifig,colors_non_minifig,total_parts_non_spare,top_color_name,top_color_share,top3_share\n"
|
||||
"1000-1,1000,Set A,2020,true,6,2,5,50,Red,0.4000,0.6500\n"
|
||||
"2000-1,2000,Set B,2021,false,4,1,3,30,Blue,0.5000,0.7500\n"
|
||||
"3000-1,3000,Set C,2021,true,5,1,4,40,Green,0.3000,0.5500\n"
|
||||
)
|
||||
boxplot_dest = tmp_path / "figures" / "step28" / "color_richness_boxplot.png"
|
||||
top_dest = tmp_path / "figures" / "step28" / "color_richness_top_sets.png"
|
||||
scatter_dest = tmp_path / "figures" / "step28" / "color_concentration_scatter.png"
|
||||
|
||||
plot_richness_boxplot(richness_path, boxplot_dest)
|
||||
plot_richness_top_sets(richness_path, top_dest)
|
||||
plot_concentration_scatter(richness_path, scatter_dest)
|
||||
|
||||
assert boxplot_dest.exists()
|
||||
assert top_dest.exists()
|
||||
assert scatter_dest.exists()
|
||||
assert boxplot_dest.stat().st_size > 0
|
||||
assert top_dest.stat().st_size > 0
|
||||
assert scatter_dest.stat().st_size > 0
|
||||
@@ -102,17 +102,6 @@ def test_build_rare_parts_detects_exclusive_variations(tmp_path: Path) -> None:
|
||||
},
|
||||
]
|
||||
assert rare_by_set == [
|
||||
{
|
||||
"set_num": "1000-1",
|
||||
"set_id": "1000",
|
||||
"name": "Set A",
|
||||
"year": "2020",
|
||||
"in_collection": "true",
|
||||
"rare_parts_distinct": "1",
|
||||
"rare_parts_quantity": "1",
|
||||
"rare_minifig_parts_distinct": "1",
|
||||
"rare_minifig_quantity": "1",
|
||||
},
|
||||
{
|
||||
"set_num": "2000-1",
|
||||
"set_id": "2000",
|
||||
@@ -124,6 +113,17 @@ def test_build_rare_parts_detects_exclusive_variations(tmp_path: Path) -> None:
|
||||
"rare_minifig_parts_distinct": "0",
|
||||
"rare_minifig_quantity": "0",
|
||||
},
|
||||
{
|
||||
"set_num": "1000-1",
|
||||
"set_id": "1000",
|
||||
"name": "Set A",
|
||||
"year": "2020",
|
||||
"in_collection": "true",
|
||||
"rare_parts_distinct": "1",
|
||||
"rare_parts_quantity": "1",
|
||||
"rare_minifig_parts_distinct": "1",
|
||||
"rare_minifig_quantity": "1",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user