pub-analyzer 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pub-analyzer might be problematic. Click here for more details.
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/PKG-INFO +5 -5
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/main.tcss +19 -13
- pub_analyzer-0.4.0/pub_analyzer/internal/templates/author/author_summary.typ +112 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/internal/templates/author/report.typ +12 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/internal/templates/author/sources.typ +1 -1
- pub_analyzer-0.4.0/pub_analyzer/internal/templates/author/works.typ +152 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/internal/templates/author/works_extended.typ +1 -2
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/main.py +5 -1
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pyproject.toml +10 -10
- pub_analyzer-0.3.0/pub_analyzer/internal/templates/author/author_summary.typ +0 -97
- pub_analyzer-0.3.0/pub_analyzer/internal/templates/author/works.typ +0 -65
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/LICENSE +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/README.md +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/__init__.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/body.tcss +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/buttons.tcss +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/checkbox.tcss +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/collapsible.tcss +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/datatable.tcss +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/report.tcss +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/search.tcss +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/summary.tcss +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/tabs.tcss +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/css/tree.tcss +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/internal/__init__.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/internal/identifier.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/internal/render.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/internal/report.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/models/__init__.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/models/author.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/models/concept.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/models/institution.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/models/report.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/models/source.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/models/topic.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/models/work.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/__init__.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/author/__init__.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/author/cards.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/author/core.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/author/tables.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/body.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/common/__init__.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/common/card.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/common/filesystem.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/common/filters.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/common/input.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/common/modal.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/common/selector.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/common/summary.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/institution/__init__.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/institution/cards.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/institution/core.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/institution/tables.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/__init__.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/author.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/cards.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/concept.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/core.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/export.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/grants.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/institution.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/locations.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/source.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/topic.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/report/work.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/search/__init__.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/search/core.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/search/results.py +0 -0
- {pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/widgets/sidebar.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pub-analyzer
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: A text user interface, written in python, which automates the generation of scientific production reports using OpenAlex
|
|
5
5
|
Home-page: https://github.com/alejandrgaspar/pub-analyzer
|
|
6
6
|
License: MIT
|
|
@@ -23,10 +23,10 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
24
|
Classifier: Typing :: Typed
|
|
25
25
|
Requires-Dist: httpx (==0.27.0)
|
|
26
|
-
Requires-Dist: jinja2 (==3.1.
|
|
27
|
-
Requires-Dist: pydantic (==2.7.
|
|
28
|
-
Requires-Dist: textual (==0.
|
|
29
|
-
Requires-Dist: typst (==0.11.
|
|
26
|
+
Requires-Dist: jinja2 (==3.1.4)
|
|
27
|
+
Requires-Dist: pydantic (==2.7.4)
|
|
28
|
+
Requires-Dist: textual (==0.70.0)
|
|
29
|
+
Requires-Dist: typst (==0.11.1)
|
|
30
30
|
Project-URL: Documentation, https://pub-analyzer.com/
|
|
31
31
|
Project-URL: Repository, https://github.com/alejandrgaspar/pub-analyzer
|
|
32
32
|
Description-Content-Type: text/markdown
|
|
@@ -19,20 +19,26 @@ Body {
|
|
|
19
19
|
Footer {
|
|
20
20
|
dock: bottom;
|
|
21
21
|
background: $primary-color;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
Footer > .footer--highlight {
|
|
25
|
-
background: $primary-color-accent;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
Footer > .footer--highlight-key {
|
|
29
|
-
background: $primary-color-highlight;
|
|
30
|
-
text-style: bold;
|
|
31
|
-
}
|
|
32
22
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
FooterKey {
|
|
24
|
+
background: $primary-color;
|
|
25
|
+
color: white;
|
|
26
|
+
|
|
27
|
+
.footer-key--key {
|
|
28
|
+
text-style: bold;
|
|
29
|
+
color: white;
|
|
30
|
+
background: $primary-color-accent;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&:hover {
|
|
34
|
+
background: $primary-color-highlight;
|
|
35
|
+
color: white;
|
|
36
|
+
text-style: bold;
|
|
37
|
+
.footer-key--key {
|
|
38
|
+
background: $primary-color-accent;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
LoadingIndicator {
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Author Summary
|
|
2
|
+
= Author.
|
|
3
|
+
|
|
4
|
+
#let summary-card(title: "Title", body) = {
|
|
5
|
+
return block(
|
|
6
|
+
width: 100%,
|
|
7
|
+
height: 150pt,
|
|
8
|
+
fill: rgb("e5e7eb"),
|
|
9
|
+
stroke: 1pt,
|
|
10
|
+
radius: 2pt,
|
|
11
|
+
)[
|
|
12
|
+
#v(20pt)
|
|
13
|
+
#align(center)[#text(size: 12pt)[#title]]
|
|
14
|
+
#v(5pt)
|
|
15
|
+
#block(width: 100%, inset: (x: 20pt))[#body]
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Cards
|
|
20
|
+
#grid(
|
|
21
|
+
columns: (1fr, 1fr, 1fr),
|
|
22
|
+
column-gutter: 15pt,
|
|
23
|
+
[
|
|
24
|
+
// Last institution.
|
|
25
|
+
#summary-card(title:"Last institution:")[
|
|
26
|
+
{% if report.author.last_known_institutions%}
|
|
27
|
+
{% set last_known_institution = report.author.last_known_institutions[0] %}
|
|
28
|
+
#grid(
|
|
29
|
+
rows: auto, row-gutter: 10pt,
|
|
30
|
+
|
|
31
|
+
[*Name:* {{ last_known_institution.display_name }}],
|
|
32
|
+
[*Country:* {{ last_known_institution.country_code }}],
|
|
33
|
+
[*Type:* {{ last_known_institution.type.value|capitalize }}],
|
|
34
|
+
)
|
|
35
|
+
{% endif %}
|
|
36
|
+
]
|
|
37
|
+
],
|
|
38
|
+
[
|
|
39
|
+
// Author identifiers.
|
|
40
|
+
#summary-card(title:"Identifiers:")[
|
|
41
|
+
#grid(
|
|
42
|
+
rows: auto, row-gutter: 10pt,
|
|
43
|
+
{% for key, value in report.author.ids.model_dump().items() %}
|
|
44
|
+
{% if value %}
|
|
45
|
+
[- #underline( [#link("{{ value }}")[{{ key }}]] )],
|
|
46
|
+
{% endif %}
|
|
47
|
+
{% endfor %}
|
|
48
|
+
)
|
|
49
|
+
]
|
|
50
|
+
],
|
|
51
|
+
[
|
|
52
|
+
// Citation metrics.
|
|
53
|
+
#summary-card(title: "Citation metrics:")[
|
|
54
|
+
#grid(
|
|
55
|
+
rows: auto, row-gutter: 10pt,
|
|
56
|
+
|
|
57
|
+
[*2-year mean:* {{ report.author.summary_stats.two_yr_mean_citedness|round(5) }}],
|
|
58
|
+
[*h-index:* {{ report.author.summary_stats.h_index }}],
|
|
59
|
+
[*i10 index:* {{ report.author.summary_stats.i10_index }}]
|
|
60
|
+
)
|
|
61
|
+
]
|
|
62
|
+
],
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
#v(10pt)
|
|
66
|
+
#align(center, text(11pt)[_Counts by year_])
|
|
67
|
+
#grid(
|
|
68
|
+
columns: (1fr, 1fr),
|
|
69
|
+
column-gutter: 15pt,
|
|
70
|
+
align: (auto, horizon),
|
|
71
|
+
|
|
72
|
+
[
|
|
73
|
+
#table(
|
|
74
|
+
columns: (1fr, 2fr, 2fr),
|
|
75
|
+
inset: 8pt,
|
|
76
|
+
align: horizon,
|
|
77
|
+
// Headers
|
|
78
|
+
[*Year*], [*Works count*], [*Cited by count*],
|
|
79
|
+
|
|
80
|
+
// Content
|
|
81
|
+
{% set max_year_count = 0 %}
|
|
82
|
+
{% for year_count in report.author.counts_by_year[:8] %}
|
|
83
|
+
[{{ year_count.year }}], [{{ year_count.works_count }}], [{{ year_count.cited_by_count }}],
|
|
84
|
+
{% set max_year_count = year_count %}
|
|
85
|
+
{% endfor %}
|
|
86
|
+
)
|
|
87
|
+
],
|
|
88
|
+
grid.cell(
|
|
89
|
+
inset: (x: 10pt, bottom: 10pt, top: 2.5pt),
|
|
90
|
+
stroke: 1pt
|
|
91
|
+
)[
|
|
92
|
+
#align(center, text(10pt)[Cites by year])
|
|
93
|
+
#v(5pt)
|
|
94
|
+
#canvas(length: 100%, {
|
|
95
|
+
plot.plot(
|
|
96
|
+
size: (0.90, 0.48),
|
|
97
|
+
axis-style: "scientific-auto",
|
|
98
|
+
plot-style: (stroke: (1pt + BLUE),),
|
|
99
|
+
x-min: auto, x-max: auto,
|
|
100
|
+
x-tick-step: 1, y-tick-step: auto,
|
|
101
|
+
x-label: none, y-label: none,
|
|
102
|
+
{
|
|
103
|
+
plot.add((
|
|
104
|
+
{% for year_count in report.author.counts_by_year[:8] %}
|
|
105
|
+
({{ year_count.year }}, {{ year_count.cited_by_count }}),
|
|
106
|
+
{% endfor %}
|
|
107
|
+
))
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
]
|
|
111
|
+
)
|
|
112
|
+
#pagebreak()
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
// This document was generated using Pub Analyzer.
|
|
2
2
|
// https://pub-analyzer.com
|
|
3
3
|
|
|
4
|
+
// Packages
|
|
5
|
+
#import "@preview/cetz:0.2.2": canvas, plot, chart, palette
|
|
6
|
+
|
|
7
|
+
// Colors
|
|
8
|
+
#let BLUE = rgb("#42a2f8")
|
|
9
|
+
#let GREEN = rgb("#82d452")
|
|
10
|
+
#let GRAY = rgb("#929292")
|
|
11
|
+
#let YELLOW = rgb("#f0bb40")
|
|
12
|
+
#let RED = rgb("#eb4025")
|
|
13
|
+
#let PURPLE = rgb("#c33375")
|
|
14
|
+
|
|
15
|
+
#let colors = (BLUE, GREEN, GRAY, YELLOW, RED, PURPLE)
|
|
4
16
|
|
|
5
17
|
// Page Layoput
|
|
6
18
|
#set page("us-letter")
|
{pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/internal/templates/author/sources.typ
RENAMED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
// Content
|
|
12
12
|
{% for source in report.sources_summary.sources %}
|
|
13
|
-
[
|
|
13
|
+
[3.{{ loop.index }}. #label("source_{{ source.id.path.rpartition("/")[2] }}")],
|
|
14
14
|
[#underline([#link("{{ source.homepage_url }}")[#"{{ source.display_name }}"]])],
|
|
15
15
|
[{{ source.host_organization_name or "-" }}],
|
|
16
16
|
[{{source.type }}],
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// Works
|
|
2
|
+
= Works.
|
|
3
|
+
|
|
4
|
+
#let works_metrics_card(title: "Title", graph, body) = {
|
|
5
|
+
grid(
|
|
6
|
+
rows: (18pt, 175pt, 60pt),
|
|
7
|
+
columns: 100%,
|
|
8
|
+
|
|
9
|
+
[
|
|
10
|
+
#block(width: 100%, height: 100%)[
|
|
11
|
+
#align(center + horizon)[#text(style: "italic")[#title]]
|
|
12
|
+
]
|
|
13
|
+
],
|
|
14
|
+
[
|
|
15
|
+
#block(width: 100%, height: 100%)[
|
|
16
|
+
#align(center + horizon)[#graph]
|
|
17
|
+
]
|
|
18
|
+
],
|
|
19
|
+
[
|
|
20
|
+
#block(width: 100%, height: 100%, inset: (x: 5pt, y: 10pt))[#body]
|
|
21
|
+
],
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
#grid(
|
|
26
|
+
columns: (1fr, 1fr, 1fr),
|
|
27
|
+
column-gutter: 15pt,
|
|
28
|
+
[
|
|
29
|
+
#let graph = {
|
|
30
|
+
canvas(length: 35%, {
|
|
31
|
+
chart.piechart(
|
|
32
|
+
(
|
|
33
|
+
{{ report.citation_summary.type_a_count }}, // Type A
|
|
34
|
+
{{ report.citation_summary.type_b_count }} // Type B
|
|
35
|
+
),
|
|
36
|
+
radius: 1,
|
|
37
|
+
slice-style: (BLUE, GREEN),
|
|
38
|
+
outer-label: (content: "%", radius: 115%),
|
|
39
|
+
)
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
#works_metrics_card(title: "Citation metrics", graph)[
|
|
44
|
+
#grid(
|
|
45
|
+
rows: auto, row-gutter: 10pt,
|
|
46
|
+
columns: (1fr, 1fr),
|
|
47
|
+
|
|
48
|
+
grid.cell(colspan: 2)[
|
|
49
|
+
*Count:* {{ report.citation_summary.type_a_count + report.citation_summary.type_b_count }}
|
|
50
|
+
],
|
|
51
|
+
[#box(height: 7pt, width: 7pt, fill: BLUE) *Type A:* {{ report.citation_summary.type_a_count }}],
|
|
52
|
+
[#box(height: 7pt, width: 7pt, fill: GREEN) *Type B:* {{ report.citation_summary.type_b_count }}],
|
|
53
|
+
)
|
|
54
|
+
]
|
|
55
|
+
],
|
|
56
|
+
[
|
|
57
|
+
#let graph = {
|
|
58
|
+
canvas(length: 35%, {
|
|
59
|
+
chart.columnchart(
|
|
60
|
+
size: (2.45, 2.0),
|
|
61
|
+
y-grid: false,
|
|
62
|
+
bar-style: palette.new(
|
|
63
|
+
base: (stroke: none, fill: none),
|
|
64
|
+
colors: colors
|
|
65
|
+
),
|
|
66
|
+
(
|
|
67
|
+
{% for work_type in report.works_type_summary[:4] %}
|
|
68
|
+
("{{ work_type.type_name[:2]|capitalize }}", {{ work_type.count }}),
|
|
69
|
+
{% endfor %}
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
#works_metrics_card(title: "Work Type", graph)[
|
|
75
|
+
#grid(
|
|
76
|
+
rows: auto, row-gutter: 10pt,
|
|
77
|
+
columns: (1fr, 1fr),
|
|
78
|
+
column-gutter: 5pt,
|
|
79
|
+
|
|
80
|
+
grid.cell(colspan: 2)[
|
|
81
|
+
*Count:* {{ report.open_access_summary.model_dump().items()|sum(attribute="1") }}
|
|
82
|
+
],
|
|
83
|
+
|
|
84
|
+
{% for work_type in report.works_type_summary[:4] %}
|
|
85
|
+
[
|
|
86
|
+
#box(height: 7pt, width: 7pt, fill: colors.at({{ loop.index0 }})) *{{ work_type.type_name|capitalize }}:* {{ work_type.count }}
|
|
87
|
+
],
|
|
88
|
+
{% endfor %}
|
|
89
|
+
)
|
|
90
|
+
]
|
|
91
|
+
],
|
|
92
|
+
[
|
|
93
|
+
#let graph = {
|
|
94
|
+
canvas(length: 35%, {
|
|
95
|
+
chart.piechart(
|
|
96
|
+
(
|
|
97
|
+
{{report.open_access_summary.gold}}, // Gold
|
|
98
|
+
{{report.open_access_summary.green}}, // Green
|
|
99
|
+
{{report.open_access_summary.hybrid}}, // Hybrid
|
|
100
|
+
{{report.open_access_summary.bronze}}, // Bronze
|
|
101
|
+
{{report.open_access_summary.closed}}, // Closed
|
|
102
|
+
),
|
|
103
|
+
radius: 1,
|
|
104
|
+
inner-radius: .4,
|
|
105
|
+
slice-style: (YELLOW, GREEN, RED, BLUE, GRAY),
|
|
106
|
+
outer-label: (content: "%", radius: 115%),
|
|
107
|
+
)
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
#works_metrics_card(title: "Open Access", graph)[
|
|
111
|
+
#grid(
|
|
112
|
+
rows: auto, row-gutter: 10pt,
|
|
113
|
+
columns: (1fr, 1fr, 1fr),
|
|
114
|
+
column-gutter: 5pt,
|
|
115
|
+
|
|
116
|
+
grid.cell(colspan: 3)[
|
|
117
|
+
*Count:* {{ report.open_access_summary.model_dump().items()|sum(attribute="1") }}
|
|
118
|
+
],
|
|
119
|
+
|
|
120
|
+
[#box(height: 7pt, width: 7pt, fill: YELLOW) *Gold:* {{report.open_access_summary.gold}}],
|
|
121
|
+
[#box(height: 7pt, width: 7pt, fill: GREEN) *Green:* {{report.open_access_summary.green}}],
|
|
122
|
+
[#box(height: 7pt, width: 7pt, fill: BLUE) *Bronze:* {{report.open_access_summary.bronze}}],
|
|
123
|
+
|
|
124
|
+
[#box(height: 7pt, width: 7pt, fill: GRAY) *Closed:* {{report.open_access_summary.closed}}],
|
|
125
|
+
[#box(height: 7pt, width: 7pt, fill: RED) *Hybrid:* {{report.open_access_summary.hybrid}}],
|
|
126
|
+
)
|
|
127
|
+
]
|
|
128
|
+
],
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
#align(center, text(11pt)[Works from {{ report.works[0].work.publication_year }} to {{ report.works[-1].work.publication_year }}])
|
|
132
|
+
#table(
|
|
133
|
+
columns: (auto, 3fr, auto, auto, auto, auto, auto, auto, auto),
|
|
134
|
+
inset: 8pt,
|
|
135
|
+
align: horizon,
|
|
136
|
+
// Headers
|
|
137
|
+
[], [*Title*], [*Type*], [*DOI*], [*Publication Date*], [*Cited by count*], [*Type A*], [*Type B*], [*OA*],
|
|
138
|
+
|
|
139
|
+
// Content
|
|
140
|
+
{% for work in report.works %}
|
|
141
|
+
[#underline([#link(label("work_{{ loop.index }}"))[@work_{{ loop.index }}]])],
|
|
142
|
+
[#"{{ work.work.title.replace('"', '\\"') }}"],
|
|
143
|
+
[{{ work.work.type }}],
|
|
144
|
+
[{% if work.work.ids.doi %}#underline([#link("{{ work.work.ids.doi }}")[DOI]]){% else %}-{% endif %}],
|
|
145
|
+
[{{ work.work.publication_date }}],
|
|
146
|
+
[{{ work.citation_summary.type_a_count + work.citation_summary.type_b_count }}],
|
|
147
|
+
[{{ work.citation_summary.type_a_count }}],
|
|
148
|
+
[{{ work.citation_summary.type_b_count }}],
|
|
149
|
+
[{{ work.work.open_access.oa_status.value }}],
|
|
150
|
+
{% endfor %}
|
|
151
|
+
)
|
|
152
|
+
#pagebreak()
|
{pub_analyzer-0.3.0 → pub_analyzer-0.4.0}/pub_analyzer/internal/templates/author/works_extended.typ
RENAMED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
== Extended info.
|
|
2
1
|
{% for work in report.works %}
|
|
3
2
|
|
|
4
3
|
{% if not loop.first %}
|
|
5
4
|
#pagebreak()
|
|
6
5
|
{% endif %}
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
== #text()[#"{{ work.work.title.replace('"', '\\"') }}"] <work_{{ loop.index }}>
|
|
9
8
|
|
|
10
9
|
#linebreak()
|
|
11
10
|
|
|
@@ -43,8 +43,12 @@ class PubAnalyzerApp(App[DOMNode]):
|
|
|
43
43
|
|
|
44
44
|
def compose(self) -> ComposeResult:
|
|
45
45
|
"""Create child widgets for the app."""
|
|
46
|
+
footer = Footer()
|
|
47
|
+
footer.upper_case_keys = True
|
|
48
|
+
footer.ctrl_to_caret = False
|
|
49
|
+
|
|
46
50
|
yield Body()
|
|
47
|
-
yield
|
|
51
|
+
yield footer
|
|
48
52
|
|
|
49
53
|
def action_toggle_dark(self) -> None:
|
|
50
54
|
"""Toggle dark mode."""
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "pub-analyzer"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "A text user interface, written in python, which automates the generation of scientific production reports using OpenAlex"
|
|
9
9
|
|
|
10
10
|
authors = ["Alejandro Gaspar <alejandro@gaspar.land>"]
|
|
@@ -40,21 +40,21 @@ pub-analyzer = "pub_analyzer.main:run"
|
|
|
40
40
|
[tool.poetry.dependencies]
|
|
41
41
|
python = "^3.10"
|
|
42
42
|
|
|
43
|
-
textual = "0.
|
|
43
|
+
textual = "0.70.0"
|
|
44
44
|
httpx = "0.27.0"
|
|
45
|
-
pydantic = "2.7.
|
|
45
|
+
pydantic = "2.7.4"
|
|
46
46
|
|
|
47
|
-
typst = "0.11.
|
|
48
|
-
jinja2 = "3.1.
|
|
47
|
+
typst = "0.11.1"
|
|
48
|
+
jinja2 = "3.1.4"
|
|
49
49
|
|
|
50
50
|
[tool.poetry.group.dev.dependencies]
|
|
51
51
|
textual-dev = "1.5.1"
|
|
52
52
|
|
|
53
|
-
pre-commit = "3.7.
|
|
53
|
+
pre-commit = "3.7.1"
|
|
54
54
|
mypy = "1.10.0"
|
|
55
|
-
ruff = "0.4.
|
|
55
|
+
ruff = "0.4.8"
|
|
56
56
|
|
|
57
|
-
pytest = "8.2.
|
|
57
|
+
pytest = "8.2.2"
|
|
58
58
|
pytest-asyncio = "0.21.1"
|
|
59
59
|
respx = "0.21.1"
|
|
60
60
|
vcrpy = "6.0.1"
|
|
@@ -64,8 +64,8 @@ pytest-recording = "0.13.1"
|
|
|
64
64
|
mkdocs = "1.5.3"
|
|
65
65
|
mkdocs-material = "9.5.18"
|
|
66
66
|
|
|
67
|
-
mkdocstrings = {extras = ["python"], version = "0.25.
|
|
68
|
-
mkdocstrings-python = "1.10.
|
|
67
|
+
mkdocstrings = {extras = ["python"], version = "0.25.1"}
|
|
68
|
+
mkdocstrings-python = "1.10.3"
|
|
69
69
|
|
|
70
70
|
[tool.mypy]
|
|
71
71
|
strict = true
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
// Author Summary
|
|
2
|
-
= Author.
|
|
3
|
-
|
|
4
|
-
// Cards
|
|
5
|
-
#grid(
|
|
6
|
-
columns: (1fr, 1fr, 1fr),
|
|
7
|
-
column-gutter: 15pt,
|
|
8
|
-
[
|
|
9
|
-
// Card
|
|
10
|
-
#rect(
|
|
11
|
-
width: 100%,
|
|
12
|
-
height: 150pt,
|
|
13
|
-
fill: rgb("e5e7eb"),
|
|
14
|
-
stroke: 1pt,
|
|
15
|
-
radius: 2pt,
|
|
16
|
-
[#linebreak()
|
|
17
|
-
#grid(
|
|
18
|
-
columns: 1fr,
|
|
19
|
-
row-gutter: (15pt, 12pt),
|
|
20
|
-
|
|
21
|
-
// Card Title
|
|
22
|
-
[#align(center)[#text(size: 12pt)[Last institution:]]],
|
|
23
|
-
|
|
24
|
-
// Card content
|
|
25
|
-
{% if report.author.last_known_institutions%}
|
|
26
|
-
{% set last_known_institution = report.author.last_known_institutions[0] %}
|
|
27
|
-
[#align(left)[#text(size: 10pt)[- *Name:* {{ last_known_institution.display_name }}]]],
|
|
28
|
-
[#align(left)[#text(size: 10pt)[- *Country:* MX]]],
|
|
29
|
-
[#align(left)[#text(size: 10pt)[- *Type:* education]]],
|
|
30
|
-
{% endif %}
|
|
31
|
-
)]
|
|
32
|
-
)
|
|
33
|
-
],
|
|
34
|
-
[
|
|
35
|
-
// Card
|
|
36
|
-
#rect(
|
|
37
|
-
width: 100%,
|
|
38
|
-
height: 150pt,
|
|
39
|
-
fill: rgb("e5e7eb"),
|
|
40
|
-
stroke: 1pt,
|
|
41
|
-
radius: 2pt,
|
|
42
|
-
[#linebreak()
|
|
43
|
-
#grid(
|
|
44
|
-
columns: 1fr,
|
|
45
|
-
row-gutter: (15pt, 12pt),
|
|
46
|
-
|
|
47
|
-
// Card Title
|
|
48
|
-
[#align(center)[#text(size: 12pt)[Identifiers:]]],
|
|
49
|
-
|
|
50
|
-
// Card content
|
|
51
|
-
{% for key, value in report.author.ids.model_dump().items() %}
|
|
52
|
-
{% if value %}
|
|
53
|
-
[#align(left)[#text(size: 10pt)[- #underline( [#link("{{ value }}")[{{ key }}]] )]]],
|
|
54
|
-
{% endif %}
|
|
55
|
-
{% endfor %}
|
|
56
|
-
)]
|
|
57
|
-
)
|
|
58
|
-
],
|
|
59
|
-
[
|
|
60
|
-
// Card
|
|
61
|
-
#rect(
|
|
62
|
-
width: 100%,
|
|
63
|
-
height: 150pt,
|
|
64
|
-
fill: rgb("e5e7eb"),
|
|
65
|
-
stroke: 1pt,
|
|
66
|
-
radius: 2pt,
|
|
67
|
-
[#linebreak()
|
|
68
|
-
#grid(
|
|
69
|
-
columns: 1fr,
|
|
70
|
-
row-gutter: (15pt, 12pt),
|
|
71
|
-
|
|
72
|
-
// Card Title
|
|
73
|
-
[#align(center)[#text(size: 12pt)[Citation metrics:]]],
|
|
74
|
-
|
|
75
|
-
// Card content
|
|
76
|
-
[#align(left)[#text(size: 10pt)[- *2-year mean:* {{ report.author.summary_stats.two_yr_mean_citedness|round(5) }}]]],
|
|
77
|
-
[#align(left)[#text(size: 10pt)[- *h-index:* {{ report.author.summary_stats.h_index }}]]],
|
|
78
|
-
[#align(left)[#text(size: 10pt)[- *i10 index:* {{ report.author.summary_stats.i10_index }}]]],
|
|
79
|
-
)]
|
|
80
|
-
)
|
|
81
|
-
],
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
#align(center, text(11pt)[_Counts by year_])
|
|
85
|
-
#table(
|
|
86
|
-
columns: (1fr, 2fr, 2fr),
|
|
87
|
-
inset: 8pt,
|
|
88
|
-
align: horizon,
|
|
89
|
-
// Headers
|
|
90
|
-
[*Year*], [*Works count*], [*Cited by count*],
|
|
91
|
-
|
|
92
|
-
// Content
|
|
93
|
-
{% for year_count in report.author.counts_by_year[:8] %}
|
|
94
|
-
[{{ year_count.year }}], [{{ year_count.works_count }}], [{{ year_count.cited_by_count }}],
|
|
95
|
-
{% endfor %}
|
|
96
|
-
)
|
|
97
|
-
#pagebreak()
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// Works
|
|
2
|
-
= Works.
|
|
3
|
-
|
|
4
|
-
#linebreak()
|
|
5
|
-
|
|
6
|
-
#grid(
|
|
7
|
-
columns: (1fr, 1fr, 1fr),
|
|
8
|
-
column-gutter: 30pt,
|
|
9
|
-
[
|
|
10
|
-
#align(center)[_Citation metrics_]
|
|
11
|
-
#parbreak()
|
|
12
|
-
- *Count:* {{ report.citation_summary.type_a_count + report.citation_summary.type_b_count }}
|
|
13
|
-
- *Type A:* {{ report.citation_summary.type_a_count }}
|
|
14
|
-
- *Type B:* {{ report.citation_summary.type_b_count }}
|
|
15
|
-
],
|
|
16
|
-
[
|
|
17
|
-
#align(center)[_Work Type_]
|
|
18
|
-
#parbreak()
|
|
19
|
-
{% for work_type in report.works_type_summary %}
|
|
20
|
-
- *{{ work_type.type_name }}:* {{ work_type.count }}
|
|
21
|
-
{% endfor %}
|
|
22
|
-
],
|
|
23
|
-
[
|
|
24
|
-
#align(center)[_Open Access_]
|
|
25
|
-
#parbreak()
|
|
26
|
-
#grid(
|
|
27
|
-
columns: (1fr, 1fr),
|
|
28
|
-
column-gutter: 15pt,
|
|
29
|
-
[
|
|
30
|
-
- *gold:* {{report.open_access_summary.gold}}
|
|
31
|
-
- *green:* {{report.open_access_summary.green}}
|
|
32
|
-
- *hybrid:* {{report.open_access_summary.hybrid}}
|
|
33
|
-
],
|
|
34
|
-
[
|
|
35
|
-
- *bronze:* {{report.open_access_summary.bronze}}
|
|
36
|
-
- *closed:* {{report.open_access_summary.closed}}
|
|
37
|
-
],
|
|
38
|
-
)
|
|
39
|
-
],
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
#linebreak()
|
|
43
|
-
|
|
44
|
-
#align(center, text(11pt)[Works from {{ report.works[0].work.publication_year }} to {{ report.works[-1].work.publication_year }}])
|
|
45
|
-
#table(
|
|
46
|
-
columns: (auto, 3fr, auto, auto, auto, auto, auto, auto, auto),
|
|
47
|
-
inset: 8pt,
|
|
48
|
-
align: horizon,
|
|
49
|
-
// Headers
|
|
50
|
-
[], [*Title*], [*Type*], [*DOI*], [*Publication Date*], [*Cited by count*], [*Type A*], [*Type B*], [*OA*],
|
|
51
|
-
|
|
52
|
-
// Content
|
|
53
|
-
{% for work in report.works %}
|
|
54
|
-
[#underline([#link(label("work_{{ loop.index }}"))[@work_{{ loop.index }}]])],
|
|
55
|
-
[#"{{ work.work.title.replace('"', '\\"') }}"],
|
|
56
|
-
[{{ work.work.type }}],
|
|
57
|
-
[{% if work.work.ids.doi %}#underline([#link("{{ work.work.ids.doi }}")[DOI]]){% else %}-{% endif %}],
|
|
58
|
-
[{{ work.work.publication_date }}],
|
|
59
|
-
[{{ work.citation_summary.type_a_count + work.citation_summary.type_b_count }}],
|
|
60
|
-
[{{ work.citation_summary.type_a_count }}],
|
|
61
|
-
[{{ work.citation_summary.type_b_count }}],
|
|
62
|
-
[{{ work.work.open_access.oa_status.value }}],
|
|
63
|
-
{% endfor %}
|
|
64
|
-
)
|
|
65
|
-
#pagebreak()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|