Mark Febrizio commited on
Commit
ec74423
1 Parent(s): a99e6cc

Revert "Merge branch 'main' of https://github.com/regulatorystudies/cra-window-rules"

Browse files

This reverts commit 48e3ba352c88eb53e07ef839420e919c72c3e3c0, reversing
changes made to 164c6c162953c6283a1474194d75d0dff27abbed.

app.py CHANGED
@@ -1,9 +1,6 @@
1
  # ----- IMPORTS ----- #
2
 
3
 
4
- # ----- IMPORTS ----- #
5
-
6
-
7
  import asyncio
8
  from datetime import datetime, date, time
9
  from pathlib import Path
@@ -27,7 +24,6 @@ from modules import (
27
  plot_agency,
28
  plot_tf,
29
  plot_NA,
30
- plot_NA,
31
  )
32
 
33
  from shiny import reactive
@@ -40,18 +36,9 @@ ui.include_css( Path(__file__).parent.joinpath("www") / "style.css")
40
  # ----- CREATE OBJECTS ----- #
41
 
42
 
43
- # this text appears in the browser tab
44
- # load css styles from external file
45
- ui.include_css( Path(__file__).parent.joinpath("www") / "style.css")
46
-
47
-
48
- # ----- CREATE OBJECTS ----- #
49
-
50
-
51
  # this text appears in the browser tab
52
  TITLE = "CRA Window Tracker - GW Regulatory Studies Center"
53
 
54
- # page header above main content
55
  # page header above main content
56
  HEADER = "Rules in the Congressional Review Act (CRA) Window"
57
  page_header = ui.HTML(
@@ -62,15 +49,6 @@ page_header = ui.HTML(
62
  """
63
  )
64
 
65
- # logo at the top of the sidebar
66
- page_header = ui.HTML(
67
- f"""
68
- <div class="header">
69
- <span>{HEADER}</span>
70
- </div>
71
- """
72
- )
73
-
74
  # logo at the top of the sidebar
75
  sidebar_logo = ui.HTML(
76
  f"""
@@ -93,23 +71,10 @@ FOOTER = f"""
93
  # ----- APP LAYOUT ----- #
94
 
95
 
96
- ui.tags.title(TITLE)
97
- # footer at the bottom of the page
98
- FOOTER = f"""
99
- -----
100
-
101
- &copy; 2024 [GW Regulatory Studies Center](https://go.gwu.edu/regstudies). See our page on the [Congressional Review Act](https://regulatorystudies.columbian.gwu.edu/congressional-review-act) for more information.
102
- """
103
-
104
-
105
- # ----- APP LAYOUT ----- #
106
-
107
-
108
  ui.tags.title(TITLE)
109
 
110
  page_header
111
 
112
- # sidebar settings
113
  # sidebar settings
114
  with ui.sidebar(open={"desktop": "open", "mobile": "closed"}):
115
  sidebar_logo
@@ -127,19 +92,15 @@ with ui.sidebar(open={"desktop": "open", "mobile": "closed"}):
127
 
128
  #ui.input_switch("switch", "Stack significant rules in plots", False)
129
 
130
- # value boxes with summary data
131
  # value boxes with summary data
132
  with ui.layout_column_wrap():
133
- with ui.value_box():
134
  with ui.value_box():
135
  "All final rules"
136
  @render.text
137
  def count_rules():
138
  return f"{filtered_df()['document_number'].count()}"
139
  ui.input_action_button("filter_all", "Clear Filters", class_="btn-filter", icon=icon_svg("book"))
140
- ui.input_action_button("filter_all", "Clear Filters", class_="btn-filter", icon=icon_svg("book"))
141
 
142
- with ui.value_box():
143
  with ui.value_box():
144
  "Section 3(f)(1) Significant rules *"
145
  @render.text
@@ -149,9 +110,7 @@ with ui.layout_column_wrap():
149
  output = f"{filtered_df()['3f1_significant'].sum()}"
150
  return output
151
  ui.input_action_button("filter_3f1", "Filter", class_="btn-filter", icon=icon_svg("book"))
152
- ui.input_action_button("filter_3f1", "Filter", class_="btn-filter", icon=icon_svg("book"))
153
 
154
- with ui.value_box():
155
  with ui.value_box():
156
  "Other Significant rules *"
157
  @render.text
@@ -161,9 +120,7 @@ with ui.layout_column_wrap():
161
  output = f"{filtered_df()['other_significant'].sum()}"
162
  return output
163
  ui.input_action_button("filter_other", "Filter", class_="btn-filter", icon=icon_svg("book"))
164
- ui.input_action_button("filter_other", "Filter", class_="btn-filter", icon=icon_svg("book"))
165
 
166
- # documentation note on significance data
167
  # documentation note on significance data
168
  ui.markdown(
169
  f"""
@@ -171,7 +128,6 @@ ui.markdown(
171
  """
172
  )
173
 
174
- # main content
175
  # main content
176
  with ui.navset_card_underline(title=""):
177
 
@@ -206,14 +162,11 @@ with ui.navset_card_underline(title=""):
206
  max_val = max(values, default=0)
207
  if (max_val < 2) or (count_gte_zero < 2):
208
  return plot_NA()
209
- return plot_NA()
210
  else:
211
  return plot_tf(
212
  grouped,
213
  input.frequency(),
214
  rule_type=filter_value.get(),
215
- input.frequency(),
216
- rule_type=filter_value.get(),
217
  )
218
 
219
  with ui.card(full_screen=True):
@@ -258,14 +211,6 @@ with ui.navset_card_underline(title=""):
258
  rule_type=filter_value.get(),
259
  )
260
  return plot
261
- if len(grouped) < 2:
262
- return plot_NA()
263
- else:
264
- plot = plot_agency(
265
- grouped.head(10),
266
- rule_type=filter_value.get(),
267
- )
268
- return plot
269
 
270
  with ui.card(full_screen=True):
271
  @render.data_frame
@@ -280,7 +225,6 @@ with ui.navset_card_underline(title=""):
280
  ]
281
  return render.DataTable(grouped.loc[:, [c for c in cols if c in grouped.columns]])
282
 
283
- # download data
284
  # download data
285
  with ui.accordion(open=False):
286
 
@@ -315,7 +259,6 @@ with ui.accordion(open=False):
315
  await asyncio.sleep(0.25)
316
  yield filtered_df().loc[:, output_cols].to_csv(index=False)
317
 
318
- # notes
319
  # notes
320
  with ui.accordion(open=False):
321
 
@@ -329,7 +272,6 @@ with ui.accordion(open=False):
329
  """
330
  )
331
 
332
- # footer citation
333
  # footer citation
334
  ui.markdown(
335
  FOOTER
 
1
  # ----- IMPORTS ----- #
2
 
3
 
 
 
 
4
  import asyncio
5
  from datetime import datetime, date, time
6
  from pathlib import Path
 
24
  plot_agency,
25
  plot_tf,
26
  plot_NA,
 
27
  )
28
 
29
  from shiny import reactive
 
36
  # ----- CREATE OBJECTS ----- #
37
 
38
 
 
 
 
 
 
 
 
 
39
  # this text appears in the browser tab
40
  TITLE = "CRA Window Tracker - GW Regulatory Studies Center"
41
 
 
42
  # page header above main content
43
  HEADER = "Rules in the Congressional Review Act (CRA) Window"
44
  page_header = ui.HTML(
 
49
  """
50
  )
51
 
 
 
 
 
 
 
 
 
 
52
  # logo at the top of the sidebar
53
  sidebar_logo = ui.HTML(
54
  f"""
 
71
  # ----- APP LAYOUT ----- #
72
 
73
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  ui.tags.title(TITLE)
75
 
76
  page_header
77
 
 
78
  # sidebar settings
79
  with ui.sidebar(open={"desktop": "open", "mobile": "closed"}):
80
  sidebar_logo
 
92
 
93
  #ui.input_switch("switch", "Stack significant rules in plots", False)
94
 
 
95
  # value boxes with summary data
96
  with ui.layout_column_wrap():
 
97
  with ui.value_box():
98
  "All final rules"
99
  @render.text
100
  def count_rules():
101
  return f"{filtered_df()['document_number'].count()}"
102
  ui.input_action_button("filter_all", "Clear Filters", class_="btn-filter", icon=icon_svg("book"))
 
103
 
 
104
  with ui.value_box():
105
  "Section 3(f)(1) Significant rules *"
106
  @render.text
 
110
  output = f"{filtered_df()['3f1_significant'].sum()}"
111
  return output
112
  ui.input_action_button("filter_3f1", "Filter", class_="btn-filter", icon=icon_svg("book"))
 
113
 
 
114
  with ui.value_box():
115
  "Other Significant rules *"
116
  @render.text
 
120
  output = f"{filtered_df()['other_significant'].sum()}"
121
  return output
122
  ui.input_action_button("filter_other", "Filter", class_="btn-filter", icon=icon_svg("book"))
 
123
 
 
124
  # documentation note on significance data
125
  ui.markdown(
126
  f"""
 
128
  """
129
  )
130
 
 
131
  # main content
132
  with ui.navset_card_underline(title=""):
133
 
 
162
  max_val = max(values, default=0)
163
  if (max_val < 2) or (count_gte_zero < 2):
164
  return plot_NA()
 
165
  else:
166
  return plot_tf(
167
  grouped,
168
  input.frequency(),
169
  rule_type=filter_value.get(),
 
 
170
  )
171
 
172
  with ui.card(full_screen=True):
 
211
  rule_type=filter_value.get(),
212
  )
213
  return plot
 
 
 
 
 
 
 
 
214
 
215
  with ui.card(full_screen=True):
216
  @render.data_frame
 
225
  ]
226
  return render.DataTable(grouped.loc[:, [c for c in cols if c in grouped.columns]])
227
 
 
228
  # download data
229
  with ui.accordion(open=False):
230
 
 
259
  await asyncio.sleep(0.25)
260
  yield filtered_df().loc[:, output_cols].to_csv(index=False)
261
 
 
262
  # notes
263
  with ui.accordion(open=False):
264
 
 
272
  """
273
  )
274
 
 
275
  # footer citation
276
  ui.markdown(
277
  FOOTER
modules/plotting.py CHANGED
@@ -4,9 +4,6 @@ from plotnine import (
4
  aes,
5
  geom_col,
6
  geom_line,
7
- annotate,
8
- theme,
9
- element_blank,
10
  labs,
11
  coord_flip,
12
  scale_x_discrete,
@@ -21,30 +18,7 @@ class DataAvailabilityError(Exception):
21
  pass
22
 
23
 
24
- def plot_NA(placeholder_text: str = "Not enough data available to visualize.", placeholder_size: int = 14):
25
- """Placeholder plot for when there is not enough data available to visualize."""
26
- return (
27
- ggplot()
28
- + annotate("text", x=0, y=0, label=placeholder_text, size=placeholder_size)
29
- + theme(axis_ticks=element_blank(), axis_text=element_blank(), panel_grid=element_blank())
30
- + labs(x="", y="", title="")
31
- )
32
-
33
-
34
- def generate_rule_axis_label(rule_type: str | None = None):
35
- """Generate axis label for rules, accounting for rule type ("all", "3f1", or "other")."""
36
- y_lab = ""
37
- if rule_type is not None:
38
- rule_type_options = {
39
- "all": "",
40
- "3f1": "3(f)(1) Significant",
41
- "other": "Other Significant",
42
- }
43
- y_lab = f"Number of {rule_type_options.get(rule_type)} rules".replace(" ", " ")
44
- return y_lab
45
-
46
-
47
- def plot_agency(df, group_col = "acronym", value_col = "rules", color="#033C5A", rule_type: str | None = None):
48
  """Plot rules by agency.
49
 
50
  Args:
@@ -56,32 +30,22 @@ def plot_agency(df, group_col = "acronym", value_col = "rules", color="#033C5A",
56
  ggplot: Plotted data.
57
  """
58
  order_list = df.loc[:, group_col].to_list()[::-1]
59
-
60
- y_lab = generate_rule_axis_label(rule_type)
61
 
62
  plot = (
63
  ggplot(
64
  df,
65
  aes(x=group_col, y=value_col),
66
  )
67
- + geom_col(color="#FFFFFF", fill=color)
68
  + coord_flip()
69
  + scale_x_discrete(limits=order_list)
70
- + labs(y=y_lab, x="", title="Rules Published by Agency")
71
  + theme_light()
72
  )
73
-
74
  return plot
75
 
76
 
77
- def plot_month(
78
- df: DataFrame,
79
- group_cols: tuple = ("publication_year", "publication_month"),
80
- value_col: str = "rules",
81
- color: str = "#033C5A",
82
- title: str | None = None,
83
- y_lab: str = "",
84
- ):
85
  """Plot rules by month.
86
 
87
  Args:
@@ -91,33 +55,24 @@ def plot_month(
91
 
92
  Returns:
93
  ggplot: Plotted data.
94
- """
95
  df.loc[:, "ym"] = df[group_cols[0]].astype(str) + "-" + df[group_cols[1]].astype(str).str.pad(2, fillchar="0")
96
  order_list = df.loc[:, "ym"].to_list()
97
- if title is None:
98
- title = "Rules Published by Month"
99
-
100
  plot = (
101
  ggplot(
102
  df,
103
  aes(x="ym", y=value_col),
104
  )
105
- + geom_col(color="#FFFFFF", fill=color)
106
  + scale_x_discrete(limits=order_list)
107
- + labs(y=y_lab, x="", title=title)
108
  + theme_light()
109
  )
110
  return plot
111
 
112
 
113
- def plot_day(
114
- df: DataFrame,
115
- group_col: str = "publication_date",
116
- value_col: str = "rules",
117
- color: str = "#033C5A",
118
- title: str | None = None,
119
- y_lab: str = "",
120
- ):
121
  """Plot rules by day.
122
 
123
  Args:
@@ -139,33 +94,22 @@ def plot_day(
139
  freq = "1 month"
140
 
141
  max_value = df.loc[:, value_col].max()
142
-
143
- if title is None:
144
- title = "Rules Published by Date"
145
 
146
  plot = (
147
  ggplot(
148
  df,
149
  aes(x=group_col, y=value_col),
150
  )
151
- + geom_line(group=1, color=color)
152
  + scale_x_datetime(date_breaks=freq, date_labels="%m-%d")
153
  + scale_y_continuous(limits=(0, max_value), expand=(0, 0, 0.1, 0))
154
- + labs(y=y_lab, x="", title=title)
155
  + theme_light()
156
  )
157
  return plot
158
 
159
 
160
- def plot_week(
161
- df: DataFrame,
162
- group_col: str = "week_of",
163
- value_col: str = "rules",
164
- color: str = "#033C5A",
165
- title: str | None = None,
166
- y_lab: str = "",
167
- show_significant: bool = False,
168
- ):
169
  max_value = df.loc[:, value_col].max()
170
 
171
  date_values = df[group_col].to_list()
@@ -184,35 +128,21 @@ def plot_week(
184
 
185
  breaks = [val for idx, val in enumerate(date_values) if idx % reduce_by == 0]
186
 
187
- if title is None:
188
- title = "Rules Published by Week"
189
-
190
  plot = (
191
  ggplot(
192
  df,
193
  aes(x=group_col, y=value_col),
194
  )
195
- + geom_line(group=1, color=color)
196
  + scale_x_datetime(breaks=breaks, labels=[f"{w.strftime('%m-%d')}" for w in breaks])
197
  + scale_y_continuous(limits=(0, max_value), expand=(0, 0, 0.1, 0))
198
- + labs(y=y_lab, x="", title=title)
199
  + theme_light()
200
  )
201
- if show_significant:
202
- # trying to add significant rules as additional lines
203
- # but getting "TypeError: Discrete value supplied to continuous scale"
204
- # for 3f1 sig rules
205
- df = df.astype({"3f1_significant": "float"})
206
- plot = (
207
- plot
208
- #+ geom_line(aes(x=group_col, y="3f1_significant"), inherit_aes=False, group=1, color="#AA9868", linetype="dotted")
209
- + geom_line(aes(x=group_col, y="other_significant"), inherit_aes=False, group=1, color="#0190DB", linetype="dashed")
210
- #+ guide_legend()
211
- )
212
  return plot
213
 
214
 
215
- def plot_tf(df: DataFrame, frequency: str, rule_type: str | None = None, **kwargs) -> ggplot:
216
  """Plot rules over time by given frequency.
217
 
218
  Args:
@@ -230,10 +160,8 @@ def plot_tf(df: DataFrame, frequency: str, rule_type: str | None = None, **kwarg
230
  "daily": plot_day,
231
  "weekly": plot_week,
232
  }
 
233
  plot_freq = freq_options.get(frequency, None)
234
  if plot_freq is None:
235
  raise ValueError(f"Frequency must be one of: {', '.join(freq_options.keys())}")
236
-
237
- y_lab = generate_rule_axis_label(rule_type)
238
-
239
- return plot_freq(df, y_lab=y_lab, **kwargs)
 
4
  aes,
5
  geom_col,
6
  geom_line,
 
 
 
7
  labs,
8
  coord_flip,
9
  scale_x_discrete,
 
18
  pass
19
 
20
 
21
+ def plot_agency(df, group_col = "acronym", value_col = "rules"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  """Plot rules by agency.
23
 
24
  Args:
 
30
  ggplot: Plotted data.
31
  """
32
  order_list = df.loc[:, group_col].to_list()[::-1]
 
 
33
 
34
  plot = (
35
  ggplot(
36
  df,
37
  aes(x=group_col, y=value_col),
38
  )
39
+ + geom_col()
40
  + coord_flip()
41
  + scale_x_discrete(limits=order_list)
42
+ + labs(y="", x="", title="Number of Rules Published by Agency")
43
  + theme_light()
44
  )
 
45
  return plot
46
 
47
 
48
+ def plot_month(df: DataFrame, group_cols: tuple = ("publication_year", "publication_month"), value_col: str = "rules"):
 
 
 
 
 
 
 
49
  """Plot rules by month.
50
 
51
  Args:
 
55
 
56
  Returns:
57
  ggplot: Plotted data.
58
+ """
59
  df.loc[:, "ym"] = df[group_cols[0]].astype(str) + "-" + df[group_cols[1]].astype(str).str.pad(2, fillchar="0")
60
  order_list = df.loc[:, "ym"].to_list()
61
+
 
 
62
  plot = (
63
  ggplot(
64
  df,
65
  aes(x="ym", y=value_col),
66
  )
67
+ + geom_col()
68
  + scale_x_discrete(limits=order_list)
69
+ + labs(y="", x="", title="Number of Rules Published by Month")
70
  + theme_light()
71
  )
72
  return plot
73
 
74
 
75
+ def plot_day(df: DataFrame, group_col: str = "publication_date", value_col: str = "rules"):
 
 
 
 
 
 
 
76
  """Plot rules by day.
77
 
78
  Args:
 
94
  freq = "1 month"
95
 
96
  max_value = df.loc[:, value_col].max()
 
 
 
97
 
98
  plot = (
99
  ggplot(
100
  df,
101
  aes(x=group_col, y=value_col),
102
  )
103
+ + geom_line(group=1)
104
  + scale_x_datetime(date_breaks=freq, date_labels="%m-%d")
105
  + scale_y_continuous(limits=(0, max_value), expand=(0, 0, 0.1, 0))
106
+ + labs(y="", x="", title="Number of Rules Published by Date")
107
  + theme_light()
108
  )
109
  return plot
110
 
111
 
112
+ def plot_week(df: DataFrame, group_col: str = "week_of", value_col: str = "rules", ):
 
 
 
 
 
 
 
 
113
  max_value = df.loc[:, value_col].max()
114
 
115
  date_values = df[group_col].to_list()
 
128
 
129
  breaks = [val for idx, val in enumerate(date_values) if idx % reduce_by == 0]
130
 
 
 
 
131
  plot = (
132
  ggplot(
133
  df,
134
  aes(x=group_col, y=value_col),
135
  )
136
+ + geom_line(group=1)
137
  + scale_x_datetime(breaks=breaks, labels=[f"{w.strftime('%m-%d')}" for w in breaks])
138
  + scale_y_continuous(limits=(0, max_value), expand=(0, 0, 0.1, 0))
139
+ + labs(y="", x="", title="Number of Rules Published by Week")
140
  + theme_light()
141
  )
 
 
 
 
 
 
 
 
 
 
 
142
  return plot
143
 
144
 
145
+ def plot_tf(df: DataFrame, frequency: str, **kwargs) -> ggplot:
146
  """Plot rules over time by given frequency.
147
 
148
  Args:
 
160
  "daily": plot_day,
161
  "weekly": plot_week,
162
  }
163
+
164
  plot_freq = freq_options.get(frequency, None)
165
  if plot_freq is None:
166
  raise ValueError(f"Frequency must be one of: {', '.join(freq_options.keys())}")
167
+ return plot_freq(df, **kwargs)
 
 
 
requirements-dev-mac.txt CHANGED
@@ -121,7 +121,7 @@ idna==3.7
121
  # requests
122
  iniconfig==2.0.0
123
  # via pytest
124
- ipykernel==6.29.5
125
  # via
126
  # -r requirements-dev.in
127
  # jupyter
@@ -150,7 +150,7 @@ json5==0.9.25
150
  # via jupyterlab-server
151
  jsonpointer==3.0.0
152
  # via jsonschema
153
- jsonschema[format-nongpl]==4.23.0
154
  # via
155
  # jupyter-events
156
  # jupyterlab-server
@@ -183,7 +183,7 @@ jupyter-events==0.10.0
183
  # via jupyter-server
184
  jupyter-lsp==2.2.5
185
  # via jupyterlab
186
- jupyter-server==2.14.2
187
  # via
188
  # jupyter-lsp
189
  # jupyterlab
@@ -196,7 +196,7 @@ jupyterlab==4.2.3
196
  # via notebook
197
  jupyterlab-pygments==0.3.0
198
  # via nbconvert
199
- jupyterlab-server==2.27.3
200
  # via
201
  # jupyterlab
202
  # notebook
@@ -417,7 +417,7 @@ rfc3986-validator==0.1.1
417
  # via
418
  # jsonschema
419
  # jupyter-events
420
- rpds-py==0.19.0
421
  # via
422
  # jsonschema
423
  # referencing
 
121
  # requests
122
  iniconfig==2.0.0
123
  # via pytest
124
+ ipykernel==6.29.4
125
  # via
126
  # -r requirements-dev.in
127
  # jupyter
 
150
  # via jupyterlab-server
151
  jsonpointer==3.0.0
152
  # via jsonschema
153
+ jsonschema[format-nongpl]==4.22.0
154
  # via
155
  # jupyter-events
156
  # jupyterlab-server
 
183
  # via jupyter-server
184
  jupyter-lsp==2.2.5
185
  # via jupyterlab
186
+ jupyter-server==2.14.1
187
  # via
188
  # jupyter-lsp
189
  # jupyterlab
 
196
  # via notebook
197
  jupyterlab-pygments==0.3.0
198
  # via nbconvert
199
+ jupyterlab-server==2.27.2
200
  # via
201
  # jupyterlab
202
  # notebook
 
417
  # via
418
  # jsonschema
419
  # jupyter-events
420
+ rpds-py==0.18.1
421
  # via
422
  # jsonschema
423
  # referencing
requirements-dev-win.txt CHANGED
@@ -78,7 +78,7 @@ cycler==0.12.1
78
  # via
79
  # -c requirements.txt
80
  # matplotlib
81
- debugpy==1.8.2
82
  # via ipykernel
83
  decorator==5.1.1
84
  # via ipython
@@ -125,7 +125,7 @@ idna==3.7
125
  # requests
126
  iniconfig==2.0.0
127
  # via pytest
128
- ipykernel==6.29.5
129
  # via
130
  # -r requirements-dev.in
131
  # jupyter
@@ -154,7 +154,7 @@ json5==0.9.25
154
  # via jupyterlab-server
155
  jsonpointer==3.0.0
156
  # via jsonschema
157
- jsonschema[format-nongpl]==4.23.0
158
  # via
159
  # jupyter-events
160
  # jupyterlab-server
@@ -187,7 +187,7 @@ jupyter-events==0.10.0
187
  # via jupyter-server
188
  jupyter-lsp==2.2.5
189
  # via jupyterlab
190
- jupyter-server==2.14.2
191
  # via
192
  # jupyter-lsp
193
  # jupyterlab
@@ -196,11 +196,11 @@ jupyter-server==2.14.2
196
  # notebook-shim
197
  jupyter-server-terminals==0.5.3
198
  # via jupyter-server
199
- jupyterlab==4.2.4
200
  # via notebook
201
  jupyterlab-pygments==0.3.0
202
  # via nbconvert
203
- jupyterlab-server==2.27.3
204
  # via
205
  # jupyterlab
206
  # notebook
@@ -339,7 +339,7 @@ prompt-toolkit==3.0.36
339
  # ipython
340
  # jupyter-console
341
  # questionary
342
- psutil==6.0.0
343
  # via ipykernel
344
  pure-eval==0.2.2
345
  # via stack-data
@@ -422,7 +422,7 @@ rfc3986-validator==0.1.1
422
  # via
423
  # jsonschema
424
  # jupyter-events
425
- rpds-py==0.19.0
426
  # via
427
  # jsonschema
428
  # referencing
 
78
  # via
79
  # -c requirements.txt
80
  # matplotlib
81
+ debugpy==1.8.1
82
  # via ipykernel
83
  decorator==5.1.1
84
  # via ipython
 
125
  # requests
126
  iniconfig==2.0.0
127
  # via pytest
128
+ ipykernel==6.29.0
129
  # via
130
  # -r requirements-dev.in
131
  # jupyter
 
154
  # via jupyterlab-server
155
  jsonpointer==3.0.0
156
  # via jsonschema
157
+ jsonschema[format-nongpl]==4.22.0
158
  # via
159
  # jupyter-events
160
  # jupyterlab-server
 
187
  # via jupyter-server
188
  jupyter-lsp==2.2.5
189
  # via jupyterlab
190
+ jupyter-server==2.14.1
191
  # via
192
  # jupyter-lsp
193
  # jupyterlab
 
196
  # notebook-shim
197
  jupyter-server-terminals==0.5.3
198
  # via jupyter-server
199
+ jupyterlab==4.2.2
200
  # via notebook
201
  jupyterlab-pygments==0.3.0
202
  # via nbconvert
203
+ jupyterlab-server==2.27.2
204
  # via
205
  # jupyterlab
206
  # notebook
 
339
  # ipython
340
  # jupyter-console
341
  # questionary
342
+ psutil==5.9.8
343
  # via ipykernel
344
  pure-eval==0.2.2
345
  # via stack-data
 
422
  # via
423
  # jsonschema
424
  # jupyter-events
425
+ rpds-py==0.18.1
426
  # via
427
  # jsonschema
428
  # referencing
requirements.in CHANGED
@@ -5,7 +5,7 @@ fr-toolbelt>=0.1.2, <1.0
5
  numpy>=1.26, <2.0
6
  pandas>=2.2, <3.0
7
  plotnine>=0.13.6, <1.0
8
- polars>=0.20.31
9
  pyarrow>=16.1.0, <17.0
10
  python-dateutil>=2.9.0.post0, <3.0
11
  requests>=2.32.2, <3.0
 
5
  numpy>=1.26, <2.0
6
  pandas>=2.2, <3.0
7
  plotnine>=0.13.6, <1.0
8
+ polars>=0.20.26, <1.0
9
  pyarrow>=16.1.0, <17.0
10
  python-dateutil>=2.9.0.post0, <3.0
11
  requests>=2.32.2, <3.0
requirements.txt CHANGED
@@ -4,7 +4,7 @@
4
  #
5
  # pip-compile requirements.in
6
  #
7
- anyio==4.4.0
8
  # via
9
  # starlette
10
  # watchfiles
@@ -30,13 +30,13 @@ cycler==0.12.1
30
  # via matplotlib
31
  faicons==0.2.2
32
  # via -r requirements.in
33
- fonttools==4.53.1
34
  # via matplotlib
35
  fr-toolbelt==0.1.3
36
  # via -r requirements.in
37
  h11==0.14.0
38
  # via uvicorn
39
- htmltools==0.5.3
40
  # via
41
  # faicons
42
  # shiny
@@ -52,13 +52,13 @@ markdown-it-py==3.0.0
52
  # via
53
  # mdit-py-plugins
54
  # shiny
55
- matplotlib==3.9.1
56
  # via plotnine
57
  mdit-py-plugins==0.4.1
58
  # via shiny
59
  mdurl==0.1.2
60
  # via markdown-it-py
61
- mizani==0.11.4
62
  # via plotnine
63
  numpy==1.26.4
64
  # via
@@ -73,7 +73,7 @@ numpy==1.26.4
73
  # pyarrow
74
  # scipy
75
  # statsmodels
76
- packaging==24.1
77
  # via
78
  # htmltools
79
  # matplotlib
@@ -88,11 +88,11 @@ pandas==2.2.2
88
  # statsmodels
89
  patsy==0.5.6
90
  # via statsmodels
91
- pillow==10.4.0
92
  # via matplotlib
93
  plotnine==0.13.6
94
  # via -r requirements.in
95
- polars==1.2.1
96
  # via -r requirements.in
97
  progress==1.6
98
  # via fr-toolbelt
@@ -117,7 +117,7 @@ requests==2.32.3
117
  # via
118
  # -r requirements.in
119
  # fr-toolbelt
120
- scipy==1.14.0
121
  # via
122
  # mizani
123
  # plotnine
@@ -134,7 +134,7 @@ starlette==0.37.2
134
  # via shiny
135
  statsmodels==0.14.2
136
  # via plotnine
137
- typing-extensions==4.12.2
138
  # via
139
  # htmltools
140
  # shiny
@@ -146,9 +146,9 @@ uc-micro-py==1.0.3
146
  # via linkify-it-py
147
  urllib3==2.2.2
148
  # via requests
149
- uvicorn==0.30.1
150
  # via shiny
151
- watchfiles==0.22.0
152
  # via shiny
153
  wcwidth==0.2.13
154
  # via prompt-toolkit
 
4
  #
5
  # pip-compile requirements.in
6
  #
7
+ anyio==4.3.0
8
  # via
9
  # starlette
10
  # watchfiles
 
30
  # via matplotlib
31
  faicons==0.2.2
32
  # via -r requirements.in
33
+ fonttools==4.51.0
34
  # via matplotlib
35
  fr-toolbelt==0.1.3
36
  # via -r requirements.in
37
  h11==0.14.0
38
  # via uvicorn
39
+ htmltools==0.5.1
40
  # via
41
  # faicons
42
  # shiny
 
52
  # via
53
  # mdit-py-plugins
54
  # shiny
55
+ matplotlib==3.8.4
56
  # via plotnine
57
  mdit-py-plugins==0.4.1
58
  # via shiny
59
  mdurl==0.1.2
60
  # via markdown-it-py
61
+ mizani==0.11.3
62
  # via plotnine
63
  numpy==1.26.4
64
  # via
 
73
  # pyarrow
74
  # scipy
75
  # statsmodels
76
+ packaging==24.0
77
  # via
78
  # htmltools
79
  # matplotlib
 
88
  # statsmodels
89
  patsy==0.5.6
90
  # via statsmodels
91
+ pillow==10.3.0
92
  # via matplotlib
93
  plotnine==0.13.6
94
  # via -r requirements.in
95
+ polars==0.20.31
96
  # via -r requirements.in
97
  progress==1.6
98
  # via fr-toolbelt
 
117
  # via
118
  # -r requirements.in
119
  # fr-toolbelt
120
+ scipy==1.13.0
121
  # via
122
  # mizani
123
  # plotnine
 
134
  # via shiny
135
  statsmodels==0.14.2
136
  # via plotnine
137
+ typing-extensions==4.11.0
138
  # via
139
  # htmltools
140
  # shiny
 
146
  # via linkify-it-py
147
  urllib3==2.2.2
148
  # via requests
149
+ uvicorn==0.29.0
150
  # via shiny
151
+ watchfiles==0.21.0
152
  # via shiny
153
  wcwidth==0.2.13
154
  # via prompt-toolkit
www/style.css CHANGED
@@ -15,9 +15,3 @@
15
  font-size: 30px;
16
  vertical-align: middle;
17
  }
18
-
19
- .btn-filter {
20
- font-size: medium;
21
- color: #FFFFFF;
22
- background-color: #0190DB;
23
- }
 
15
  font-size: 30px;
16
  vertical-align: middle;
17
  }