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