mikonvergence commited on
Commit
4cb7bec
·
verified ·
1 Parent(s): 8e51157

Sync from GitHub ce8d2eb

Browse files
Files changed (2) hide show
  1. aef.js +19 -10
  2. app.js +1 -0
aef.js CHANGED
@@ -32,15 +32,17 @@ export function aefViews() {
32
  ...Array.from({ length: 64 }, (_, b) => ({ id: `band:${b}`, label: `Band A${String(b).padStart(2, '0')}, 10 m` }))]
33
  }
34
 
35
- /** A geotiff.js client that counts what it reads into `stats`. */
36
  function countingClient(url, stats) {
37
- return {
 
38
  async request({ headers, signal } = {}) {
39
  const r = await fetch(url, { headers, signal }), data = await r.arrayBuffer()
40
- stats.bytes += data.byteLength; stats.requests += 1
41
  return { ok: r.ok, status: r.status, getHeader: name => r.headers.get(name), getData: async () => data }
42
  },
43
  }
 
44
  }
45
 
46
  /** One tile's rows (one per year): {year, epsg, west, north, path}. */
@@ -69,18 +71,25 @@ export async function aefCell(info, sample, stats = newStats()) {
69
  return { epsg, cx, cy, corners, urls: tiles.map(x => `${info.files}${x.path}`) }
70
  }
71
 
72
- const opened = new Map() // COG url -> {tiff, left, top, dy}
 
73
 
74
- /** A COG, opened once (its headers in one 1 MB block), with its origin and row direction. */
75
- function openCog(url, stats) {
76
- if (!opened.has(url)) {
 
 
77
  opened.set(url, (async () => {
78
- const tiff = await fromCustomClient(countingClient(url, stats), { blockSize: 2 ** 20 })
 
79
  const [, , , left, , dy, , top] = (await tiff.getImage(0)).fileDirectory.ModelTransformation // dy > 0: south-up
80
- return { url, tiff, left, top, dy }
81
  })().catch(e => { opened.delete(url); throw e }))
 
82
  }
83
- return opened.get(url)
 
 
84
  }
85
 
86
  /** Every tile's part of the window, joined: one Int8Array per band (NODATA where no tile covers). */
 
32
  ...Array.from({ length: 64 }, (_, b) => ({ id: `band:${b}`, label: `Band A${String(b).padStart(2, '0')}, 10 m` }))]
33
  }
34
 
35
+ /** A geotiff.js client that counts what it reads into `client.stats`: the read under way, set again by openCog. */
36
  function countingClient(url, stats) {
37
+ const client = {
38
+ stats,
39
  async request({ headers, signal } = {}) {
40
  const r = await fetch(url, { headers, signal }), data = await r.arrayBuffer()
41
+ client.stats.bytes += data.byteLength; client.stats.requests += 1
42
  return { ok: r.ok, status: r.status, getHeader: name => r.headers.get(name), getData: async () => data }
43
  },
44
  }
45
+ return client
46
  }
47
 
48
  /** One tile's rows (one per year): {year, epsg, west, north, path}. */
 
71
  return { epsg, cx, cy, corners, urls: tiles.map(x => `${info.files}${x.path}`) }
72
  }
73
 
74
+ const opened = new Map() // COG url -> {tiff, client, left, top, dy}, most recently used last
75
+ const KEEP = 4 // COGs kept open; older ones are dropped with their block cache
76
 
77
+ /** A COG, opened once (its headers in one 1 MB block), with its origin and row direction; its reads are counted
78
+ * into `stats` from now on. At most KEEP stay open, each caching at most 16 blocks (16 MB). */
79
+ async function openCog(url, stats) {
80
+ if (opened.has(url)) { const c = opened.get(url); opened.delete(url); opened.set(url, c) }
81
+ else {
82
  opened.set(url, (async () => {
83
+ const client = countingClient(url, stats)
84
+ const tiff = await fromCustomClient(client, { blockSize: 2 ** 20, cacheSize: 16 })
85
  const [, , , left, , dy, , top] = (await tiff.getImage(0)).fileDirectory.ModelTransformation // dy > 0: south-up
86
+ return { url, tiff, client, left, top, dy }
87
  })().catch(e => { opened.delete(url); throw e }))
88
+ while (opened.size > KEEP) opened.delete(opened.keys().next().value)
89
  }
90
+ const cog = await opened.get(url)
91
+ cog.client.stats = stats
92
+ return cog
93
  }
94
 
95
  /** Every tile's part of the window, joined: one Int8Array per band (NODATA where no tile covers). */
app.js CHANGED
@@ -26,6 +26,7 @@ import { aefCell, aefViews, aefWindow, renderAef } from './aef.js'
26
  import { aefSnippet, downloadAefTiff, downloadAll, downloadBand, downloadImage, downloadViirs, pythonSnippet, viirsSnippet }
27
  from './download.js'
28
  import { cellAt, cellIndex, renderTile } from './tiles.js'
 
29
 
30
  const $ = id => document.getElementById(id)
31
  const COLOURS = { S2L2A: [57, 181, 74], S2L1C: [0, 113, 188], S1RTC: [241, 90, 36], DEM: [180, 140, 90], VIIRS: [126, 87, 194], AEF: [32, 150, 150] }
 
26
  import { aefSnippet, downloadAefTiff, downloadAll, downloadBand, downloadImage, downloadViirs, pythonSnippet, viirsSnippet }
27
  from './download.js'
28
  import { cellAt, cellIndex, renderTile } from './tiles.js'
29
+ import './zstd.js' // also here: on the private Space a module is served only if its referer carries the token, as app.js's does
30
 
31
  const $ = id => document.getElementById(id)
32
  const COLOURS = { S2L2A: [57, 181, 74], S2L1C: [0, 113, 188], S1RTC: [241, 90, 36], DEM: [180, 140, 90], VIIRS: [126, 87, 194], AEF: [32, 150, 150] }