Skip to content

Commit 57ecfd1

Browse files
committed
add bubble to patents
1 parent bd54012 commit 57ecfd1

File tree

4 files changed

+176
-11
lines changed

4 files changed

+176
-11
lines changed

client/src/api/patents/aggregate/analytic-tool.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,9 @@ export async function aggregatePatentsForAnalyticTool(
5353
},
5454
byCpc: {
5555
terms: {
56-
field: "cpc.classe.code.keyword",
56+
field: "cpc.classe.id_name.keyword",
5757
size: 10000,
5858
},
59-
aggs: {
60-
bySectionLabel: {
61-
terms: {
62-
field: "cpc.section.label.keyword",
63-
size: 1,
64-
},
65-
},
66-
},
6759
},
6860
}
6961
}
@@ -76,6 +68,9 @@ export async function aggregatePatentsForAnalyticTool(
7668
const result = await res.json()
7769
const { aggregations: data} = result;
7870

71+
console.log(data?.byCpc?.buckets)
72+
73+
7974
const _100Year =
8075
data?.byYear?.buckets &&
8176
Math.max(...data.byYear.buckets.map((el) => el.doc_count));
@@ -107,9 +102,17 @@ export async function aggregatePatentsForAnalyticTool(
107102
}
108103
}).filter(el => el) || [];
109104
const patentsCount = data.patentsCount?.value;
105+
const byCpc = data?.byCpc?.buckets?.map((element) => {
106+
return {
107+
value: element.key.split("###")?.[0],
108+
label: element.key.split("###")?.[1],
109+
count: element.doc_count,
110+
}
111+
}).filter(el => el) || [];
110112
return {
111113
byInventors,
112114
byApplicants,
115+
byCpc,
113116
patentsCount,
114117
byYear,
115118
};
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import React from "react";
2+
import Highcharts from "highcharts";
3+
import HighchartsReact from "highcharts-react-official";
4+
import HighchartsMore from "highcharts/highcharts-more";
5+
import { Aggregation } from "../../types/commons";
6+
7+
HighchartsMore(Highcharts);
8+
9+
type CpcChartProps = {
10+
data: Aggregation[];
11+
};
12+
13+
const sectionLabels: Record<string, string> = {
14+
A: "Nécessités courantes de la vie",
15+
B: "Techniques industrielles diverses; transports",
16+
C: "Chimie; métallurgie",
17+
D: "Textiles; papier",
18+
E: "Constructions fixes",
19+
F: "Mécanique; éclairage; chauffage; armement; sautage",
20+
G: "Physique",
21+
H: "Electricité",
22+
Y: "Technologies émergentes ou celles qui couvrent plusieurs sections",
23+
};
24+
25+
const CpcChart: React.FC<CpcChartProps> = ({ data }) => {
26+
const colorPalette = [
27+
"#7AB1E8",
28+
"#21AB8E",
29+
"#f6e157",
30+
"#CE70CC",
31+
"#FF9575",
32+
"#FFCA00",
33+
"#FF732C",
34+
"#E6BE92",
35+
"#AEA397",
36+
];
37+
const groupedData = data.reduce((acc, item) => {
38+
const firstLetter = item.value.charAt(0).toUpperCase();
39+
if (!acc[firstLetter]) acc[firstLetter] = [];
40+
acc[firstLetter].push({
41+
name: item.value,
42+
value: item.count,
43+
label: item.label,
44+
});
45+
return acc;
46+
}, {} as Record<string, { name: string; value: number; label: string }[]>);
47+
48+
const seriesData = Object.entries(groupedData).map(
49+
([letter, items], index) => {
50+
const totalCount = items.reduce((sum, item) => sum + item.value, 0);
51+
return {
52+
name: `Section ${sectionLabels[letter]}`,
53+
color: colorPalette[index % colorPalette.length],
54+
data: items.map((item) => ({
55+
name: item.name,
56+
value: item.value,
57+
label: item.label,
58+
})),
59+
totalCount,
60+
};
61+
}
62+
);
63+
64+
const values = seriesData.flatMap((series) =>
65+
series.data.map((point) => point.value)
66+
);
67+
const zMin = Math.min(...values);
68+
const zMax = Math.max(...values);
69+
70+
const options = {
71+
chart: {
72+
type: "packedbubble",
73+
backgroundColor: "#f4f4f4",
74+
height: "600px",
75+
},
76+
title: {
77+
text: null,
78+
},
79+
tooltip: {
80+
formatter: function () {
81+
const pointName =
82+
this.point.name && this.point.name !== "undefined"
83+
? `<b>${this.point.name}</b>`
84+
: "";
85+
const pointLabel =
86+
this.point.label && this.point.label !== "undefined"
87+
? `<b>${this.point.label}</b>`
88+
: "";
89+
const familiesText = `Familles de brevets: ${this.point.value}`;
90+
91+
const sectionName = this.series.name;
92+
const totalCount = this.series.data.reduce(
93+
(sum, item) => sum + item.value,
94+
0
95+
);
96+
const totalFamiliesText = `${totalCount} famille${totalCount > 1 ? "s" : ""}`
97+
98+
if (!pointName && !pointLabel) {
99+
return `<b>${sectionName}</b>: ${totalFamiliesText}`;
100+
}
101+
102+
return `${pointName} ${
103+
pointLabel ? `- ${pointLabel}` : ""
104+
}: ${familiesText}`;
105+
},
106+
},
107+
108+
plotOptions: {
109+
packedbubble: {
110+
minSize: "45%",
111+
maxSize: "120%",
112+
zMin: zMin,
113+
zMax: zMax,
114+
layoutAlgorithm: {
115+
gravitationalConstant: 0.05,
116+
splitSeries: true,
117+
seriesInteraction: false,
118+
parentNodeLimit: true,
119+
},
120+
dataLabels: {
121+
enabled: true,
122+
formatter: function () {
123+
return this.point.name !== "undefined" ? this.point.name : "";
124+
},
125+
style: {
126+
color: "black",
127+
textOutline: "none",
128+
fontWeight: "normal",
129+
},
130+
},
131+
},
132+
},
133+
series: seriesData,
134+
};
135+
136+
return (
137+
<>
138+
<HighchartsReact highcharts={Highcharts} options={options} />
139+
</>
140+
);
141+
};
142+
143+
export default CpcChart;

client/src/pages/analytics/patents/components/content.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import getBarChartOptions from "../../../../components/analytics-graph/graph-opt
44
import getYearChartOptions from "../../../../components/analytics-graph/graph-options/years";
55
import AnalyticsSkeleton from "../../../../components/skeleton/analytics-skeleton";
66
import usePatentsAnalyticsData from "../hooks/usePatentsAnalyticsData";
7+
import CpcChart from "../../../../components/patent-chart/cpc";
8+
79

810

911
export default function PatentsAnalyticsContent() {
@@ -15,7 +17,8 @@ export default function PatentsAnalyticsContent() {
1517
byInventors,
1618
byApplicants,
1719
patentsCount,
18-
byYear: patentsByYear,
20+
byYear,
21+
byCpc,
1922
} = data;
2023

2124
const patentInventorsOptions = getBarChartOptions({
@@ -27,7 +30,7 @@ export default function PatentsAnalyticsContent() {
2730
colors: ["var(--organizations-analytics)"],
2831
});
2932
const patentYearsOptions = getYearChartOptions({
30-
data: patentsByYear,
33+
data: byYear,
3134
colors: ["var(--patents-analytics)"],
3235
});
3336

@@ -62,6 +65,21 @@ export default function PatentsAnalyticsContent() {
6265
options={patentApplicantsOptions}
6366
/>
6467
</Col>
68+
<Col xs="12">
69+
<div className="fr-pb-3w">
70+
<div style={{ display: 'flex', alignItems: 'start' }}>
71+
<div style={{ flexGrow: 1 }}>
72+
<Title as="h2" className="fr-text--md fr-text--bold fr-m-0">
73+
Répartition par classification CPC
74+
</Title>
75+
<p className="fr-text--xs fr-text-mention--grey">Domaines technologiques identifiés dans les familles de brevets</p>
76+
</div>
77+
</div>
78+
<div style={{ height: "600px"}}>
79+
<CpcChart data={byCpc} />
80+
</div>
81+
</div>
82+
</Col>
6583
</Row>
6684
</>
6785
);

client/src/types/patent.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export type PatentsAggregationsForAnalyticTool = {
9191
byInventors: Aggregation[];
9292
patentsCount: number;
9393
byYear: Aggregation[];
94+
byCpc: Aggregation[];
9495
};
9596

9697
export type ExportPatent = {

0 commit comments

Comments
 (0)