-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9f006d9
Showing
65 changed files
with
9,459 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# tandy-blog | ||
Data blog for [Tandy Center for Ocean Forecasting](https://www.bigelow.org/services/ocean-forecasting/) | ||
|
||
## General guidelines | ||
|
||
Follow this [general guide](https://quarto.org/docs/websites/website-blog.html) New posts should follow [this guide](https://quarto.org/docs/websites/website-blog.html) which explains about making sub-directories in the `post/` directory. | ||
|
||
### Post naming | ||
|
||
Please use the `YYYY-mm-dd_my_post_name` format. | ||
|
||
### To code or not to code? | ||
|
||
To keep things light weight please do **not** include code in your `index.qmd` unless it is pseudo-code. If you want to have some code that will generate output to be inlcuded in you post, then please make a separate un-rendered file (like `script.R` or `script.py`). | ||
|
||
|
||
### An example post directory | ||
|
||
``` | ||
<tandy-blog>/ | ||
posts/ | ||
2024-09-30_my_cool_post/ | ||
index.qmd | ||
script.R | ||
some_small_data.csv.gz | ||
some_image.png | ||
another_image.png | ||
``` | ||
|
||
|
||
## Categories | ||
|
||
Let's be judicious in our use of categories (tags really) to facilitate searching by keywords. | ||
|
||
|
||
## Programming examples vs tutorials | ||
|
||
Tutorials probably belong elsewhere - like [here](https://github.com/BigelowLab/handytandy) - but brief examples are good for here. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"hash": "8e88a5e5941a44008b9d2358243e0acf", | ||
"result": { | ||
"markdown": "---\ntitle: \"Intro to cefi\"\nformat: html\ndescription: \"Introduction to the cefi package\"\nauthor: \"Ben Tupper\"\ndate: \"2024-09-27\"\n---\n\n\nRecently we started investigating the relatively new [CEFI data portal](https://psl.noaa.gov/cefi_portal/) which looks to be a promising source of modeled environmental covariates suitable for ecological forecasting. The services and datasets are not fully implemented yet, but we are looking ahead to when we might be able to roll these into our workflows. To that end we have created the [cefi](https://github.com/BigelowLab/cefi) R package. \n\nCEFI data is served via a [THREDDS](https://docs.unidata.ucar.edu/tds/current/userguide/index.html) and provides dynamic data access using [OPeNDAP](https://www.opendap.org/). We have always leveraged the [ncdf4 R package](https://CRAN.R-project.org/package=ncdf4), but this time we decided to try our hand at Michael Sumner's [tidync R package](https://CRAN.R-project.org/package=tidync). CEFI data elements are arrayed outputs from model runs (historical and forecast); to cast these as geospatial raster data we access a second \"static\" data element (also OPeNDAP). \n\nHere we show a single forecasted data product for the temperature of the sea floor in the Northwest Atlantic region in 1995.\n\n\n::: {.cell}\n\n:::\n\n\nHere we show the temperature of the bottom (C) for one month. Then we extract the values for the complete forecast (12 months) at the location shown using the blue circle. Then we plot the forecasted temperatures at that location. We are still learning the finer details of how to work with this data, but it looks promising.\n\n~[map](tob-map.png)\n~[timeseries](tob-timeseries.png)\n\n", | ||
"supporting": [], | ||
"filters": [ | ||
"rmarkdown/pagebreak.lua" | ||
], | ||
"includes": {}, | ||
"engineDependencies": {}, | ||
"preserve": {}, | ||
"postProcess": true | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
_freeze/posts/post-with-code/index/execute-results/html.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"hash": "642ea65437e65466944030df23b5d2fb", | ||
"result": { | ||
"markdown": "---\ntitle: \"Post With Code\"\nauthor: \"Harlow Malloc\"\ndate: \"2024-09-20\"\ncategories: [news, code, analysis]\nimage: \"image.jpg\"\n---\n\n\nThis is a post with executable code.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n1 + 1\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 2\n```\n:::\n:::\n", | ||
"supporting": [], | ||
"filters": [ | ||
"rmarkdown/pagebreak.lua" | ||
], | ||
"includes": {}, | ||
"engineDependencies": {}, | ||
"preserve": {}, | ||
"postProcess": true | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
const kProgressiveAttr = "data-src"; | ||
let categoriesLoaded = false; | ||
|
||
window.quartoListingCategory = (category) => { | ||
if (categoriesLoaded) { | ||
activateCategory(category); | ||
setCategoryHash(category); | ||
} | ||
}; | ||
|
||
window["quarto-listing-loaded"] = () => { | ||
// Process any existing hash | ||
const hash = getHash(); | ||
|
||
if (hash) { | ||
// If there is a category, switch to that | ||
if (hash.category) { | ||
activateCategory(hash.category); | ||
} | ||
// Paginate a specific listing | ||
const listingIds = Object.keys(window["quarto-listings"]); | ||
for (const listingId of listingIds) { | ||
const page = hash[getListingPageKey(listingId)]; | ||
if (page) { | ||
showPage(listingId, page); | ||
} | ||
} | ||
} | ||
|
||
const listingIds = Object.keys(window["quarto-listings"]); | ||
for (const listingId of listingIds) { | ||
// The actual list | ||
const list = window["quarto-listings"][listingId]; | ||
|
||
// Update the handlers for pagination events | ||
refreshPaginationHandlers(listingId); | ||
|
||
// Render any visible items that need it | ||
renderVisibleProgressiveImages(list); | ||
|
||
// Whenever the list is updated, we also need to | ||
// attach handlers to the new pagination elements | ||
// and refresh any newly visible items. | ||
list.on("updated", function () { | ||
renderVisibleProgressiveImages(list); | ||
setTimeout(() => refreshPaginationHandlers(listingId)); | ||
|
||
// Show or hide the no matching message | ||
toggleNoMatchingMessage(list); | ||
}); | ||
} | ||
}; | ||
|
||
window.document.addEventListener("DOMContentLoaded", function (_event) { | ||
// Attach click handlers to categories | ||
const categoryEls = window.document.querySelectorAll( | ||
".quarto-listing-category .category" | ||
); | ||
|
||
for (const categoryEl of categoryEls) { | ||
const category = categoryEl.getAttribute("data-category"); | ||
categoryEl.onclick = () => { | ||
activateCategory(category); | ||
setCategoryHash(category); | ||
}; | ||
} | ||
|
||
// Attach a click handler to the category title | ||
// (there should be only one, but since it is a class name, handle N) | ||
const categoryTitleEls = window.document.querySelectorAll( | ||
".quarto-listing-category-title" | ||
); | ||
for (const categoryTitleEl of categoryTitleEls) { | ||
categoryTitleEl.onclick = () => { | ||
activateCategory(""); | ||
setCategoryHash(""); | ||
}; | ||
} | ||
|
||
categoriesLoaded = true; | ||
}); | ||
|
||
function toggleNoMatchingMessage(list) { | ||
const selector = `#${list.listContainer.id} .listing-no-matching`; | ||
const noMatchingEl = window.document.querySelector(selector); | ||
if (noMatchingEl) { | ||
if (list.visibleItems.length === 0) { | ||
noMatchingEl.classList.remove("d-none"); | ||
} else { | ||
if (!noMatchingEl.classList.contains("d-none")) { | ||
noMatchingEl.classList.add("d-none"); | ||
} | ||
} | ||
} | ||
} | ||
|
||
function setCategoryHash(category) { | ||
setHash({ category }); | ||
} | ||
|
||
function setPageHash(listingId, page) { | ||
const currentHash = getHash() || {}; | ||
currentHash[getListingPageKey(listingId)] = page; | ||
setHash(currentHash); | ||
} | ||
|
||
function getListingPageKey(listingId) { | ||
return `${listingId}-page`; | ||
} | ||
|
||
function refreshPaginationHandlers(listingId) { | ||
const listingEl = window.document.getElementById(listingId); | ||
const paginationEls = listingEl.querySelectorAll( | ||
".pagination li.page-item:not(.disabled) .page.page-link" | ||
); | ||
for (const paginationEl of paginationEls) { | ||
paginationEl.onclick = (sender) => { | ||
setPageHash(listingId, sender.target.getAttribute("data-i")); | ||
showPage(listingId, sender.target.getAttribute("data-i")); | ||
return false; | ||
}; | ||
} | ||
} | ||
|
||
function renderVisibleProgressiveImages(list) { | ||
// Run through the visible items and render any progressive images | ||
for (const item of list.visibleItems) { | ||
const itemEl = item.elm; | ||
if (itemEl) { | ||
const progressiveImgs = itemEl.querySelectorAll( | ||
`img[${kProgressiveAttr}]` | ||
); | ||
for (const progressiveImg of progressiveImgs) { | ||
const srcValue = progressiveImg.getAttribute(kProgressiveAttr); | ||
if (srcValue) { | ||
progressiveImg.setAttribute("src", srcValue); | ||
} | ||
progressiveImg.removeAttribute(kProgressiveAttr); | ||
} | ||
} | ||
} | ||
} | ||
|
||
function getHash() { | ||
// Hashes are of the form | ||
// #name:value|name1:value1|name2:value2 | ||
const currentUrl = new URL(window.location); | ||
const hashRaw = currentUrl.hash ? currentUrl.hash.slice(1) : undefined; | ||
return parseHash(hashRaw); | ||
} | ||
|
||
const kAnd = "&"; | ||
const kEquals = "="; | ||
|
||
function parseHash(hash) { | ||
if (!hash) { | ||
return undefined; | ||
} | ||
const hasValuesStrs = hash.split(kAnd); | ||
const hashValues = hasValuesStrs | ||
.map((hashValueStr) => { | ||
const vals = hashValueStr.split(kEquals); | ||
if (vals.length === 2) { | ||
return { name: vals[0], value: vals[1] }; | ||
} else { | ||
return undefined; | ||
} | ||
}) | ||
.filter((value) => { | ||
return value !== undefined; | ||
}); | ||
|
||
const hashObj = {}; | ||
hashValues.forEach((hashValue) => { | ||
hashObj[hashValue.name] = decodeURIComponent(hashValue.value); | ||
}); | ||
return hashObj; | ||
} | ||
|
||
function makeHash(obj) { | ||
return Object.keys(obj) | ||
.map((key) => { | ||
return `${key}${kEquals}${obj[key]}`; | ||
}) | ||
.join(kAnd); | ||
} | ||
|
||
function setHash(obj) { | ||
const hash = makeHash(obj); | ||
window.history.pushState(null, null, `#${hash}`); | ||
} | ||
|
||
function showPage(listingId, page) { | ||
const list = window["quarto-listings"][listingId]; | ||
if (list) { | ||
list.show((page - 1) * list.page + 1, list.page); | ||
} | ||
} | ||
|
||
function activateCategory(category) { | ||
// Deactivate existing categories | ||
const activeEls = window.document.querySelectorAll( | ||
".quarto-listing-category .category.active" | ||
); | ||
for (const activeEl of activeEls) { | ||
activeEl.classList.remove("active"); | ||
} | ||
|
||
// Activate this category | ||
const categoryEl = window.document.querySelector( | ||
`.quarto-listing-category .category[data-category='${category}'` | ||
); | ||
if (categoryEl) { | ||
categoryEl.classList.add("active"); | ||
} | ||
|
||
// Filter the listings to this category | ||
filterListingCategory(category); | ||
} | ||
|
||
function filterListingCategory(category) { | ||
const listingIds = Object.keys(window["quarto-listings"]); | ||
for (const listingId of listingIds) { | ||
const list = window["quarto-listings"][listingId]; | ||
if (list) { | ||
if (category === "") { | ||
// resets the filter | ||
list.filter(); | ||
} else { | ||
// filter to this category | ||
list.filter(function (item) { | ||
const itemValues = item.values(); | ||
if (itemValues.categories !== null) { | ||
const categories = itemValues.categories.split(","); | ||
return categories.includes(category); | ||
} else { | ||
return false; | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
project: | ||
type: website | ||
|
||
website: | ||
title: "Tandy Center for Ocean Forecasting" | ||
description: "Data science blog for the Tandy Center" | ||
navbar: | ||
right: | ||
- about.qmd | ||
- icon: github | ||
href: https://github.com/bigelowlab/tandy-blog | ||
html: | ||
theme: cosmo | ||
css: styles.css |
Empty file.
Oops, something went wrong.