czyoung commited on
Commit
7860d14
·
verified ·
1 Parent(s): 094a4d0

Moved functions and updated to use Annotations

Browse files
Files changed (1) hide show
  1. sonogram_utility.py +284 -1
sonogram_utility.py CHANGED
@@ -193,4 +193,287 @@ def speakerListToDataFrame(speakerList):
193
  dtEnd = dt.datetime.combine(dt.date.today(), time1)
194
  dataList.append(dict(Task=f"Speaker {j}.{k}", Start=dtStart, Finish=dtEnd, Resource=f"Speaker {j+1}"))
195
  df = pd.DataFrame(dataList)
196
- return df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  dtEnd = dt.datetime.combine(dt.date.today(), time1)
194
  dataList.append(dict(Task=f"Speaker {j}.{k}", Start=dtStart, Finish=dtEnd, Resource=f"Speaker {j+1}"))
195
  df = pd.DataFrame(dataList)
196
+ return df
197
+
198
+ def removeOverlap(timeSegment,overlap):
199
+ times = []
200
+ if timeSegment.start < overlap.start:
201
+ times.append(Segment(timeSegment.start,min(overlap.start,timeSegment.end)))
202
+ if timeSegment.end > overlap.end:
203
+ times.append(Segment(max(timeSegment.start,overlap.end),timeSegment.end))
204
+ return times
205
+
206
+ def checkForOverlap(time1, time2):
207
+ overlap = time1 & time2
208
+ if overlap:
209
+ return overlap
210
+ else:
211
+ return None
212
+
213
+
214
+ def calcCategories(annotation,maxTime):
215
+ noVoice = [Segment(0,maxTime)]
216
+ oneVoice = []
217
+ multiVoice = []
218
+ # TBD Clean this up!!!
219
+ rawData = {}
220
+ for speakerName in annotation.labels():
221
+ if speakerName not in rawData.keys():
222
+ rawData[speakerName] = []
223
+ for segmentItem in annotation.label_support(speakerName):
224
+ rawData[speakerName].append(segmentItem)
225
+ for speaker in rawData.keys():
226
+ timesToProcess = []
227
+ for timeSlot in rawData[speaker]:
228
+ timesToProcess.append((speaker,timeSlot))
229
+ while len(timesToProcess) > 0:
230
+ currID, currTime = timesToProcess[0]
231
+ timesToProcess.remove(timesToProcess[0])
232
+ resetCheck = False
233
+ # Check in multi
234
+ for compareID,timeSlot in multiVoice:
235
+ overlapTime = checkForOverlap(currTime,timeSlot)
236
+ if overlapTime is None:
237
+ continue
238
+ else:
239
+ compareID.append(currID)
240
+ newTimes = removeOverlap(currTime,timeSlot)#+removeOverlap(timeSlot,currTime)
241
+ for i in range(len(newTimes)):
242
+ newTimes[i] = (currID,newTimes[i])
243
+ timesToProcess += newTimes
244
+ resetCheck = True
245
+ break
246
+ if resetCheck:
247
+ continue
248
+ # Check in one voice
249
+ for timeSlot in oneVoice:
250
+ tID = timeSlot[0]
251
+ tTime = timeSlot[1]
252
+ overlapTime = checkForOverlap(currTime,tTime)
253
+ if overlapTime is None:
254
+ continue
255
+ else:
256
+ oneVoice.remove(timeSlot)
257
+ # Add back non overlap
258
+ newTimes = removeOverlap(tTime,currTime)
259
+ for i in range(len(newTimes)):
260
+ newTimes[i] = (tID,newTimes[i])
261
+ oneVoice += newTimes
262
+ # Add overlap time to multivoice
263
+ multiVoice.append(([tID,currID],overlapTime))
264
+ # Add new times back to process
265
+ newTimes = removeOverlap(currTime,tTime)
266
+ for i in range(len(newTimes)):
267
+ newTimes[i] = (currID,newTimes[i])
268
+ timesToProcess += newTimes
269
+ resetCheck = True
270
+ break
271
+ if resetCheck:
272
+ continue
273
+ # Add to one voice
274
+ oneVoice.append((currID,currTime))
275
+ for _,timeSlot in multiVoice:
276
+ copyOfNo = copy.deepcopy(noVoice)
277
+ for emptySlot in noVoice:
278
+ if checkForOverlap(timeSlot,emptySlot) is None:
279
+ continue
280
+ else:
281
+ copyOfNo.remove(emptySlot)
282
+ copyOfNo += removeOverlap(emptySlot,timeSlot)
283
+ noVoice = copyOfNo
284
+ for _,timeSlot in oneVoice:
285
+ copyOfNo = copy.deepcopy(noVoice)
286
+ for emptySlot in noVoice:
287
+ if checkForOverlap(timeSlot,emptySlot) is None:
288
+ continue
289
+ else:
290
+ copyOfNo.remove(emptySlot)
291
+ copyOfNo += removeOverlap(emptySlot,timeSlot)
292
+ noVoice = copyOfNo
293
+ return noVoice, oneVoice, multiVoice, rawData
294
+
295
+ def sumTimes(annotation):
296
+ return annotation.get_timeline(False).duration()
297
+
298
+ def sumTimesPerSpeaker(timeSlotList):
299
+ speakerList = []
300
+ timeList = []
301
+ for speaker,timeSlot in timeSlotList:
302
+ if speaker not in speakerList:
303
+ speakerList.append(speaker)
304
+ timeList.append(0)
305
+ timeList[speakerList.index(speaker)] += timeSlot.duration
306
+ return speakerList, timeList
307
+
308
+ def sumMultiTimesPerSpeaker(timeSlotList):
309
+ speakerList = []
310
+ timeList = []
311
+ sList,tList = sumTimesPerSpeaker(timeSlotList)
312
+ for i,speakerGroup in enumerate(sList):
313
+ for speaker in speakerGroup:
314
+ if speaker not in speakerList:
315
+ speakerList.append(speaker)
316
+ timeList.append(0)
317
+ timeList[speakerList.index(speaker)] += tList[i]
318
+ return speakerList, timeList
319
+
320
+ def annotationToDataFrame(myAnnotation):
321
+ dataList = []
322
+ speakerDict = {}
323
+ for currSpeaker in myAnnotation.labels():
324
+ if currSpeaker not in speakerDict.keys():
325
+ speakerDict[currSpeaker] = []
326
+ for currSegment in myAnnotation.subset([speaker]).itersegments():
327
+ speakerDict[currSpeaker].append(currSegment)
328
+
329
+ timeSummary = {}
330
+ for key in speakerDict.keys():
331
+ if key not in timeSummary.keys():
332
+ timeSummary[key] = 0
333
+ for speakingSegment in speakerDict[key]:
334
+ timeSummary[key] += speakingSegment.duration
335
+
336
+ for key in speakerDict.keys():
337
+ for k, speakingSegment in enumerate(speakerDict[key]):
338
+ speakerName = key
339
+ startPoint = speakingSegment.start
340
+ endPoint = speakingSegment.end
341
+ h0 = int(startPoint//3600)
342
+ m0 = int(startPoint%3600//60)
343
+ s0 = int(startPoint%60)
344
+ ms0 = int(startPoint*1000000%1000000)
345
+ time0 = dt.time(h0,m0,s0,ms0)
346
+ dtStart = dt.datetime.combine(dt.date.today(), time0)
347
+ h1 = int(endPoint//3600)
348
+ m1 = int(endPoint%3600//60)
349
+ s1 = int(endPoint%60)
350
+ ms1 = int(endPoint*1000000%1000000)
351
+ time1 = dt.time(h1,m1,s1,ms1)
352
+ dtEnd = dt.datetime.combine(dt.date.today(), time1)
353
+ dataList.append(dict(Task=speakerName + f".{k}", Start=dtStart, Finish=dtEnd, Resource=speakerName))
354
+ df = pd.DataFrame(dataList)
355
+ return df, timeSummary
356
+
357
+
358
+
359
+ def calcCategories(rawData,categories):
360
+ categorySlots = []
361
+ extraCategories = []
362
+ for category in categories:
363
+ categorySlots.append([])
364
+ for speaker in rawData.keys():
365
+ targetCategory = None
366
+ for i, category in enumerate(categories):
367
+ if speaker in category:
368
+ targetCategory = i
369
+ if targetCategory is None:
370
+ targetCategory = len(categorySlots)
371
+ categorySlots.append([])
372
+ extraCategories.append(speaker)
373
+
374
+ for timeSlot in rawData[speaker]:
375
+ categorySlots[targetCategory].append((speaker,timeSlot))
376
+ # Clean up categories
377
+ cleanCategories = []
378
+ for category in categorySlots:
379
+ newCategory = []
380
+ catSorted = copy.deepcopy(sorted(category,key=lambda slot: slot[1][0]))
381
+ currID, currTime = None, None
382
+ if len(catSorted) > 0:
383
+ currID, currTime = catSorted[0]
384
+ for sp, timeSlot in catSorted[1:]:
385
+ overlapTime = checkForOverlap(currTime,timeSlot)
386
+ if overlapTime is None:
387
+ newCategory.append((currID,currTime))
388
+ currID = sp
389
+ currTime = timeSlot
390
+ else:
391
+ currID = currID + "+" + sp
392
+ currTime[1] = max(currTime[1],timeSlot[1])
393
+ if currTime is not None:
394
+ newCategory.append((currID,currTime))
395
+ cleanCategories.append(newCategory)
396
+ return cleanCategories,extraCategories
397
+
398
+ def calcSpeakingTypes(myAnnotation,maxTime):
399
+ noVoice = [[0,maxTime]]
400
+ oneVoice = []
401
+ multiVoice = []
402
+ for speaker in myAnnotation.labels():
403
+ timesToProcess = []
404
+ for timeSegment in myAnnotation.subset([speaker]).itersegments():
405
+ timesToProcess.append((speaker,timeSegment))
406
+ while len(timesToProcess) > 0:
407
+ currID, currSegment = timesToProcess[0]
408
+ timesToProcess.remove(timesToProcess[0])
409
+ resetCheck = False
410
+ # Check in multi
411
+ for compareID,timeSegment in multiVoice:
412
+ overlapTime = checkForOverlap(currSegment,timeSegment)
413
+ if overlapTime is None:
414
+ continue
415
+ else:
416
+ compareID.append(currID)
417
+ newTimes = removeOverlap(currSegment,timeSegment)
418
+ for i in range(len(newTimes)):
419
+ newTimes[i] = (currID,newTimes[i])
420
+ timesToProcess += newTimes
421
+ resetCheck = True
422
+ break
423
+ if resetCheck:
424
+ continue
425
+ # Check in one voice
426
+ for timeSlot in oneVoice:
427
+ tID = timeSlot[0]
428
+ tSegment = timeSlot[1]
429
+ overlapTime = checkForOverlap(currSegment,tSegment)
430
+ if overlapTime is None:
431
+ continue
432
+ else:
433
+ oneVoice.remove(timeSlot)
434
+ # Add back non overlap
435
+ newTimes = removeOverlap(tSegment,currSegment)
436
+ for i in range(len(newTimes)):
437
+ newTimes[i] = (tID,newTimes[i])
438
+ oneVoice += newTimes
439
+ # Add overlap time to multivoice
440
+ multiVoice.append(([tID,currID],overlapTime))
441
+ # Add new times back to process
442
+ newTimes = removeOverlap(currSegment,tSegment)
443
+ for i in range(len(newTimes)):
444
+ newTimes[i] = (currID,newTimes[i])
445
+ timesToProcess += newTimes
446
+ resetCheck = True
447
+ break
448
+ if resetCheck:
449
+ continue
450
+ # Add to one voice
451
+ oneVoice.append((currID,currSegment))
452
+ for _,timeSlot in multiVoice:
453
+ copyOfNo = copy.deepcopy(noVoice)
454
+ for emptySlot in noVoice:
455
+ if checkForOverlap(timeSlot,emptySlot) is None:
456
+ continue
457
+ else:
458
+ copyOfNo.remove(emptySlot)
459
+ copyOfNo += removeOverlap(emptySlot,timeSlot)
460
+ noVoice = copyOfNo
461
+ for _,timeSlot in oneVoice:
462
+ copyOfNo = copy.deepcopy(noVoice)
463
+ for emptySlot in noVoice:
464
+ if checkForOverlap(timeSlot,emptySlot) is None:
465
+ continue
466
+ else:
467
+ copyOfNo.remove(emptySlot)
468
+ copyOfNo += removeOverlap(emptySlot,timeSlot)
469
+ noVoice = copyOfNo
470
+ return noVoice, oneVoice, multiVoice
471
+
472
+ def timeToString(timeInSeconds):
473
+ if isinstance(timeInSeconds,list):
474
+ return [timeToString(t) for t in timeInSeconds]
475
+ else:
476
+ h = int(timeInSeconds//3600)
477
+ m = int(timeInSeconds%3600//60)
478
+ s = timeInSeconds%60
479
+ return f'{h:02d}::{m:02d}::{s:02.2f}'