rbiswasfc commited on
Commit
52b731a
β€’
1 Parent(s): 969e3f2
Files changed (2) hide show
  1. app.py +96 -2
  2. requirements.txt +2 -0
app.py CHANGED
@@ -6,10 +6,13 @@ from datetime import date, datetime, timedelta
6
  from io import BytesIO
7
 
8
  import dotenv
 
 
9
  from datasets import load_dataset
10
  from dateutil.parser import parse
11
  from dateutil.tz import tzutc
12
  from fasthtml.common import *
 
13
  from huggingface_hub import login, whoami
14
 
15
  dotenv.load_dotenv()
@@ -23,6 +26,7 @@ style = Style("""
23
  .card a:hover { text-decoration: underline; }
24
  """)
25
 
 
26
  # delete data folder
27
  if os.path.exists("data"):
28
  try:
@@ -80,7 +84,7 @@ def generate_week_content(current_week):
80
  prev_week = weeks[week_index + 1] if week_index < len(weeks) - 1 else None
81
  next_week = weeks[week_index - 1] if week_index > 0 else None
82
 
83
- nav_buttons = Group(
84
  Button(
85
  "← Previous Week",
86
  hx_get=f"/week/{prev_week}" if prev_week else "#",
@@ -95,6 +99,7 @@ def generate_week_content(current_week):
95
  hx_swap="innerHTML",
96
  disabled=not next_week,
97
  ),
 
98
  )
99
 
100
  articles = week2articles[current_week]
@@ -115,6 +120,7 @@ def generate_week_content(current_week):
115
 
116
  if image:
117
  pil_image = image["image"] # image[0]["image"]
 
118
  img_byte_arr = BytesIO()
119
  pil_image.save(img_byte_arr, format="JPEG")
120
  img_byte_arr = img_byte_arr.getvalue()
@@ -138,7 +144,9 @@ def generate_week_content(current_week):
138
  week_end = current_week + timedelta(days=6)
139
  return Div(
140
  nav_buttons,
141
- H3(f"Week of {current_week.strftime('%B %d')} - {week_end.strftime('%B %d, %Y')} ({len(articles)} articles)"),
 
 
142
  grid,
143
  nav_buttons,
144
  id="content",
@@ -159,6 +167,92 @@ def get(date: str):
159
  return Div(f"Error displaying articles: {str(e)}")
160
 
161
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  # serve()
163
 
164
  if __name__ == "__main__":
 
6
  from io import BytesIO
7
 
8
  import dotenv
9
+ import matplotlib.pyplot as plt
10
+ import seaborn as sns
11
  from datasets import load_dataset
12
  from dateutil.parser import parse
13
  from dateutil.tz import tzutc
14
  from fasthtml.common import *
15
+ from fh_matplotlib import matplotlib2fasthtml
16
  from huggingface_hub import login, whoami
17
 
18
  dotenv.load_dotenv()
 
26
  .card a:hover { text-decoration: underline; }
27
  """)
28
 
29
+
30
  # delete data folder
31
  if os.path.exists("data"):
32
  try:
 
84
  prev_week = weeks[week_index + 1] if week_index < len(weeks) - 1 else None
85
  next_week = weeks[week_index - 1] if week_index > 0 else None
86
 
87
+ nav_buttons = Div(
88
  Button(
89
  "← Previous Week",
90
  hx_get=f"/week/{prev_week}" if prev_week else "#",
 
99
  hx_swap="innerHTML",
100
  disabled=not next_week,
101
  ),
102
+ A("View Stats", href="/stats", cls="button"),
103
  )
104
 
105
  articles = week2articles[current_week]
 
120
 
121
  if image:
122
  pil_image = image["image"] # image[0]["image"]
123
+ pil_image.thumbnail((500, 500))
124
  img_byte_arr = BytesIO()
125
  pil_image.save(img_byte_arr, format="JPEG")
126
  img_byte_arr = img_byte_arr.getvalue()
 
144
  week_end = current_week + timedelta(days=6)
145
  return Div(
146
  nav_buttons,
147
+ Br(),
148
+ H5(f"{current_week.strftime('%B %d')} - {week_end.strftime('%B %d, %Y')} ({len(articles)} articles)"),
149
+ Br(),
150
  grid,
151
  nav_buttons,
152
  id="content",
 
167
  return Div(f"Error displaying articles: {str(e)}")
168
 
169
 
170
+ @rt("/stats")
171
+ async def get():
172
+ @matplotlib2fasthtml
173
+ def generate_chart():
174
+ end_date = max(weeks)
175
+ start_date = end_date - timedelta(weeks=11)
176
+
177
+ dates = []
178
+ counts = []
179
+ current_date = start_date
180
+ while current_date <= end_date:
181
+ count = len(week2articles[current_date])
182
+ date_str = current_date.strftime("%d-%B-%Y")
183
+ dates.append(date_str)
184
+ counts.append(count)
185
+ current_date += timedelta(weeks=1)
186
+
187
+ plt.figure(figsize=(12, 6))
188
+ sns.set_style("darkgrid")
189
+ # sns.set_palette("deep")
190
+
191
+ ax = sns.barplot(x=dates, y=counts)
192
+
193
+ plt.title("Papers per Week (Last 12 Weeks)", fontsize=16, fontweight="bold")
194
+ plt.xlabel("Week", fontsize=12)
195
+ plt.ylabel("Number of Papers", fontsize=12)
196
+
197
+ # Rotate and align the tick labels so they look better
198
+ plt.xticks(rotation=45, ha="right")
199
+
200
+ # Use a tight layout to prevent the labels from being cut off
201
+ plt.tight_layout()
202
+
203
+ # Add value labels on top of each bar
204
+ for i, v in enumerate(counts):
205
+ ax.text(i, v + 0.5, str(v), ha="center", va="bottom")
206
+
207
+ # Increase y-axis limit slightly to accommodate the value labels
208
+ plt.ylim(0, max(counts) * 1.1)
209
+
210
+ @matplotlib2fasthtml
211
+ def generate_contributions_chart():
212
+ article_df = article_ds.data.to_pandas()
213
+ added_by_df = article_df.groupby("added_by").size().reset_index(name="count")
214
+ added_by_df = added_by_df.sort_values("count", ascending=False) # Ascending for bottom-to-top order
215
+
216
+ plt.figure(figsize=(12, 8))
217
+ sns.set_style("darkgrid")
218
+ sns.set_palette("deep")
219
+
220
+ ax = sns.barplot(x="count", y="added_by", data=added_by_df)
221
+
222
+ plt.title("Upload Counts", fontsize=16, fontweight="bold")
223
+ plt.xlabel("Number of Articles Added", fontsize=12)
224
+ plt.ylabel("User", fontsize=12)
225
+
226
+ # Add value labels to the end of each bar
227
+ for i, v in enumerate(added_by_df["count"]):
228
+ ax.text(v + 0.5, i, str(v), va="center")
229
+
230
+ # Adjust x-axis to make room for labels
231
+ plt.xlim(0, max(added_by_df["count"]) * 1.1)
232
+
233
+ plt.tight_layout()
234
+
235
+ # chart = Div(generate_chart(), id="chart")
236
+ bar_chart = Div(generate_chart(), id="bar-chart")
237
+ pie_chart = Div(generate_contributions_chart(), id="pie-chart")
238
+
239
+ # add contributions
240
+ article_df = article_ds.data.to_pandas()
241
+ added_by_df = article_df.groupby("added_by").size().reset_index(name="count")
242
+ added_by_df = added_by_df.sort_values("count", ascending=False)
243
+
244
+ return Titled(
245
+ "AnswerAI Zotero Stats",
246
+ H5("Papers per Week (Last 12 Weeks)"),
247
+ bar_chart,
248
+ Br(),
249
+ H5("Contributions by User"),
250
+ pie_chart,
251
+ Br(),
252
+ A("Back to Weekly View", href="/", cls="button"),
253
+ )
254
+
255
+
256
  # serve()
257
 
258
  if __name__ == "__main__":
requirements.txt CHANGED
@@ -12,3 +12,5 @@ datasets
12
  PyMuPDF
13
  pillow
14
  tqdm
 
 
 
12
  PyMuPDF
13
  pillow
14
  tqdm
15
+ fh-matplotlib
16
+ seaborn