@@ -346,6 +346,19 @@ def upload_requested_slice(slice_index):
346
346
slice = img_array_to_uri (self ._slice (slice_index ))
347
347
return {"index" : slice_index , "slice" : slice }
348
348
349
+ def _clientside_callback (self , code , * args ):
350
+ """Helper function to define a clientside callback."""
351
+
352
+ slicer_state = """
353
+ if (!window._slicer_{{ID}}) window._slicer_{{ID}} = {};
354
+ let slicer_state = window._slicer_{{ID}};
355
+ """ .replace (
356
+ "{{ID}}" , self ._context_id
357
+ )
358
+ code = code .replace ("let slicer_state;" , slicer_state )
359
+
360
+ return self ._app .clientside_callback (code , * args )
361
+
349
362
def _create_client_callbacks (self ):
350
363
"""Create the callbacks that run client-side."""
351
364
@@ -363,12 +376,10 @@ def _create_client_callbacks(self):
363
376
# /
364
377
# pos (external)
365
378
366
- app = self ._app
367
-
368
379
# ----------------------------------------------------------------------
369
380
# Callback to trigger fellow slicers to go to a specific position on click.
370
381
371
- app . clientside_callback (
382
+ self . _clientside_callback (
372
383
"""
373
384
function update_setpos_from_click(data, index, info) {
374
385
if (data && data.points && data.points.length) {
@@ -389,7 +400,7 @@ def _create_client_callbacks(self):
389
400
# ----------------------------------------------------------------------
390
401
# Callback to update slider based on external setpos signals.
391
402
392
- app . clientside_callback (
403
+ self . _clientside_callback (
393
404
"""
394
405
function update_slider_value(positions, cur_index, info) {
395
406
for (let trigger of dash_clientside.callback_context.triggered) {
@@ -420,11 +431,11 @@ def _create_client_callbacks(self):
420
431
# ----------------------------------------------------------------------
421
432
# Callback to rate-limit the index (using a timer/interval).
422
433
423
- app . clientside_callback (
434
+ self . _clientside_callback (
424
435
"""
425
436
function update_index_by_rate_limiting_the_slider_value(index, n_intervals, interval) {
426
- if (!window._slicer_{{ID}}) window._slicer_{{ID}} = {};
427
- let slicer_info = window._slicer_{{ID}};
437
+
438
+ let slicer_state; // filled in
428
439
let now = window.performance.now();
429
440
430
441
// Get whether the slider was moved
@@ -438,10 +449,10 @@ def _create_client_callbacks(self):
438
449
let disable_timer = false;
439
450
440
451
// If the slider moved, remember the time when this happened
441
- slicer_info .new_time = slicer_info .new_time || 0;
452
+ slicer_state .new_time = slicer_state .new_time || 0;
442
453
443
454
if (slider_was_moved) {
444
- slicer_info .new_time = now;
455
+ slicer_state .new_time = now;
445
456
} else if (!n_intervals) {
446
457
disable_timer = true; // start disabled
447
458
}
@@ -451,28 +462,20 @@ def _create_client_callbacks(self):
451
462
// changing. The former makes the indicators come along while
452
463
// dragging the slider, the latter is better for a smooth
453
464
// experience, and the interval can be set much lower.
454
- if (index != slicer_info .req_index) {
455
- if (now - slicer_info .new_time >= interval * 2) {
456
- req_index = slicer_info .req_index = index;
465
+ if (index != slicer_state .req_index) {
466
+ if (now - slicer_state .new_time >= interval * 2) {
467
+ req_index = slicer_state .req_index = index;
457
468
disable_timer = true;
458
-
459
- // Get cache
460
- // todo: _index is now our rate-limited index, so we need to always apply
461
- //if (!window.slicecache_for_{{ID}}) { window.slicecache_for_{{ID}} = {}; }
462
- //let slice_cache = window.slicecache_for_{{ID}};
463
- //if (slice_cache[req_index]) {
464
- // req_index = dash_clientside.no_update;
465
- //} else {
466
- console.log('requesting slice ' + req_index);
467
- //}
469
+ console.log('requesting slice ' + req_index);
470
+ // If we want to re-enable the cache, we'd need an extra store
471
+ // that we set here too, and which we do *not* set if req_index
472
+ // is already in thec cache.
468
473
}
469
474
}
470
475
471
476
return [req_index, disable_timer];
472
477
}
473
- """ .replace (
474
- "{{ID}}" , self ._context_id
475
- ),
478
+ """ ,
476
479
[
477
480
Output (self ._index .id , "data" ),
478
481
Output (self ._timer .id , "disabled" ),
@@ -484,14 +487,12 @@ def _create_client_callbacks(self):
484
487
# ----------------------------------------------------------------------
485
488
# Callback to update position (in scene coordinates) from the index.
486
489
487
- app . clientside_callback (
490
+ self . _clientside_callback (
488
491
"""
489
492
function update_pos(index, info) {
490
493
return info.origin[2] + index * info.spacing[2];
491
494
}
492
- """ .replace (
493
- "{{ID}}" , self ._context_id
494
- ),
495
+ """ ,
495
496
Output (self ._pos .id , "data" ),
496
497
[Input (self ._index .id , "data" )],
497
498
[State (self ._info .id , "data" )],
@@ -500,19 +501,21 @@ def _create_client_callbacks(self):
500
501
# ----------------------------------------------------------------------
501
502
# Callback that creates a list of image traces (slice and overlay).
502
503
503
- app . clientside_callback (
504
+ self . _clientside_callback (
504
505
"""
505
506
function update_image_traces(index, server_data, overlays, lowres, info, current_traces) {
506
507
508
+
507
509
// Add data to the cache if the data is indeed new
508
- if (!window.slicecache_for_{{ID}}) { window.slicecache_for_{{ID}} = {}; }
509
- let slice_cache = window.slicecache_for_{{ID}};
510
- for (let trigger of dash_clientside.callback_context.triggered) {
511
- if (trigger.prop_id.indexOf('server-data') >= 0) {
512
- slice_cache[server_data.index] = server_data;
513
- break;
514
- }
515
- }
510
+ let slicer_state; // filled in
511
+ slicer_state.cache = slicer_state.cache || {};
512
+ // Cache is disabled for now ...
513
+ //for (let trigger of dash_clientside.callback_context.triggered) {
514
+ // if (trigger.prop_id.indexOf('server-data') >= 0) {
515
+ // slicer_state.cache[server_data.index] = server_data;
516
+ // break;
517
+ // }
518
+ //}
516
519
517
520
// Prepare traces
518
521
let slice_trace = {
@@ -530,9 +533,11 @@ def _create_client_callbacks(self):
530
533
let new_traces = [slice_trace, overlay_trace];
531
534
532
535
// Depending on the state of the cache, use full data, or use lowres and request slice
533
- if (slice_cache [index]) {
534
- let cached = slice_cache [index];
536
+ if (slicer_state.cache [index]) {
537
+ let cached = slicer_state.cache [index];
535
538
slice_trace.source = cached.slice;
539
+ } else if (index == server_data.index) {
540
+ slice_trace.source = server_data.slice;
536
541
} else {
537
542
slice_trace.source = lowres[index];
538
543
// Scale the image to take the exact same space as the full-res
@@ -574,7 +579,7 @@ def _create_client_callbacks(self):
574
579
# * corresponding to the same volume data
575
580
# * match any of the selected axii
576
581
577
- app . clientside_callback (
582
+ self . _clientside_callback (
578
583
"""
579
584
function update_indicator_traces(positions1, positions2, info, current) {
580
585
let x0 = info.origin[0], y0 = info.origin[1];
@@ -626,7 +631,7 @@ def _create_client_callbacks(self):
626
631
# ----------------------------------------------------------------------
627
632
# Callback that composes a figure from multiple trace sources.
628
633
629
- app . clientside_callback (
634
+ self . _clientside_callback (
630
635
"""
631
636
function update_figure(img_traces, indicators, ori_figure) {
632
637
0 commit comments