duongthienz commited on
Commit
ed5370f
·
verified ·
1 Parent(s): 0da24ba

update timespoken for multi

Browse files
Files changed (1) hide show
  1. utils.py +76 -102
utils.py CHANGED
@@ -333,7 +333,7 @@ def build_fig_pie1(df3, catTypeColors):
333
  """Voice category pie chart."""
334
  fig = go.Figure()
335
  fig.update_layout(
336
- title_text="Percentage of each voice category",
337
  colorway=catTypeColors,
338
  **TRANSPARENT_BG,
339
  )
@@ -348,7 +348,7 @@ def build_fig_pie2(df4, speakerNames, speaker_color_map, catColors, get_display_
348
  colors = [speaker_color_map.get(n, _SPEAKER_PALETTE[i % len(_SPEAKER_PALETTE)])
349
  for i, n in enumerate(df4["names"])]
350
  fig = go.Figure()
351
- fig.update_layout(title_text="Percentage of speakers per role", **TRANSPARENT_BG)
352
  fig.add_trace(go.Pie(values=df4["values"], labels=df4["names"],
353
  marker_colors=colors, sort=False))
354
  return fig
@@ -392,7 +392,7 @@ def build_fig_sunburst(df5, catTypeColors, speaker_color_map, get_display_name_f
392
  values="percentiles",
393
  custom_data=["labels", "valueStrings", "percentiles", "parentNames", "parentPercentiles"],
394
  color="labels",
395
- title="Percentage of each voice category with speakers (Combination)",
396
  color_discrete_map=color_map,
397
  )
398
  fig.update_traces(hovertemplate="<br>".join([
@@ -406,84 +406,6 @@ def build_fig_sunburst(df5, catTypeColors, speaker_color_map, get_display_name_f
406
  return fig
407
 
408
 
409
- def build_fig_sunburst_single(df5, speaker_color_map, get_display_name_fn, currFile):
410
- """Sunburst showing only Single Voice speakers."""
411
- df5 = df5.copy()
412
- df5["labels"] = df5["labels"].apply(lambda s: get_display_name_fn(s, currFile))
413
- df5["parentNames"] = df5["parentNames"].apply(lambda s: get_display_name_fn(s, currFile))
414
-
415
- # Keep only the Single Voice parent row and its children
416
- keep_ids = {"OV"} | {row["ids"] for _, row in df5.iterrows()
417
- if row["parents"] == "OV"}
418
- df5 = df5[df5["ids"].isin(keep_ids)].copy()
419
- # Re-root: Single Voice becomes the top-level (parent = "")
420
- df5.loc[df5["ids"] == "OV", "parents"] = ""
421
-
422
- color_map = {lbl: speaker_color_map.get(lbl, _SPEAKER_PALETTE[i % len(_SPEAKER_PALETTE)])
423
- for i, lbl in enumerate(df5["labels"])}
424
- color_map["Single Voice"] = _PALETTE[0]
425
-
426
- fig = px.sunburst(
427
- df5,
428
- branchvalues="total",
429
- names="labels", ids="ids", parents="parents",
430
- values="percentiles",
431
- custom_data=["labels", "valueStrings", "percentiles", "parentNames", "parentPercentiles"],
432
- color="labels",
433
- title="Percentage of each voice category with speakers (Single Voice)",
434
- color_discrete_map=color_map,
435
- )
436
- fig.update_traces(hovertemplate="<br>".join([
437
- "<b>%{customdata[0]}</b>",
438
- "Duration: %{customdata[1]}s",
439
- "Percentage of Total: %{customdata[2]:.2f}%",
440
- "Parent: %{customdata[3]}",
441
- "Percentage of Parent: %{customdata[4]:.2f}%",
442
- ]))
443
- fig.update_layout(**TRANSPARENT_BG, font_color="#323236")
444
- return fig
445
-
446
-
447
- def build_fig_sunburst_multi(df5, speaker_color_map, get_display_name_fn, currFile):
448
- """Sunburst showing only Multi Voice speakers."""
449
- df5 = df5.copy()
450
- df5["labels"] = df5["labels"].apply(lambda s: get_display_name_fn(s, currFile))
451
- df5["parentNames"] = df5["parentNames"].apply(lambda s: get_display_name_fn(s, currFile))
452
-
453
- # Keep only the Multi Voice parent row and its children
454
- keep_ids = {"MV"} | {row["ids"] for _, row in df5.iterrows()
455
- if row["parents"] == "MV"}
456
- df5 = df5[df5["ids"].isin(keep_ids)].copy()
457
- if df5.empty:
458
- return None
459
- # Re-root: Multi Voice becomes the top-level (parent = "")
460
- df5.loc[df5["ids"] == "MV", "parents"] = ""
461
-
462
- color_map = {lbl: speaker_color_map.get(lbl, _SPEAKER_PALETTE[i % len(_SPEAKER_PALETTE)])
463
- for i, lbl in enumerate(df5["labels"])}
464
- color_map["Multi Voice"] = _PALETTE[9]
465
-
466
- fig = px.sunburst(
467
- df5,
468
- branchvalues="total",
469
- names="labels", ids="ids", parents="parents",
470
- values="percentiles",
471
- custom_data=["labels", "valueStrings", "percentiles", "parentNames", "parentPercentiles"],
472
- color="labels",
473
- title="Percentage of each voice category with speakers (Multiple Voices)",
474
- color_discrete_map=color_map,
475
- )
476
- fig.update_traces(hovertemplate="<br>".join([
477
- "<b>%{customdata[0]}</b>",
478
- "Duration: %{customdata[1]}s",
479
- "Percentage of Total: %{customdata[2]:.2f}%",
480
- "Parent: %{customdata[3]}",
481
- "Percentage of Parent: %{customdata[4]:.2f}%",
482
- ]))
483
- fig.update_layout(**TRANSPARENT_BG, font_color="#323236")
484
- return fig
485
-
486
-
487
  def build_fig_treemap(df5, catTypeColors, speaker_color_map, get_display_name_fn, currFile):
488
  """Treemap voice-category chart."""
489
  df5 = df5.copy()
@@ -499,7 +421,7 @@ def build_fig_treemap(df5, catTypeColors, speaker_color_map, get_display_name_fn
499
  values="percentiles",
500
  custom_data=["labels", "valueStrings", "percentiles", "parentNames", "parentPercentiles"],
501
  color="labels",
502
- title="Division of speakers in each voice category",
503
  color_discrete_map=color_map,
504
  )
505
  fig.update_traces(hovertemplate="<br>".join([
@@ -533,7 +455,7 @@ def build_fig_timeline(speakers_dataFrame, currTotalTime, speaker_color_map, get
533
 
534
  fig = px.timeline(
535
  df, x_start="Start", x_end="Finish", y="Resource", color="Resource",
536
- title="Timeline of audio with speakers",
537
  color_discrete_map=speaker_color_map,
538
  )
539
  fig.update_yaxes(autorange="reversed")
@@ -571,36 +493,88 @@ def _seconds_to_hhmmss(seconds):
571
  return f"{h:02d}:{m:02d}:{s:05.2f}"
572
 
573
 
574
- def build_fig_bar(df2, speakerNames, catColors, speaker_color_map, get_display_name_fn, currFile):
 
 
 
 
 
 
 
 
 
 
 
575
  """Horizontal bar chart — time spoken per speaker (hh:mm:ss.ss).
576
  Only individual speakers are shown; role/category rows are excluded.
577
  """
 
578
  df2 = df2.copy()
579
- # Keep only rows whose raw name is an actual speaker (not a category label)
580
  df2 = df2[df2["names"].isin(speakerNames)]
581
- df2["names"] = df2["names"].apply(lambda s: get_display_name_fn(s, currFile))
582
- df2["time_label"] = df2["values"].apply(_seconds_to_hhmmss)
583
- fig = px.bar(
584
- df2, x="values", y="names", color="names", orientation="h",
585
- custom_data=["names", "time_label"],
586
- title="Time spoken by each speaker",
587
- color_discrete_map=speaker_color_map,
588
- )
589
- # Hide x-axis tick labels — values are crowded with many speakers.
590
- # The exact time is still visible on hover via the hovertemplate.
591
- fig.update_xaxes(showticklabels=False)
592
- fig.update_yaxes(autorange="reversed")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
  fig.update_layout(
 
 
594
  xaxis_title="Time Spoken",
595
  yaxis_title=None,
596
  showlegend=False,
597
- yaxis={"showticklabels": True},
 
598
  **TRANSPARENT_BG,
599
  )
600
- fig.update_traces(hovertemplate="<br>".join([
601
- "<b>%{customdata[0]}</b>",
602
- "Time Spoken: %{customdata[1]}",
603
- ]))
604
  return fig
605
 
606
 
 
333
  """Voice category pie chart."""
334
  fig = go.Figure()
335
  fig.update_layout(
336
+ title_text="Percentage of each Voice Category",
337
  colorway=catTypeColors,
338
  **TRANSPARENT_BG,
339
  )
 
348
  colors = [speaker_color_map.get(n, _SPEAKER_PALETTE[i % len(_SPEAKER_PALETTE)])
349
  for i, n in enumerate(df4["names"])]
350
  fig = go.Figure()
351
+ fig.update_layout(title_text="Percentage of Speakers per Role", **TRANSPARENT_BG)
352
  fig.add_trace(go.Pie(values=df4["values"], labels=df4["names"],
353
  marker_colors=colors, sort=False))
354
  return fig
 
392
  values="percentiles",
393
  custom_data=["labels", "valueStrings", "percentiles", "parentNames", "parentPercentiles"],
394
  color="labels",
395
+ title="Percentage of each Voice Category with Speakers",
396
  color_discrete_map=color_map,
397
  )
398
  fig.update_traces(hovertemplate="<br>".join([
 
406
  return fig
407
 
408
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409
  def build_fig_treemap(df5, catTypeColors, speaker_color_map, get_display_name_fn, currFile):
410
  """Treemap voice-category chart."""
411
  df5 = df5.copy()
 
421
  values="percentiles",
422
  custom_data=["labels", "valueStrings", "percentiles", "parentNames", "parentPercentiles"],
423
  color="labels",
424
+ title="Division of Speakers in each Voice Category",
425
  color_discrete_map=color_map,
426
  )
427
  fig.update_traces(hovertemplate="<br>".join([
 
455
 
456
  fig = px.timeline(
457
  df, x_start="Start", x_end="Finish", y="Resource", color="Resource",
458
+ title="Timeline of Audio with Speakers",
459
  color_discrete_map=speaker_color_map,
460
  )
461
  fig.update_yaxes(autorange="reversed")
 
493
  return f"{h:02d}:{m:02d}:{s:05.2f}"
494
 
495
 
496
+ def _darken_hex(hex_color, factor=0.55):
497
+ """Return a darker version of a hex color by reducing brightness."""
498
+ import colorsys
499
+ h = hex_color.lstrip('#')
500
+ r, g, b = int(h[0:2],16)/255, int(h[2:4],16)/255, int(h[4:6],16)/255
501
+ hue, sat, val = colorsys.rgb_to_hsv(r, g, b)
502
+ val = max(val * factor, 0.0)
503
+ r2, g2, b2 = colorsys.hsv_to_rgb(hue, sat, val)
504
+ return f"#{int(r2*255):02X}{int(g2*255):02X}{int(b2*255):02X}"
505
+
506
+
507
+ def build_fig_bar(df2, speakerNames, catColors, speaker_color_map, get_display_name_fn, currFile, mv_per_speaker=None):
508
  """Horizontal bar chart — time spoken per speaker (hh:mm:ss.ss).
509
  Only individual speakers are shown; role/category rows are excluded.
510
  """
511
+ mv_per_speaker = mv_per_speaker or {}
512
  df2 = df2.copy()
 
513
  df2 = df2[df2["names"].isin(speakerNames)]
514
+
515
+ # Map raw speaker names to display names
516
+ raw_to_display = {sp: get_display_name_fn(sp, currFile) for sp in df2["names"]}
517
+ df2["display"] = df2["names"].map(raw_to_display)
518
+ df2["mv_secs"] = df2["names"].map(lambda sp: mv_per_speaker.get(sp, 0.0))
519
+ df2["sv_secs"] = (df2["values"] - df2["mv_secs"]).clip(lower=0)
520
+ df2["time_label"] = df2["values"].apply(_seconds_to_hhmmss)
521
+ df2["mv_time_label"] = df2["mv_secs"].apply(_seconds_to_hhmmss)
522
+
523
+ # Build display-keyed color maps
524
+ disp_color_map = {raw_to_display[sp]: speaker_color_map.get(raw_to_display[sp], "#aaaaaa")
525
+ for sp in df2["names"]}
526
+ disp_dark_map = {disp: _darken_hex(col) for disp, col in disp_color_map.items()}
527
+
528
+ fig = go.Figure()
529
+
530
+ # Trace 1: single-voice portion (base color)
531
+ for _, row in df2.iterrows():
532
+ col = disp_color_map.get(row["display"], "#aaaaaa")
533
+ fig.add_trace(go.Bar(
534
+ x=[row["sv_secs"]],
535
+ y=[row["display"]],
536
+ orientation="h",
537
+ marker_color=col,
538
+ showlegend=False,
539
+ customdata=[[row["display"], row["time_label"], row["mv_time_label"]]],
540
+ hovertemplate=(
541
+ "<b>%{customdata[0]}</b><br>"
542
+ "Total: %{customdata[1]}<br>"
543
+ "Multi Voice: %{customdata[2]}"
544
+ "<extra></extra>"
545
+ ),
546
+ ))
547
+
548
+ # Trace 2: multi-voice portion (darker shade stacked on top)
549
+ for _, row in df2.iterrows():
550
+ if row["mv_secs"] <= 0:
551
+ continue
552
+ dark = disp_dark_map.get(row["display"], "#555555")
553
+ fig.add_trace(go.Bar(
554
+ x=[row["mv_secs"]],
555
+ y=[row["display"]],
556
+ orientation="h",
557
+ marker_color=dark,
558
+ showlegend=False,
559
+ customdata=[[row["display"], row["time_label"], row["mv_time_label"]]],
560
+ hovertemplate=(
561
+ "<b>%{customdata[0]}</b><br>"
562
+ "Total: %{customdata[1]}<br>"
563
+ "Multi Voice: %{customdata[2]}"
564
+ "<extra></extra>"
565
+ ),
566
+ ))
567
+
568
  fig.update_layout(
569
+ barmode="stack",
570
+ title="Time spoken by each speaker",
571
  xaxis_title="Time Spoken",
572
  yaxis_title=None,
573
  showlegend=False,
574
+ yaxis={"showticklabels": True, "autorange": "reversed"},
575
+ xaxis={"showticklabels": False},
576
  **TRANSPARENT_BG,
577
  )
 
 
 
 
578
  return fig
579
 
580