averye-duke commited on
Commit
5e43d07
·
1 Parent(s): 6a60300

move app to src

Browse files
Files changed (2) hide show
  1. src/streamlit_app.py +198 -34
  2. streamlit_app.py +0 -204
src/streamlit_app.py CHANGED
@@ -1,40 +1,204 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
- import streamlit as st
 
 
 
 
 
 
5
 
 
 
6
  """
7
- # Welcome to Streamlit!
8
 
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- In the meantime, below is an example of what you can do with just a few lines of code:
 
 
 
 
 
 
 
14
  """
15
 
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ VIN Decoder Streamlit App
3
+
4
+ This app allows users to input a Vehicle Identification Number (VIN) and fetch vehicle
5
+ information (year, make, model). The data is retrieved from the NHTSA (National Highway Traffic Safety
6
+ Administration) VIN decoding API via the helper module `nhtsa_api_call.py`.
7
+ Useful for car dealerships who need quick VIN lookups.
8
+
9
+ Usage:
10
+ streamlit run streamlit_vin_decoder.py
11
 
12
+ Author: Sharmil Nanjappa
13
+ Date: August 25, 2025
14
  """
 
15
 
16
+ import streamlit as st # Import the Streamlit library for creating the web app
17
+ import nhtsa_api_call # Import the API call function from external file
18
+ import os
19
+ import re
20
+ import pandas as pd
21
+ import matplotlib.pyplot as plt
22
+ from collections import Counter
23
+
24
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # Gets the current directory
25
+ logo_img_file = os.path.join(BASE_DIR, "logo_image.png")
26
+ car_img_file = os.path.join(BASE_DIR, "car_image.png")
27
+ TOP3 = 3 # Define top N makes to display
28
+
29
+ # Check if the 'make_history' key is already in Streamlit's session state
30
+ if "make_history" not in st.session_state:
31
+ # If not, initialize it as an empty list to store searched vehicle makes
32
+ st.session_state.make_history = []
33
+
34
+ # Define a function to track the vehicle make each time a VIN is decoded
35
+ def track_make(make):
36
+ """
37
+ Store the searched make in session state for pie chart stats.
38
+ """
39
+ # Proceed only if a valid make value is provided
40
+ if make:
41
+ # Capitalize and append the make to the session history list
42
+ st.session_state.make_history.append(make.title())
43
+ # Optional: Display the current list of searched makes in the sidebar for debugging
44
+ #st.sidebar.write("Debug – History:", st.session_state.make_history)
45
 
46
+
47
+ def show_top_3_makes():
48
+ """
49
+ Display a pie chart of the top 3 most searched vehicle makes.
50
+
51
+ if not st.session_state.make_history:
52
+ st.warning("No vehicle makes have been searched yet.")
53
+ return
54
  """
55
 
56
+
57
+
58
+ if not st.session_state.make_history:
59
+ st.warning("No vehicle makes have been searched yet.")
60
+ return
61
+
62
+ # Count how many times each make was searched
63
+ counts = Counter(st.session_state.make_history)
64
+
65
+ if len(counts) < TOP3:
66
+ st.warning(f"Not enough data to display Top 3. Showing Top {len(counts)} instead.")
67
+
68
+ # Get the top N (3 or fewer)
69
+ top_n = counts.most_common(min(len(counts), TOP3))
70
+
71
+ labels = [item[0].upper() for item in top_n] # Label for the vehicle make, displayed in upper case for each slice of the pie chart
72
+ sizes = [item[1] for item in top_n] # Count of each make in the Top3. Used to determine how large each slice of the pie chart is.
73
+ colors = ['#4682B4', '#1E3F66', '#0B1F3A'][:len(labels)] #[colors of pie chart slices][match slice count]
74
+ with st.container():
75
+
76
+ st.markdown("""
77
+ <div style="
78
+ max-width: 700px;
79
+ margin: 0 auto;
80
+ padding: 12px 24px;
81
+ border: 1px solid #ccc;
82
+ border-radius: 10px;
83
+ background-color: #f9f9f9;
84
+ text-align: center;
85
+ font-size: 16px;
86
+ font-weight: 500;
87
+ ">
88
+ Pie chart displaying the Top 3 Vehicles<br>
89
+ searched based on their Make
90
+ </div>
91
+ """, unsafe_allow_html=True)
92
+
93
+ fig, ax = plt.subplots(figsize=(3,3), dpi=150)
94
+
95
+ # Draw pie chart with borders and percentage labels
96
+ wedges, texts, autotexts = ax.pie(
97
+ sizes,
98
+ labels=labels,
99
+ colors=colors,
100
+ autopct='%1.1f%%',
101
+ startangle=90, # autopct shows % and startangle starts the first slice from the top
102
+ wedgeprops={'edgecolor': 'white', 'linewidth': 1}
103
+ )
104
+
105
+ ax.axis('equal') # Forces the chart to be a perfect circle
106
+
107
+ # Style text and labels
108
+ for text in texts: #The labels of each pie slice
109
+ text.set_fontsize(5)
110
+ text.set_color('#000') # text color: Black
111
+ text.set_fontweight('semibold')
112
+
113
+ for autotext in autotexts: #The percentages shown on each slice
114
+ autotext.set_fontsize(5)
115
+ autotext.set_color('#fff') # text color: White
116
+
117
+ st.pyplot(fig)
118
+ st.markdown("</div>", unsafe_allow_html=True)
119
+
120
+ def get_vin(vin):
121
+ """
122
+ Decodes the VIN and displays model,make, model year.
123
+ Validates VIN format and displays vehicle details or error message.
124
+ """
125
+ status_area = st.empty()
126
+ col1, col2 = st.columns([1, 1])
127
+
128
+ if len(vin) != 17:
129
+ status_area.error(f"VIN must be exactly 17 characters long.")
130
+ return
131
+ elif not re.match(r'^[A-HJ-NPR-Z0-9]{17}$', vin):
132
+ status_area.error(f"VIN must be alpha-numeric and cannot include letters I, O, Q.")
133
+ return
134
+ else:
135
+ status_area.info("Decoding VIN...")
136
+
137
+ try:
138
+ year, make, model = nhtsa_api_call.get_vehicle_info(vin)
139
+
140
+ if not all([year, make, model]) or any([v is None for v in [year, make, model]]):
141
+ status_area.warning(f"Incomplete vehicle data returned. Please verify the VIN and try again.")
142
+ else:
143
+ status_area.success("VIN decoded successfully!")
144
+
145
+ track_make(make)
146
+ with col1:
147
+ st.image(car_img_file, use_container_width=True)
148
+
149
+ with col2:
150
+ st.write(f"Below are the vehicle details :")
151
+ st.write("🔍 Vehicle Information")
152
+ st.write(f"**Make:** {make}")
153
+ st.write(f"**Model:** {model}")
154
+ st.write(f"**Model Year:** {year}")
155
+
156
+ except Exception as e:
157
+ status_area.error(f"An error occurred while decoding the VIN: {e}")
158
+
159
+ def main():
160
+ """
161
+ Sets Streamlitcomponents for the page layout, handles user input, and calls get_vin function.
162
+ """
163
+
164
+ col1, col2 = st.columns([1, 2])
165
+ with col1:
166
+ st.image(logo_img_file, width=180)
167
+ with col2:
168
+ st.markdown("""
169
+ <div style='text-align: left; margin-top: 30px;'>
170
+ <h1 style='font-size: 38px;'>Vehicle VIN Decoder</h1>
171
+ </div>
172
+ """, unsafe_allow_html=True)
173
+ st.write("*" * 50)
174
+
175
+ st.markdown("<h5 style='text-align: center;'>Welcome to the Car Dealership VIN Lookup!</h5>", unsafe_allow_html=True)
176
+
177
+
178
+ with st.expander("ℹ️ About this app"):
179
+ st.write("This app is designed to help car dealerships and automotive professionals effortlessly decode Vehicle Identification Numbers (VINs) to retrieve key vehicle details such as model,make and model year. By simply entering a 17-character VIN, users can access verified vehicle information. The data is fetched in real-time from the National Highway Traffic Safety Administration (NHTSA). Whether you're validating trade-ins, checking vehicle specs, or streamlining inventory intake, this tool delivers quick and reliable insights.")
180
+
181
+
182
+
183
+ st.markdown("Enter a **17-character VIN** below to decode the vehicle info.")
184
+
185
+ vin = st.text_input("Enter VIN:", max_chars=17).strip().upper()
186
+ if st.button("Decode VIN", use_container_width=True):
187
+ if vin:
188
+ get_vin(vin)
189
+ else:
190
+ st.error(f"❌ Please enter a VIN before fetching the vehicle information.")
191
+
192
+ # Show top 3 searched makes
193
+ st.markdown("---")
194
+ if st.button("Top 3 Makes Searched", use_container_width=True):
195
+ show_top_3_makes()
196
+
197
+ st.markdown("___")
198
+ st.markdown("<p style='text-align: center; font-size: 14px;'>© 2025 Car Dealership VIN Lookup", unsafe_allow_html=True) #Footer for the webpage
199
+
200
+
201
+
202
+
203
+ if __name__ == "__main__":
204
+ main()
streamlit_app.py DELETED
@@ -1,204 +0,0 @@
1
- """
2
- VIN Decoder Streamlit App
3
-
4
- This app allows users to input a Vehicle Identification Number (VIN) and fetch vehicle
5
- information (year, make, model). The data is retrieved from the NHTSA (National Highway Traffic Safety
6
- Administration) VIN decoding API via the helper module `nhtsa_api_call.py`.
7
- Useful for car dealerships who need quick VIN lookups.
8
-
9
- Usage:
10
- streamlit run streamlit_vin_decoder.py
11
-
12
- Author: Sharmil Nanjappa
13
- Date: August 25, 2025
14
- """
15
-
16
- import streamlit as st # Import the Streamlit library for creating the web app
17
- import nhtsa_api_call # Import the API call function from external file
18
- import os
19
- import re
20
- import pandas as pd
21
- import matplotlib.pyplot as plt
22
- from collections import Counter
23
-
24
- BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # Gets the current directory
25
- logo_img_file = os.path.join(BASE_DIR, "logo_image.png")
26
- car_img_file = os.path.join(BASE_DIR, "car_image.png")
27
- TOP3 = 3 # Define top N makes to display
28
-
29
- # Check if the 'make_history' key is already in Streamlit's session state
30
- if "make_history" not in st.session_state:
31
- # If not, initialize it as an empty list to store searched vehicle makes
32
- st.session_state.make_history = []
33
-
34
- # Define a function to track the vehicle make each time a VIN is decoded
35
- def track_make(make):
36
- """
37
- Store the searched make in session state for pie chart stats.
38
- """
39
- # Proceed only if a valid make value is provided
40
- if make:
41
- # Capitalize and append the make to the session history list
42
- st.session_state.make_history.append(make.title())
43
- # Optional: Display the current list of searched makes in the sidebar for debugging
44
- #st.sidebar.write("Debug – History:", st.session_state.make_history)
45
-
46
-
47
- def show_top_3_makes():
48
- """
49
- Display a pie chart of the top 3 most searched vehicle makes.
50
-
51
- if not st.session_state.make_history:
52
- st.warning("No vehicle makes have been searched yet.")
53
- return
54
- """
55
-
56
-
57
-
58
- if not st.session_state.make_history:
59
- st.warning("No vehicle makes have been searched yet.")
60
- return
61
-
62
- # Count how many times each make was searched
63
- counts = Counter(st.session_state.make_history)
64
-
65
- if len(counts) < TOP3:
66
- st.warning(f"Not enough data to display Top 3. Showing Top {len(counts)} instead.")
67
-
68
- # Get the top N (3 or fewer)
69
- top_n = counts.most_common(min(len(counts), TOP3))
70
-
71
- labels = [item[0].upper() for item in top_n] # Label for the vehicle make, displayed in upper case for each slice of the pie chart
72
- sizes = [item[1] for item in top_n] # Count of each make in the Top3. Used to determine how large each slice of the pie chart is.
73
- colors = ['#4682B4', '#1E3F66', '#0B1F3A'][:len(labels)] #[colors of pie chart slices][match slice count]
74
- with st.container():
75
-
76
- st.markdown("""
77
- <div style="
78
- max-width: 700px;
79
- margin: 0 auto;
80
- padding: 12px 24px;
81
- border: 1px solid #ccc;
82
- border-radius: 10px;
83
- background-color: #f9f9f9;
84
- text-align: center;
85
- font-size: 16px;
86
- font-weight: 500;
87
- ">
88
- Pie chart displaying the Top 3 Vehicles<br>
89
- searched based on their Make
90
- </div>
91
- """, unsafe_allow_html=True)
92
-
93
- fig, ax = plt.subplots(figsize=(3,3), dpi=150)
94
-
95
- # Draw pie chart with borders and percentage labels
96
- wedges, texts, autotexts = ax.pie(
97
- sizes,
98
- labels=labels,
99
- colors=colors,
100
- autopct='%1.1f%%',
101
- startangle=90, # autopct shows % and startangle starts the first slice from the top
102
- wedgeprops={'edgecolor': 'white', 'linewidth': 1}
103
- )
104
-
105
- ax.axis('equal') # Forces the chart to be a perfect circle
106
-
107
- # Style text and labels
108
- for text in texts: #The labels of each pie slice
109
- text.set_fontsize(5)
110
- text.set_color('#000') # text color: Black
111
- text.set_fontweight('semibold')
112
-
113
- for autotext in autotexts: #The percentages shown on each slice
114
- autotext.set_fontsize(5)
115
- autotext.set_color('#fff') # text color: White
116
-
117
- st.pyplot(fig)
118
- st.markdown("</div>", unsafe_allow_html=True)
119
-
120
- def get_vin(vin):
121
- """
122
- Decodes the VIN and displays model,make, model year.
123
- Validates VIN format and displays vehicle details or error message.
124
- """
125
- status_area = st.empty()
126
- col1, col2 = st.columns([1, 1])
127
-
128
- if len(vin) != 17:
129
- status_area.error(f"VIN must be exactly 17 characters long.")
130
- return
131
- elif not re.match(r'^[A-HJ-NPR-Z0-9]{17}$', vin):
132
- status_area.error(f"VIN must be alpha-numeric and cannot include letters I, O, Q.")
133
- return
134
- else:
135
- status_area.info("Decoding VIN...")
136
-
137
- try:
138
- year, make, model = nhtsa_api_call.get_vehicle_info(vin)
139
-
140
- if not all([year, make, model]) or any([v is None for v in [year, make, model]]):
141
- status_area.warning(f"Incomplete vehicle data returned. Please verify the VIN and try again.")
142
- else:
143
- status_area.success("VIN decoded successfully!")
144
-
145
- track_make(make)
146
- with col1:
147
- st.image(car_img_file, use_container_width=True)
148
-
149
- with col2:
150
- st.write(f"Below are the vehicle details :")
151
- st.write("🔍 Vehicle Information")
152
- st.write(f"**Make:** {make}")
153
- st.write(f"**Model:** {model}")
154
- st.write(f"**Model Year:** {year}")
155
-
156
- except Exception as e:
157
- status_area.error(f"An error occurred while decoding the VIN: {e}")
158
-
159
- def main():
160
- """
161
- Sets Streamlitcomponents for the page layout, handles user input, and calls get_vin function.
162
- """
163
-
164
- col1, col2 = st.columns([1, 2])
165
- with col1:
166
- st.image(logo_img_file, width=180)
167
- with col2:
168
- st.markdown("""
169
- <div style='text-align: left; margin-top: 30px;'>
170
- <h1 style='font-size: 38px;'>Vehicle VIN Decoder</h1>
171
- </div>
172
- """, unsafe_allow_html=True)
173
- st.write("*" * 50)
174
-
175
- st.markdown("<h5 style='text-align: center;'>Welcome to the Car Dealership VIN Lookup!</h5>", unsafe_allow_html=True)
176
-
177
-
178
- with st.expander("ℹ️ About this app"):
179
- st.write("This app is designed to help car dealerships and automotive professionals effortlessly decode Vehicle Identification Numbers (VINs) to retrieve key vehicle details such as model,make and model year. By simply entering a 17-character VIN, users can access verified vehicle information. The data is fetched in real-time from the National Highway Traffic Safety Administration (NHTSA). Whether you're validating trade-ins, checking vehicle specs, or streamlining inventory intake, this tool delivers quick and reliable insights.")
180
-
181
-
182
-
183
- st.markdown("Enter a **17-character VIN** below to decode the vehicle info.")
184
-
185
- vin = st.text_input("Enter VIN:", max_chars=17).strip().upper()
186
- if st.button("Decode VIN", use_container_width=True):
187
- if vin:
188
- get_vin(vin)
189
- else:
190
- st.error(f"❌ Please enter a VIN before fetching the vehicle information.")
191
-
192
- # Show top 3 searched makes
193
- st.markdown("---")
194
- if st.button("Top 3 Makes Searched", use_container_width=True):
195
- show_top_3_makes()
196
-
197
- st.markdown("___")
198
- st.markdown("<p style='text-align: center; font-size: 14px;'>© 2025 Car Dealership VIN Lookup", unsafe_allow_html=True) #Footer for the webpage
199
-
200
-
201
-
202
-
203
- if __name__ == "__main__":
204
- main()