Venkatakrishnan commited on
Commit
cdd0177
1 Parent(s): 552b715
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ data processing/*
2
+ *.csv
app.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import yaml
2
+ import streamlit as st
3
+ from yaml.loader import SafeLoader
4
+ import streamlit_authenticator as stauth
5
+ from streamlit_authenticator.utilities.exceptions import (CredentialsError,ForgotError,LoginError,RegisterError,ResetError,UpdateError)
6
+ from streamlit_extras.switch_page_button import switch_page
7
+ import pickle
8
+
9
+ # https://docs.kanaries.net/topics/Streamlit/streamlit-authentication
10
+ # Loading config file
11
+
12
+
13
+ if 'auth' not in st.session_state:
14
+ st.session_state['auth'] = ''
15
+ if 'logged_in' not in st.session_state:
16
+ st.session_state['logged_in'] = ''
17
+
18
+ st.session_state["authentication_status"] = None
19
+ st.session_state['logged_in'] = False
20
+
21
+ filehandler = open(b"login_state.pkl","wb")
22
+ pickle.dump(st.session_state['logged_in'],filehandler)
23
+
24
+ with open('config.yaml', 'r', encoding='utf-8') as file:
25
+ config = yaml.load(file, Loader=SafeLoader)
26
+
27
+ # Creating the authenticator object
28
+ authenticator = stauth.Authenticate(
29
+ config['credentials'],
30
+ config['cookie']['name'],
31
+ config['cookie']['key'],
32
+ config['cookie']['expiry_days'],
33
+ config['pre-authorized']
34
+ )
35
+ st.session_state['auth'] = authenticator
36
+ # Creating a login widget
37
+ try:
38
+ a = authenticator.login()
39
+ print(a)
40
+ except LoginError as e:
41
+ st.error(e)
42
+
43
+ if st.session_state["authentication_status"]:
44
+ authenticator.logout()
45
+ st.session_state["logged_in"] = True
46
+ filehandler = open(b"login_state.pkl","wb")
47
+ pickle.dump(st.session_state['logged_in'],filehandler)
48
+ switch_page("page_0")
49
+ elif st.session_state["authentication_status"] is False:
50
+ st.error('Username/password is incorrect')
51
+ elif st.session_state["authentication_status"] is None:
52
+ st.warning('Please enter your username and password')
53
+
54
+ st.subheader("CONFIDENTIALITY NOTICE: This Dashboard, its analysis and any accompanying data / documents contain information belonging to the San Bernardino Public Defender's Office which may be confidential and legally bounded by The work product doctrine. This information is only for the use of the individual or entity to which it was intended.")
55
+
56
+
57
+
config.yaml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cookie:
2
+ expiry_days: 30
3
+ key: some_signature_key
4
+ name: some_cookie_name
5
+ credentials:
6
+ usernames:
7
+ jsmith:
8
9
+ failed_login_attempts: 1
10
+ logged_in: false
11
+ name: John Smith
12
+ password: $2b$12$s2mQzQ48FgmiSAMOoCzdouAkPQHsedGRez3YzENiXg1GbfSVgh9.S
13
+ rbriggs:
14
15
+ failed_login_attempts: 0
16
+ logged_in: false
17
+ name: Rebecca Briggs
18
+ password: $2b$12$2dsnPNiOaHWTitR2cml/u.Uc8SS0Akwte8YUbGnpQvaPGuyVgEcce
19
+
20
+ pre-authorized:
21
+ emails:
22
list_of_charges.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c405a2ac0a2a45f1422252d7ce4045863c265107bad8e22faee67bc3d1efe888
3
+ size 17682
list_of_charges_detailed.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c9de3714c2ce0a0bc7b7b65daf673472223fb98bbe78e9a4f9c5d8f8226d6d20
3
+ size 103520
login_state.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:112bda3b495d867b6a98c899fac7c25eb60ca4b6e6fe5ec7ab9299f93e8274bc
3
+ size 4
pages/page_0.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import numpy as np
3
+ import plotly.figure_factory as ff
4
+ import plotly.express as px
5
+ import pandas as pd
6
+ import plotly.graph_objects as go
7
+ import streamlit_authenticator as stauth
8
+ from st_aggrid import GridOptionsBuilder, AgGrid, GridUpdateMode, DataReturnMode
9
+ from streamlit_extras.stylable_container import stylable_container
10
+ from streamlit_extras.metric_cards import style_metric_cards
11
+ import warnings
12
+ from streamlit_extras.switch_page_button import switch_page
13
+ import pickle
14
+ import time
15
+ import plotly.io as pio
16
+
17
+ pio.templates.default = 'plotly'
18
+ warnings.filterwarnings('ignore')
19
+
20
+ st.set_page_config(layout="wide")
21
+ color = {'Unknown/Other':'#3a393a', 'Black or African American': '#2993A3', 'White':'#666766', 'Native American':'#f4b780', 'Hispanic':'#a0cd7c', 'Pacific Islander':'#a680ba','Asian':'#f37e85'}
22
+
23
+ file = open("login_state.pkl",'rb')
24
+ st.session_state['logged_in'] = pickle.load(file)
25
+ file.close()
26
+
27
+ #----------------------------NavBar-------------------------------#
28
+ hide_menu_style = """
29
+ <style>
30
+ #MainMenu {visibility: hidden;}
31
+ header {visibility: hidden;}
32
+ </style>
33
+ """
34
+ st.markdown(hide_menu_style, unsafe_allow_html=True)
35
+
36
+ if st.session_state.get("logged_in") == False or st.session_state.get("logged_in") == None:
37
+ st.switch_page("app.py")
38
+
39
+ st.markdown('<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">', unsafe_allow_html=True)
40
+ st.markdown("""
41
+ <head>
42
+ <script defer src="https://pyscript.net/latest/pyscript.js"></script>
43
+ </head>
44
+ <nav class="navbar fixed-top navbar-expand-lg navbar-dark" style="background-color: #3498DB;">
45
+ <a class="navbar-brand" href="https://www.ipr.northwestern.edu/who-we-are/faculty-experts/redbird.html" target="_blank">RJA Dashboard</a>
46
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
47
+ <span class="navbar-toggler-icon"></span>
48
+ </button>
49
+ <div class="collapse navbar-collapse" id="navbarNav" style="width:100%;">
50
+ <ul class="navbar-nav">
51
+ <li class="nav-item active">
52
+ <a class="nav-link disabled" href="https://sanbernardinorja.streamlit.app/page_0" target="_self">Arrest Summary<span class="sr-only">(current)</span></a>
53
+ </li>
54
+ <li class="nav-item">
55
+ <a class="nav-link" href="https://sanbernardinorja.streamlit.app/page_1" target="_self">Charge By Race</a>
56
+ </li>
57
+ <li class="nav-item">
58
+ <a class="nav-link" href="https://sanbernardinorja.streamlit.app/page_2" target="_self">Download Data</a>
59
+ </li>
60
+ </ul>
61
+ <ul class="navbar-nav ml-auto">
62
+ <li class="nav-item mr-auto" style="padding-left:5px;padding-right:5px;outline-color:#f0f2f5;border: 2px solid white;border-radius:10px;">
63
+ <a class="nav-link" href="https://sanbernardinorja.streamlit.app/" target="_self" >Logout</a>
64
+ </li>
65
+ </ul>
66
+ </div>
67
+
68
+ </nav>
69
+
70
+ """, unsafe_allow_html=True)
71
+
72
+ #------------------------------- Metric Cards ------------------------#
73
+
74
+ pop = pd.read_csv("Population.csv")
75
+ cols = st.columns(2)
76
+ cols[0].metric(label="Felony Convicitons for the Population (2015-2023)", value=32979, delta='inc')
77
+ v = int(pop.loc[0, pop.columns.str.contains("Black")].values[0]) / int(pop.loc[0, pop.columns.str.contains("White")].values[0])
78
+ cols[1].metric(label="Black : White Population ratio", value=str(round(v*100, 2))+"/100", delta = "As per 2020")
79
+ style_metric_cards()
80
+
81
+ #------------------------------- Page 0 ------------------------------#
82
+ Page0 = st.container(border=True)
83
+ Page0 = stylable_container(key="Page0", css_styles=[""" {box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 25px;}"""])#, """{background-color:white;opacity:0.8;}"""])#, """ {border: 2px solid rgba(49, 51, 63, 0.2); border-radius: 10px;}"""])
84
+
85
+ cols = Page0.columns([0.5,5.5,0.2,3.3,0.5])
86
+ cols[1].header("Most Common Charges Booked in the County", anchor='section-1', help="A Graph to understrand the most commnly charged crimes in the county by racial distribution. The graph gives a yearly estimates of the crimes. You can choose to see the data by Race/Race and see upto top 300.")
87
+
88
+ cols = Page0.columns([0.5,3, 3,3,0.5])
89
+ Race = cols[1].selectbox('Select Race', tuple(color.keys()), index=None)
90
+ Dec = cols[2].selectbox('Change Data', tuple(['Court Data', 'Curently Incarcerated']), index=0)
91
+
92
+ st.markdown("""
93
+ <style>
94
+ .stSlider [data-baseweb=slider]{
95
+ width: 100%;
96
+ }
97
+ </style>
98
+ """,unsafe_allow_html=True)
99
+ timeline = cols[3].slider('Select Timeline for Cases', 1990, 2022, (2015,2021))
100
+
101
+ cols = Page0.columns([6.5,3.5])
102
+
103
+ if Race != None:
104
+ df1 = pd.read_csv("Court_appA.csv") if Dec == 'Court Data' else pd.read_csv("Incarceration_appA.csv")
105
+ df1 = df1[df1['Race'] == Race]
106
+ df1 = df1[(df1['year'] >= timeline[0]) & (df1['year'] <= timeline[1])]
107
+ df1 = df1[['Charges', 'Race', 'count']].groupby('Charges').agg({'count':'sum'}).reset_index()
108
+ df1['count'] = (df1['count'] / (timeline[1] - timeline[0])) if timeline[1] != timeline[0] else df1['count']
109
+ df1 = df1.sort_values('count')
110
+ fig = px.bar(pd.DataFrame(df1[-40:]), y='Charges', x='count', orientation='h')
111
+ fig.update_traces(marker_color=color[Race])
112
+ else:
113
+ df1 = pd.read_csv("Court_appB.csv") if Dec == 'Court Data' else pd.read_csv("Incarceration_appB.csv")
114
+ df1 = df1[(df1['year'] >= timeline[0]) & (df1['year'] <= timeline[1])]
115
+ df1 = df1[['Charges', 'Race', 'count']].groupby(['Charges','Race']).agg({'count':'sum'}).reset_index()
116
+ df1['count'] = (df1['count'] / (timeline[1] - timeline[0])) if timeline[1] != timeline[0] else df1['count']
117
+ df1 = df1.sort_values(['Charges', 'count'])
118
+ fig = px.bar(df1, y='Charges', x='count', orientation='h', color_discrete_map=color, color='Race')
119
+ fig.update_layout(barmode='stack', yaxis={'categoryorder':'total ascending'})
120
+
121
+ if Dec == 'Court Data':
122
+ fig.update_layout(width=900, height=900, xaxis = {'side':'top'},title_y=0.99, xaxis_title="Number of Cases Per Year", yaxis_title="Charges")
123
+ else:
124
+ fig.update_layout(width=900, height=900, xaxis = {'side':'top'},title_y=0.99, xaxis_title="Total Cases", yaxis_title="Charges")
125
+
126
+ fig.update_layout(legend=dict(yanchor="top", y=0.7, xanchor="left", x=0.6))
127
+
128
+ cols[0].plotly_chart(fig, theme=None)
129
+
130
+ # df = pd.read_excel("California Penal Code .xlsx")
131
+ # # dfx = pd.read_csv("Court_appB.csv")
132
+ # # df1 = df1[['Charges', 'count']].groupby(['Charges']).agg({'count':'sum'}).reset_index()
133
+ # # df1 = df1.sort_values(['Charges', 'count'])
134
+
135
+ # cols[1].markdown('######')
136
+ # cols[1].markdown('####')
137
+ # cols[1].dataframe(df, height=760)
138
+
139
+ # if st.session_state["authentication_status"]:
140
+ # st.session_state.auth.logout()
141
+ # else:
142
+ # switch_page('app')
pages/page_1.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import numpy as np
3
+ import plotly.figure_factory as ff
4
+ import plotly.express as px
5
+ import pandas as pd
6
+ import plotly.graph_objects as go
7
+ import os
8
+ import argparse
9
+ from st_aggrid import GridOptionsBuilder, AgGrid, GridUpdateMode, DataReturnMode
10
+ from PIL import Image
11
+ from streamlit_extras.stylable_container import stylable_container
12
+ from streamlit_extras.metric_cards import style_metric_cards
13
+ import pickle
14
+
15
+ # Implement AND condition when downloading data
16
+ st.set_page_config(layout="wide")
17
+ color = {'Black or African American': '#2993A3', 'White':'#666766', 'Native American':'#f4b780', 'Hispanic':'#a0cd7c', 'Pacific Islander':'#a680ba', 'Unknown/Other':'#3a393a','Asian':'#f37e85'}
18
+
19
+ file = open("login_state.pkl",'rb')
20
+ st.session_state['logged_in'] = pickle.load(file)
21
+ file.close()
22
+ #print(st.session_state.get("logged_in"))
23
+
24
+
25
+ #----------------------------NavBar-------------------------#
26
+ hide_menu_style = """
27
+ <style>
28
+ #MainMenu {visibility: hidden;}
29
+ header {visibility: hidden;}
30
+ </style>
31
+ """
32
+ st.markdown(hide_menu_style, unsafe_allow_html=True)
33
+ # print(st.session_state.get("logged_in"))
34
+
35
+ if st.session_state.get("logged_in") == False or st.session_state.get("logged_in") == None:
36
+ st.switch_page("app.py")
37
+
38
+
39
+
40
+ st.markdown('<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">', unsafe_allow_html=True)
41
+
42
+ st.markdown("""
43
+ <nav class="navbar fixed-top navbar-expand-lg navbar-dark" style="background-color: #3498DB;background-image:url('/Users/shaashwatagrawal/Documents/SF County/dashboard/Background.jpeg');">
44
+ <a class="navbar-brand" href="https://www.ipr.northwestern.edu/who-we-are/faculty-experts/redbird.html" target="_blank">RJA Dashboard</a>
45
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
46
+ <span class="navbar-toggler-icon"></span>
47
+ </button>
48
+ <div class="collapse navbar-collapse" id="navbarNav">
49
+ <ul class="navbar-nav">
50
+ <li class="nav-item">
51
+ <a class="nav-link disabled" href="https://sanbernardinorja.streamlit.app/page_0" target="_self">Arrest Summary</a>
52
+ </li>
53
+ <li class="nav-item active">
54
+ <a class="nav-link" href="https://sanbernardinorja.streamlit.app/page_1" target="_self">Charge By Race<span class="sr-only">(current)</span></a>
55
+ </li>
56
+ <li class="nav-item">
57
+ <a class="nav-link" href="https://sanbernardinorja.streamlit.app/page_2" target="_self">Download Data</a>
58
+ </li>
59
+ </ul>
60
+ <ul class="navbar-nav ml-auto">
61
+ <li class="nav-item mr-auto" style="padding-left:5px;padding-right:5px;outline-color:#f0f2f5;border: 2px solid white;border-radius:10px;">
62
+ <a class="nav-link" href="https://sanbernardinorja.streamlit.app/" target="_self" >Logout</a>
63
+ </li>
64
+ </ul>
65
+ </div>
66
+ </nav>
67
+ """, unsafe_allow_html=True)
68
+
69
+
70
+ #---------------------------- Page 2 ----------------------------#
71
+ cols = st.columns(2)
72
+
73
+ Page2 = stylable_container(key="Page2", css_styles=""" {box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 15px;}""")
74
+ cols = Page2.columns([4,3,3])
75
+ cols[1].header("Charges By Race", anchor = 'section-2', help = 'Understanding Disparity at different stages of a criminal proceeding (i.e. Arrest, Charging and Sentencing).')
76
+ # parser = argparse.ArgumentParser()
77
+ # parser.add_argument('--charge', type=str, default='187A')
78
+ # args = parser.parse_args()
79
+
80
+ with open("list_of_charges.pkl", "rb") as fp: # Unpickling
81
+ charges = pickle.load(fp)
82
+
83
+ col = Page2.columns([0.5, 9, 0.5])
84
+ PC = col[1].multiselect('Select Type of Charge', tuple(charges), default='459')#index=list(charges).index(args.charge))
85
+
86
+ # Reading and Processing Data
87
+ pop = pd.read_csv("Population.csv")
88
+
89
+ df = pd.read_csv("Arrest_page1.csv")
90
+ #df = df[df['Charges'].str.contains('|'.join(PC))]
91
+
92
+ dfr = pd.read_csv("Court_page1.csv")
93
+ #print(PC)
94
+ #dfr = dfr[dfr['Charges'].str.contains('|'.join(PC))]
95
+ #print(dfr)
96
+
97
+ dfd = pd.read_csv("Sentence_page1.csv")
98
+ #dfd = dfd[dfd['Charges'].str.contains('|'.join(PC))]
99
+
100
+ cols = Page2.columns([0.5,2.25,2.25,0.5,2.5,1.5,0.5])
101
+ #cols[1].subheader("Offence by Race")
102
+
103
+ st.markdown("""
104
+ <style>
105
+ .stSlider [data-baseweb=slider]{
106
+ width: 100%;
107
+ }
108
+ </style>
109
+ """,unsafe_allow_html=True)
110
+ timeline = cols[2].slider('Select Timeline for Cases', 1990, 2024, (2015,2023))
111
+ perCap = cols[1].selectbox("Display Graph Per Capita", ("No", "Yes"), index=1)
112
+ cols[4].subheader("Charge Percentage Ratio")
113
+
114
+ c1, c2, c3, c4, c5 = Page2.columns([4.5, 0.5, 0.5, 4, 0.5])
115
+ with c1:
116
+ df = pd.concat([dfd, dfr, df], ignore_index=True, axis=0)
117
+ df = df[df['Charges'].str.fullmatch('|'.join(PC), na=False)]
118
+ df = df[(df['year'] >= timeline[0]) & (df['year'] <= timeline[1])]
119
+ df = df[df['Race'] != 'Unknown/Other']
120
+
121
+ df = df[['Charge Type', 'Race', 'Charges', 'count', 'normalized_vals']].groupby(['Charge Type','Race']).agg({'count':'sum', 'normalized_vals':'sum'}).reset_index()
122
+ custom_dict = {'Booking Charge': 0, 'Filed Charge': 1, 'Conviction Charge': 2}
123
+
124
+ df = df.sort_values(by=['Charge Type'], key=lambda x: x.map(custom_dict), ascending=False)
125
+ xaxs = 'count' if perCap == "No" else "normalized_vals"
126
+ fig = px.bar(df, y='Charge Type', x=xaxs,color_discrete_map=color, color='Race', orientation='h')
127
+ fig.update_layout(width=700, height=600,)
128
+ fig.update_layout(xaxis_title="Number of Cases", yaxis_title="")
129
+ fig.update_layout(legend=dict(yanchor="bottom", y=1.0, xanchor="left", x=-0.17, orientation='h', entrywidth=150))
130
+ fig.update_layout(font=dict(family="Myriad Pro",size=14))
131
+ fig.update_yaxes(tickangle=270, automargin= True)
132
+ st.plotly_chart(fig, theme=None)
133
+
134
+ with c4:
135
+ sel_col = 'count' if perCap == "No" else "normalized_vals"
136
+ cc1, cc2 = st.columns(2)
137
+ with cc1:
138
+ PCRace = st.selectbox('Select Race to Compare with', tuple(set(list(df['Race'].unique()) + list(dfr['Race'].unique()))))
139
+ with cc2:
140
+ st.header(" / White")
141
+ r1 = df[(df['Race'] == PCRace) & (df['Charge Type'] == 'Booking Charge')][sel_col].sum()*(10000000)
142
+ r2 = df[(df['Race'] == 'White') & (df['Charge Type'] == 'Booking Charge')][sel_col].sum()*(10000000)
143
+
144
+ if r2 != 0:
145
+ val = '%0.2f'%(r1/r2)+'/1'
146
+ else:
147
+ val = '%0.2f'%(r1)+'/'+str(r2)
148
+ new_title = '<p style="font-family:Myriad Pro; color:Black; font-size: 20px;display: inline;vertical-align: top;">'+PCRace+' rate of arrests by the white rate of arrests: '+val+'</p>'
149
+ #st.markdown(new_title, unsafe_allow_html=True)
150
+ #st.markdown('####')
151
+ #st.markdown('####')
152
+ st.metric(label= PCRace+' rate of arrests by the white rate of arrests:' , value=val, delta=None)
153
+ style_metric_cards()
154
+
155
+
156
+ r1 = df[(df['Race'] == PCRace) & (df['Charge Type'] == 'Filed Charge')][sel_col].sum()*(10000000)
157
+ r2 = df[(df['Race'] == 'White') & (df['Charge Type'] == 'Filed Charge')][sel_col].sum()*(10000000)
158
+
159
+ if r2 != 0:
160
+ val = '%0.2f'%(r1/r2)+'/1'
161
+ else:
162
+ val = '%0.2f'%(r1)+'/'+str(r2)
163
+ new_title = '<p style="font-family:Myriad Pro; color:Black; font-size: 20px;display: inline;vertical-align: top;">'+PCRace+' rate of charging by the white rate of charging is: '+val+'</p>'
164
+ # st.markdown(new_title, unsafe_allow_html=True)
165
+ # st.markdown('####')
166
+ # st.markdown('####')
167
+ st.metric(label=PCRace+' rate of charging by the white rate of charging is: ', value=val, delta=None)
168
+ style_metric_cards()
169
+
170
+ r1 = (df[(df['Race'] == PCRace) & (df['Charge Type'] == 'Conviction Charge')][sel_col].sum()*(10000000))
171
+ r2 = (df[(df['Race'] == 'White') & (df['Charge Type'] == 'Conviction Charge')][sel_col].sum()*(10000000))
172
+
173
+ #st.text(PCRace3+" rate of being sentenced by the white rate of being sentenced")
174
+ if r2 != 0:
175
+ val = '%0.2f'%(r1/r2)+'/1'
176
+ else:
177
+ val = '%0.2f'%(r1)+'/'+str(r2)
178
+ new_title = '<p style="font-family:Myriad Pro; color:Black; font-size: 20px;display: inline;vertical-align: top;">'+PCRace+' rate of being sentenced by the white rate of being sentenced is: '+val+'</p>'
179
+ # st.markdown(new_title, unsafe_allow_html=True)
180
+ st.metric(label=PCRace+' rate of being sentenced by the white rate of being sentenced is: ', value=val, delta=None)
181
+ style_metric_cards()
182
+
183
+
184
+
185
+
186
+
187
+
pages/page_2.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import numpy as np
3
+ import plotly.figure_factory as ff
4
+ import plotly.express as px
5
+ import pandas as pd
6
+ import plotly.graph_objects as go
7
+ from streamlit_extras.stylable_container import stylable_container
8
+ import pickle
9
+ import ast
10
+
11
+ # Implement AND condition when downloading data
12
+
13
+ st.set_page_config(layout="wide")
14
+ color = {'Black or African American': '#ff7eb6', 'White':'#be95ff', 'Native American':'#0f62fe', 'Indian':'#82cfff', 'Japanese':'lightyellow', 'Korean':'gray','Chinese':'yellow', 'Hispanic':'#dface6', 'Pacific Islander':'#3ddbd9', 'Unkown/Other':'#c1c7cd','Filipino':'Green', 'Middle Eastern':'#000000','Vietnamese':'coral','Laotian':'cornsilk','Cambodian':'darkcyan','Other Asian':'darkgoldenrod', 'Asian':'#82cfff',}
15
+
16
+ file = open("login_state.pkl",'rb')
17
+ st.session_state['logged_in'] = pickle.load(file)
18
+ file.close()
19
+
20
+ #----------------------------NavBar-------------------------#
21
+ hide_menu_style = """
22
+ <style>
23
+ #MainMenu {visibility: hidden;}
24
+ header {visibility: hidden;}
25
+ </style>
26
+ """
27
+ st.markdown(hide_menu_style, unsafe_allow_html=True)
28
+
29
+ if st.session_state.get("logged_in") == False or st.session_state.get("logged_in") == None:
30
+ st.switch_page("app.py")
31
+
32
+
33
+ st.markdown('<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">', unsafe_allow_html=True)
34
+
35
+ st.markdown("""
36
+ <head>
37
+ <script defer src="https://pyscript.net/latest/pyscript.js"></script>
38
+ </head>
39
+ <nav class="navbar fixed-top navbar-expand-lg navbar-dark" style="background-color: #3498DB;">
40
+ <a class="navbar-brand" href="https://www.ipr.northwestern.edu/who-we-are/faculty-experts/redbird.html" target="_blank">RJA Dashboard</a>
41
+ <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
42
+ <span class="navbar-toggler-icon"></span>
43
+ </button>
44
+ <div class="collapse navbar-collapse" id="navbarNav" style="width:100%;">
45
+ <ul class="navbar-nav">
46
+ <li class="nav-item active">
47
+ <a class="nav-link disabled" href="https://sanbernardinorja.streamlit.app/page_0" target="_self">Arrest Summary<span class="sr-only">(current)</span></a>
48
+ </li>
49
+ <li class="nav-item">
50
+ <a class="nav-link" href="https://sanbernardinorja.streamlit.app/page_1" target="_self">Charge By Race</a>
51
+ </li>
52
+ <li class="nav-item">
53
+ <a class="nav-link" href="https://sanbernardinorja.streamlit.app/page_2" target="_self">Download Data</a>
54
+ </li>
55
+ </ul>
56
+ <ul class="navbar-nav ml-auto">
57
+ <li class="nav-item mr-auto" style="padding-left:5px;padding-right:5px;outline-color:#f0f2f5;border: 2px solid white;border-radius:10px;">
58
+ <a class="nav-link" href="https://sanbernardinorja.streamlit.app/ target="_self" >Logout</a>
59
+ </li>
60
+ </ul>
61
+ </div>
62
+
63
+ </nav>
64
+
65
+ """, unsafe_allow_html=True)
66
+ # with open("list_of_charges.pkl", "rb") as fp: # Unpickling
67
+ # charges = pickle.load(fp)
68
+
69
+ # Page 3
70
+ Page3 = stylable_container(key="Page3", css_styles=""" {box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 15px;} """)
71
+ Page3.header("Download Data", anchor = 'section-3', help = 'Download data relevant to your case. Use the filters to Determine what data do you need.')
72
+ selected_point = []
73
+ #loc = "DA_referrals_2022(1).csv"
74
+
75
+ Charge = Page3.selectbox('Select Type of Charge', ('Booking Charge', 'Filed Charge', 'CDCR'))
76
+
77
+ loc = "Referral_page2.csv" if Charge == 'Booking Charge' else "Court_page2.csv" if Charge == 'Filed Charge' else "Sentence_page2.csv"
78
+ df = pd.read_csv(loc)
79
+ df = df.drop(columns='Unnamed: 0')
80
+ uid = 'UID' if Charge == 'Booking Charge' else 'Case Number'
81
+ filename = "list_of_charges.pkl" if Charge == 'Booking Charge' else "list_of_charges_detailed.pkl"
82
+ with open(filename, "rb") as fp: # Unpickling
83
+ charges = pickle.load(fp)
84
+
85
+
86
+ #split_first = False if loc == "Referral_page2.csv" else True
87
+
88
+ cols = Page3.columns(4)
89
+ Filtera = cols[0].multiselect('Select Charges', tuple(charges), help='Select Charges relevant to your case and client')
90
+ Filterb = cols[2].multiselect('Select Ethnicity', tuple(color.keys()), help='Select relevant Ethnicity')
91
+ Filterc = cols[1].selectbox('Select Function - Charges', ("AND", "OR"), help="AND - All Clients charged with all chosen charges \n\n OR - All Clients charged with atleast one of the chosen charges")
92
+ cols_list = df.columns.tolist()
93
+ cols_list.remove('Charges')
94
+ cols_list.remove('Race')
95
+ cols_list.remove(uid)
96
+ Filterd = cols[3].multiselect('Select Additional Columns to View', tuple(cols_list), help="1. Incident Number - Unique Incident ID assigned to SF Cases \n\n 2. Gender - Gender of the perpetrator \n\n 3. Booked.Case.Type / Filed.Case.Type - Felony / Misdemeanor \n\n 4. Age.at.Arrest - Age at which the person was arrested \n\n 5. Status.CTNum / Status.CTNum.Agg - Case Status After arrest or filing i.e. new charges filed or discharged \n\n 6. Description - Arrest / Charges Description \n\n 7. Year - Year of Arrest for Booking charge / Year of Charging for Filed Charge or Sentenced For \n\n 8. Case.Dispo - Case Disposition Number \n\n 9. Dispo.Description - Final court decision")
97
+
98
+ if len(Filtera) > 0:
99
+ filst = "|".join(Filtera)
100
+ df = df[df['Charges'].str.contains(filst, regex=True, na=False)]
101
+
102
+ if len(Filterb) > 0:
103
+ filst = "|".join(Filterb)
104
+ df = df[df['Races'].str.contains(filst, regex=True, na=False)]
105
+
106
+ if Filterc == 'AND' and len(Filtera) > 0:
107
+ cnos = [df[df['Charges'].str.contains(i)][uid].tolist() for i in Filtera]
108
+ cm_cnos = list(set.intersection(*map(set, cnos)))
109
+ df = df[df[uid].isin(cm_cnos)]
110
+ df = df.drop_duplicates()
111
+
112
+ df[uid] = df[uid].map(str)
113
+
114
+ for i in df.columns[1:]:
115
+ df[i] = df[i].str.strip('[]').str.split(',')
116
+
117
+ disp_cols = [uid, 'Charges', 'Race'] + Filterd
118
+
119
+
120
+ Page3.dataframe(df[disp_cols],width=1300)
121
+