-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprototype.py
242 lines (201 loc) · 8.26 KB
/
prototype.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
from sqlite3 import connect
import pandas as pd
import streamlit as st
from PIL import Image
import requests
import general_statistics as gs
import graph_logic as gl
class GraphData:
def __init__(self, name, isVisible, absoluteData, relativeData, color):
self.name = name
self.isVisible = isVisible
self.absoluteData = absoluteData
self.relativeData = relativeData
self.color = color
def main():
global logtxt
# Basic page configurations
img = Image.open("assets/page_icon.ico")
st.set_page_config(
page_title="GAP • Hasso-Plattner-Institut",
page_icon=img,
layout="wide",
)
st.title("GAP: Gender Analysis for Publications")
st.markdown(
"The GAP-Tool allows users to explore the gender diversity in computer science publications. By choosing different venues, countries, research areas, one can highlight differences within the community. \n *Please note*: The gender-data used by this tool are based on GenderAPI, which automatically classifies authors based on their first names. Thus, we distinguish only female and male gender and cannot reflect the full gender spectrum. Further, country information is based on the currently known affiliation from DBLP. It does not reflect the nationality of the author nor necessarily the affiliation of the author at the time of publication."
)
# Connect to SQLite database
with st.spinner("Opening datasbase connection (This can take a while)..."):
if "connection" not in st.session_state:
st.session_state.connection = connect("gap.db", check_same_thread=False)
# Create cursor object
if "cursor" not in st.session_state:
st.session_state.cursor = st.session_state.connection.cursor()
# Initialize all the necessary session states
with st.spinner("Initializing..."):
st.session_state.setdefault('y_columns', [])
if "min_max" not in st.session_state:
sql = """SELECT min(Year),max(Year) - 1 FROM AllTogether;"""
st.session_state.min_max = query_action(sql, "check")[0]
st.session_state.setdefault("year_range", (1980, 2023))
st.session_state.setdefault("widget_data_representation", "Absolute numbers")
st.session_state.setdefault("widget_venues", "")
st.session_state.setdefault("widget_countries", "")
st.session_state.setdefault("widget_continents", [])
st.session_state.setdefault("widget_publication_types", "")
st.session_state.setdefault("widget_author_position", "")
st.session_state.setdefault("widget_research_areas", "")
st.session_state.setdefault("country_continent_dataframe", pd.DataFrame())
st.session_state.setdefault("is_first_run", True)
st.session_state.setdefault("is_first_submit", True)
st.session_state.setdefault("graph_years", None)
st.session_state.setdefault("grouped_absolutes", {})
if st.session_state.is_first_run:
try:
requests.get('http://localhost:6502/log_visitor')
except requests.exceptions.RequestException as e:
print(f"Error logging visitor: {e}")
# Get all the filters out of the pre-calculated filter csv files
with st.spinner("Loading filters..."):
gl.display_filters()
# If there is no graph created yet, display a placeholder
if "graph" not in st.session_state or st.session_state.graph == None or not st.session_state.graph.data:
st.markdown(
"<h5 style='text-align: center;'>You have not selected any graphs yet </h5>",
unsafe_allow_html=True,
)
image = Image.open("assets/no_data.png")
col1, col2, col3 = st.columns(3)
with col1:
st.write("")
with col2:
st.image(image, use_column_width=True)
with col3:
st.write("")
# If there is data already, start process of showing the chart
else:
col1, col2 = st.columns([4, 1])
# Show the data representation at the side
widget_data_representation = col2.radio(
"Select if the data will be shown in percentage or absolute numbers:",
["Absolute numbers", "Relative numbers"],
index=1,
)
# Selector for the year range displayed in the chart
col2.slider(
"Select years range:",
min_value=st.session_state.min_max[0],
max_value=st.session_state.min_max[1],
key="year_range",
on_change=gl.update_year_range(),
)
if widget_data_representation != st.session_state.widget_data_representation:
st.session_state.widget_data_representation = widget_data_representation
gl.paint_graph()
# Show the chart
# Because it is connected to session state, it will automatically update
# when "graph" session state updates
col1.plotly_chart(st.session_state.graph, use_container_width=True, theme="streamlit")
# Display the graph history checkboxes
gl.display_graph_checkboxes()
# Display statistics
gs.display_general_statistics(st.session_state.cursor)
display_footer()
st.markdown(
"""
<style>
a:link, a:visited {
color: #b1073b;
text-decoration: underline;
}
.css-13m4bxd, .e19lei0e1 {
visibility: hidden;
}
.css-nps9tx, .e1m3hlzs0, .css-1p0bytv, .e1m3hlzs1 {
visibility: collapse;
height: 0px;
}
</style>
""",
unsafe_allow_html=True,
)
# Hide the hamburger menu provided by streamlit
hide_hamburger_menu = """
<style>
#MainMenu {
content:url("https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/HPI_logo.svg/1200px-HPI_logo.svg.png");
width: 50px;
height: 50px;
visibility: visible;
pointer-events: none;
}
</style>
"""
st.markdown(hide_hamburger_menu, unsafe_allow_html=True)
st.markdown(
"""
<style>
.css-1gx893w, .egzxvld2 {
margin-top: -60px;
}
</style>
""",
unsafe_allow_html=True,
)
def query_action(sql, action="run"):
# global cursor
# Executing the query
st.session_state.cursor.execute(sql)
if action != "run":
store = {}
# Fetching rows from the result table
result = st.session_state.cursor.fetchall()
if action == "check":
return result
for row in result:
store[row[0]] = row[1]
return store
def display_footer():
# Show a small divider
st.markdown(
'<hr style="height:1px;border:none;color:#D3D3D3;background-color:#D3D3D3;"/>',
unsafe_allow_html=True,
)
# Show a reference to HPI
st.markdown(
'<h6 style=\'text-align: center;\'>Presented by <a href="https://hpi.de/naumann/home.html" style="color: #b1073b">HPI Information Systems Group</a></h6>',
unsafe_allow_html=True,
)
col1, col2, col3 = st.columns([2, 1, 2])
col2.image("assets/hpi_logo.png")
# Create empty lines with the approximate size of a heading
# Don't use a heading, because this creates the bug that
# The site scrolls down automatically at loading
# -> This is something Streamlit does
for i in range(1, 3):
st.write(" ")
# Legal references (Imprint, Privacy policy)
st.markdown(
"""
<p align="center"><a href='https://hpi.de/impressum.html' style='color: #b1073b'>Imprint</a><br><a href='https://hpi.de/datenschutz.html' style='color: #b1073b'>Privacy policy</a></p>""",
unsafe_allow_html=True,
)
# Hide the streamlit footer and display
# a very small HPI footer
hide_streamlit_style = """
<style>
footer {visibility: hidden;}
footer:after {
content:'Made by HPI Information Systems Group';
visibility: visible;
display: block;
position: relative;
#background-color: red;
padding: 5px;
top: 2px;
}
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True)
if __name__ == "__main__":
main()