celldega 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/js/widget.js DELETED
@@ -1,701 +0,0 @@
1
- import "./widget.css";
2
-
3
- import { Deck, ScatterplotLayer, TileLayer, BitmapLayer, OrthographicView, PathLayer } from 'deck.gl';
4
- import * as arrow from "apache-arrow";
5
- // import { load } from 'https://esm.sh/@loaders.gl/core@4.1.1'; // 4.1.2 is not working???
6
- import { load } from '@loaders.gl/core';
7
- import * as mathGl from 'math.gl';
8
-
9
- // local file from unpkg
10
- console.log('using local version of unpng parquet-wasm')
11
- import * as pq from "./vendor/parquet-wasm/parquet-wasm_unpkg.js";
12
-
13
-
14
- export async function render({ model, el }) {
15
-
16
- const cache_trx = new Map();
17
- const cache_cell = new Map();
18
- const MAX_CACHE_SIZE = 20; // Example size
19
-
20
- // functions
21
- ////////////////
22
-
23
- // console.log('function definitions')
24
-
25
- const grab_trx_tiles_in_view = async (tiles_in_view) => {
26
-
27
- const tile_trx_urls = tiles_in_view.map(tile => {
28
- return `${base_url}/real_transcript_tiles_mosaic/transcripts_tile_${tile.tileX}_${tile.tileY}.parquet`;
29
- });
30
-
31
- var tile_trx_tables = await fetch_all_tables_v2(cache_trx, tile_trx_urls)
32
- var trx_arrow_table = concatenate_arrow_tables(tile_trx_tables)
33
- trx_names_array = trx_arrow_table.getChild("name").toArray();
34
- var trx_scatter_data = get_scatter_data(trx_arrow_table)
35
-
36
- return trx_scatter_data
37
- }
38
-
39
- const grab_cell_tiles_in_view = async (tiles_in_view) => {
40
-
41
- const tile_cell_urls = tiles_in_view.map(tile => {
42
- return `${base_url}/cell_segmentation_v2/cell_tile_${tile.tileX}_${tile.tileY}.parquet`;
43
- });
44
-
45
- var tile_cell_tables = await fetch_all_tables_v2(cache_cell, tile_cell_urls)
46
-
47
- var polygon_datas = tile_cell_tables.map(x => get_data(x))
48
-
49
- // this can be used directly in the SolidPolygonLayer
50
- var polygon_data = concatenate_polygon_data(polygon_datas);
51
-
52
- var polygonPathsConcat = extractPolygonPaths(polygon_data)
53
-
54
- return polygonPathsConcat
55
- }
56
-
57
- const calc_viewport = async ({ height, width, zoom, target }) => {
58
-
59
- const zoomFactor = Math.pow(2, zoom);
60
- const [targetX, targetY] = target;
61
- const halfWidthZoomed = width / (2 * zoomFactor);
62
- const halfHeightZoomed = height / (2 * zoomFactor);
63
-
64
- const minX = targetX - halfWidthZoomed;
65
- const maxX = targetX + halfWidthZoomed;
66
- const minY = targetY - halfHeightZoomed;
67
- const maxY = targetY + halfHeightZoomed;
68
-
69
- const tiles_in_view = visibleTiles(minX, maxX, minY, maxY, tileSize);
70
-
71
- var num_tiles_to_viz = tiles_in_view.length
72
-
73
- if (num_tiles_to_viz < max_tiles_to_view) {
74
-
75
- // trx tiles
76
- ////////////////////////////////
77
- const trx_scatter_data = grab_trx_tiles_in_view(tiles_in_view)
78
-
79
- const trx_layer_new = new ScatterplotLayer({
80
- // Re-use existing layer props
81
- ...trx_layer.props,
82
- data: trx_scatter_data,
83
- });
84
-
85
- // cell tiles
86
- ////////////////////////////////
87
-
88
- const polygonPathsConcat = grab_cell_tiles_in_view(tiles_in_view)
89
-
90
- const polygon_layer_new = new PathLayer({
91
- // Re-use existing layer props
92
- ...polygon_layer.props,
93
- data: polygonPathsConcat,
94
- });
95
-
96
- // console.log('cache_trx size', cache_trx.size)
97
-
98
- // update layer
99
- deck.setProps({
100
- // layers: [tile_layer, polygon_layer_new, cell_layer, trx_layer_new]
101
- layers: [tile_layer_2, tile_layer, polygon_layer_new, cell_layer, trx_layer_new]
102
- // layers: [tile_layer_2, tile_layer] // , trx_layer_new]
103
- });
104
-
105
- } else {
106
- deck.setProps({
107
- // layers: [tile_layer, cell_layer]
108
- layers: [tile_layer_2, tile_layer, cell_layer]
109
- // layers: [tile_layer_2, tile_layer]
110
- });
111
- }
112
- };
113
-
114
- const arrayBufferToArrowTable = (arrayBuffer) => {
115
-
116
- // console.log('arrayBufferToArrowTable: starting')
117
- const arr = new Uint8Array(arrayBuffer);
118
-
119
- // console.log('arr', arr.byteLength)
120
-
121
- // console.log('about to use readParquet')
122
- // console.log(pq.readParquet)
123
- // console.log(pq.readParquet())
124
- // console.log('***********************************')
125
- const arrowIPC = pq.readParquet(arr);
126
- // console.log('readParquet done!!!')
127
- // console.log(arrowIPC)
128
-
129
- return arrow.tableFromIPC(arrowIPC);
130
- };
131
-
132
- const fetch_all_tables_v2 = async (cache_trx, urls) => {
133
- return Promise.all(urls.map(url => get_arrow_table_and_cache(cache_trx, url)));
134
- };
135
-
136
-
137
- // Function to access (fetch or retrieve from cache) and cache the table
138
- const get_arrow_table_and_cache = async (cache, url) => {
139
- let data;
140
-
141
- if (cache.has(url)) {
142
- // console.log('Using cached data for:', url);
143
- // Accessing the item, so move it to the end to mark it as most recently used
144
- data = cache.get(url);
145
- cache.delete(url); // Remove the item
146
- cache.set(url, data); // Re-insert to update its position
147
- } else {
148
- // Item is not in the cache, fetch it
149
- const response = await fetch(url, options.fetch);
150
- const arrayBuffer = await response.arrayBuffer();
151
- data = arrayBufferToArrowTable(arrayBuffer);
152
-
153
- // Check if the cache is exceeding the size limit before adding the new item
154
- if (cache.size >= MAX_CACHE_SIZE) {
155
- // Evict the least recently used item, which is the first item in the Map
156
- const leastRecentlyUsedKey = cache.keys().next().value;
157
- cache.delete(leastRecentlyUsedKey);
158
- // console.log(`Evicted ${leastRecentlyUsedKey}`);
159
- }
160
-
161
- // Add the new item to the cache
162
- cache.set(url, data);
163
- }
164
-
165
- // console.log(`Cache size: ${cache.size}`);
166
- return data;
167
- };
168
-
169
- const debounce = (func, wait, immediate) => {
170
- let timeout;
171
- return (...args) => {
172
- const context = this;
173
- const later = () => {
174
- timeout = null;
175
- if (!immediate) func.apply(context, args);
176
- };
177
- const callNow = immediate && !timeout;
178
- clearTimeout(timeout);
179
- timeout = setTimeout(later, wait);
180
- if (callNow) func.apply(context, args);
181
- };
182
- };
183
-
184
- const visibleTiles = (minX, maxX, minY, maxY, tileSize) => {
185
- const startTileX = Math.floor(minX / tileSize);
186
- const endTileX = Math.floor(maxX / tileSize);
187
- const startTileY = Math.floor(minY / tileSize);
188
- const endTileY = Math.floor(maxY / tileSize);
189
-
190
- const tiles = [];
191
- for (let x = startTileX; x <= endTileX; x++) {
192
- for (let y = startTileY; y <= endTileY; y++) {
193
- tiles.push({ tileX: x, tileY: y, name: x + '_' + y });
194
- }
195
- }
196
- return tiles;
197
- }
198
-
199
- const concatenate_polygon_data = (dataObjects) => {
200
- // Initialize concatenated data structure
201
- let concatenatedData = {
202
- length: 0,
203
- startIndices: new Int32Array(),
204
- attributes: {
205
- getPolygon: {
206
- value: new Float64Array(),
207
- size: 2 // Assuming 'size' remains constant
208
- }
209
- }
210
- };
211
-
212
- // Iterate over each data object to combine them
213
- dataObjects.forEach((data, index) => {
214
- concatenatedData.length += data.length;
215
-
216
- // Handle startIndices
217
- let lastValue = concatenatedData.attributes.getPolygon.value.length/2;
218
- let adjustedStartIndices = data.startIndices;
219
-
220
- if (index > 0) {
221
- // Adjust startIndices (except for the first data object)
222
- adjustedStartIndices = new Int32Array(data.startIndices.length);
223
- for (let i = 0; i < data.startIndices.length; i++) {
224
- adjustedStartIndices[i] = data.startIndices[i] + lastValue;
225
- }
226
- }
227
-
228
- // Combine startIndices and coordinate values
229
- concatenatedData.startIndices = new Int32Array([...concatenatedData.startIndices, ...adjustedStartIndices.slice(index > 0 ? 1 : 0)]);
230
- concatenatedData.attributes.getPolygon.value = new Float64Array([...concatenatedData.attributes.getPolygon.value, ...data.attributes.getPolygon.value]);
231
- });
232
-
233
- return concatenatedData;
234
- }
235
-
236
- const concatenate_arrow_tables = (tables) => {
237
- if (tables.length === 0) return null; // No tables to concatenate
238
- let baseTable = tables[0]; // Use the first table as the base
239
- for (let i = 1; i < tables.length; i++) { // Start from the second table
240
- baseTable = baseTable.concat(tables[i]); // Concatenate each table to the base table
241
- }
242
- return baseTable;
243
- };
244
-
245
- const extractPolygonPaths = (data) => {
246
- const paths = [];
247
- const { startIndices, attributes } = data;
248
- const coordinates = attributes.getPolygon.value;
249
- const numPolygons = startIndices.length - 1;
250
-
251
- for (let i = 0; i < numPolygons; ++i) {
252
- // Multiply by 2 because each coordinate is a pair of values (x, y)
253
- const startIndex = startIndices[i] * 2;
254
- // The next start index marks the end of the current polygon
255
- const endIndex = startIndices[i + 1] * 2;
256
- const path = [];
257
-
258
- for (let j = startIndex; j < endIndex; j += 2) {
259
- const x = coordinates[j];
260
- const y = coordinates[j + 1];
261
- path.push([x, y]);
262
- }
263
-
264
- paths.push(path);
265
- }
266
-
267
- return paths;
268
- }
269
-
270
- const get_arrow_table = async (url, fetch_options) => {
271
- try {
272
- // console.log('get_arrow_table: starting')
273
- const response = await fetch(url, fetch_options);
274
- // console.log('got response', response)
275
- const arrayBuffer = await response.arrayBuffer();
276
- // console.log('got array buffer', arrayBuffer.byteLength)
277
- const arrowTable = arrayBufferToArrowTable(arrayBuffer)
278
- // console.log('got arrow table', arrowTable.numRows)
279
- return arrowTable
280
- } catch (error) {
281
- console.error("Error loading data:", error);
282
- return [];
283
- }
284
- }
285
-
286
- const get_scatter_data = (arrow_table) => {
287
- try {
288
-
289
- const flatCoordinateArray = arrow_table.getChild("geometry").getChildAt(0).data
290
- .map(x => x.values)
291
- .reduce((acc, val) => {
292
- const combined = new Float64Array(acc.length + val.length);
293
- combined.set(acc);
294
- combined.set(val, acc.length);
295
- return combined;
296
- }, new Float64Array(0));
297
-
298
- const scatter_data = {
299
- length: arrow_table.numRows,
300
- attributes: {
301
- getPosition: { value: flatCoordinateArray, size: 2 },
302
- }
303
- };
304
-
305
- return scatter_data
306
- } catch (error) {
307
- console.error("Error loading data:", error);
308
- return [];
309
- }
310
- };
311
-
312
- const make_tooltip = (info) => {
313
-
314
- // Check if there's a valid index
315
- if (info.index === -1 || !info.layer) return null;
316
-
317
- const dataIndex = info.index;
318
-
319
- let inst_name
320
-
321
- if (info.layer.id === 'cell-layer'){
322
- inst_name = cell_names_array[info.index]
323
-
324
- } else if (info.layer.id === 'trx-layer') {
325
- inst_name = trx_names_array[info.index]
326
- }
327
-
328
- // Make sure to check that `dataItem` and the property you want to display exist
329
- return {
330
- html: `<div>${inst_name}</div?`,
331
- };
332
-
333
- return null;
334
- }
335
-
336
- var get_data = (arrowTable) => {
337
-
338
- var geometryColumn = arrowTable.getChildAt(0)
339
- var polygonIndices = geometryColumn.data[0].valueOffsets
340
- var ringIndices = geometryColumn.getChildAt(0).data[0].valueOffsets
341
- var flatCoordinateVector = geometryColumn.getChildAt(0).getChildAt(0).getChildAt(0)
342
- var flatCoordinateArray = flatCoordinateVector.data[0].values
343
- const resolvedIndices = new Int32Array(polygonIndices.length);
344
-
345
- for (let i = 0; i < resolvedIndices.length; ++i) {
346
- // Perform the lookup into the ringIndices array using the polygonIndices array
347
- resolvedIndices[i] = ringIndices[polygonIndices[i]]
348
- }
349
-
350
- var data = {
351
- // Number of geometries
352
- length: arrowTable.numRows,
353
- // Indices into coordinateArray where each polygon starts
354
- startIndices: resolvedIndices,
355
- // Flat coordinates array
356
- attributes: {
357
- getPolygon: { value: flatCoordinateArray, size: 2 }
358
- }
359
- }
360
- return data
361
- }
362
-
363
- // console.log('getting traitlets')
364
-
365
- // Deck.gl Viz
366
- const token = model.get('token_traitlet')
367
- const ini_x = model.get('ini_x');
368
- const ini_y = model.get('ini_y');
369
- const ini_zoom = model.get('ini_zoom');
370
- const max_image_zoom = model.get('max_image_zoom')
371
- const bounce_time = model.get('bounce_time')
372
- const base_url = model.get('base_url')
373
-
374
- // console.log('getting traitlets done')
375
- // console.log('token', token)
376
-
377
-
378
-
379
- // authorization token for bucket
380
- const options = ({
381
- fetch: {
382
- headers: {
383
- 'Authorization': `Bearer ${token}` // Use the token in the Authorization header
384
- }
385
- }
386
- })
387
-
388
- const image_name = 'cellbound' // 'dapi' // 'brain';
389
-
390
- const dzi_url = `${base_url}/pyramid_images/${image_name}.image.dzi`
391
- const response = await fetch(dzi_url, options.fetch)
392
- const xmlText = await response.text()
393
- const dziXML = new DOMParser().parseFromString(xmlText, 'text/xml')
394
-
395
-
396
- // Image Code
397
- const dimensions = {
398
- height: Number(dziXML.getElementsByTagName('Size')[0].attributes.Height.value),
399
- width: Number(dziXML.getElementsByTagName('Size')[0].attributes.Width.value),
400
- tileSize: Number(dziXML.getElementsByTagName('Image')[0].attributes.TileSize.value)
401
- };
402
-
403
-
404
- // console.log(dimensions)
405
-
406
-
407
-
408
- // class CustomBitmapLayer extends BitmapLayer {
409
- // getShaders() {
410
- // const shaders = super.getShaders();
411
- // shaders.inject = {
412
- // 'fs:DECKGL_FILTER_COLOR': `
413
- // // Convert color to grayscale
414
- // float grayscale = (color.r + color.g + color.b) / 2.5;
415
- // // Map grayscale to blue color, varying alpha with intensity
416
- // color = vec4(0.0, 1.0, 0.0, grayscale); `
417
- // };
418
- // return shaders;
419
- // }
420
- // }
421
-
422
-
423
- class CustomBitmapLayer extends BitmapLayer {
424
- getShaders() {
425
- const shaders = super.getShaders();
426
- // Directly injecting shader code
427
- shaders.inject = {
428
- 'fs:#decl': `uniform vec3 uColor; uniform float uOpacityScale;`,
429
- 'fs:DECKGL_FILTER_COLOR': `
430
- // Convert color to grayscale and apply opacity scale
431
- float grayscale = ((color.r + color.g + color.b) / 3.0) * uOpacityScale;
432
- // Clamp grayscale to valid range
433
- grayscale = clamp(grayscale, 0.0, 1.0);
434
- // Apply custom color and scaled opacity
435
- color = vec4(uColor, grayscale);
436
- `
437
- };
438
- return shaders;
439
- }
440
-
441
- // Properly passing uniforms through updateState lifecycle hook
442
- updateState(params) {
443
- super.updateState(params);
444
- // Extracting custom props
445
- const {props, oldProps} = params;
446
- if (props.color !== oldProps.color || props.opacityScale !== oldProps.opacityScale) {
447
- // Update uniforms when props change
448
- this.setState({
449
- uniforms: {
450
- uColor: props.color.map(c => c / 255), // Normalize RGB to [0, 1] range
451
- uOpacityScale: props.opacityScale
452
- }
453
- });
454
- }
455
- }
456
-
457
- draw(opts) {
458
- // Ensuring custom uniforms are passed to the shader program
459
- const {uniforms} = this.state;
460
- super.draw({
461
- ...opts,
462
- uniforms: {
463
- ...opts.uniforms,
464
- ...uniforms, // Spread in custom uniforms
465
- },
466
- });
467
- }
468
- }
469
-
470
- // console.log('creating tile layer')
471
- const tile_layer = new TileLayer({
472
- tileSize: dimensions.tileSize,
473
- refinementStrategy: 'no-overlap',
474
- minZoom: -7,
475
- maxZoom: 0,
476
- maxCacheSize: 20, // 5
477
- extent: [0, 0, dimensions.width, dimensions.height],
478
- getTileData: ({index}) => {
479
- const {x, y, z} = index;
480
- const full_url = `${base_url}/pyramid_images/${image_name}.image_files/${max_image_zoom + z}/${x}_${y}.jpeg`;
481
-
482
- return load(full_url, options).then(data => {
483
- return data; // Successfully loaded the tile data
484
- }).catch(error => {
485
- console.error('Failed to load tile:', error);
486
- // Handle the error, e.g., return a fallback value or null
487
- return null;
488
- });
489
- },
490
-
491
- renderSubLayers: props => {
492
- const {
493
- bbox: {left, bottom, right, top}
494
- } = props.tile;
495
- const {width, height} = dimensions;
496
-
497
- // return new BitmapLayer(props, {
498
- return new CustomBitmapLayer(props, {
499
- data: null,
500
- image: props.data,
501
- bounds: [
502
- mathGl.clamp(left, 0, width),
503
- mathGl.clamp(bottom, 0, height),
504
- mathGl.clamp(right, 0, width),
505
- mathGl.clamp(top, 0, height)
506
- ],
507
- color: [255, 0, 0], // Custom color
508
- opacityScale: 3.0, // Custom opacity scale
509
- });
510
- },
511
- });
512
-
513
- const image_name_2 = 'dapi'
514
-
515
- // console.log('creating tile layer 2')
516
-
517
- const tile_layer_2 = new TileLayer({
518
- id: 'tile_layer_2',
519
- tileSize: dimensions.tileSize,
520
- refinementStrategy: 'no-overlap',
521
- minZoom: -7,
522
- maxZoom: 0,
523
- maxCacheSize: 20, // 5
524
- extent: [0, 0, dimensions.width, dimensions.height],
525
- getTileData: ({index}) => {
526
- const {x, y, z} = index;
527
- const full_url = `${base_url}/pyramid_images/${image_name_2}.image_files/${max_image_zoom + z}/${x}_${y}.jpeg`;
528
-
529
- return load(full_url, options).then(data => {
530
- return data; // Successfully loaded the tile data
531
- }).catch(error => {
532
- console.error('Failed to load tile:', error);
533
- // Handle the error, e.g., return a fallback value or null
534
- return null;
535
- });
536
- },
537
-
538
- renderSubLayers: props => {
539
- const {
540
- bbox: {left, bottom, right, top}
541
- } = props.tile;
542
- const {width, height} = dimensions;
543
-
544
- return new BitmapLayer(props, {
545
- // return new CustomBitmapLayer(props, {
546
- data: null,
547
- image: props.data,
548
- bounds: [
549
- mathGl.clamp(left, 0, width),
550
- mathGl.clamp(bottom, 0, height),
551
- mathGl.clamp(right, 0, width),
552
- mathGl.clamp(top, 0, height)
553
- ]
554
- });
555
- },
556
- });
557
-
558
- //////////////////////////////////////////
559
- // Cell/Trx Code
560
- //////////////////////////////////////////
561
-
562
- const tileSize = 1000;
563
- const max_tiles_to_view = 15
564
-
565
- const debounced_calc_viewport = debounce(calc_viewport, bounce_time);
566
-
567
- await pq.default();
568
-
569
- // console.log('pq', pq)
570
-
571
-
572
- // console.log('pq pre-default', pq)
573
-
574
- // console.log('pq post-default', pq)
575
-
576
- // console.log('reading cell data as parquet file')
577
- const cell_url = base_url + `/real_cells_mosaic.parquet`;
578
- var cell_arrow_table = await get_arrow_table(cell_url, options.fetch)
579
-
580
- // console.log('finished reading and have cell_arrow_table', cell_arrow_table)
581
-
582
- var cell_scatter_data = get_scatter_data(cell_arrow_table)
583
-
584
- const meta_gene_url = base_url + `/meta_gene.parquet`;
585
- var meta_gene = await get_arrow_table(meta_gene_url, options.fetch)
586
-
587
- let geneNames = [];
588
- let colors = [];
589
-
590
- // Assuming 'cell_arrow_table' is your ArrowTable
591
- // And it has columns named '__index_level_0__' for gene names and 'color' for colors
592
- const geneNameColumn = meta_gene.getChild('__index_level_0__');
593
- const colorColumn = meta_gene.getChild('color');
594
-
595
- if (geneNameColumn && colorColumn) {
596
- // If the table is large, consider a more efficient way to handle data extraction
597
- geneNames = geneNameColumn.toArray();
598
- colors = colorColumn.toArray();
599
- }
600
-
601
- let color_dict = {};
602
-
603
- function hexToRgb(hex) {
604
- // Remove the hash at the start if it's there
605
- hex = hex.replace(/^#/, '');
606
- let r = 0, g = 0, b = 0;
607
- // 3 digits
608
- if (hex.length === 3) {
609
- r = parseInt(hex.charAt(0) + hex.charAt(0), 16);
610
- g = parseInt(hex.charAt(1) + hex.charAt(1), 16);
611
- b = parseInt(hex.charAt(2) + hex.charAt(2), 16);
612
- }
613
- // 6 digits
614
- else if (hex.length === 6) {
615
- r = parseInt(hex.substring(0, 2), 16);
616
- g = parseInt(hex.substring(2, 4), 16);
617
- b = parseInt(hex.substring(4, 6), 16);
618
- }
619
- // return `rgb(${r}, ${g}, ${b})`;
620
- return [r, g, b];
621
- }
622
-
623
- geneNames.forEach((geneName, index) => {
624
- color_dict[geneName] = hexToRgb(colors[index]);
625
- });
626
-
627
- const cell_names_array = cell_arrow_table.getChild("name").toArray();
628
-
629
- let trx_names_array;
630
-
631
- const cell_layer = new ScatterplotLayer({
632
- id: 'cell-layer',
633
- data: cell_scatter_data,
634
- getRadius: 5.0,
635
- pickable: true,
636
- getColor: [0, 0, 255, 240],
637
- onClick: info => {
638
- console.log('click!!')
639
- console.log(info.index)
640
- console.log(cell_names_array[info.index])
641
- },
642
- });
643
-
644
- // mutable transcript data is initialized as an empty array
645
- var trx_data = []
646
-
647
- // console.log('creating trx layer')
648
-
649
- const trx_layer = new ScatterplotLayer({
650
- id: 'trx-layer',
651
- data: trx_data,
652
- getRadius: 0.5,
653
- pickable: true,
654
- // getColor: [200, 0, 0, 150],
655
- getColor: (i, d) => {
656
- var inst_gene = trx_names_array[d.index]
657
- var inst_color = color_dict[inst_gene]
658
- return [inst_color[0], inst_color[1], inst_color[2], 255]
659
- },
660
-
661
- });
662
-
663
- // console.log('creating polygonlayer')
664
- const polygon_layer = new PathLayer({
665
- id: 'path_layer',
666
- data: [],
667
- pickable: true,
668
- widthScale: 3,
669
- widthMinPixels: 1,
670
- getPath: d => d,
671
- getColor: d => [255, 255, 255, 150], // white outline
672
- widthUnits: 'pixels',
673
- })
674
-
675
- // Create and append the visualization.
676
- let root = document.createElement("div");
677
- root.style.height = "800px";
678
- let deck = new Deck({
679
- parent: root,
680
- controller: {doubleClickZoom: false},
681
- initialViewState: {target: [ini_x, ini_y, 0], zoom: ini_zoom},
682
- views: [new OrthographicView({id: 'ortho'})],
683
-
684
- layers: [tile_layer_2, tile_layer, cell_layer],
685
- // layers: [tile_layer, cell_layer],
686
-
687
- onViewStateChange: ({viewState}) => {
688
- debounced_calc_viewport(viewState)
689
- return viewState
690
- },
691
- getTooltip: make_tooltip,
692
- });
693
- el.appendChild(root);
694
-
695
- // console.log('returning deck')
696
-
697
- return () => deck.finalize();
698
-
699
- }
700
-
701
- export default { render };