Skip to content

Commit 8d50e57

Browse files
authored
geotiff example (#1356)
1 parent 52e76db commit 8d50e57

File tree

9 files changed

+202
-1
lines changed

9 files changed

+202
-1
lines changed

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
### Charts
3535

36+
* [`geotiff`](https://observablehq.observablehq.cloud/framework-example-geotiff/) - Parsing GeoTIFF with geotiff.js, then visualizing with Observable Plot
3637
* [`netcdf`](https://observablehq.observablehq.cloud/framework-example-netcdf/) - Parsing NetCDF with `netcdfjs`, then visualizing with Observable Plot
3738
* [`vega-dark`](https://observablehq.observablehq.cloud/framework-example-vega-dark/) - Responsive dark mode in Vega-Lite
3839
* [`vega-responsive`](https://observablehq.observablehq.cloud/framework-example-vega-responsive/) - Responsive width in Vega-Lite using ResizeObserver

examples/geotiff/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.DS_Store
2+
/dist/
3+
node_modules/
4+
yarn-error.log

examples/geotiff/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Observable Framework
2+
3+
This is an [Observable Framework](https://observablehq.com/framework) project. To start the local preview server, run:
4+
5+
```
6+
yarn dev
7+
```
8+
9+
Then visit <http://localhost:3000> to preview your project.
10+
11+
For more, see <https://observablehq.com/framework/getting-started>.
12+
13+
## Project structure
14+
15+
A typical Framework project looks like this:
16+
17+
```ini
18+
.
19+
├─ src
20+
│ ├─ components
21+
│ │ └─ timeline.js # an importable module
22+
│ ├─ data
23+
│ │ ├─ launches.csv.js # a data loader
24+
│ │ └─ events.json # a static data file
25+
│ ├─ example-dashboard.md # a page
26+
│ ├─ example-report.md # another page
27+
│ └─ index.md # the home page
28+
├─ .gitignore
29+
├─ observablehq.config.js # the project config file
30+
├─ package.json
31+
└─ README.md
32+
```
33+
34+
**`src`** - This is the “source root” — where your source files live. Pages go here. Each page is a Markdown file. Observable Framework uses [file-based routing](https://observablehq.com/framework/routing), which means that the name of the file controls where the page is served. You can create as many pages as you like. Use folders to organize your pages.
35+
36+
**`src/index.md`** - This is the home page for your site. You can have as many additional pages as you’d like, but you should always have a home page, too.
37+
38+
**`src/data`** - You can put [data loaders](https://observablehq.com/framework/loaders) or static data files anywhere in your source root, but we recommend putting them here.
39+
40+
**`src/components`** - You can put shared [JavaScript modules](https://observablehq.com/framework/javascript/imports) anywhere in your source root, but we recommend putting them here. This helps you pull code out of Markdown files and into JavaScript modules, making it easier to reuse code across pages, write tests and run linters, and even share code with vanilla web applications.
41+
42+
**`observablehq.config.js`** - This is the [project configuration](https://observablehq.com/framework/config) file, such as the pages and sections in the sidebar navigation, and the project’s title.
43+
44+
## Command reference
45+
46+
| Command | Description |
47+
| ----------------- | -------------------------------------------------------- |
48+
| `yarn install` | Install or reinstall dependencies |
49+
| `yarn dev` | Start local preview server |
50+
| `yarn build` | Build your static site, generating `./dist` |
51+
| `yarn deploy` | Deploy your project to Observable |
52+
| `yarn clean` | Clear the local data loader cache |
53+
| `yarn observable` | Run commands like `observable help` |
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
export default {
2+
root: "src",
3+
4+
// Shared Observable example configuration; feel free to remove this.
5+
title: "Observable Framework",
6+
pager: false,
7+
toc: false,
8+
sidebar: false,
9+
head:
10+
process.env.CI &&
11+
`<script type="module" async src="https://events.observablehq.com/client.js?pageLoad"></script>
12+
<script async src="https://www.googletagmanager.com/gtag/js?id=G-9B88TP6PKQ"></script>
13+
<script>window.dataLayer=window.dataLayer||[];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js',new Date());\ngtag('config','G-9B88TP6PKQ');</script>`,
14+
header: `<style>
15+
16+
#observablehq-header a[href] {
17+
color: inherit;
18+
}
19+
20+
#observablehq-header a[target="_blank"] {
21+
display: flex;
22+
align-items: center;
23+
gap: 0.25rem;
24+
text-decoration: none;
25+
}
26+
27+
#observablehq-header a[target="_blank"]:hover span {
28+
text-decoration: underline;
29+
}
30+
31+
#observablehq-header a[target="_blank"]::after {
32+
content: "\\2197";
33+
}
34+
35+
#observablehq-header a[target="_blank"]:not(:hover, :focus)::after {
36+
color: var(--theme-foreground-muted);
37+
}
38+
39+
@container not (min-width: 640px) {
40+
.hide-if-small {
41+
display: none;
42+
}
43+
}
44+
45+
</style>
46+
<div style="display: flex; align-items: center; gap: 0.5rem; height: 2.2rem; margin: -1.5rem -2rem 2rem -2rem; padding: 0.5rem 2rem; border-bottom: solid 1px var(--theme-foreground-faintest); font: 500 16px var(--sans-serif);">
47+
<a href="https://observablehq.com/" target="_self" rel="" style="display: flex; align-items: center;">
48+
<svg width="22" height="22" viewBox="0 0 21.92930030822754 22.68549919128418" fill="currentColor">
49+
<path d="M10.9646 18.9046C9.95224 18.9046 9.07507 18.6853 8.33313 18.2467C7.59386 17.8098 7.0028 17.1909 6.62722 16.4604C6.22789 15.7003 5.93558 14.8965 5.75735 14.0684C5.56825 13.1704 5.47613 12.2574 5.48232 11.3427C5.48232 10.6185 5.52984 9.92616 5.62578 9.26408C5.7208 8.60284 5.89715 7.93067 6.15391 7.24843C6.41066 6.56618 6.74143 5.97468 7.14438 5.47308C7.56389 4.9592 8.1063 4.54092 8.72969 4.25059C9.38391 3.93719 10.1277 3.78091 10.9646 3.78091C11.977 3.78091 12.8542 4.00021 13.5962 4.43879C14.3354 4.87564 14.9265 5.49454 15.3021 6.22506C15.6986 6.97704 15.9883 7.7744 16.1719 8.61712C16.3547 9.459 16.447 10.3681 16.447 11.3427C16.447 12.067 16.3995 12.7593 16.3035 13.4214C16.2013 14.1088 16.0206 14.7844 15.7644 15.437C15.4994 16.1193 15.1705 16.7108 14.7739 17.2124C14.3774 17.714 13.8529 18.1215 13.1996 18.4349C12.5463 18.7483 11.8016 18.9046 10.9646 18.9046ZM12.8999 13.3447C13.4242 12.8211 13.7159 12.0966 13.7058 11.3427C13.7058 10.5639 13.4436 9.89654 12.92 9.34074C12.3955 8.78495 11.7441 8.50705 10.9646 8.50705C10.1852 8.50705 9.53376 8.78495 9.00928 9.34074C8.49569 9.87018 8.21207 10.5928 8.22348 11.3427C8.22348 12.1216 8.48572 12.7889 9.00928 13.3447C9.53376 13.9005 10.1852 14.1784 10.9646 14.1784C11.7441 14.1784 12.3891 13.9005 12.8999 13.3447ZM10.9646 22.6855C17.0199 22.6855 21.9293 17.6068 21.9293 11.3427C21.9293 5.07871 17.0199 0 10.9646 0C4.90942 0 0 5.07871 0 11.3427C0 17.6068 4.90942 22.6855 10.9646 22.6855Z"></path>
50+
</svg>
51+
</a>
52+
<div style="display: flex; flex-grow: 1; justify-content: space-between; align-items: baseline;">
53+
<a href="https://observablehq.com/framework/" target="_self" rel="">
54+
<span class="hide-if-small">Observable</span> Framework
55+
</a>
56+
<span style="display: flex; align-items: baseline; gap: 0.5rem; font-size: 14px;">
57+
<a target="_blank" href="https://github.com/observablehq/framework/tree/main/examples/geotiff"><span>View source</span></a>
58+
</span>
59+
</div>
60+
</div>`
61+
};

examples/geotiff/package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"type": "module",
3+
"private": true,
4+
"scripts": {
5+
"clean": "rimraf src/.observablehq/cache",
6+
"build": "rimraf dist && observable build",
7+
"dev": "observable preview",
8+
"deploy": "observable deploy",
9+
"observable": "observable"
10+
},
11+
"dependencies": {
12+
"@observablehq/framework": "^1.7.1"
13+
},
14+
"devDependencies": {
15+
"rimraf": "^5.0.5"
16+
},
17+
"engines": {
18+
"node": ">=18"
19+
}
20+
}

examples/geotiff/src/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/.observablehq/cache/

examples/geotiff/src/index.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# GeoTIFF
2+
3+
This example demonstrates how to read a GeoTIFF file using [geotiff.js](https://geotiffjs.github.io/) and then visualize it with Observable Plot’s [raster mark](https://observablehq.com/plot/marks/raster). The data represents global surface temperatures (from an unknown source, by way of [Roger Veciana](https://gist.github.com/rveciana/de0bd586eafd7fcdfe29227ccbdcd511)).
4+
5+
To start, let’s import `fromArrayBuffer` from geotiff.js:
6+
7+
```js echo
8+
import {fromArrayBuffer} from "npm:geotiff";
9+
```
10+
11+
Then we’ll declare a `FileAttachment` for the GeoTIFF file and load it as an `ArrayBuffer` (since it’s binary). `FileAttachment.arrayBuffer` returns a `Promise`, which we chain with the `fromArrayBuffer` constructor.
12+
13+
```js echo
14+
const sfctmp = FileAttachment("sfctmp.tiff").arrayBuffer().then(fromArrayBuffer);
15+
```
16+
17+
Now `sfctmp` is a promise to a `GeoTIFF`. (Promises are implicitly awaited across code blocks, so we don’t need to explicitly `await` below.) This object allows us to read the contents and metadata of the parsed GeoTIFF file.
18+
19+
```js echo
20+
const image = await sfctmp.getImage();
21+
const [values] = await image.readRasters();
22+
```
23+
24+
Now let’s visualize surface temperature using a raster plot. Since the values are represented as a one-dimensional array of numbers, we can use them as the raster mark’s data; but we also need to specify the `width` and `height` of the grid.
25+
26+
```js echo
27+
Plot.plot({
28+
width,
29+
aspectRatio: 1, // preserve the aspect ratio of the data
30+
color: {label: "SFCTMP", legend: true},
31+
y: {reverse: true},
32+
marks: [
33+
Plot.raster(values, {width: image.getWidth(), height: image.getHeight()})
34+
]
35+
})
36+
```
37+
38+
(I’m not sure what the temperature units are here… it might be degrees Fahrenheit?)
39+
40+
We can use [Plot’s projection system](https://observablehq.com/plot/features/projections) to apply a suitable global projection. Below we use the Equal Earth projection, an equal-area projection preserving the relative size of areas. The `x1`, `y1`, `x2`, and `y2` options specify the bounds of the grid in geographic coordinates, while the `clip` option clips the data to the globe.
41+
42+
```js echo
43+
Plot.plot({
44+
width,
45+
projection: "equal-earth",
46+
color: {label: "SFCTMP", legend: true},
47+
marks: [
48+
Plot.raster(values, {
49+
width: image.getWidth(),
50+
height: image.getHeight(),
51+
x1: 0,
52+
y1: 90,
53+
x2: 360,
54+
y2: -90,
55+
interpolate: "barycentric",
56+
clip: "sphere"
57+
}),
58+
Plot.graticule({stroke: "black"})
59+
]
60+
})
61+
```

examples/geotiff/src/sfctmp.tiff

1.99 MB
Binary file not shown.

examples/netcdf/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# NetCDF
22

3-
This example demonstrates how to read a NetCDF file using [`netcdfjs`](https://github.com/cheminfo/netcdfjs) and visualize it with Observable Plot’s [raster mark](https://observablehq.com/plot/marks/raster). The data is from [NOAA’s Pacific Marine Environmental Laboratory](https://ferret.pmel.noaa.gov/Ferret/documentation/users-guide/introduction/SAMPLE-DATA-SETS), by way of [Patrick Brockmann](https://github.com/PBrockmann/D3_netcdfjs), and represents global marine winds for the period 1982–1990.
3+
This example demonstrates how to read a NetCDF file using [`netcdfjs`](https://github.com/cheminfo/netcdfjs) and then visualize it with Observable Plot’s [raster mark](https://observablehq.com/plot/marks/raster). The data is from [NOAA’s Pacific Marine Environmental Laboratory](https://ferret.pmel.noaa.gov/Ferret/documentation/users-guide/introduction/SAMPLE-DATA-SETS), by way of [Patrick Brockmann](https://github.com/PBrockmann/D3_netcdfjs), and represents global marine winds for the period 1982–1990.
44

55
To start, let’s import `NetCDFReader` from `netcdfjs`:
66

0 commit comments

Comments
 (0)