aghilTQ commited on
Commit
3e17b19
Β·
verified Β·
1 Parent(s): 885c93b

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +85 -239
src/streamlit_app.py CHANGED
@@ -2,8 +2,7 @@ import streamlit as st
2
  import pyphen
3
  import re
4
  import random
5
- from typing import List, Tuple, Dict
6
- import requests
7
 
8
  # Configure page
9
  st.set_page_config(
@@ -18,60 +17,43 @@ st.set_page_config(
18
  def get_pyphen_dict():
19
  return pyphen.Pyphen(lang='en')
20
 
21
- # Cache for IPA pronunciations to avoid repeated API calls
22
- @st.cache_data
23
- def get_ipa_pronunciation(word: str) -> str:
24
- """Get IPA pronunciation for a word using a free dictionary API"""
25
- try:
26
- clean_word = re.sub(r'[^\w]', '', word.lower())
27
- if not clean_word:
28
- return ""
29
-
30
- url = f"https://api.dictionaryapi.dev/api/v2/entries/en/{clean_word}"
31
- response = requests.get(url, timeout=2)
32
-
33
- if response.status_code == 200:
34
- data = response.json()
35
- if data and len(data) > 0:
36
- phonetics = data[0].get('phonetics', [])
37
- for phonetic in phonetics:
38
- if 'text' in phonetic and phonetic['text']:
39
- return phonetic['text']
40
- return ""
41
- except:
42
- return ""
43
-
44
  def generate_color_palette(num_colors: int) -> List[str]:
45
- """Generate colors for syllables"""
46
- colors = [
47
- "#2C3E50", "#E74C3C", "#3498DB", "#2ECC71", "#F39C12",
48
- "#9B59B6", "#1ABC9C", "#E67E22", "#34495E", "#F1C40F",
49
- "#8E44AD", "#16A085", "#27AE60", "#E8753F", "#BDC3C7",
50
- "#95A5A6", "#D35400", "#C0392B", "#8B4513", "#FF6347"
 
51
  ]
52
 
53
- while len(colors) < num_colors:
54
- r = random.randint(50, 200)
55
- g = random.randint(50, 200)
56
- b = random.randint(50, 200)
57
- colors.append(f"#{r:02x}{g:02x}{b:02x}")
 
58
 
59
- return colors[:num_colors]
60
 
61
  def syllabify_word(word: str, pyphen_dict) -> List[str]:
62
  """Syllabify a single word using pyphen"""
 
63
  clean_word = re.sub(r'[^\w]', '', word)
64
 
65
  if not clean_word:
66
  return [word]
67
 
68
  try:
 
69
  syllabified = pyphen_dict.inserted(clean_word.lower())
70
  syllables = syllabified.split('-')
71
 
 
72
  if len(syllables) == 1 and syllables[0] == clean_word.lower():
73
  return [clean_word]
74
 
 
75
  if clean_word.isupper():
76
  syllables = [syl.upper() for syl in syllables]
77
  elif clean_word[0].isupper():
@@ -85,260 +67,124 @@ def syllabify_word(word: str, pyphen_dict) -> List[str]:
85
  except:
86
  return [clean_word]
87
 
88
- def process_text(text: str) -> Tuple[List[Tuple[str, str, str]], List[Tuple[str, List[Tuple[str, str]]]], Dict[str, str]]:
89
- """Process text and return original words, syllable breakdown, and IPA dictionary"""
90
  pyphen_dict = get_pyphen_dict()
91
 
 
92
  words = re.findall(r'\b\w+\b', text)
93
- original_words = []
94
  syllable_breakdown = []
95
- ipa_dict = {}
96
-
97
- # Generate colors for unique words
98
- unique_words = list(set([word.lower() for word in words]))
99
- word_colors = {}
100
- colors = generate_color_palette(len(unique_words))
101
 
102
- for i, unique_word in enumerate(unique_words):
103
- word_colors[unique_word] = colors[i % len(colors)]
104
-
105
- for i, word in enumerate(words):
106
- # Get IPA pronunciation
107
- ipa = get_ipa_pronunciation(word)
108
- ipa_dict[word.lower()] = ipa
109
-
110
- color = word_colors[word.lower()]
111
- word_id = f"word_{i}"
112
 
113
- # Add to original words
114
- original_words.append((word, color, word_id))
115
 
116
- # Process syllables
117
- syllables_list = syllabify_word(word, pyphen_dict)
118
- syllable_colored = [(syl, color) for syl in syllables_list]
119
  syllable_breakdown.append((word, syllable_colored))
120
 
121
- return original_words, syllable_breakdown, ipa_dict
122
 
123
- def display_text_with_colors(words_data: List[Tuple[str, str, str]], title: str, is_syllables: bool = False):
124
- """Display text with colors using Streamlit columns for hover effect simulation"""
125
- st.markdown(f"### {title}")
126
-
127
- # Create a grid layout for words
128
- cols_per_row = 8
129
- word_chunks = [words_data[i:i + cols_per_row] for i in range(0, len(words_data), cols_per_row)]
130
-
131
- for chunk in word_chunks:
132
- cols = st.columns(len(chunk))
133
- for i, (word_info, col) in enumerate(zip(chunk, cols)):
134
- if is_syllables:
135
- word, syllables = word_info
136
- if len(syllables) > 1:
137
- display_text = '-'.join([syl for syl, _ in syllables])
138
- else:
139
- display_text = syllables[0][0] if syllables else word
140
- color = syllables[0][1] if syllables else "#333333"
141
- else:
142
- word, color, word_id = word_info
143
- display_text = word
144
-
145
- with col:
146
- st.markdown(
147
- f'<span style="color: {color}; font-weight: bold; font-size: 16px; padding: 4px; display: inline-block;">{display_text}</span>',
148
- unsafe_allow_html=True
149
- )
150
 
151
- def display_word_grid_with_ipa(original_words, syllable_breakdown, ipa_dict, selected_word_idx=None):
152
- """Display words in a grid format with IPA information"""
153
-
154
- # Create tabs for different views
155
- tab1, tab2 = st.tabs(["πŸ“ Original Text", "πŸ”€ Syllabified Text"])
156
-
157
- with tab1:
158
- st.markdown("*Click on a word to see its IPA pronunciation*")
159
-
160
- # Display original words in a flowing text format
161
- html_words = []
162
- for i, (word, color, word_id) in enumerate(original_words):
163
- if i == selected_word_idx:
164
- # Highlight selected word
165
- html_words.append(f'<strong style="color: {color}; background-color: yellow; padding: 2px 4px; border-radius: 3px; font-size: 18px;">{word}</strong>')
166
  else:
167
- html_words.append(f'<span style="color: {color}; font-weight: bold; font-size: 16px; margin: 0 2px;">{word}</span>')
168
-
169
- text_html = ' '.join(html_words)
170
- st.markdown(f'<div style="line-height: 1.8; padding: 15px; border: 2px solid #ddd; border-radius: 8px; background-color: #f9f9f9;">{text_html}</div>', unsafe_allow_html=True)
171
 
172
- with tab2:
173
- st.markdown("*Click on a word to see its IPA pronunciation*")
174
-
175
- # Display syllabified words
176
- html_words = []
177
- for i, (word, syllables) in enumerate(syllable_breakdown):
178
- if syllables:
179
- if len(syllables) > 1:
180
- syllable_parts = []
181
- for syl, color in syllables:
182
- syllable_parts.append(f'<span style="color: {color}; font-weight: bold;">{syl}</span>')
183
- syllable_text = '<span style="color: #666;">-</span>'.join(syllable_parts)
184
- else:
185
- syllable_text = f'<span style="color: {syllables[0][1]}; font-weight: bold;">{syllables[0][0]}</span>'
186
-
187
- if i == selected_word_idx:
188
- html_words.append(f'<span style="background-color: yellow; padding: 2px 4px; border-radius: 3px; font-size: 18px;">{syllable_text}</span>')
189
- else:
190
- html_words.append(f'<span style="font-size: 16px; margin: 0 4px;">{syllable_text}</span>')
191
-
192
- syllable_html = ' '.join(html_words)
193
- st.markdown(f'<div style="line-height: 1.8; padding: 15px; border: 2px solid #ddd; border-radius: 8px; background-color: #f0f8ff;">{syllable_html}</div>', unsafe_allow_html=True)
194
 
 
195
  def main():
196
- st.title("πŸ”€ Enhanced Text Syllabification Tool")
197
- st.markdown("*Enter text to see syllable breakdown with IPA pronunciation and interactive word selection*")
198
 
199
  # Input text area
200
  input_text = st.text_area(
201
  "Enter your text:",
202
  placeholder="Type or paste your text here...",
203
  height=100,
204
- help="Enter any text to see syllables and IPA pronunciations"
205
  )
206
 
207
  # Submit button
208
  submit_clicked = st.button("πŸ” Submit", type="primary", use_container_width=True)
209
 
210
  if submit_clicked and input_text.strip():
211
- with st.spinner("Processing text and fetching pronunciations..."):
212
- original_words, syllable_breakdown, ipa_dict = process_text(input_text)
213
-
214
- # Word selection interface
215
- st.subheader("πŸ“š Interactive Word Explorer")
216
-
217
- # Create word selection buttons
218
- word_list = [word for word, _, _ in original_words]
219
-
220
- # Display words as clickable buttons in columns
221
- st.markdown("**Click on any word to see detailed information:**")
222
-
223
- cols_per_row = 6
224
- word_chunks = [word_list[i:i + cols_per_row] for i in range(0, len(word_list), cols_per_row)]
225
 
226
- selected_word_idx = None
227
- selected_word = None
228
-
229
- for chunk_idx, chunk in enumerate(word_chunks):
230
- cols = st.columns(len(chunk))
231
- for word_idx_in_chunk, (word, col) in enumerate(zip(chunk, cols)):
232
- actual_word_idx = chunk_idx * cols_per_row + word_idx_in_chunk
233
- with col:
234
- if st.button(word, key=f"word_btn_{actual_word_idx}", use_container_width=True):
235
- selected_word_idx = actual_word_idx
236
- selected_word = word
237
-
238
- # Display text with highlighting
239
- display_word_grid_with_ipa(original_words, syllable_breakdown, ipa_dict, selected_word_idx)
240
-
241
- # Show detailed information for selected word
242
- if selected_word_idx is not None and selected_word:
243
- st.subheader(f"πŸ” Details for: **{selected_word}**")
244
-
245
- col1, col2, col3 = st.columns(3)
246
-
247
- with col1:
248
- st.markdown("**Original Word:**")
249
- word_info = original_words[selected_word_idx]
250
- st.markdown(f'<span style="color: {word_info[1]}; font-weight: bold; font-size: 20px;">{word_info[0]}</span>', unsafe_allow_html=True)
251
-
252
- with col2:
253
- st.markdown("**Syllables:**")
254
- syllables = syllable_breakdown[selected_word_idx][1]
255
- if len(syllables) > 1:
256
- syllable_display = " - ".join([syl for syl, _ in syllables])
257
- st.markdown(f"**{syllable_display}** ({len(syllables)} syllables)")
258
- else:
259
- st.markdown(f"**{syllables[0][0]}** (1 syllable)")
260
-
261
- with col3:
262
- st.markdown("**IPA Pronunciation:**")
263
- ipa = ipa_dict.get(selected_word.lower(), "")
264
- if ipa:
265
- st.markdown(f"**{ipa}**")
266
- st.markdown("πŸ”Š *Hover to hear pronunciation*")
267
- else:
268
- st.markdown("*Not available*")
269
 
270
  # Statistics
271
  total_words = len(syllable_breakdown)
272
  total_syllables = sum(len(syls) for _, syls in syllable_breakdown)
273
 
274
- st.markdown(f"**πŸ“Š Statistics: {total_words} words β€’ {total_syllables} syllables**")
275
 
276
- # Detailed information in expandable section
277
- with st.expander("πŸ“ˆ Complete Analysis", expanded=False):
278
- col1, col2 = st.columns(2)
279
-
280
- with col1:
281
- st.markdown("**Syllable Counts:**")
282
- for word, syllables in syllable_breakdown:
283
- st.text(f"{word}: {len(syllables)} syllable{'s' if len(syllables) > 1 else ''}")
284
-
285
- with col2:
286
- st.markdown("**IPA Pronunciations:**")
287
- ipa_available = {word: ipa for word, ipa in ipa_dict.items() if ipa}
288
- if ipa_available:
289
- for word, ipa in sorted(ipa_available.items()):
290
- st.text(f"{word}: {ipa}")
291
- else:
292
- st.text("No IPA pronunciations available.")
293
 
294
  elif submit_clicked and not input_text.strip():
295
  st.warning("⚠️ Please enter some text first!")
296
 
297
- else:
298
- st.info("πŸ‘† Enter some text above and click Submit to start exploring!")
299
 
300
  # Example
301
  st.subheader("Example")
302
- example_text = "The preparation of abstracts requires intellectual familiarity."
303
  st.code(example_text)
304
 
305
  if st.button("Try Example"):
306
- with st.spinner("Processing example..."):
307
- original_words, syllable_breakdown, ipa_dict = process_text(example_text)
308
 
309
- display_word_grid_with_ipa(original_words, syllable_breakdown, ipa_dict)
 
310
 
 
311
  total_words = len(syllable_breakdown)
312
  total_syllables = sum(len(syls) for _, syls in syllable_breakdown)
313
  st.markdown(f"**πŸ“Š {total_words} words β€’ {total_syllables} syllables**")
314
 
315
  # About section
316
- with st.expander("About this Enhanced Tool"):
317
  st.markdown("""
318
- This enhanced syllabification tool provides:
319
-
320
- **πŸ”€ Core Features:**
321
- - Accurate English syllabification using pyphen (Hunspell algorithm)
322
- - Color-coded words and syllables for easy identification
323
- - Two view modes: Original text and Syllabified text
324
-
325
- **🎯 Interactive Features:**
326
- - **Click-to-explore**: Click any word button to see detailed analysis
327
- - **Word highlighting**: Selected words are highlighted in both views
328
- - **IPA pronunciations**: See phonetic transcriptions for each word
329
- - **Syllable counting**: Visual breakdown of syllable structure
330
-
331
- **πŸ“Š Analysis Tools:**
332
- - Complete syllable counts for all words
333
- - Statistical overview (total words and syllables)
334
- - Pronunciation data from Free Dictionary API
335
-
336
- **πŸ’‘ How to Use:**
337
- 1. Enter your text in the input area
338
- 2. Click Submit to process the text
339
- 3. Click on any word button to see detailed information
340
- 4. Switch between Original and Syllabified views using tabs
341
- 5. Check the Complete Analysis section for full details
342
  """)
343
 
344
  if __name__ == "__main__":
 
2
  import pyphen
3
  import re
4
  import random
5
+ from typing import List, Tuple
 
6
 
7
  # Configure page
8
  st.set_page_config(
 
17
  def get_pyphen_dict():
18
  return pyphen.Pyphen(lang='en')
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  def generate_color_palette(num_colors: int) -> List[str]:
21
+ """Generate gray shades for syllables"""
22
+ # Use different shades of gray instead of bright colors
23
+ base_grays = [
24
+ "#2C3E50", "#34495E", "#5D6D7E", "#85929E", "#566573",
25
+ "#515A5A", "#626567", "#797D7F", "#922B21", "#A93226",
26
+ "#B7472A", "#C0392B", "#CD6155", "#D98880", "#E8DAEF",
27
+ "#D7BDE2", "#BB8FCE", "#A569BD", "#8E44AD", "#7D3C98"
28
  ]
29
 
30
+ # Generate more gray shades if needed
31
+ while len(base_grays) < num_colors:
32
+ # Generate random gray shades
33
+ gray_val = random.randint(60, 140)
34
+ color = f"#{gray_val:02x}{gray_val:02x}{gray_val:02x}"
35
+ base_grays.append(color)
36
 
37
+ return base_grays[:num_colors]
38
 
39
  def syllabify_word(word: str, pyphen_dict) -> List[str]:
40
  """Syllabify a single word using pyphen"""
41
+ # Clean the word of punctuation for syllabification
42
  clean_word = re.sub(r'[^\w]', '', word)
43
 
44
  if not clean_word:
45
  return [word]
46
 
47
  try:
48
+ # Use pyphen to get syllables
49
  syllabified = pyphen_dict.inserted(clean_word.lower())
50
  syllables = syllabified.split('-')
51
 
52
+ # If no syllables found (single syllable word), return the word
53
  if len(syllables) == 1 and syllables[0] == clean_word.lower():
54
  return [clean_word]
55
 
56
+ # Handle case preservation
57
  if clean_word.isupper():
58
  syllables = [syl.upper() for syl in syllables]
59
  elif clean_word[0].isupper():
 
67
  except:
68
  return [clean_word]
69
 
70
+ def process_text(text: str) -> List[Tuple[str, List[Tuple[str, str]]]]:
71
+ """Process text and return syllable breakdown only"""
72
  pyphen_dict = get_pyphen_dict()
73
 
74
+ # Split into words
75
  words = re.findall(r'\b\w+\b', text)
 
76
  syllable_breakdown = []
 
 
 
 
 
 
77
 
78
+ for word in words:
79
+ syllables_list = syllabify_word(word, pyphen_dict)
 
 
 
 
 
 
 
 
80
 
81
+ # Generate gray colors for this word's syllables
82
+ colors = generate_color_palette(len(syllables_list))
83
 
84
+ # Add to syllable breakdown
85
+ syllable_colored = [(syl, colors[i % len(colors)]) for i, syl in enumerate(syllables_list)]
 
86
  syllable_breakdown.append((word, syllable_colored))
87
 
88
+ return syllable_breakdown
89
 
90
+ def display_colored_text(colored_words: List[Tuple[str, str]]):
91
+ """Display text with colored words"""
92
+ html_parts = []
93
+ for word, color in colored_words:
94
+ if word.strip():
95
+ html_parts.append(f'<span style="color: {color}; font-weight: bold; font-size: 16px;">{word}</span>')
96
+ else:
97
+ html_parts.append(word)
98
+
99
+ html_content = ''.join(html_parts)
100
+ st.markdown(f'<div style="font-size: 16px; line-height: 1.6; padding: 15px; border: 2px solid #ddd; border-radius: 8px; background-color: #f9f9f9;">{html_content}</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
+ def display_syllable_breakdown(syllable_breakdown: List[Tuple[str, List[Tuple[str, str]]]]):
103
+ """Display syllable breakdown with hyphens"""
104
+ html_parts = []
105
+
106
+ for word, syllables in syllable_breakdown:
107
+ if syllables and len(syllables) > 0:
108
+ # Create hyphenated syllable display
109
+ syllable_spans = []
110
+ for syl, color in syllables:
111
+ syllable_spans.append(f'<span style="color: {color}; font-weight: bold; font-size: 16px;">{syl}</span>')
112
+
113
+ # Join with hyphens for multi-syllable words
114
+ if len(syllables) > 1:
115
+ syllable_display = '<span style="color: #666; font-weight: bold;">-</span>'.join(syllable_spans)
 
116
  else:
117
+ syllable_display = syllable_spans[0]
118
+
119
+ html_parts.append(f'<span style="margin-right: 12px; display: inline-block; margin-bottom: 6px;">{syllable_display}</span>')
 
120
 
121
+ if html_parts:
122
+ html_content = ''.join(html_parts)
123
+ st.markdown(f'<div style="font-size: 16px; line-height: 1.6; padding: 15px; border: 2px solid #ddd; border-radius: 8px; background-color: #f0f8ff;">{html_content}</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
+ # Main app
126
  def main():
127
+ st.title("πŸ”€ Text Syllabification Tool")
128
+ st.markdown("*Enter text to see accurate syllable breakdown with color coding*")
129
 
130
  # Input text area
131
  input_text = st.text_area(
132
  "Enter your text:",
133
  placeholder="Type or paste your text here...",
134
  height=100,
135
+ help="Enter any text to see how words are broken down into syllables"
136
  )
137
 
138
  # Submit button
139
  submit_clicked = st.button("πŸ” Submit", type="primary", use_container_width=True)
140
 
141
  if submit_clicked and input_text.strip():
142
+ # Process the text
143
+ syllable_breakdown = process_text(input_text)
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
+ # Display syllable breakdown
146
+ st.subheader("Syllable Breakdown")
147
+ display_syllable_breakdown(syllable_breakdown)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
  # Statistics
150
  total_words = len(syllable_breakdown)
151
  total_syllables = sum(len(syls) for _, syls in syllable_breakdown)
152
 
153
+ st.markdown(f"**πŸ“Š {total_words} words β€’ {total_syllables} syllables**")
154
 
155
+ # Show syllable counts in a more compact way
156
+ if syllable_breakdown:
157
+ with st.expander("πŸ“ˆ Syllable Counts per Word", expanded=False):
158
+ counts_text = " β€’ ".join([f"{word}: {len(syllables)}" for word, syllables in syllable_breakdown])
159
+ st.markdown(f"<small>{counts_text}</small>", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  elif submit_clicked and not input_text.strip():
162
  st.warning("⚠️ Please enter some text first!")
163
 
164
+ elif not submit_clicked:
165
+ st.info("πŸ‘† Enter some text above and click Submit to see the syllabification!")
166
 
167
  # Example
168
  st.subheader("Example")
169
+ example_text = "The preparation of abstracts is an intellectual effort requiring general familiarity."
170
  st.code(example_text)
171
 
172
  if st.button("Try Example"):
173
+ # Process example
174
+ syllable_breakdown = process_text(example_text)
175
 
176
+ st.subheader("Syllable Breakdown")
177
+ display_syllable_breakdown(syllable_breakdown)
178
 
179
+ # Show example statistics
180
  total_words = len(syllable_breakdown)
181
  total_syllables = sum(len(syls) for _, syls in syllable_breakdown)
182
  st.markdown(f"**πŸ“Š {total_words} words β€’ {total_syllables} syllables**")
183
 
184
  # About section
185
+ with st.expander("About this tool"):
186
  st.markdown("""
187
+ Created by @aghilalb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  """)
189
 
190
  if __name__ == "__main__":