duongthienz commited on
Commit
9fd0b16
Β·
verified Β·
1 Parent(s): fc51005

Update state.py

Browse files
Files changed (1) hide show
  1. state.py +33 -74
state.py CHANGED
@@ -55,6 +55,7 @@ def init_session_state():
55
  "speakerSegments": {}, # {filename: {speaker: [(start,end), ...]}}
56
  "speakerWaveforms": {}, # {filename: (waveform_tensor, sample_rate)}
57
  "globalRenames": [], # [{"name": str, "speakers": ["file: SPEAKER_##", ...]}]
 
58
  "analyzeAllToggle": False,
59
  }
60
  for key, value in defaults.items():
@@ -143,73 +144,48 @@ def _global_rename_key(index):
143
 
144
 
145
  def applyGlobalRenames():
146
- """Sync speakerRenames from globalRenames without clobbering inline-only renames.
147
- DEBUG VERSION.
148
-
149
- Strategy: only touch speakers whose token appears in globalRenames. Speakers
150
- with no globalRenames entry keep whatever speakerRenames already has for them
151
- (set by apply_inline_rename). This prevents the sidebar from wiping a rename
152
- that was made via the Rename Speaker tab but whose token was later removed from
153
- a globalRenames entry.
154
  """
155
- print(f"[DEBUG applyGlobalRenames] globalRenames={st.session_state.globalRenames}")
156
- print(f"[DEBUG applyGlobalRenames] speakerRenames before={st.session_state.speakerRenames}")
157
- # Build a map of token -> display_name from globalRenames
158
  token_to_name: dict = {}
159
  for entry in st.session_state.globalRenames:
160
  for token in entry["speakers"]:
161
  token_to_name[token] = entry["name"]
162
 
163
- # Collect every token that exists in ANY globalRenames entry (assigned or not)
164
- all_global_tokens: set = {
165
- token
166
- for entry in st.session_state.globalRenames
167
- for token in entry["speakers"]
168
- }
169
-
170
  for fname in st.session_state.speakerRenames:
171
- renames = st.session_state.speakerRenames[fname]
172
- for sp in list(renames.keys()):
 
 
 
 
 
173
  token = f"{fname}: {sp}"
174
  if token in token_to_name:
175
- # Overwrite with the current globalRenames name
176
- renames[sp] = token_to_name[token]
177
- elif token in all_global_tokens:
178
- # Token was explicitly unassigned from all entries β€” clear the rename
179
- del renames[sp]
180
- # else: inline-only rename with no globalRenames record β€” leave untouched
181
-
182
- # Apply any newly assigned tokens not yet in speakerRenames
183
- for token, name in token_to_name.items():
184
- if ": " not in token:
185
- continue
186
- fname, raw_sp = token.split(": ", 1)
187
- if fname in st.session_state.speakerRenames:
188
- st.session_state.speakerRenames[fname][raw_sp] = name
189
-
190
- print(f"[DEBUG applyGlobalRenames] speakerRenames after={st.session_state.speakerRenames}")
191
- curr = st.session_state.get("select_currFile")
192
- if curr and curr in st.session_state.speakerRenames:
193
- saved = st.session_state.speakerRenames[curr]
194
- results = st.session_state.results.get(curr)
195
- if results:
196
- for sp in results[0].labels():
197
- st.session_state[f"rename_{curr}_{sp}"] = saved.get(sp, "")
198
 
199
 
200
  def enforceGlobalRenameExclusivity(changed_idx):
201
  """Ensure a token assigned to entry[changed_idx] is removed from all others."""
202
  changed_tokens = set(st.session_state.globalRenames[changed_idx]["speakers"])
203
- print(f"[DEBUG enforceExclusivity] idx={changed_idx} tokens={changed_tokens}")
204
  for idx, entry in enumerate(st.session_state.globalRenames):
205
  if idx == changed_idx:
206
  continue
207
  new_speakers = [t for t in entry["speakers"] if t not in changed_tokens]
208
- print(f"[DEBUG enforceExclusivity] entry[{idx}] {entry['name']}: {entry['speakers']} -> {new_speakers}")
209
  if new_speakers != entry["speakers"]:
210
  entry["speakers"] = new_speakers
211
  st.session_state.pop(_global_rename_key(idx), None)
212
- print(f"[DEBUG enforceExclusivity] globalRenames after: {st.session_state.globalRenames}")
213
  applyGlobalRenames()
214
 
215
 
@@ -235,40 +211,22 @@ def removeGlobalRename(index):
235
 
236
 
237
  def apply_inline_rename(currFile, raw_sp, new_name):
238
- """Write a single inline rename into both speakerRenames and globalRenames.
239
 
240
- Keeps the sidebar global-rename list in sync so applyGlobalRenames()
241
- won't overwrite the change on the next rerun.
 
242
  """
243
  new_name = new_name.strip()
244
- token = f"{currFile}: {raw_sp}"
245
-
246
- # Always remove this token from every existing entry first so it can't
247
- # be claimed by more than one name at the same time.
248
- # We delete the widget key (rather than overwriting it) to avoid the
249
- # Streamlit "cannot modify after widget is instantiated" error β€” the
250
- # render loop will reseed it from globalRenames data on the next rerun.
251
- for idx, entry in enumerate(st.session_state.globalRenames):
252
- if token in entry["speakers"]:
253
- entry["speakers"].remove(token)
254
- st.session_state.pop(_global_rename_key(idx), None)
255
 
 
256
  if new_name:
257
- # Write into speakerRenames immediately
258
- st.session_state.speakerRenames.setdefault(currFile, {})[raw_sp] = new_name
259
- # Find an existing globalRenames entry for this name, or create one
260
- for idx, entry in enumerate(st.session_state.globalRenames):
261
- if entry["name"] == new_name:
262
- entry["speakers"].append(token)
263
- st.session_state.pop(_global_rename_key(idx), None)
264
- return
265
- # No existing entry β€” create a new one
266
- idx = len(st.session_state.globalRenames)
267
- st.session_state.globalRenames.append({"name": new_name, "speakers": [token]})
268
- # Don't pre-set the widget key here β€” render loop will seed it
269
  else:
270
- # Empty name β€” clear the rename for this speaker (token already removed above)
271
- st.session_state.speakerRenames.setdefault(currFile, {}).pop(raw_sp, None)
 
 
272
 
273
 
274
  # ---------------------------------------------------------------------------
@@ -332,6 +290,7 @@ def register_file(fname):
332
  while len(st.session_state.categorySelect) < len(st.session_state.categories):
333
  st.session_state.categorySelect.append([])
334
  st.session_state.speakerRenames.setdefault(fname, {})
 
335
  st.session_state.speakerClips.setdefault(fname, {})
336
  if fname not in st.session_state.file_names:
337
  st.session_state.file_names.append(fname)
 
55
  "speakerSegments": {}, # {filename: {speaker: [(start,end), ...]}}
56
  "speakerWaveforms": {}, # {filename: (waveform_tensor, sample_rate)}
57
  "globalRenames": [], # [{"name": str, "speakers": ["file: SPEAKER_##", ...]}]
58
+ "inlineRenames": {}, # {filename: {speaker: name}} β€” set by Rename Speaker tab only
59
  "analyzeAllToggle": False,
60
  }
61
  for key, value in defaults.items():
 
144
 
145
 
146
  def applyGlobalRenames():
147
+ """Rebuild speakerRenames from two independent sources:
148
+ 1. globalRenames β€” sidebar assignments (always authoritative for tokens it covers)
149
+ 2. inlineRenames β€” Rename Speaker tab assignments (used only when globalRenames
150
+ has no claim on that token)
151
+ Any speaker not covered by either source gets cleared.
 
 
 
152
  """
153
+ # Build token->name map from globalRenames
 
 
154
  token_to_name: dict = {}
155
  for entry in st.session_state.globalRenames:
156
  for token in entry["speakers"]:
157
  token_to_name[token] = entry["name"]
158
 
159
+ # Rebuild speakerRenames for every file from scratch
 
 
 
 
 
 
160
  for fname in st.session_state.speakerRenames:
161
+ new_renames = {}
162
+ inline = st.session_state.inlineRenames.get(fname, {})
163
+ # Check every known speaker for this file
164
+ result = st.session_state.results.get(fname)
165
+ if not result or len(result) != 2:
166
+ continue
167
+ for sp in result[0].labels():
168
  token = f"{fname}: {sp}"
169
  if token in token_to_name:
170
+ # Sidebar assignment wins
171
+ new_renames[sp] = token_to_name[token]
172
+ elif sp in inline:
173
+ # Tab assignment used only when sidebar has no claim
174
+ new_renames[sp] = inline[sp]
175
+ # else: no assignment β€” omit (raw label will be used)
176
+ st.session_state.speakerRenames[fname] = new_renames
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
 
178
 
179
  def enforceGlobalRenameExclusivity(changed_idx):
180
  """Ensure a token assigned to entry[changed_idx] is removed from all others."""
181
  changed_tokens = set(st.session_state.globalRenames[changed_idx]["speakers"])
 
182
  for idx, entry in enumerate(st.session_state.globalRenames):
183
  if idx == changed_idx:
184
  continue
185
  new_speakers = [t for t in entry["speakers"] if t not in changed_tokens]
 
186
  if new_speakers != entry["speakers"]:
187
  entry["speakers"] = new_speakers
188
  st.session_state.pop(_global_rename_key(idx), None)
 
189
  applyGlobalRenames()
190
 
191
 
 
211
 
212
 
213
  def apply_inline_rename(currFile, raw_sp, new_name):
214
+ """Write a tab-originated rename into inlineRenames, then sync speakerRenames.
215
 
216
+ inlineRenames is the sole record of tab renames. applyGlobalRenames() merges
217
+ inlineRenames with globalRenames every time it runs, so sidebar assignments
218
+ always win and tab assignments fill the rest.
219
  """
220
  new_name = new_name.strip()
 
 
 
 
 
 
 
 
 
 
 
221
 
222
+ inline = st.session_state.inlineRenames.setdefault(currFile, {})
223
  if new_name:
224
+ inline[raw_sp] = new_name
 
 
 
 
 
 
 
 
 
 
 
225
  else:
226
+ inline.pop(raw_sp, None)
227
+
228
+ # Immediately reflect in speakerRenames (sidebar may override on next run)
229
+ applyGlobalRenames()
230
 
231
 
232
  # ---------------------------------------------------------------------------
 
290
  while len(st.session_state.categorySelect) < len(st.session_state.categories):
291
  st.session_state.categorySelect.append([])
292
  st.session_state.speakerRenames.setdefault(fname, {})
293
+ st.session_state.inlineRenames.setdefault(fname, {})
294
  st.session_state.speakerClips.setdefault(fname, {})
295
  if fname not in st.session_state.file_names:
296
  st.session_state.file_names.append(fname)