5
5
drawStateTransitionStep,
6
6
drawStateMachineHistory,
7
7
animateStateMachineHistoryByTime,
8
- animateStateMachineHistoryByTimeCompound
8
+ animateStateMachineHistoryByTimeCompound,
9
+ animateStateMachineHistoryIntervalCompound
9
10
10
11
11
12
"""
@@ -287,3 +288,138 @@ function animateStateMachineHistoryByTimeCompound(hists::Dict{Symbol, Vector{Tup
287
288
end
288
289
289
290
end
291
+
292
+ # count the total number of transitions contained in hists
293
+ function getTotalNumberSteps ( hists:: Dict{Symbol, Vector{Tuple{DateTime, Int, <: Function, T}}} ) where T
294
+ totSteps = 0
295
+ for (whId, hist) in hists, hi in hist
296
+ totSteps += 1
297
+ end
298
+ return totSteps
299
+ end
300
+
301
+ # point to the start step among all history steps
302
+ function getFirstStepHist ( hists:: Dict{Symbol, Vector{Tuple{DateTime, Int, <: Function, T}}} ) where T
303
+ startTime = now ()
304
+ maxTime = DateTime (0 )
305
+ # NOTE, this whichId=:null is super important to ensure rendering loop can exit properly
306
+ whichId, whichStep = :null , 0
307
+ for (whId, hist) in hists, (st,hi) in enumerate (hist)
308
+ if hi[1 ] < startTime
309
+ # new starting point indicator
310
+ whichId = whId
311
+ whichStep = st
312
+ startTime = hi[1 ]
313
+ end
314
+ if maxTime < hi[1 ]
315
+ maxTime = hi[1 ]
316
+ end
317
+ end
318
+ return whichId, whichStep, startTime, maxTime
319
+ end
320
+
321
+ # give the next step, closest in time and that has not previously been added to `prevList`.
322
+ # Also update prevList
323
+ function getNextStepHist! (hists,
324
+ intuple:: Tuple{Symbol, Int, DateTime} ,
325
+ maxTime:: DateTime ,
326
+ prevList:: Dict{Symbol, Vector{Int}} )
327
+ #
328
+ oldId, oldStep, oldT = intuple
329
+
330
+ whichId, whichStep, newT = :null , 0 , maxTime
331
+ for (whId, hist) in hists, (st,hi) in enumerate (hist)
332
+ # make sure all options are populated in previous list tracker
333
+ if ! haskey (prevList, whId) prevList[whId] = Int[]; end
334
+ if oldT < hi[1 ] && Millisecond (0 ) <= (hi[1 ] - oldT) < (newT- oldT) &&
335
+ ! (st in prevList[whId]) # must be a different step than before
336
+ # new closest next step
337
+ whichId = whId
338
+ whichStep = st
339
+ newT = hi[1 ]
340
+ end
341
+ end
342
+
343
+ # register this step has previously been taken
344
+ if ! haskey (prevList, whichId)
345
+ prevList[whichId] = Int[]
346
+ end
347
+ push! (prevList[whichId], whichStep)
348
+
349
+ return whichId, whichStep, newT
350
+ end
351
+
352
+
353
+ # for slower movies, use a slower fps
354
+ # run(`ffmpeg -r 10 -i /tmp/caesar/csmCompound/csm_%d.png -c:v libtheora -vf fps=5 -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -q 10 /tmp/caesar/csmCompound/out.ogv`)
355
+ # @async run(`totem /tmp/caesar/csmCompound/out.ogv`)
356
+ function animateStateMachineHistoryIntervalCompound (hists:: Dict{Symbol, Vector{Tuple{DateTime, Int, <: Function, T}}} ;
357
+ interval:: Int = 2 , # frames
358
+ # frames::Int=100,
359
+ folder= " animatestate" ,
360
+ title:: String = " " ,
361
+ show:: Bool = false ,
362
+ clearstale:: Bool = true ,
363
+ rmfirst:: Bool = true ) where T
364
+ #
365
+ # Dict{Symbol, Vector{Symbol}}
366
+ stateVisits = Dict {Symbol, Vector{Symbol}} ()
367
+ allStates = Vector {Symbol} ()
368
+ for (csym,hist) in hists
369
+ stateVisits, allStates = histStateMachineTransitions (hist,allStates= allStates, stateVisits= stateVisits )
370
+ end
371
+
372
+ #
373
+ vg, lookup = histGraphStateMachineTransitions (stateVisits, allStates)
374
+
375
+ # total draw time and step initialization
376
+ # totT = stopT - startT
377
+ # totT = Millisecond(round(Int, 1.05*totT.value))
378
+ # histsteps = ones(Int, length(hists))
379
+
380
+ # clear any stale state
381
+ clearstale ? clearVisGraphAttributes! (vg) : nothing
382
+
383
+ totSteps = getTotalNumberSteps (hists)
384
+ whId, fsmStep, aniT, maxTime = getFirstStepHist (hists)
385
+ prevList = Dict {Symbol, Vector{Int}} ()
386
+ latestList = Dict {Symbol, Int} (whId => fsmStep)
387
+
388
+ frameCount = 0
389
+ # loop across time
390
+ @showprogress " exporting state machine images, $title " for stepCount in 1 : totSteps
391
+ # which step among the hist fsms is next
392
+ if 1 < stepCount
393
+ # skip first would-be repeat
394
+ whId, fsmStep, aniT = getNextStepHist! (hists, (whId, fsmStep, aniT), maxTime, prevList)
395
+ latestList[whId] = fsmStep
396
+ end
397
+
398
+ # loop over all state "known" machines
399
+ for (csym, lstep) in latestList
400
+ # modify vg for each history
401
+ csym == :null ? break : nothing
402
+ lbl = getStateLabel (hists[csym][lstep][3 ])
403
+ vertid = lookup[lbl]
404
+ setVisGraphOnState! (vg, vertid, appendxlabel= string (csym)* " ," )
405
+ end
406
+
407
+ # and draw as many frames for that setup
408
+ for itr in 1 : interval
409
+ # increment frame counter
410
+ frameCount += 1
411
+ # finally render one frame
412
+ renderStateMachineFrame (vg,
413
+ frameCount,
414
+ title= title,
415
+ show= false ,
416
+ folder= folder,
417
+ timest= string (split (string (aniT),' ' )[1 ]),
418
+ rmfirst= false )
419
+ #
420
+ end
421
+ # clear current frame in prep for the next interval
422
+ clearVisGraphAttributes! (vg)
423
+ end
424
+
425
+ end
0 commit comments