new render
10
RojavaRefineries_files/libs/bootstrap/bootstrap.min.css
vendored
Normal file
760
RojavaRefineries_files/libs/quarto-html/quarto.js
Normal file
@@ -0,0 +1,760 @@
|
||||
const sectionChanged = new CustomEvent("quarto-sectionChanged", {
|
||||
detail: {},
|
||||
bubbles: true,
|
||||
cancelable: false,
|
||||
composed: false,
|
||||
});
|
||||
|
||||
window.document.addEventListener("DOMContentLoaded", function (_event) {
|
||||
const tocEl = window.document.querySelector('nav.toc-active[role="doc-toc"]');
|
||||
const sidebarEl = window.document.getElementById("quarto-sidebar");
|
||||
const leftTocEl = window.document.getElementById("quarto-sidebar-toc-left");
|
||||
const marginSidebarEl = window.document.getElementById(
|
||||
"quarto-margin-sidebar"
|
||||
);
|
||||
// function to determine whether the element has a previous sibling that is active
|
||||
const prevSiblingIsActiveLink = (el) => {
|
||||
const sibling = el.previousElementSibling;
|
||||
if (sibling && sibling.tagName === "A") {
|
||||
return sibling.classList.contains("active");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// fire slideEnter for bootstrap tab activations (for htmlwidget resize behavior)
|
||||
function fireSlideEnter(e) {
|
||||
const event = window.document.createEvent("Event");
|
||||
event.initEvent("slideenter", true, true);
|
||||
window.document.dispatchEvent(event);
|
||||
}
|
||||
const tabs = window.document.querySelectorAll('a[data-bs-toggle="tab"]');
|
||||
tabs.forEach((tab) => {
|
||||
tab.addEventListener("shown.bs.tab", fireSlideEnter);
|
||||
});
|
||||
|
||||
// Track scrolling and mark TOC links as active
|
||||
// get table of contents and sidebar (bail if we don't have at least one)
|
||||
const tocLinks = tocEl
|
||||
? [...tocEl.querySelectorAll("a[data-scroll-target]")]
|
||||
: [];
|
||||
const makeActive = (link) => tocLinks[link].classList.add("active");
|
||||
const removeActive = (link) => tocLinks[link].classList.remove("active");
|
||||
const removeAllActive = () =>
|
||||
[...Array(tocLinks.length).keys()].forEach((link) => removeActive(link));
|
||||
|
||||
// activate the anchor for a section associated with this TOC entry
|
||||
tocLinks.forEach((link) => {
|
||||
link.addEventListener("click", () => {
|
||||
if (link.href.indexOf("#") !== -1) {
|
||||
const anchor = link.href.split("#")[1];
|
||||
const heading = window.document.querySelector(
|
||||
`[data-anchor-id=${anchor}]`
|
||||
);
|
||||
if (heading) {
|
||||
// Add the class
|
||||
heading.classList.add("reveal-anchorjs-link");
|
||||
|
||||
// function to show the anchor
|
||||
const handleMouseout = () => {
|
||||
heading.classList.remove("reveal-anchorjs-link");
|
||||
heading.removeEventListener("mouseout", handleMouseout);
|
||||
};
|
||||
|
||||
// add a function to clear the anchor when the user mouses out of it
|
||||
heading.addEventListener("mouseout", handleMouseout);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const sections = tocLinks.map((link) => {
|
||||
const target = link.getAttribute("data-scroll-target");
|
||||
if (target.startsWith("#")) {
|
||||
return window.document.getElementById(decodeURI(`${target.slice(1)}`));
|
||||
} else {
|
||||
return window.document.querySelector(decodeURI(`${target}`));
|
||||
}
|
||||
});
|
||||
|
||||
const sectionMargin = 200;
|
||||
let currentActive = 0;
|
||||
// track whether we've initialized state the first time
|
||||
let init = false;
|
||||
|
||||
const updateActiveLink = () => {
|
||||
// The index from bottom to top (e.g. reversed list)
|
||||
let sectionIndex = -1;
|
||||
if (
|
||||
window.innerHeight + window.pageYOffset >=
|
||||
window.document.body.offsetHeight
|
||||
) {
|
||||
sectionIndex = 0;
|
||||
} else {
|
||||
sectionIndex = [...sections].reverse().findIndex((section) => {
|
||||
if (section) {
|
||||
return window.pageYOffset >= section.offsetTop - sectionMargin;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (sectionIndex > -1) {
|
||||
const current = sections.length - sectionIndex - 1;
|
||||
if (current !== currentActive) {
|
||||
removeAllActive();
|
||||
currentActive = current;
|
||||
makeActive(current);
|
||||
if (init) {
|
||||
window.dispatchEvent(sectionChanged);
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const inHiddenRegion = (top, bottom, hiddenRegions) => {
|
||||
for (const region of hiddenRegions) {
|
||||
if (top <= region.bottom && bottom >= region.top) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const categorySelector = "header.quarto-title-block .quarto-category";
|
||||
const activateCategories = (href) => {
|
||||
// Find any categories
|
||||
// Surround them with a link pointing back to:
|
||||
// #category=Authoring
|
||||
try {
|
||||
const categoryEls = window.document.querySelectorAll(categorySelector);
|
||||
for (const categoryEl of categoryEls) {
|
||||
const categoryText = categoryEl.textContent;
|
||||
if (categoryText) {
|
||||
const link = `${href}#category=${encodeURIComponent(categoryText)}`;
|
||||
const linkEl = window.document.createElement("a");
|
||||
linkEl.setAttribute("href", link);
|
||||
for (const child of categoryEl.childNodes) {
|
||||
linkEl.append(child);
|
||||
}
|
||||
categoryEl.appendChild(linkEl);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Ignore errors
|
||||
}
|
||||
};
|
||||
function hasTitleCategories() {
|
||||
return window.document.querySelector(categorySelector) !== null;
|
||||
}
|
||||
|
||||
function offsetRelativeUrl(url) {
|
||||
const offset = getMeta("quarto:offset");
|
||||
return offset ? offset + url : url;
|
||||
}
|
||||
|
||||
function offsetAbsoluteUrl(url) {
|
||||
const offset = getMeta("quarto:offset");
|
||||
const baseUrl = new URL(offset, window.location);
|
||||
|
||||
const projRelativeUrl = url.replace(baseUrl, "");
|
||||
if (projRelativeUrl.startsWith("/")) {
|
||||
return projRelativeUrl;
|
||||
} else {
|
||||
return "/" + projRelativeUrl;
|
||||
}
|
||||
}
|
||||
|
||||
// read a meta tag value
|
||||
function getMeta(metaName) {
|
||||
const metas = window.document.getElementsByTagName("meta");
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
if (metas[i].getAttribute("name") === metaName) {
|
||||
return metas[i].getAttribute("content");
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
async function findAndActivateCategories() {
|
||||
const currentPagePath = offsetAbsoluteUrl(window.location.href);
|
||||
const response = await fetch(offsetRelativeUrl("listings.json"));
|
||||
if (response.status == 200) {
|
||||
return response.json().then(function (listingPaths) {
|
||||
const listingHrefs = [];
|
||||
for (const listingPath of listingPaths) {
|
||||
const pathWithoutLeadingSlash = listingPath.listing.substring(1);
|
||||
for (const item of listingPath.items) {
|
||||
if (
|
||||
item === currentPagePath ||
|
||||
item === currentPagePath + "index.html"
|
||||
) {
|
||||
// Resolve this path against the offset to be sure
|
||||
// we already are using the correct path to the listing
|
||||
// (this adjusts the listing urls to be rooted against
|
||||
// whatever root the page is actually running against)
|
||||
const relative = offsetRelativeUrl(pathWithoutLeadingSlash);
|
||||
const baseUrl = window.location;
|
||||
const resolvedPath = new URL(relative, baseUrl);
|
||||
listingHrefs.push(resolvedPath.pathname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Look up the tree for a nearby linting and use that if we find one
|
||||
const nearestListing = findNearestParentListing(
|
||||
offsetAbsoluteUrl(window.location.pathname),
|
||||
listingHrefs
|
||||
);
|
||||
if (nearestListing) {
|
||||
activateCategories(nearestListing);
|
||||
} else {
|
||||
// See if the referrer is a listing page for this item
|
||||
const referredRelativePath = offsetAbsoluteUrl(document.referrer);
|
||||
const referrerListing = listingHrefs.find((listingHref) => {
|
||||
const isListingReferrer =
|
||||
listingHref === referredRelativePath ||
|
||||
listingHref === referredRelativePath + "index.html";
|
||||
return isListingReferrer;
|
||||
});
|
||||
|
||||
if (referrerListing) {
|
||||
// Try to use the referrer if possible
|
||||
activateCategories(referrerListing);
|
||||
} else if (listingHrefs.length > 0) {
|
||||
// Otherwise, just fall back to the first listing
|
||||
activateCategories(listingHrefs[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (hasTitleCategories()) {
|
||||
findAndActivateCategories();
|
||||
}
|
||||
|
||||
const findNearestParentListing = (href, listingHrefs) => {
|
||||
if (!href || !listingHrefs) {
|
||||
return undefined;
|
||||
}
|
||||
// Look up the tree for a nearby linting and use that if we find one
|
||||
const relativeParts = href.substring(1).split("/");
|
||||
while (relativeParts.length > 0) {
|
||||
const path = relativeParts.join("/");
|
||||
for (const listingHref of listingHrefs) {
|
||||
if (listingHref.startsWith(path)) {
|
||||
return listingHref;
|
||||
}
|
||||
}
|
||||
relativeParts.pop();
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const manageSidebarVisiblity = (el, placeholderDescriptor) => {
|
||||
let isVisible = true;
|
||||
|
||||
return (hiddenRegions) => {
|
||||
if (el === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the last element of the TOC
|
||||
const lastChildEl = el.lastElementChild;
|
||||
|
||||
if (lastChildEl) {
|
||||
// Find the top and bottom o the element that is being managed
|
||||
const elTop = el.offsetTop;
|
||||
const elBottom =
|
||||
elTop + lastChildEl.offsetTop + lastChildEl.offsetHeight;
|
||||
|
||||
// Converts the sidebar to a menu
|
||||
const convertToMenu = () => {
|
||||
for (const child of el.children) {
|
||||
child.style.opacity = 0;
|
||||
child.style.overflow = "hidden";
|
||||
}
|
||||
|
||||
const toggleContainer = window.document.createElement("div");
|
||||
toggleContainer.style.width = "100%";
|
||||
toggleContainer.classList.add("zindex-over-content");
|
||||
toggleContainer.classList.add("quarto-sidebar-toggle");
|
||||
toggleContainer.classList.add("headroom-target"); // Marks this to be managed by headeroom
|
||||
toggleContainer.id = placeholderDescriptor.id;
|
||||
toggleContainer.style.position = "fixed";
|
||||
|
||||
const toggleIcon = window.document.createElement("i");
|
||||
toggleIcon.classList.add("quarto-sidebar-toggle-icon");
|
||||
toggleIcon.classList.add("bi");
|
||||
toggleIcon.classList.add("bi-caret-down-fill");
|
||||
|
||||
const toggleTitle = window.document.createElement("div");
|
||||
const titleEl = window.document.body.querySelector(
|
||||
placeholderDescriptor.titleSelector
|
||||
);
|
||||
if (titleEl) {
|
||||
toggleTitle.append(titleEl.innerText, toggleIcon);
|
||||
}
|
||||
toggleTitle.classList.add("zindex-over-content");
|
||||
toggleTitle.classList.add("quarto-sidebar-toggle-title");
|
||||
toggleContainer.append(toggleTitle);
|
||||
|
||||
const toggleContents = window.document.createElement("div");
|
||||
toggleContents.classList = el.classList;
|
||||
toggleContents.classList.add("zindex-over-content");
|
||||
toggleContents.classList.add("quarto-sidebar-toggle-contents");
|
||||
for (const child of el.children) {
|
||||
if (child.id === "toc-title") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const clone = child.cloneNode(true);
|
||||
clone.style.opacity = 1;
|
||||
clone.style.display = null;
|
||||
toggleContents.append(clone);
|
||||
}
|
||||
toggleContents.style.height = "0px";
|
||||
toggleContainer.append(toggleContents);
|
||||
el.parentElement.prepend(toggleContainer);
|
||||
|
||||
// Process clicks
|
||||
let tocShowing = false;
|
||||
// Allow the caller to control whether this is dismissed
|
||||
// when it is clicked (e.g. sidebar navigation supports
|
||||
// opening and closing the nav tree, so don't dismiss on click)
|
||||
const clickEl = placeholderDescriptor.dismissOnClick
|
||||
? toggleContainer
|
||||
: toggleTitle;
|
||||
|
||||
const closeToggle = () => {
|
||||
if (tocShowing) {
|
||||
toggleContainer.classList.remove("expanded");
|
||||
toggleContents.style.height = "0px";
|
||||
tocShowing = false;
|
||||
}
|
||||
};
|
||||
|
||||
const positionToggle = () => {
|
||||
// position the element (top left of parent, same width as parent)
|
||||
const elRect = el.getBoundingClientRect();
|
||||
toggleContainer.style.left = `${elRect.left}px`;
|
||||
toggleContainer.style.top = `${elRect.top}px`;
|
||||
toggleContainer.style.width = `${elRect.width}px`;
|
||||
};
|
||||
|
||||
// Get rid of any expanded toggle if the user scrolls
|
||||
window.document.addEventListener(
|
||||
"scroll",
|
||||
throttle(() => {
|
||||
closeToggle();
|
||||
}, 50)
|
||||
);
|
||||
|
||||
// Handle positioning of the toggle
|
||||
window.addEventListener(
|
||||
"resize",
|
||||
throttle(() => {
|
||||
positionToggle();
|
||||
}, 50)
|
||||
);
|
||||
positionToggle();
|
||||
|
||||
// Process the click
|
||||
clickEl.onclick = () => {
|
||||
if (!tocShowing) {
|
||||
toggleContainer.classList.add("expanded");
|
||||
toggleContents.style.height = null;
|
||||
tocShowing = true;
|
||||
} else {
|
||||
closeToggle();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Converts a sidebar from a menu back to a sidebar
|
||||
const convertToSidebar = () => {
|
||||
for (const child of el.children) {
|
||||
child.style.opacity = 1;
|
||||
child.style.overflow = null;
|
||||
}
|
||||
|
||||
const placeholderEl = window.document.getElementById(
|
||||
placeholderDescriptor.id
|
||||
);
|
||||
if (placeholderEl) {
|
||||
placeholderEl.remove();
|
||||
}
|
||||
|
||||
el.classList.remove("rollup");
|
||||
};
|
||||
|
||||
if (isReaderMode()) {
|
||||
convertToMenu();
|
||||
isVisible = false;
|
||||
} else {
|
||||
if (!isVisible) {
|
||||
// If the element is current not visible reveal if there are
|
||||
// no conflicts with overlay regions
|
||||
if (!inHiddenRegion(elTop, elBottom, hiddenRegions)) {
|
||||
convertToSidebar();
|
||||
isVisible = true;
|
||||
}
|
||||
} else {
|
||||
// If the element is visible, hide it if it conflicts with overlay regions
|
||||
// and insert a placeholder toggle (or if we're in reader mode)
|
||||
if (inHiddenRegion(elTop, elBottom, hiddenRegions)) {
|
||||
convertToMenu();
|
||||
isVisible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Find any conflicting margin elements and add margins to the
|
||||
// top to prevent overlap
|
||||
const marginChildren = window.document.querySelectorAll(
|
||||
".column-margin.column-container > * "
|
||||
);
|
||||
let lastBottom = 0;
|
||||
for (const marginChild of marginChildren) {
|
||||
const top = marginChild.getBoundingClientRect().top;
|
||||
if (top < lastBottom) {
|
||||
const margin = lastBottom - top;
|
||||
marginChild.style.marginTop = `${margin}px`;
|
||||
}
|
||||
const styles = window.getComputedStyle(marginChild);
|
||||
const marginTop = parseFloat(styles["marginTop"]);
|
||||
|
||||
lastBottom = top + marginChild.getBoundingClientRect().height + marginTop;
|
||||
}
|
||||
|
||||
// Manage the visibility of the toc and the sidebar
|
||||
const marginScrollVisibility = manageSidebarVisiblity(marginSidebarEl, {
|
||||
id: "quarto-toc-toggle",
|
||||
titleSelector: "#toc-title",
|
||||
dismissOnClick: true,
|
||||
});
|
||||
const sidebarScrollVisiblity = manageSidebarVisiblity(sidebarEl, {
|
||||
id: "quarto-sidebarnav-toggle",
|
||||
titleSelector: ".title",
|
||||
dismissOnClick: false,
|
||||
});
|
||||
let tocLeftScrollVisibility;
|
||||
if (leftTocEl) {
|
||||
tocLeftScrollVisibility = manageSidebarVisiblity(leftTocEl, {
|
||||
id: "quarto-lefttoc-toggle",
|
||||
titleSelector: "#toc-title",
|
||||
dismissOnClick: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Find the first element that uses formatting in special columns
|
||||
const conflictingEls = window.document.body.querySelectorAll(
|
||||
'[class^="column-"], [class*=" column-"], aside, [class*="margin-caption"], [class*=" margin-caption"], [class*="margin-ref"], [class*=" margin-ref"]'
|
||||
);
|
||||
|
||||
// Filter all the possibly conflicting elements into ones
|
||||
// the do conflict on the left or ride side
|
||||
const arrConflictingEls = Array.from(conflictingEls);
|
||||
const leftSideConflictEls = arrConflictingEls.filter((el) => {
|
||||
if (el.tagName === "ASIDE") {
|
||||
return false;
|
||||
}
|
||||
return Array.from(el.classList).find((className) => {
|
||||
return (
|
||||
className !== "column-body" &&
|
||||
className.startsWith("column-") &&
|
||||
!className.endsWith("right") &&
|
||||
!className.endsWith("container") &&
|
||||
className !== "column-margin"
|
||||
);
|
||||
});
|
||||
});
|
||||
const rightSideConflictEls = arrConflictingEls.filter((el) => {
|
||||
if (el.tagName === "ASIDE") {
|
||||
return true;
|
||||
}
|
||||
|
||||
const hasMarginCaption = Array.from(el.classList).find((className) => {
|
||||
return className == "margin-caption";
|
||||
});
|
||||
if (hasMarginCaption) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Array.from(el.classList).find((className) => {
|
||||
return (
|
||||
className !== "column-body" &&
|
||||
!className.endsWith("container") &&
|
||||
className.startsWith("column-") &&
|
||||
!className.endsWith("left")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
const kOverlapPaddingSize = 10;
|
||||
function toRegions(els) {
|
||||
return els.map((el) => {
|
||||
const top =
|
||||
el.getBoundingClientRect().top +
|
||||
document.documentElement.scrollTop -
|
||||
kOverlapPaddingSize;
|
||||
return {
|
||||
top,
|
||||
bottom: top + el.scrollHeight + 2 * kOverlapPaddingSize,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const hideOverlappedSidebars = () => {
|
||||
marginScrollVisibility(toRegions(rightSideConflictEls));
|
||||
sidebarScrollVisiblity(toRegions(leftSideConflictEls));
|
||||
if (tocLeftScrollVisibility) {
|
||||
tocLeftScrollVisibility(toRegions(leftSideConflictEls));
|
||||
}
|
||||
};
|
||||
|
||||
window.quartoToggleReader = () => {
|
||||
// Applies a slow class (or removes it)
|
||||
// to update the transition speed
|
||||
const slowTransition = (slow) => {
|
||||
const manageTransition = (id, slow) => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) {
|
||||
if (slow) {
|
||||
el.classList.add("slow");
|
||||
} else {
|
||||
el.classList.remove("slow");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
manageTransition("TOC", slow);
|
||||
manageTransition("quarto-sidebar", slow);
|
||||
};
|
||||
|
||||
const readerMode = !isReaderMode();
|
||||
setReaderModeValue(readerMode);
|
||||
|
||||
// If we're entering reader mode, slow the transition
|
||||
if (readerMode) {
|
||||
slowTransition(readerMode);
|
||||
}
|
||||
highlightReaderToggle(readerMode);
|
||||
hideOverlappedSidebars();
|
||||
|
||||
// If we're exiting reader mode, restore the non-slow transition
|
||||
if (!readerMode) {
|
||||
slowTransition(!readerMode);
|
||||
}
|
||||
};
|
||||
|
||||
const highlightReaderToggle = (readerMode) => {
|
||||
const els = document.querySelectorAll(".quarto-reader-toggle");
|
||||
if (els) {
|
||||
els.forEach((el) => {
|
||||
if (readerMode) {
|
||||
el.classList.add("reader");
|
||||
} else {
|
||||
el.classList.remove("reader");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const setReaderModeValue = (val) => {
|
||||
if (window.location.protocol !== "file:") {
|
||||
window.localStorage.setItem("quarto-reader-mode", val);
|
||||
} else {
|
||||
localReaderMode = val;
|
||||
}
|
||||
};
|
||||
|
||||
const isReaderMode = () => {
|
||||
if (window.location.protocol !== "file:") {
|
||||
return window.localStorage.getItem("quarto-reader-mode") === "true";
|
||||
} else {
|
||||
return localReaderMode;
|
||||
}
|
||||
};
|
||||
let localReaderMode = null;
|
||||
|
||||
// Walk the TOC and collapse/expand nodes
|
||||
// Nodes are expanded if:
|
||||
// - they are top level
|
||||
// - they have children that are 'active' links
|
||||
// - they are directly below an link that is 'active'
|
||||
const walk = (el, depth) => {
|
||||
// Tick depth when we enter a UL
|
||||
if (el.tagName === "UL") {
|
||||
depth = depth + 1;
|
||||
}
|
||||
|
||||
// It this is active link
|
||||
let isActiveNode = false;
|
||||
if (el.tagName === "A" && el.classList.contains("active")) {
|
||||
isActiveNode = true;
|
||||
}
|
||||
|
||||
// See if there is an active child to this element
|
||||
let hasActiveChild = false;
|
||||
for (child of el.children) {
|
||||
hasActiveChild = walk(child, depth) || hasActiveChild;
|
||||
}
|
||||
|
||||
// Process the collapse state if this is an UL
|
||||
if (el.tagName === "UL") {
|
||||
if (depth === 1 || hasActiveChild || prevSiblingIsActiveLink(el)) {
|
||||
el.classList.remove("collapse");
|
||||
} else {
|
||||
el.classList.add("collapse");
|
||||
}
|
||||
|
||||
// untick depth when we leave a UL
|
||||
depth = depth - 1;
|
||||
}
|
||||
return hasActiveChild || isActiveNode;
|
||||
};
|
||||
|
||||
// walk the TOC and expand / collapse any items that should be shown
|
||||
|
||||
if (tocEl) {
|
||||
walk(tocEl, 0);
|
||||
updateActiveLink();
|
||||
}
|
||||
|
||||
// Throttle the scroll event and walk peridiocally
|
||||
window.document.addEventListener(
|
||||
"scroll",
|
||||
throttle(() => {
|
||||
if (tocEl) {
|
||||
updateActiveLink();
|
||||
walk(tocEl, 0);
|
||||
}
|
||||
if (!isReaderMode()) {
|
||||
hideOverlappedSidebars();
|
||||
}
|
||||
}, 5)
|
||||
);
|
||||
window.addEventListener(
|
||||
"resize",
|
||||
throttle(() => {
|
||||
if (!isReaderMode()) {
|
||||
hideOverlappedSidebars();
|
||||
}
|
||||
}, 10)
|
||||
);
|
||||
hideOverlappedSidebars();
|
||||
highlightReaderToggle(isReaderMode());
|
||||
});
|
||||
|
||||
// grouped tabsets
|
||||
window.addEventListener("pageshow", (_event) => {
|
||||
function getTabSettings() {
|
||||
const data = localStorage.getItem("quarto-persistent-tabsets-data");
|
||||
if (!data) {
|
||||
localStorage.setItem("quarto-persistent-tabsets-data", "{}");
|
||||
return {};
|
||||
}
|
||||
if (data) {
|
||||
return JSON.parse(data);
|
||||
}
|
||||
}
|
||||
|
||||
function setTabSettings(data) {
|
||||
localStorage.setItem(
|
||||
"quarto-persistent-tabsets-data",
|
||||
JSON.stringify(data)
|
||||
);
|
||||
}
|
||||
|
||||
function setTabState(groupName, groupValue) {
|
||||
const data = getTabSettings();
|
||||
data[groupName] = groupValue;
|
||||
setTabSettings(data);
|
||||
}
|
||||
|
||||
function toggleTab(tab, active) {
|
||||
const tabPanelId = tab.getAttribute("aria-controls");
|
||||
const tabPanel = document.getElementById(tabPanelId);
|
||||
if (active) {
|
||||
tab.classList.add("active");
|
||||
tabPanel.classList.add("active");
|
||||
} else {
|
||||
tab.classList.remove("active");
|
||||
tabPanel.classList.remove("active");
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAll(selectedGroup, selectorsToSync) {
|
||||
for (const [thisGroup, tabs] of Object.entries(selectorsToSync)) {
|
||||
const active = selectedGroup === thisGroup;
|
||||
for (const tab of tabs) {
|
||||
toggleTab(tab, active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function findSelectorsToSyncByLanguage() {
|
||||
const result = {};
|
||||
const tabs = Array.from(
|
||||
document.querySelectorAll(`div[data-group] a[id^='tabset-']`)
|
||||
);
|
||||
for (const item of tabs) {
|
||||
const div = item.parentElement.parentElement.parentElement;
|
||||
const group = div.getAttribute("data-group");
|
||||
if (!result[group]) {
|
||||
result[group] = {};
|
||||
}
|
||||
const selectorsToSync = result[group];
|
||||
const value = item.innerHTML;
|
||||
if (!selectorsToSync[value]) {
|
||||
selectorsToSync[value] = [];
|
||||
}
|
||||
selectorsToSync[value].push(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function setupSelectorSync() {
|
||||
const selectorsToSync = findSelectorsToSyncByLanguage();
|
||||
Object.entries(selectorsToSync).forEach(([group, tabSetsByValue]) => {
|
||||
Object.entries(tabSetsByValue).forEach(([value, items]) => {
|
||||
items.forEach((item) => {
|
||||
item.addEventListener("click", (_event) => {
|
||||
setTabState(group, value);
|
||||
toggleAll(value, selectorsToSync[group]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return selectorsToSync;
|
||||
}
|
||||
|
||||
const selectorsToSync = setupSelectorSync();
|
||||
for (const [group, selectedName] of Object.entries(getTabSettings())) {
|
||||
const selectors = selectorsToSync[group];
|
||||
// it's possible that stale state gives us empty selections, so we explicitly check here.
|
||||
if (selectors) {
|
||||
toggleAll(selectedName, selectors);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function throttle(func, wait) {
|
||||
let waiting = false;
|
||||
return function () {
|
||||
if (!waiting) {
|
||||
func.apply(this, arguments);
|
||||
waiting = true;
|
||||
setTimeout(function () {
|
||||
waiting = false;
|
||||
}, wait);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -19,6 +19,7 @@ book:
|
||||
- SyriaNTL.qmd
|
||||
- RojavaRefineries.qmd
|
||||
repo-url: https://github.com/oballinger/GEE_OSINT/
|
||||
google-analytics: G-RK9ZLZQ6GL
|
||||
repo-actions: [edit]
|
||||
downloads: [pdf, epub]
|
||||
sharing: [twitter, facebook]
|
||||
|
||||
@@ -64,6 +64,15 @@ ul.task-list li input[type="checkbox"] {
|
||||
"search-submit-button-title": "Submit"
|
||||
}
|
||||
}</script>
|
||||
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-RK9ZLZQ6GL"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-RK9ZLZQ6GL', { 'anonymize_ip': true});
|
||||
</script>
|
||||
|
||||
|
||||
</head>
|
||||
@@ -198,13 +207,14 @@ ul.task-list li input[type="checkbox"] {
|
||||
<h2 id="toc-title">Table of contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#resolution" id="toc-resolution" class="nav-link active" data-scroll-target="#resolution"><span class="toc-section-number">1.1</span> Resolution</a>
|
||||
<li><a href="#active-and-passive-sensors" id="toc-active-and-passive-sensors" class="nav-link active" data-scroll-target="#active-and-passive-sensors"><span class="toc-section-number">1.1</span> Active and Passive Sensors</a></li>
|
||||
<li><a href="#resolution" id="toc-resolution" class="nav-link" data-scroll-target="#resolution"><span class="toc-section-number">1.2</span> Resolution</a>
|
||||
<ul class="collapse">
|
||||
<li><a href="#spatial-resolution" id="toc-spatial-resolution" class="nav-link" data-scroll-target="#spatial-resolution"><span class="toc-section-number">1.1.1</span> Spatial Resolution</a></li>
|
||||
<li><a href="#spectral-resolution" id="toc-spectral-resolution" class="nav-link" data-scroll-target="#spectral-resolution"><span class="toc-section-number">1.1.2</span> Spectral Resolution</a></li>
|
||||
<li><a href="#temporal-resolution" id="toc-temporal-resolution" class="nav-link" data-scroll-target="#temporal-resolution"><span class="toc-section-number">1.1.3</span> Temporal Resolution</a></li>
|
||||
<li><a href="#spatial-resolution" id="toc-spatial-resolution" class="nav-link" data-scroll-target="#spatial-resolution"><span class="toc-section-number">1.2.1</span> Spatial Resolution</a></li>
|
||||
<li><a href="#spectral-resolution" id="toc-spectral-resolution" class="nav-link" data-scroll-target="#spectral-resolution"><span class="toc-section-number">1.2.2</span> Spectral Resolution</a></li>
|
||||
<li><a href="#temporal-resolution" id="toc-temporal-resolution" class="nav-link" data-scroll-target="#temporal-resolution"><span class="toc-section-number">1.2.3</span> Temporal Resolution</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#orbits" id="toc-orbits" class="nav-link" data-scroll-target="#orbits"><span class="toc-section-number">1.2</span> Orbits</a></li>
|
||||
<li><a href="#orbits" id="toc-orbits" class="nav-link" data-scroll-target="#orbits"><span class="toc-section-number">1.3</span> Orbits</a></li>
|
||||
</ul>
|
||||
<div class="toc-actions"><div><i class="bi bi-github"></i></div><div class="action-links"><p><a href="https://github.com/oballinger/GEE_OSINT/edit/main/ch1.qmd" class="toc-action">Edit this page</a></p></div></div></nav>
|
||||
</div>
|
||||
@@ -228,21 +238,24 @@ ul.task-list li input[type="checkbox"] {
|
||||
|
||||
</header>
|
||||
|
||||
<p>Before learning how to load, process, and analyze satellite imagery in Google Earth Engine, it will be helpful to know a few basic principles of remote sensing. This section provides a brief overview of some important concepts and terminology that will be used throughout the course, including active and passive sensors; spatial, spectral, and temporal resolution; and orbits.</p>
|
||||
<section id="active-and-passive-sensors" class="level2" data-number="1.1">
|
||||
<h2 data-number="1.1" class="anchored" data-anchor-id="active-and-passive-sensors"><span class="header-section-number">1.1</span> Active and Passive Sensors</h2>
|
||||
<p><a href="https://www.sciencedirect.com/topics/medicine-and-dentistry/remote-sensing">Remote sensing</a> is the science of obtaining information about an object or phenomenon without making physical contact with the object. Remote sensing can be done with various types of electromagnetic radiation such as visible, infrared, or microwave. The electromagnetic radiation is either emitted or reflected from the object being sensed. The reflected radiation is then collected by a sensor and processed to obtain information about the object.</p>
|
||||
<p><img src="./images/diagram.png" class="img-fluid"></p>
|
||||
<p>passive remote sensing is the collection of information about an object or phenomenon without the use of an active energy source. Passive remote sensing is done by collecting the energy emitted or reflected from the object being sensed. Passive remote sensing is done with various types of electromagnetic radiation such as visible, infrared, or microwave. The electromagnetic radiation is either emitted or reflected from the object being sensed. The reflected radiation is then collected by a sensor and processed to obtain information about the object.</p>
|
||||
<section id="resolution" class="level2" data-number="1.1">
|
||||
<h2 data-number="1.1" class="anchored" data-anchor-id="resolution"><span class="header-section-number">1.1</span> Resolution</h2>
|
||||
<p>While most satellite imagery is optical, meaning it captures sunlight reflected by the earth’s surface, Synthetic Aperture Radar (SAR) satellites such as Sentinel-1 work by emitting pulses of radio waves and measuring how much of the signal is reflected back. This is similar to the way a bat uses sonar to “see” in the dark: by emitting calls and listening to echoes.</p>
|
||||
</section>
|
||||
<section id="resolution" class="level2" data-number="1.2">
|
||||
<h2 data-number="1.2" class="anchored" data-anchor-id="resolution"><span class="header-section-number">1.2</span> Resolution</h2>
|
||||
<p>Resolution is one of the most important attributes of satellite imagery.</p>
|
||||
<p>here are three types of resolution: spatial, spectral, and temporal.</p>
|
||||
<section id="spatial-resolution" class="level3" data-number="1.1.1">
|
||||
<h3 data-number="1.1.1" class="anchored" data-anchor-id="spatial-resolution"><span class="header-section-number">1.1.1</span> Spatial Resolution</h3>
|
||||
<section id="spatial-resolution" class="level3" data-number="1.2.1">
|
||||
<h3 data-number="1.2.1" class="anchored" data-anchor-id="spatial-resolution"><span class="header-section-number">1.2.1</span> Spatial Resolution</h3>
|
||||
<p>Spatial resolution governs how “sharp” an image looks. The Google Maps satellite basemap, for example, is really sharp Most of the optical imagery that is freely available has relatively low spatial resolution (it looks more grainy than, for example, the Google satellite basemap),</p>
|
||||
<p><img src="./images/Landsat.png" class="img-fluid"> <img src="./images/Sentinel2.png" class="img-fluid"> <img src="./images/Maxar.png" class="img-fluid"></p>
|
||||
<p><img src="./images/kh11.png" class="img-fluid"></p>
|
||||
</section>
|
||||
<section id="spectral-resolution" class="level3" data-number="1.1.2">
|
||||
<h3 data-number="1.1.2" class="anchored" data-anchor-id="spectral-resolution"><span class="header-section-number">1.1.2</span> Spectral Resolution</h3>
|
||||
<section id="spectral-resolution" class="level3" data-number="1.2.2">
|
||||
<h3 data-number="1.2.2" class="anchored" data-anchor-id="spectral-resolution"><span class="header-section-number">1.2.2</span> Spectral Resolution</h3>
|
||||
<p>What open source imagery lacks in spatial resolution it often makes up for with <em>spectral</em> resolution. Really sharp imagery from MAXAR, for example, collects</p>
|
||||
<p>Different materials reflect light differently. An apple absorbs shorter wavelengths (e.g. blue and green), and reflects longer wavelengths (red). Our eyes use that information– the color– to distinguish between different objects. But our eyes can only see a relatively small sliver of the electromagnetic spectrum covering blue, yellow, and red; we can’t see UV or infrared wavelengths, for example, though the extent to which different materials reflect or absorb these wavelengths is just as useful for distinguishing between them. For example, Astroturf (fake plastic grass) and real grass will both look green to us, espeically from a satellite image. But living plants absorb radiation from the sun in a part of the light spectrum that we can’t see. There’s a spectral index called the Normalized Difference Vegetation Index (NDVI) which exploits this fact to isolate vegetation in multispectral satellite imagery. So if we look at <a href="https://en.wikipedia.org/wiki/Gillette_Stadium">Gilette Stadium</a> near Boston, we can tell that the three training fields south of the stadium are real grass (they generate high NDVI values, showing up red), while the pitch in the stadium itself is astroturf (generating low NDVI values, showing up blue).</p>
|
||||
<div class="quarto-figure quarto-figure-center">
|
||||
@@ -260,8 +273,8 @@ ul.task-list li input[type="checkbox"] {
|
||||
<p><img src="images/S2_bands.png" class="img-fluid"></p>
|
||||
<p>We’ll be using this satellite to distinguish between oil and other materials, similar to the way we were able to distinguish between real and fake grass at Gilette Stadium. First, we’ll have to do a bit of pre-processing on the Sentinel-2 imagery after which we’ll train a machine learning model to identify oil.</p>
|
||||
</section>
|
||||
<section id="temporal-resolution" class="level3" data-number="1.1.3">
|
||||
<h3 data-number="1.1.3" class="anchored" data-anchor-id="temporal-resolution"><span class="header-section-number">1.1.3</span> Temporal Resolution</h3>
|
||||
<section id="temporal-resolution" class="level3" data-number="1.2.3">
|
||||
<h3 data-number="1.2.3" class="anchored" data-anchor-id="temporal-resolution"><span class="header-section-number">1.2.3</span> Temporal Resolution</h3>
|
||||
<p>Finally, the frequency with which we There is often a tradeoff between spatial and temporal resolution.</p>
|
||||
<p>The Google Maps basemap is very high resolution, available globally, and is freely available. But it has no <em>temporal</em> dimension: it’s a snapshot from one particular point in time. If the thing we’re interested in involves <em>changes</em> over time, this basemap will be of limited use.</p>
|
||||
<p>The <strong>“revisit rate”</strong> is the amount of time it takes for the satellite to pass over the same location twice. The revisit rate is inversely proportional to the satellite’s altitude: the higher the satellite is, the more frequently it can pass over the same location. This generally means that there’s a tradeoff between spatial resolution and temporal resolution: the higher the spatial resolution, the lower the revisit rate. However, some satellite constellations such as Planet’s SkySat are able to achieve both high spatial and temporal resolution by launching lots of small satellites into orbit at once. Below is a comparison of revisit rates for various satellites:</p>
|
||||
@@ -273,8 +286,8 @@ ul.task-list li input[type="checkbox"] {
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
<section id="orbits" class="level2" data-number="1.2">
|
||||
<h2 data-number="1.2" class="anchored" data-anchor-id="orbits"><span class="header-section-number">1.2</span> Orbits</h2>
|
||||
<section id="orbits" class="level2" data-number="1.3">
|
||||
<h2 data-number="1.3" class="anchored" data-anchor-id="orbits"><span class="header-section-number">1.3</span> Orbits</h2>
|
||||
<p>The Landsat satellites are in a sun-synchronous orbit, meaning they pass over the same spot on Earth at the same time every day. The Sentinel satellites are in a polar orbit, meaning they pass over the same spot on Earth twice a day, once in the morning and once in the afternoon. NASA have created a great <a href="https://svs.gsfc.nasa.gov/4745">visualisation</a> showing the orbits of the Landsat and Sentinel-2 satellites:</p>
|
||||
<div class="quarto-video"><video id="video_shortcode_videojs_video1" class="video-js vjs-default-skin vjs-fluid" controls="" preload="auto" data-setup="{}" title=""><source src="https://svs.gsfc.nasa.gov/vis/a000000/a004700/a004745/landsat_w_sentinel_ls8ls9sAsB_fade_1080p60.mp4"></video></div>
|
||||
<p>The Sentinel satellites are in a lower orbit than Landsat, meaning they are closer to the Earth and have a higher resolution.</p>
|
||||
@@ -62,6 +62,15 @@ ul.task-list li input[type="checkbox"] {
|
||||
"search-submit-button-title": "Submit"
|
||||
}
|
||||
}</script>
|
||||
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-RK9ZLZQ6GL"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-RK9ZLZQ6GL', { 'anonymize_ip': true});
|
||||
</script>
|
||||
<script src="site_libs/quarto-diagram/mermaid.min.js"></script>
|
||||
<script src="site_libs/quarto-diagram/mermaid-init.js"></script>
|
||||
<link href="site_libs/quarto-diagram/mermaid.css" rel="stylesheet">
|
||||
@@ -409,7 +418,7 @@ C-->H
|
||||
<p></p><figcaption class="figure-caption">Ships and interference from a radar system are visible in Zhuanghe Wan, near North Korea.</figcaption><p></p>
|
||||
</figure>
|
||||
</div>
|
||||
<p>Alongside</p>
|
||||
<p>Synthetic Aperture Radar imagery (SAR) is a type of remote sensing that uses radio waves to detect objects on the ground. SAR imagery is useful for detecting objects that are small, or that are obscured by clouds or other weather phenomena. SAR imagery is also useful for detecting objects that are moving, such as ships or cars.</p>
|
||||
<section id="applications-1" class="level3 unnumbered">
|
||||
<h3 class="unnumbered anchored" data-anchor-id="applications-1">Applications</h3>
|
||||
<ul>
|
||||
2
ch2.qmd
@@ -69,7 +69,7 @@ There are several different types of optical satellite imagery available in the
|
||||
## Radar Imagery
|
||||

|
||||
|
||||
Alongside
|
||||
Synthetic Aperture Radar imagery (SAR) is a type of remote sensing that uses radio waves to detect objects on the ground. SAR imagery is useful for detecting objects that are small, or that are obscured by clouds or other weather phenomena. SAR imagery is also useful for detecting objects that are moving, such as ships or cars.
|
||||
|
||||
### Applications {.unnumbered}
|
||||
|
||||
|
||||
@@ -1,784 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.2.269">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
|
||||
<title>Google Earth Engine for OSINT - War at Night</title>
|
||||
<style>
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
ul.task-list{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
pre > code.sourceCode { white-space: pre; position: relative; }
|
||||
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
|
||||
pre > code.sourceCode > span:empty { height: 1.2em; }
|
||||
.sourceCode { overflow: visible; }
|
||||
code.sourceCode > span { color: inherit; text-decoration: inherit; }
|
||||
div.sourceCode { margin: 1em 0; }
|
||||
pre.sourceCode { margin: 0; }
|
||||
@media screen {
|
||||
div.sourceCode { overflow: auto; }
|
||||
}
|
||||
@media print {
|
||||
pre > code.sourceCode { white-space: pre-wrap; }
|
||||
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
|
||||
}
|
||||
pre.numberSource code
|
||||
{ counter-reset: source-line 0; }
|
||||
pre.numberSource code > span
|
||||
{ position: relative; left: -4em; counter-increment: source-line; }
|
||||
pre.numberSource code > span > a:first-child::before
|
||||
{ content: counter(source-line);
|
||||
position: relative; left: -1em; text-align: right; vertical-align: baseline;
|
||||
border: none; display: inline-block;
|
||||
-webkit-touch-callout: none; -webkit-user-select: none;
|
||||
-khtml-user-select: none; -moz-user-select: none;
|
||||
-ms-user-select: none; user-select: none;
|
||||
padding: 0 4px; width: 4em;
|
||||
color: #aaaaaa;
|
||||
}
|
||||
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
|
||||
div.sourceCode
|
||||
{ }
|
||||
@media screen {
|
||||
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
|
||||
}
|
||||
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
|
||||
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
|
||||
code span.at { color: #7d9029; } /* Attribute */
|
||||
code span.bn { color: #40a070; } /* BaseN */
|
||||
code span.bu { color: #008000; } /* BuiltIn */
|
||||
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
|
||||
code span.ch { color: #4070a0; } /* Char */
|
||||
code span.cn { color: #880000; } /* Constant */
|
||||
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
|
||||
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
|
||||
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
|
||||
code span.dt { color: #902000; } /* DataType */
|
||||
code span.dv { color: #40a070; } /* DecVal */
|
||||
code span.er { color: #ff0000; font-weight: bold; } /* Error */
|
||||
code span.ex { } /* Extension */
|
||||
code span.fl { color: #40a070; } /* Float */
|
||||
code span.fu { color: #06287e; } /* Function */
|
||||
code span.im { color: #008000; font-weight: bold; } /* Import */
|
||||
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
|
||||
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
|
||||
code span.op { color: #666666; } /* Operator */
|
||||
code span.ot { color: #007020; } /* Other */
|
||||
code span.pp { color: #bc7a00; } /* Preprocessor */
|
||||
code span.sc { color: #4070a0; } /* SpecialChar */
|
||||
code span.ss { color: #bb6688; } /* SpecialString */
|
||||
code span.st { color: #4070a0; } /* String */
|
||||
code span.va { color: #19177c; } /* Variable */
|
||||
code span.vs { color: #4070a0; } /* VerbatimString */
|
||||
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
||||
</style>
|
||||
|
||||
|
||||
<script src="site_libs/quarto-nav/quarto-nav.js"></script>
|
||||
<script src="site_libs/quarto-nav/headroom.min.js"></script>
|
||||
<script src="site_libs/clipboard/clipboard.min.js"></script>
|
||||
<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
|
||||
<script src="site_libs/quarto-search/fuse.min.js"></script>
|
||||
<script src="site_libs/quarto-search/quarto-search.js"></script>
|
||||
<meta name="quarto:offset" content="./">
|
||||
<link href="./RojavaRefineries.html" rel="next">
|
||||
<link href="./ch4.html" rel="prev">
|
||||
<script src="site_libs/quarto-html/quarto.js"></script>
|
||||
<script src="site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="site_libs/quarto-html/quarto-syntax-highlighting.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="site_libs/quarto-html/quarto-syntax-highlighting-dark.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<script src="site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="site_libs/bootstrap/bootstrap.min.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="site_libs/bootstrap/bootstrap-dark.min.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "sidebar",
|
||||
"copy-button": false,
|
||||
"collapse-after": 3,
|
||||
"panel-placement": "start",
|
||||
"type": "textbox",
|
||||
"limit": 20,
|
||||
"language": {
|
||||
"search-no-results-text": "No results",
|
||||
"search-matching-documents-text": "matching documents",
|
||||
"search-copy-link-title": "Copy link to search",
|
||||
"search-hide-matches-text": "Hide additional matches",
|
||||
"search-more-match-text": "more match in this document",
|
||||
"search-more-matches-text": "more matches in this document",
|
||||
"search-clear-button-title": "Clear",
|
||||
"search-detached-cancel-button-title": "Cancel",
|
||||
"search-submit-button-title": "Submit"
|
||||
}
|
||||
}</script>
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body class="nav-sidebar floating">
|
||||
|
||||
<div id="quarto-search-results"></div>
|
||||
<header id="quarto-header" class="headroom fixed-top">
|
||||
<nav class="quarto-secondary-nav" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
|
||||
<div class="container-fluid d-flex justify-content-between">
|
||||
<h1 class="quarto-secondary-nav-title">War at Night</h1>
|
||||
<button type="button" class="quarto-btn-toggle btn" aria-label="Show secondary navigation">
|
||||
<i class="bi bi-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<!-- content -->
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse sidebar-navigation floating overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header sidebar-header-stacked">
|
||||
<a href="./index.html" class="sidebar-logo-link">
|
||||
<img src="./logo_white.png" alt="" class="sidebar-logo py-0 d-lg-inline d-none">
|
||||
</a>
|
||||
<div class="sidebar-title mb-0 py-0">
|
||||
<a href="./">Google Earth Engine for OSINT</a>
|
||||
<div class="sidebar-tools-main tools-wide">
|
||||
<a href="https://github.com/oballinger/GEE_OSINT/" title="Source Code" class="sidebar-tool px-1"><i class="bi bi-github"></i></a>
|
||||
<a href="" title="Download" id="sidebar-tool-dropdown-0" class="sidebar-tool dropdown-toggle px-1" data-bs-toggle="dropdown" aria-expanded="false"><i class="bi bi-download"></i></a>
|
||||
<ul class="dropdown-menu" aria-labelledby="sidebar-tool-dropdown-0">
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="./Google-Earth-Engine-for-OSINT.pdf">
|
||||
<i class="bi bi-bi-file-pdf pe-1"></i>
|
||||
Download PDF
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="./Google-Earth-Engine-for-OSINT.epub">
|
||||
<i class="bi bi-bi-journal pe-1"></i>
|
||||
Download ePub
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a href="" title="Share" id="sidebar-tool-dropdown-1" class="sidebar-tool dropdown-toggle px-1" data-bs-toggle="dropdown" aria-expanded="false"><i class="bi bi-share"></i></a>
|
||||
<ul class="dropdown-menu" aria-labelledby="sidebar-tool-dropdown-1">
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="https://twitter.com/intent/tweet?url=|url|">
|
||||
<i class="bi bi-bi-twitter pe-1"></i>
|
||||
Twitter
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="https://www.facebook.com/sharer/sharer.php?u=|url|">
|
||||
<i class="bi bi-bi-facebook pe-1"></i>
|
||||
Facebook
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a href="" class="quarto-color-scheme-toggle sidebar-tool" onclick="window.quartoToggleColorScheme(); return false;" title="Toggle dark mode"><i class="bi"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 flex-shrink-0 align-items-center">
|
||||
<div class="sidebar-search">
|
||||
<div id="quarto-search" class="" title="Search"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./index.html" class="sidebar-item-text sidebar-link">Introduction</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
<div class="sidebar-item-container">
|
||||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-1" aria-expanded="true">Learning</a>
|
||||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-1" aria-expanded="true">
|
||||
<i class="bi bi-chevron-right ms-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
<ul id="quarto-sidebar-section-1" class="collapse list-unstyled sidebar-section depth1 show">
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch1.html" class="sidebar-item-text sidebar-link"><span class="chapter-number">1</span> <span class="chapter-title">Remote Sensing</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch2.html" class="sidebar-item-text sidebar-link"><span class="chapter-number">2</span> <span class="chapter-title">Data Acquisition</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch3.html" class="sidebar-item-text sidebar-link"><span class="chapter-number">3</span> <span class="chapter-title">Algorithms</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch4.html" class="sidebar-item-text sidebar-link"><span class="chapter-number">4</span> <span class="chapter-title">Application Development</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
<div class="sidebar-item-container">
|
||||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-2" aria-expanded="true">Case Studies</a>
|
||||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-2" aria-expanded="true">
|
||||
<i class="bi bi-chevron-right ms-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
<ul id="quarto-sidebar-section-2" class="collapse list-unstyled sidebar-section depth1 show">
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./SyriaNTL.html" class="sidebar-item-text sidebar-link active">War at Night</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./RojavaRefineries.html" class="sidebar-item-text sidebar-link">Refinery Detection</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- margin-sidebar -->
|
||||
<div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
|
||||
<nav id="TOC" role="doc-toc" class="toc-active">
|
||||
<h2 id="toc-title">Table of contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#data" id="toc-data" class="nav-link active" data-scroll-target="#data">Data</a></li>
|
||||
<li><a href="#ukraine" id="toc-ukraine" class="nav-link" data-scroll-target="#ukraine">Ukraine</a>
|
||||
<ul class="collapse">
|
||||
<li><a href="#pre-processing" id="toc-pre-processing" class="nav-link" data-scroll-target="#pre-processing">Pre-Processing</a></li>
|
||||
<li><a href="#analysis" id="toc-analysis" class="nav-link" data-scroll-target="#analysis">Analysis</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#iraq" id="toc-iraq" class="nav-link" data-scroll-target="#iraq">Iraq</a>
|
||||
<ul class="collapse">
|
||||
<li><a href="#pre-processing-1" id="toc-pre-processing-1" class="nav-link" data-scroll-target="#pre-processing-1">Pre-Processing</a></li>
|
||||
<li><a href="#analysis-1" id="toc-analysis-1" class="nav-link" data-scroll-target="#analysis-1">Analysis</a></li>
|
||||
<li><a href="#the-battle-for-aleppo" id="toc-the-battle-for-aleppo" class="nav-link" data-scroll-target="#the-battle-for-aleppo">The Battle for Aleppo</a></li>
|
||||
<li><a href="#fighting-for-oil" id="toc-fighting-for-oil" class="nav-link" data-scroll-target="#fighting-for-oil">Fighting for Oil</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
<div class="toc-actions"><div><i class="bi bi-github"></i></div><div class="action-links"><p><a href="https://github.com/oballinger/GEE_OSINT/edit/main/SyriaNTL.qmd" class="toc-action">Edit this page</a></p></div></div></nav>
|
||||
</div>
|
||||
<!-- main -->
|
||||
<main class="content" id="quarto-document-content">
|
||||
|
||||
<header id="title-block-header" class="quarto-title-block default">
|
||||
<div class="quarto-title">
|
||||
<h1 class="title d-none d-lg-block">War at Night</h1>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="quarto-title-meta">
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<section id="data" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="data">Data</h2>
|
||||
<p>Satellite images of Syria taken at night capture a subtle trace left by human civilization: lights. Apartment buildings, street lights, highways, powerplants– all are illuminated at night and can be seen from space. Researchers often use these nighttime lights signatures to track development; as cities grow, villages recieve power, and infrastructure is built, areas emit more light. But this works both ways. As cities are demolished, villages burned, and highways cutoff, they stop emitting lights.</p>
|
||||
<p>The timelapse below uses imagery from the Defense Meteorological Satellite Program (DMSP), a joint program run by the U.S. Department of Defense and the National Oceanographic and Atmospheric Agency. One image is taken per year between 2005 and 2013:</p>
|
||||
</section>
|
||||
<section id="ukraine" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="ukraine">Ukraine</h2>
|
||||
<section id="pre-processing" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="pre-processing">Pre-Processing</h3>
|
||||
</section>
|
||||
<section id="analysis" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="analysis">Analysis</h3>
|
||||
</section>
|
||||
</section>
|
||||
<section id="iraq" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="iraq">Iraq</h2>
|
||||
<p>A link to the GEE code for this section can be found <a href="https://code.earthengine.google.com/2cf77d8cb9afd76b73100637fbffdf5d">here</a>.</p>
|
||||
<section id="pre-processing-1" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="pre-processing-1">Pre-Processing</h3>
|
||||
<p>First, let’s start by importing a few useful packages written by <a href="https://twitter.com/gena_d">Gennadii Donchyts</a>. We’ll use <code>utils</code> and <code>text</code> to annotate the date of each image on the timelapse. We’ll also define an Area of Interest (AOI), which is just a rectangle. You can do this manually by clicking the drawing tools in the top left. I’ve drawn an AOI over the area covering Mosul, Irbil, and Kirkuk in Northern Iraq.</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode js code-with-copy"><code class="sourceCode javascript"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> utils <span class="op">=</span> <span class="pp">require</span>(<span class="st">"users/gena/packages:utils"</span>)<span class="op">;</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> text <span class="op">=</span> <span class="pp">require</span>(<span class="st">"users/gena/packages:text"</span>)<span class="op">;</span></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="co">// define the Area of Interest (AOI)</span></span>
|
||||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> AOI <span class="op">=</span> ee<span class="op">.</span><span class="at">Geometry</span><span class="op">.</span><span class="fu">Polygon</span>(</span>
|
||||
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> [[[<span class="fl">42.555362833405326</span><span class="op">,</span> <span class="fl">36.62010778397765</span>]<span class="op">,</span></span>
|
||||
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> [<span class="fl">42.555362833405326</span><span class="op">,</span> <span class="fl">35.18296243288332</span>]<span class="op">,</span></span>
|
||||
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> [<span class="fl">44.681217325592826</span><span class="op">,</span> <span class="fl">35.18296243288332</span>]<span class="op">,</span></span>
|
||||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> [<span class="fl">44.681217325592826</span><span class="op">,</span> <span class="fl">36.62010778397765</span>]]])</span>
|
||||
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="co">// start and end dates for our gif </span></span>
|
||||
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> startDate <span class="op">=</span> <span class="st">'2013-01-01'</span><span class="op">;</span></span>
|
||||
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> endDate <span class="op">=</span> <span class="st">'2018-01-01'</span><span class="op">;</span></span>
|
||||
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="co">// a filename for when we export the gif</span></span>
|
||||
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> export_name<span class="op">=</span><span class="st">'qayyarah_viirs'</span></span>
|
||||
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="co">// A palette to visualize the VIIRS imagery. This one is similar to Matplotlib's "Magma" palette. </span></span>
|
||||
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> viirs_palette <span class="op">=</span> [</span>
|
||||
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> <span class="st">"#000004"</span><span class="op">,</span></span>
|
||||
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a> <span class="st">"#320a5a"</span><span class="op">,</span></span>
|
||||
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a> <span class="st">"#781b6c"</span><span class="op">,</span></span>
|
||||
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a> <span class="st">"#bb3654"</span><span class="op">,</span></span>
|
||||
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a> <span class="st">"#ec6824"</span><span class="op">,</span></span>
|
||||
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a> <span class="st">"#fbb41a"</span><span class="op">,</span></span>
|
||||
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a> <span class="st">"#fcffa4"</span><span class="op">,</span></span>
|
||||
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>]<span class="op">;</span></span>
|
||||
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a><span class="co">// Visualisation parameters for the VIIRS imagery, defining a minimum and maximum value, and referencing the palette we just created</span></span>
|
||||
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> VIIRSvis <span class="op">=</span> { <span class="dt">min</span><span class="op">:</span> <span class="op">-</span><span class="fl">0.1</span><span class="op">,</span> <span class="dt">max</span><span class="op">:</span> <span class="fl">1.6</span><span class="op">,</span> <span class="dt">palette</span><span class="op">:</span> viirs_palette }<span class="op">;</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<p>Next, we’ll load the VIIRS nighttime lights imagery. We want to select the <code>avg_rad</code> band of the image collection, and filter blank images. Sometimes, we get blank images over an area in VIIRS if our AOI is on the edge of the satellite’s imaging swath. We can filter these images, similarly to how we filter for cloudy images in Sentinel-2:</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode js code-with-copy"><code class="sourceCode javascript"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> VIIRS<span class="op">=</span> ee<span class="op">.</span><span class="fu">ImageCollection</span>(<span class="st">"NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG"</span>) </span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span><span class="fu">select</span>(<span class="st">'avg_rad'</span>)</span>
|
||||
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="co">// Calculate the sum of the 'avg_rad' band within the AOI</span></span>
|
||||
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span><span class="fu">map</span>(<span class="kw">function</span>(image) { </span>
|
||||
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">var</span> blank<span class="op">=</span>image<span class="op">.</span><span class="fu">reduceRegions</span>({</span>
|
||||
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">collection</span><span class="op">:</span> AOI<span class="op">,</span> </span>
|
||||
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">reducer</span><span class="op">:</span> ee<span class="op">.</span><span class="at">Reducer</span><span class="op">.</span><span class="fu">sum</span>()<span class="op">,</span> </span>
|
||||
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="dt">scale</span><span class="op">:</span> <span class="dv">10</span>})</span>
|
||||
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span><span class="fu">first</span>()</span>
|
||||
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span><span class="fu">get</span>(<span class="st">'sum'</span>)</span>
|
||||
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="co">// For each image, define a property 'blank' that stores the sum of the 'avg_rad' band within the AOI. </span></span>
|
||||
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> <span class="co">// We're also going to take a base 10 log of the image-- this will help us visualize the data by dampening extreme values </span></span>
|
||||
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> image<span class="op">.</span><span class="fu">set</span>(<span class="st">'blank'</span><span class="op">,</span> blank)<span class="op">.</span><span class="fu">log10</span>()<span class="op">.</span><span class="fu">unmask</span>(<span class="dv">0</span>)</span>
|
||||
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> })</span>
|
||||
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a> <span class="co">// Now, we can filter images which are fully or partially blank over our AOI</span></span>
|
||||
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span><span class="fu">filter</span>(ee<span class="op">.</span><span class="at">Filter</span><span class="op">.</span><span class="fu">gt</span>(<span class="st">'blank'</span><span class="op">,</span> <span class="dv">10</span>))</span>
|
||||
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a> <span class="co">// Finally, we filter the collection to the specified date range</span></span>
|
||||
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span><span class="fu">filterDate</span>(startDate<span class="op">,</span> endDate)</span>
|
||||
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a> </span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<p>Let’s have a look at the first image in the collection to make sure everything’s looking right. We’ll set the basemap to satellite and center our AOI:</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode js code-with-copy"><code class="sourceCode javascript"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="bu">Map</span><span class="op">.</span><span class="fu">setOptions</span>(<span class="st">'HYBRID'</span>)</span>
|
||||
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="bu">Map</span><span class="op">.</span><span class="fu">centerObject</span>(AOI)</span>
|
||||
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="bu">Map</span><span class="op">.</span><span class="fu">addLayer</span>(VIIRS<span class="op">.</span><span class="fu">first</span>()<span class="op">,</span>VIIRSvis<span class="op">,</span><span class="st">'Nighttime Lights'</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<p><img src="./images/iraq_check.png" class="img-fluid"></p>
|
||||
<p>If we decrease the opacity of the VIIRS layer, we can see the cities of Mosul, Erbil, and Kirkuk shining brightly at night. We can also see a string of bright lights between Kirkuk and Erbil– these are methane flares from oil wells.</p>
|
||||
</section>
|
||||
<section id="analysis-1" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="analysis-1">Analysis</h3>
|
||||
<p>Having pre-processed the VIIRS imagery, we can now define a function <code>gif</code> that will take:</p>
|
||||
<ol type="1">
|
||||
<li>An image collection (<code>col</code>, in this case the nighttime lights imagery <code>VIIRS</code>)</li>
|
||||
<li>Visualization parameters (<code>col_vis</code>, in this case <code>VIIRSvis</code>)</li>
|
||||
<li>An Area of Interest <code>AOI</code></li>
|
||||
</ol>
|
||||
<p>The function will then return a timelapse.</p>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode js code-with-copy"><code class="sourceCode javascript"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> gif <span class="op">=</span> <span class="kw">function</span> (col<span class="op">,</span> col_vis<span class="op">,</span> AOI) {</span>
|
||||
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="co">// Define the date annotations to be printed in the top left of the gif in white</span></span>
|
||||
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">var</span> annotations <span class="op">=</span> [</span>
|
||||
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a> {</span>
|
||||
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">textColor</span><span class="op">:</span> <span class="st">"white"</span><span class="op">,</span></span>
|
||||
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">position</span><span class="op">:</span> <span class="st">"left"</span><span class="op">,</span></span>
|
||||
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a> <span class="dt">offset</span><span class="op">:</span> <span class="st">"1%"</span><span class="op">,</span></span>
|
||||
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">margin</span><span class="op">:</span> <span class="st">"1%"</span><span class="op">,</span></span>
|
||||
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a> <span class="dt">property</span><span class="op">:</span> <span class="st">"label"</span><span class="op">,</span></span>
|
||||
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a> <span class="co">// Dynamically size the annotations according to the size of the AOI</span></span>
|
||||
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a> <span class="dt">scale</span><span class="op">:</span> AOI<span class="op">.</span><span class="fu">area</span>(<span class="dv">100</span>)<span class="op">.</span><span class="fu">sqrt</span>()<span class="op">.</span><span class="fu">divide</span>(<span class="dv">200</span>)<span class="op">,</span></span>
|
||||
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a> }<span class="op">,</span></span>
|
||||
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a> ]<span class="op">;</span></span>
|
||||
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a> <span class="co">// Next, we want to map over the image collection,</span></span>
|
||||
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">var</span> rgbVis <span class="op">=</span> col<span class="op">.</span><span class="fu">map</span>(<span class="kw">function</span> (image) {</span>
|
||||
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a> <span class="co">// Get the date of the image and format it</span></span>
|
||||
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a> <span class="kw">var</span> start <span class="op">=</span> ee<span class="op">.</span><span class="fu">Date</span>(image<span class="op">.</span><span class="fu">get</span>(<span class="st">"system:time_start"</span>))<span class="op">;</span></span>
|
||||
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a> <span class="kw">var</span> label <span class="op">=</span> start<span class="op">.</span><span class="fu">format</span>(<span class="st">"YYYY-MM-dd"</span>)<span class="op">;</span></span>
|
||||
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a> <span class="co">// And visualize the image using the visualization parameters defined earlier.</span></span>
|
||||
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a> <span class="co">// We also want to set a property called "label" that stores the formatted date </span></span>
|
||||
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> image<span class="op">.</span><span class="fu">visualize</span>(col_vis)<span class="op">.</span><span class="fu">set</span>({ <span class="dt">label</span><span class="op">:</span> label })<span class="op">;</span></span>
|
||||
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a> })<span class="op">;</span></span>
|
||||
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a> <span class="co">// Now we use the label proprty and the annotateImage function from @gena_d to annotate each image with the date. </span></span>
|
||||
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a> rgbVis <span class="op">=</span> rgbVis<span class="op">.</span><span class="fu">map</span>(<span class="kw">function</span> (image) {</span>
|
||||
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> text<span class="op">.</span><span class="fu">annotateImage</span>(image<span class="op">,</span> {}<span class="op">,</span> AOI<span class="op">,</span> annotations)<span class="op">;</span></span>
|
||||
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true" tabindex="-1"></a> })<span class="op">;</span></span>
|
||||
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true" tabindex="-1"></a> <span class="co">// Define GIF visualization parameters.</span></span>
|
||||
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true" tabindex="-1"></a> <span class="kw">var</span> gifParams <span class="op">=</span> {</span>
|
||||
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true" tabindex="-1"></a> <span class="dt">maxPixels</span><span class="op">:</span> <span class="dv">27017280</span><span class="op">,</span></span>
|
||||
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true" tabindex="-1"></a> <span class="dt">region</span><span class="op">:</span> AOI<span class="op">,</span></span>
|
||||
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true" tabindex="-1"></a> <span class="dt">crs</span><span class="op">:</span> <span class="st">"EPSG:3857"</span><span class="op">,</span></span>
|
||||
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true" tabindex="-1"></a> <span class="dt">dimensions</span><span class="op">:</span> <span class="dv">640</span><span class="op">,</span></span>
|
||||
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true" tabindex="-1"></a> <span class="dt">framesPerSecond</span><span class="op">:</span> <span class="dv">5</span><span class="op">,</span></span>
|
||||
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true" tabindex="-1"></a> }<span class="op">;</span></span>
|
||||
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true" tabindex="-1"></a> <span class="co">// Export the gif to Google Drive</span></span>
|
||||
<span id="cb4-41"><a href="#cb4-41" aria-hidden="true" tabindex="-1"></a> Export<span class="op">.</span><span class="at">video</span><span class="op">.</span><span class="fu">toDrive</span>({</span>
|
||||
<span id="cb4-42"><a href="#cb4-42" aria-hidden="true" tabindex="-1"></a> <span class="dt">collection</span><span class="op">:</span> rgbVis<span class="op">,</span></span>
|
||||
<span id="cb4-43"><a href="#cb4-43" aria-hidden="true" tabindex="-1"></a> <span class="dt">description</span><span class="op">:</span> export_name<span class="op">,</span></span>
|
||||
<span id="cb4-44"><a href="#cb4-44" aria-hidden="true" tabindex="-1"></a> <span class="dt">dimensions</span><span class="op">:</span> <span class="dv">1080</span><span class="op">,</span></span>
|
||||
<span id="cb4-45"><a href="#cb4-45" aria-hidden="true" tabindex="-1"></a> <span class="dt">framesPerSecond</span><span class="op">:</span> <span class="dv">5</span><span class="op">,</span></span>
|
||||
<span id="cb4-46"><a href="#cb4-46" aria-hidden="true" tabindex="-1"></a> <span class="dt">region</span><span class="op">:</span> AOI<span class="op">,</span></span>
|
||||
<span id="cb4-47"><a href="#cb4-47" aria-hidden="true" tabindex="-1"></a> })<span class="op">;</span></span>
|
||||
<span id="cb4-48"><a href="#cb4-48" aria-hidden="true" tabindex="-1"></a> <span class="co">// Print the GIF URL to the console.</span></span>
|
||||
<span id="cb4-49"><a href="#cb4-49" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span>(rgbVis<span class="op">.</span><span class="fu">getVideoThumbURL</span>(gifParams))<span class="op">;</span></span>
|
||||
<span id="cb4-50"><a href="#cb4-50" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-51"><a href="#cb4-51" aria-hidden="true" tabindex="-1"></a> <span class="co">// Render the GIF animation in the console.</span></span>
|
||||
<span id="cb4-52"><a href="#cb4-52" aria-hidden="true" tabindex="-1"></a> <span class="fu">print</span>(ui<span class="op">.</span><span class="fu">Thumbnail</span>(rgbVis<span class="op">,</span> gifParams))<span class="op">;</span></span>
|
||||
<span id="cb4-53"><a href="#cb4-53" aria-hidden="true" tabindex="-1"></a>}<span class="op">;</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<p>Ok that was a pretty big chunk of code. But the good news is that we basically never have to touch it again, since we can just feed it different inputs. For example, if I want to generate a gif of nighttime lights over a different area, it’s as simple as dragging the AOI. If I want to look at a different time period, I can just edit the <code>startDate</code> and <code>endDate</code> variables. And if I want to visualize an entirely different type of satellite imagery– Sentinel-1, Sentinel-2, or anything else, all I have to do is change the image collection (<code>col</code>) and visualization parameters (<code>col_vis</code>) variables. Now, let’s look at some timelapses.</p>
|
||||
<section id="the-fall-of-mosul" class="level4">
|
||||
<h4 class="anchored" data-anchor-id="the-fall-of-mosul">The Fall of Mosul</h4>
|
||||
<p>The function returns a timelapse of nighttime lights over Northern Iraq:</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode js code-with-copy"><code class="sourceCode javascript"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gif</span>(VIIRS<span class="op">,</span> VIIRSvis<span class="op">,</span> AOI)<span class="op">;</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<div class="quarto-figure quarto-figure-center">
|
||||
<figure class="figure">
|
||||
<p><img src="./images/Figure_1.gif" class="img-fluid figure-img"></p>
|
||||
<p></p><figcaption class="figure-caption">I’ve done a bit of post-processing to this gif, adding more annotations and blending between frames to make it a bit smoother. I typically use <a href="https://ffmpeg.org/">ffmpeg</a> and <a href="https://ezgif.com/">ezgif</a> for the finishing touches.</figcaption><p></p>
|
||||
</figure>
|
||||
</div>
|
||||
<p>This timelapse gives a play-by-play of one of the most important campaigns in the war against the Islamic State. In the first few frames, Mosul is under the control of the Kurdistan Regional Government (KRG). In the summer of 2014, ISIS captures the city, and power is cut off. Mosul and many villages along the Tigris river are plunged into darkness. In 2015, the front line in the campaign to retake the city emerges around Mosul, advancing in 2016 and 2017. Mosul is eventually retaken by the KRG in 2017, after which it brightens once again as electricity is restored.</p>
|
||||
</section>
|
||||
<section id="the-qayyarah-fires" class="level4">
|
||||
<h4 class="anchored" data-anchor-id="the-qayyarah-fires">The Qayyarah Fires</h4>
|
||||
<p>Farther south, there is an interesting detail. Above the “h” in “Qayyarah”, a bright set of lights emerges just before Mosul is recaptured, around December 2016. Fleeing Islamic State fighters <a href="https://time.com/iraq-fires/">set fire to the Qayyarah oilfields</a>, which burned for months.</p>
|
||||
<p>Using the VIIRS data we’ve already loaded, we can further analyze the effect of the conflict using a chart. First, let’s define two rectangles (again, you can draw these) over Mosul and Qayyarah:</p>
|
||||
<div class="sourceCode" id="cb6"><pre class="sourceCode js code-with-copy"><code class="sourceCode javascript"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> mosul <span class="op">=</span> ee<span class="op">.</span><span class="fu">Feature</span>(</span>
|
||||
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> ee<span class="op">.</span><span class="at">Geometry</span><span class="op">.</span><span class="fu">Polygon</span>(</span>
|
||||
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> [[[<span class="fl">43.054977780266675</span><span class="op">,</span> <span class="fl">36.438274276521234</span>]<span class="op">,</span></span>
|
||||
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> [<span class="fl">43.054977780266675</span><span class="op">,</span> <span class="fl">36.290642221212416</span>]<span class="op">,</span></span>
|
||||
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> [<span class="fl">43.24792516796199</span><span class="op">,</span> <span class="fl">36.290642221212416</span>]<span class="op">,</span></span>
|
||||
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a> [<span class="fl">43.24792516796199</span><span class="op">,</span> <span class="fl">36.438274276521234</span>]]]<span class="op">,</span> <span class="kw">null</span><span class="op">,</span> <span class="kw">false</span>)<span class="op">,</span></span>
|
||||
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a> {</span>
|
||||
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a> <span class="st">"label"</span><span class="op">:</span> <span class="st">"Mosul"</span><span class="op">,</span></span>
|
||||
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a> <span class="st">"system:index"</span><span class="op">:</span> <span class="st">"0"</span></span>
|
||||
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a> })<span class="op">,</span></span>
|
||||
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a> qayyarah <span class="op">=</span> ee<span class="op">.</span><span class="fu">Feature</span>(</span>
|
||||
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a> ee<span class="op">.</span><span class="at">Geometry</span><span class="op">.</span><span class="fu">Polygon</span>(</span>
|
||||
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a> [[[<span class="fl">43.08240275545117</span><span class="op">,</span> <span class="fl">35.8925587996721</span>]<span class="op">,</span></span>
|
||||
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a> [<span class="fl">43.08240275545117</span><span class="op">,</span> <span class="fl">35.77899970860588</span>]<span class="op">,</span></span>
|
||||
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a> [<span class="fl">43.26642375154492</span><span class="op">,</span> <span class="fl">35.77899970860588</span>]<span class="op">,</span></span>
|
||||
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a> [<span class="fl">43.26642375154492</span><span class="op">,</span> <span class="fl">35.8925587996721</span>]]]<span class="op">,</span> <span class="kw">null</span><span class="op">,</span> <span class="kw">false</span>)<span class="op">,</span></span>
|
||||
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a> {</span>
|
||||
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a> <span class="st">"label"</span><span class="op">:</span> <span class="st">"Qayyarah"</span><span class="op">,</span></span>
|
||||
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a> <span class="st">"system:index"</span><span class="op">:</span> <span class="st">"0"</span></span>
|
||||
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a> })</span>
|
||||
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a><span class="co">// Let's put these together in a list </span></span>
|
||||
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> regions<span class="op">=</span>[qayyarah<span class="op">,</span> mosul]</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<p>Once we’ve got the rectangles, we can make a chart that will take the mean value of the VIIRS images in each rectangle over time:</p>
|
||||
<div class="sourceCode" id="cb7"><pre class="sourceCode js code-with-copy"><code class="sourceCode javascript"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> chart <span class="op">=</span></span>
|
||||
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a> ui<span class="op">.</span><span class="at">Chart</span><span class="op">.</span><span class="at">image</span></span>
|
||||
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span><span class="fu">seriesByRegion</span>({</span>
|
||||
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">imageCollection</span><span class="op">:</span> VIIRS<span class="op">,</span></span>
|
||||
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">regions</span><span class="op">:</span> regions<span class="op">,</span></span>
|
||||
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">reducer</span><span class="op">:</span> ee<span class="op">.</span><span class="at">Reducer</span><span class="op">.</span><span class="fu">mean</span>()<span class="op">,</span></span>
|
||||
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">seriesProperty</span><span class="op">:</span><span class="st">'label'</span></span>
|
||||
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a> })<span class="op">.</span><span class="fu">setOptions</span>({</span>
|
||||
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">title</span><span class="op">:</span> <span class="st">'Nighttime Lights'</span></span>
|
||||
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a> })<span class="op">;</span></span>
|
||||
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a> </span>
|
||||
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a><span class="fu">print</span>(chart)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||
<p><img src="./images/qayyarah_chart.png" class="img-fluid"></p>
|
||||
<p>We can clearly see Mosul (the red line) darkening in 2014 as the city is taken by ISIS. During this period the Qayyarah oilfileds are, as we might expect, quite dark. All of a sudden in 2016 Qayyarah becomes brighter at night than the city of Mosul ever was, as the oilfields are set on fire. Then, almost exactly when the blaze in Qayyarah is extinguished and the area darkens (i.e. when the blue line falls back to near zero), Mosul brightens once again (i.e. the red line rises) as the city is liberated.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="the-battle-for-aleppo" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="the-battle-for-aleppo">The Battle for Aleppo</h3>
|
||||
<p>The images below were taken between 2012 and 2014. Vast swaths of the city darken as neighbourhoods are razed by fighting.</p>
|
||||
<p><timelapse></timelapse></p>
|
||||
<p>Though this is a trend that can be observed across the country, nowhere is the decline in nightlights more visible than in Aleppo. Below is a comparison of longitudinal trends in nighlights signatures between several cities:</p>
|
||||
<p><graph></graph></p>
|
||||
<p>The most salient trend is Aleppo plummeting over the course of 2012, and becoming steadily darker over the course of the next four years. Raqqa drops in 2012 as well, but remains in flux until 2017, when the battle to reclaim the city pluges it into near total darkness. Damascus also experiences a dip in 2012, but stabilizes relatively quickly. The Turkish city of Gaziantep– less than 100km from Aleppo and roughly 1/5th the size– stands in stark contrast to the Syrian cities, becoming progressively brighter over the entire period.</p>
|
||||
<p>Another interesting pattern here is the difference in seasonal trends in nightlights. Under normal circumstances in this part of the world, cities become brighter at night during the summer months. Restaurants, bars, and markets stay open later and conduct business outdoors. Gaziantep, which still attracts scores of tourists every year, displays pronounced seasonality. Damascus, the most stable of the three Syrian cities, also maintains a seasonal trend throughout the war. In contrast, both Raqqa and Aleppo maintain extremely low and roughly constant levels of nightlights year-round during the periods following intense fighting.</p>
|
||||
<p>Reliable economic data for Syria haven’t been available for nearly a decade, and assessing the country’s recovery is consequently difficult. But subtle indications of economic growth are visible above: all three Syrian cities have been on a steady upward trend since 2017, and beginning to display seasonal variation once again.</p>
|
||||
</section>
|
||||
<section id="fighting-for-oil" class="level3">
|
||||
<h3 class="anchored" data-anchor-id="fighting-for-oil">Fighting for Oil</h3>
|
||||
<p>Throughout the war, sudden massive spikes in nightlights signatures can be observed throughout the country. In the center of the map just west of Palmyra, some particularly large spikes occur in 2017:</p>
|
||||
<p>These flashes of light show gas wells being set on fire, a common form of sabotage carried out by retreating Islamic State fighters. Modified Sentinel-2 imagery of the Hayyan gas field (indicated by the green box above) shows this in greater detail. Substituing the Red band in an RGB image with Near Infrared (NIR) highlights thermal signatures, showing fires burning brightly even during the day.</p>
|
||||
<p>The large complex on the right is the Hayyan Gas Plant, which produced nearly 1/3 of Syria’s electricity. The plant and its associated wells changed hands several times throughout the war, but were under Islamic State control until February 2017. In the video below, Islamic State fighters can be seen rigging the plant with explosives and destroying it on January 8th:</p>
|
||||
<p>In February, three Russian oil and gas companies (Zarubij Naft, Lukoil and Gazprom Neft) were given restoration, exploration, and production rights to the hydrocarbon deposits West of Palmyra. On January 12th, 2017, the Syrian Army’s 5th Legion and Russian special forces launched a counterattack known as the “Palmyra offensive”, with the aim of retaking several important hydrocarbon deposits including Hayyan.</p>
|
||||
<p>The timing of well fires aligns closely with a detailed timeline of the campaign.The Near Infrared Sentinel-2 image below shows the layout of the Hayyan Gas Plant and the wells in the Hayyan gas field:</p>
|
||||
<p>The Syrian Army took the Hayyan gas field on <a href="https://www.almasdarnews.com/article/syrian-army-liberates-hayyan-gas-fields-west-palmyra/">February 4th</a>, and retreating ISIS fighters set fire to wells 1, and 3. However, ISIS managed to briefly retake the Hayyan field on <a href="https://www.almasdarnews.com/article/isis-retakes-hayyan-gas-fields-new-bid-expand-west-palmyra/">February 7th</a>, setting fire to wells 2 and 4. These moments in the Palmyra Offensive are captured in NIR signatures</p>
|
||||
<p>Interestingly, despite the massive explosion caused by the bombing of the Hayyan Gas Plant, no prolonged thermal anomalies were detected over the area of the plant itself. The well fires, on the other hand, lasted for months. Below is an image of well fire at the Hayyan field taken from this <a href="https://www.youtube.com/watch?v=WFe9abYyqK0">video</a>; based on the nearby infrastructure and date (04/02/2017) of posting, it is likely Well-3.</p>
|
||||
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
</main> <!-- /main -->
|
||||
<script id="quarto-html-after-body" type="application/javascript">
|
||||
window.document.addEventListener("DOMContentLoaded", function (event) {
|
||||
const toggleBodyColorMode = (bsSheetEl) => {
|
||||
const mode = bsSheetEl.getAttribute("data-mode");
|
||||
const bodyEl = window.document.querySelector("body");
|
||||
if (mode === "dark") {
|
||||
bodyEl.classList.add("quarto-dark");
|
||||
bodyEl.classList.remove("quarto-light");
|
||||
} else {
|
||||
bodyEl.classList.add("quarto-light");
|
||||
bodyEl.classList.remove("quarto-dark");
|
||||
}
|
||||
}
|
||||
const toggleBodyColorPrimary = () => {
|
||||
const bsSheetEl = window.document.querySelector("link#quarto-bootstrap");
|
||||
if (bsSheetEl) {
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
toggleBodyColorPrimary();
|
||||
const disableStylesheet = (stylesheets) => {
|
||||
for (let i=0; i < stylesheets.length; i++) {
|
||||
const stylesheet = stylesheets[i];
|
||||
stylesheet.rel = 'prefetch';
|
||||
}
|
||||
}
|
||||
const enableStylesheet = (stylesheets) => {
|
||||
for (let i=0; i < stylesheets.length; i++) {
|
||||
const stylesheet = stylesheets[i];
|
||||
stylesheet.rel = 'stylesheet';
|
||||
}
|
||||
}
|
||||
const manageTransitions = (selector, allowTransitions) => {
|
||||
const els = window.document.querySelectorAll(selector);
|
||||
for (let i=0; i < els.length; i++) {
|
||||
const el = els[i];
|
||||
if (allowTransitions) {
|
||||
el.classList.remove('notransition');
|
||||
} else {
|
||||
el.classList.add('notransition');
|
||||
}
|
||||
}
|
||||
}
|
||||
const toggleColorMode = (alternate) => {
|
||||
// Switch the stylesheets
|
||||
const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate');
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', false);
|
||||
if (alternate) {
|
||||
enableStylesheet(alternateStylesheets);
|
||||
for (const sheetNode of alternateStylesheets) {
|
||||
if (sheetNode.id === "quarto-bootstrap") {
|
||||
toggleBodyColorMode(sheetNode);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
disableStylesheet(alternateStylesheets);
|
||||
toggleBodyColorPrimary();
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
if (toggle) {
|
||||
if (alternate) {
|
||||
toggle.classList.add("alternate");
|
||||
} else {
|
||||
toggle.classList.remove("alternate");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
manageTransitions("body", false);
|
||||
window.scrollTo(0, 1);
|
||||
setTimeout(() => {
|
||||
window.scrollTo(0, 0);
|
||||
manageTransitions("body", true);
|
||||
}, 40);
|
||||
}
|
||||
}
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const setStyleSentinel = (alternate) => {
|
||||
const value = alternate ? "alternate" : "default";
|
||||
if (!isFileUrl()) {
|
||||
window.localStorage.setItem("quarto-color-scheme", value);
|
||||
} else {
|
||||
localAlternateSentinel = value;
|
||||
}
|
||||
}
|
||||
const getColorSchemeSentinel = () => {
|
||||
if (!isFileUrl()) {
|
||||
const storageValue = window.localStorage.getItem("quarto-color-scheme");
|
||||
return storageValue != null ? storageValue : localAlternateSentinel;
|
||||
} else {
|
||||
return localAlternateSentinel;
|
||||
}
|
||||
}
|
||||
let localAlternateSentinel = 'alternate';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
};
|
||||
// Ensure there is a toggle, if there isn't float one in the top right
|
||||
if (window.document.querySelector('.quarto-color-scheme-toggle') === null) {
|
||||
const a = window.document.createElement('a');
|
||||
a.classList.add('top-right');
|
||||
a.classList.add('quarto-color-scheme-toggle');
|
||||
a.href = "";
|
||||
a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; };
|
||||
const i = window.document.createElement("i");
|
||||
i.classList.add('bi');
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
// Switch to dark mode if need be
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
}
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
placement: 'right',
|
||||
icon: icon
|
||||
};
|
||||
anchorJS.add('.anchored');
|
||||
const clipboard = new window.ClipboardJS('.code-copy-button', {
|
||||
target: function(trigger) {
|
||||
return trigger.previousElementSibling;
|
||||
}
|
||||
});
|
||||
clipboard.on('success', function(e) {
|
||||
// button target
|
||||
const button = e.trigger;
|
||||
// don't keep focus
|
||||
button.blur();
|
||||
// flash "checked"
|
||||
button.classList.add('code-copy-button-checked');
|
||||
var currentTitle = button.getAttribute("title");
|
||||
button.setAttribute("title", "Copied!");
|
||||
let tooltip;
|
||||
if (window.bootstrap) {
|
||||
button.setAttribute("data-bs-toggle", "tooltip");
|
||||
button.setAttribute("data-bs-placement", "left");
|
||||
button.setAttribute("data-bs-title", "Copied!");
|
||||
tooltip = new bootstrap.Tooltip(button,
|
||||
{ trigger: "manual",
|
||||
customClass: "code-copy-button-tooltip",
|
||||
offset: [0, -8]});
|
||||
tooltip.show();
|
||||
}
|
||||
setTimeout(function() {
|
||||
if (tooltip) {
|
||||
tooltip.hide();
|
||||
button.removeAttribute("data-bs-title");
|
||||
button.removeAttribute("data-bs-toggle");
|
||||
button.removeAttribute("data-bs-placement");
|
||||
}
|
||||
button.setAttribute("title", currentTitle);
|
||||
button.classList.remove('code-copy-button-checked');
|
||||
}, 1000);
|
||||
// clear code selection
|
||||
e.clearSelection();
|
||||
});
|
||||
function tippyHover(el, contentFn) {
|
||||
const config = {
|
||||
allowHTML: true,
|
||||
content: contentFn,
|
||||
maxWidth: 500,
|
||||
delay: 100,
|
||||
arrow: false,
|
||||
appendTo: function(el) {
|
||||
return el.parentElement;
|
||||
},
|
||||
interactive: true,
|
||||
interactiveBorder: 10,
|
||||
theme: 'quarto',
|
||||
placement: 'bottom-start'
|
||||
};
|
||||
window.tippy(el, config);
|
||||
}
|
||||
const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
|
||||
for (var i=0; i<noterefs.length; i++) {
|
||||
const ref = noterefs[i];
|
||||
tippyHover(ref, function() {
|
||||
// use id or data attribute instead here
|
||||
let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
|
||||
try { href = new URL(href).hash; } catch {}
|
||||
const id = href.replace(/^#\/?/, "");
|
||||
const note = window.document.getElementById(id);
|
||||
return note.innerHTML;
|
||||
});
|
||||
}
|
||||
const findCites = (el) => {
|
||||
const parentEl = el.parentElement;
|
||||
if (parentEl) {
|
||||
const cites = parentEl.dataset.cites;
|
||||
if (cites) {
|
||||
return {
|
||||
el,
|
||||
cites: cites.split(' ')
|
||||
};
|
||||
} else {
|
||||
return findCites(el.parentElement)
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
|
||||
for (var i=0; i<bibliorefs.length; i++) {
|
||||
const ref = bibliorefs[i];
|
||||
const citeInfo = findCites(ref);
|
||||
if (citeInfo) {
|
||||
tippyHover(citeInfo.el, function() {
|
||||
var popup = window.document.createElement('div');
|
||||
citeInfo.cites.forEach(function(cite) {
|
||||
var citeDiv = window.document.createElement('div');
|
||||
citeDiv.classList.add('hanging-indent');
|
||||
citeDiv.classList.add('csl-entry');
|
||||
var biblioDiv = window.document.getElementById('ref-' + cite);
|
||||
if (biblioDiv) {
|
||||
citeDiv.innerHTML = biblioDiv.innerHTML;
|
||||
}
|
||||
popup.appendChild(citeDiv);
|
||||
});
|
||||
return popup.innerHTML;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<nav class="page-navigation">
|
||||
<div class="nav-page nav-page-previous">
|
||||
<a href="./ch4.html" class="pagination-link">
|
||||
<i class="bi bi-arrow-left-short"></i> <span class="nav-page-text"><span class="chapter-number">4</span> <span class="chapter-title">Application Development</span></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="nav-page nav-page-next">
|
||||
<a href="./RojavaRefineries.html" class="pagination-link">
|
||||
<span class="nav-page-text">Refinery Detection</span> <i class="bi bi-arrow-right-short"></i>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</div> <!-- /content -->
|
||||
|
||||
|
||||
|
||||
</body></html>
|
||||
494
docs/ch3.html
@@ -1,494 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.2.269">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
|
||||
<title>Google Earth Engine for OSINT - 3 Algorithms</title>
|
||||
<style>
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
ul.task-list{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script src="site_libs/quarto-nav/quarto-nav.js"></script>
|
||||
<script src="site_libs/quarto-nav/headroom.min.js"></script>
|
||||
<script src="site_libs/clipboard/clipboard.min.js"></script>
|
||||
<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
|
||||
<script src="site_libs/quarto-search/fuse.min.js"></script>
|
||||
<script src="site_libs/quarto-search/quarto-search.js"></script>
|
||||
<meta name="quarto:offset" content="./">
|
||||
<link href="./ch4.html" rel="next">
|
||||
<link href="./ch2.html" rel="prev">
|
||||
<script src="site_libs/quarto-html/quarto.js"></script>
|
||||
<script src="site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="site_libs/quarto-html/quarto-syntax-highlighting.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="site_libs/quarto-html/quarto-syntax-highlighting-dark.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<script src="site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="site_libs/bootstrap/bootstrap.min.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="site_libs/bootstrap/bootstrap-dark.min.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "sidebar",
|
||||
"copy-button": false,
|
||||
"collapse-after": 3,
|
||||
"panel-placement": "start",
|
||||
"type": "textbox",
|
||||
"limit": 20,
|
||||
"language": {
|
||||
"search-no-results-text": "No results",
|
||||
"search-matching-documents-text": "matching documents",
|
||||
"search-copy-link-title": "Copy link to search",
|
||||
"search-hide-matches-text": "Hide additional matches",
|
||||
"search-more-match-text": "more match in this document",
|
||||
"search-more-matches-text": "more matches in this document",
|
||||
"search-clear-button-title": "Clear",
|
||||
"search-detached-cancel-button-title": "Cancel",
|
||||
"search-submit-button-title": "Submit"
|
||||
}
|
||||
}</script>
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body class="nav-sidebar floating">
|
||||
|
||||
<div id="quarto-search-results"></div>
|
||||
<header id="quarto-header" class="headroom fixed-top">
|
||||
<nav class="quarto-secondary-nav" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
|
||||
<div class="container-fluid d-flex justify-content-between">
|
||||
<h1 class="quarto-secondary-nav-title"><span class="chapter-number">3</span> <span class="chapter-title">Algorithms</span></h1>
|
||||
<button type="button" class="quarto-btn-toggle btn" aria-label="Show secondary navigation">
|
||||
<i class="bi bi-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<!-- content -->
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse sidebar-navigation floating overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header sidebar-header-stacked">
|
||||
<a href="./index.html" class="sidebar-logo-link">
|
||||
<img src="./logo_white.png" alt="" class="sidebar-logo py-0 d-lg-inline d-none">
|
||||
</a>
|
||||
<div class="sidebar-title mb-0 py-0">
|
||||
<a href="./">Google Earth Engine for OSINT</a>
|
||||
<div class="sidebar-tools-main tools-wide">
|
||||
<a href="https://github.com/oballinger/GEE_OSINT/" title="Source Code" class="sidebar-tool px-1"><i class="bi bi-github"></i></a>
|
||||
<a href="" title="Download" id="sidebar-tool-dropdown-0" class="sidebar-tool dropdown-toggle px-1" data-bs-toggle="dropdown" aria-expanded="false"><i class="bi bi-download"></i></a>
|
||||
<ul class="dropdown-menu" aria-labelledby="sidebar-tool-dropdown-0">
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="./Google-Earth-Engine-for-OSINT.pdf">
|
||||
<i class="bi bi-bi-file-pdf pe-1"></i>
|
||||
Download PDF
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="./Google-Earth-Engine-for-OSINT.epub">
|
||||
<i class="bi bi-bi-journal pe-1"></i>
|
||||
Download ePub
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a href="" title="Share" id="sidebar-tool-dropdown-1" class="sidebar-tool dropdown-toggle px-1" data-bs-toggle="dropdown" aria-expanded="false"><i class="bi bi-share"></i></a>
|
||||
<ul class="dropdown-menu" aria-labelledby="sidebar-tool-dropdown-1">
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="https://twitter.com/intent/tweet?url=|url|">
|
||||
<i class="bi bi-bi-twitter pe-1"></i>
|
||||
Twitter
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="https://www.facebook.com/sharer/sharer.php?u=|url|">
|
||||
<i class="bi bi-bi-facebook pe-1"></i>
|
||||
Facebook
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a href="" class="quarto-color-scheme-toggle sidebar-tool" onclick="window.quartoToggleColorScheme(); return false;" title="Toggle dark mode"><i class="bi"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 flex-shrink-0 align-items-center">
|
||||
<div class="sidebar-search">
|
||||
<div id="quarto-search" class="" title="Search"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./index.html" class="sidebar-item-text sidebar-link">Introduction</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
<div class="sidebar-item-container">
|
||||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-1" aria-expanded="true">Learning</a>
|
||||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-1" aria-expanded="true">
|
||||
<i class="bi bi-chevron-right ms-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
<ul id="quarto-sidebar-section-1" class="collapse list-unstyled sidebar-section depth1 show">
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch1.html" class="sidebar-item-text sidebar-link"><span class="chapter-number">1</span> <span class="chapter-title">Remote Sensing</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch2.html" class="sidebar-item-text sidebar-link"><span class="chapter-number">2</span> <span class="chapter-title">Data Acquisition</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch3.html" class="sidebar-item-text sidebar-link active"><span class="chapter-number">3</span> <span class="chapter-title">Algorithms</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch4.html" class="sidebar-item-text sidebar-link"><span class="chapter-number">4</span> <span class="chapter-title">Application Development</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
<div class="sidebar-item-container">
|
||||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-2" aria-expanded="true">Case Studies</a>
|
||||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-2" aria-expanded="true">
|
||||
<i class="bi bi-chevron-right ms-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
<ul id="quarto-sidebar-section-2" class="collapse list-unstyled sidebar-section depth1 show">
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./SyriaNTL.html" class="sidebar-item-text sidebar-link">War at Night</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./RojavaRefineries.html" class="sidebar-item-text sidebar-link">Refinery Detection</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- margin-sidebar -->
|
||||
<div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
|
||||
<nav id="TOC" role="doc-toc" class="toc-active">
|
||||
<h2 id="toc-title">Table of contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#getting-started" id="toc-getting-started" class="nav-link active" data-scroll-target="#getting-started"><span class="toc-section-number">3.1</span> Getting Started</a></li>
|
||||
</ul>
|
||||
<div class="toc-actions"><div><i class="bi bi-github"></i></div><div class="action-links"><p><a href="https://github.com/oballinger/GEE_OSINT/edit/main/ch3.qmd" class="toc-action">Edit this page</a></p></div></div></nav>
|
||||
</div>
|
||||
<!-- main -->
|
||||
<main class="content" id="quarto-document-content">
|
||||
|
||||
<header id="title-block-header" class="quarto-title-block default">
|
||||
<div class="quarto-title">
|
||||
<h1 class="title"><span id="sec-algorithms" class="quarto-section-identifier d-none d-lg-block"><span class="chapter-number">3</span> <span class="chapter-title">Algorithms</span></span></h1>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="quarto-title-meta">
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<section id="getting-started" class="level2" data-number="3.1">
|
||||
<h2 data-number="3.1" class="anchored" data-anchor-id="getting-started"><span class="header-section-number">3.1</span> Getting Started</h2>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
</main> <!-- /main -->
|
||||
<script id="quarto-html-after-body" type="application/javascript">
|
||||
window.document.addEventListener("DOMContentLoaded", function (event) {
|
||||
const toggleBodyColorMode = (bsSheetEl) => {
|
||||
const mode = bsSheetEl.getAttribute("data-mode");
|
||||
const bodyEl = window.document.querySelector("body");
|
||||
if (mode === "dark") {
|
||||
bodyEl.classList.add("quarto-dark");
|
||||
bodyEl.classList.remove("quarto-light");
|
||||
} else {
|
||||
bodyEl.classList.add("quarto-light");
|
||||
bodyEl.classList.remove("quarto-dark");
|
||||
}
|
||||
}
|
||||
const toggleBodyColorPrimary = () => {
|
||||
const bsSheetEl = window.document.querySelector("link#quarto-bootstrap");
|
||||
if (bsSheetEl) {
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
toggleBodyColorPrimary();
|
||||
const disableStylesheet = (stylesheets) => {
|
||||
for (let i=0; i < stylesheets.length; i++) {
|
||||
const stylesheet = stylesheets[i];
|
||||
stylesheet.rel = 'prefetch';
|
||||
}
|
||||
}
|
||||
const enableStylesheet = (stylesheets) => {
|
||||
for (let i=0; i < stylesheets.length; i++) {
|
||||
const stylesheet = stylesheets[i];
|
||||
stylesheet.rel = 'stylesheet';
|
||||
}
|
||||
}
|
||||
const manageTransitions = (selector, allowTransitions) => {
|
||||
const els = window.document.querySelectorAll(selector);
|
||||
for (let i=0; i < els.length; i++) {
|
||||
const el = els[i];
|
||||
if (allowTransitions) {
|
||||
el.classList.remove('notransition');
|
||||
} else {
|
||||
el.classList.add('notransition');
|
||||
}
|
||||
}
|
||||
}
|
||||
const toggleColorMode = (alternate) => {
|
||||
// Switch the stylesheets
|
||||
const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate');
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', false);
|
||||
if (alternate) {
|
||||
enableStylesheet(alternateStylesheets);
|
||||
for (const sheetNode of alternateStylesheets) {
|
||||
if (sheetNode.id === "quarto-bootstrap") {
|
||||
toggleBodyColorMode(sheetNode);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
disableStylesheet(alternateStylesheets);
|
||||
toggleBodyColorPrimary();
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
if (toggle) {
|
||||
if (alternate) {
|
||||
toggle.classList.add("alternate");
|
||||
} else {
|
||||
toggle.classList.remove("alternate");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
manageTransitions("body", false);
|
||||
window.scrollTo(0, 1);
|
||||
setTimeout(() => {
|
||||
window.scrollTo(0, 0);
|
||||
manageTransitions("body", true);
|
||||
}, 40);
|
||||
}
|
||||
}
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const setStyleSentinel = (alternate) => {
|
||||
const value = alternate ? "alternate" : "default";
|
||||
if (!isFileUrl()) {
|
||||
window.localStorage.setItem("quarto-color-scheme", value);
|
||||
} else {
|
||||
localAlternateSentinel = value;
|
||||
}
|
||||
}
|
||||
const getColorSchemeSentinel = () => {
|
||||
if (!isFileUrl()) {
|
||||
const storageValue = window.localStorage.getItem("quarto-color-scheme");
|
||||
return storageValue != null ? storageValue : localAlternateSentinel;
|
||||
} else {
|
||||
return localAlternateSentinel;
|
||||
}
|
||||
}
|
||||
let localAlternateSentinel = 'alternate';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
};
|
||||
// Ensure there is a toggle, if there isn't float one in the top right
|
||||
if (window.document.querySelector('.quarto-color-scheme-toggle') === null) {
|
||||
const a = window.document.createElement('a');
|
||||
a.classList.add('top-right');
|
||||
a.classList.add('quarto-color-scheme-toggle');
|
||||
a.href = "";
|
||||
a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; };
|
||||
const i = window.document.createElement("i");
|
||||
i.classList.add('bi');
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
// Switch to dark mode if need be
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
}
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
placement: 'right',
|
||||
icon: icon
|
||||
};
|
||||
anchorJS.add('.anchored');
|
||||
const clipboard = new window.ClipboardJS('.code-copy-button', {
|
||||
target: function(trigger) {
|
||||
return trigger.previousElementSibling;
|
||||
}
|
||||
});
|
||||
clipboard.on('success', function(e) {
|
||||
// button target
|
||||
const button = e.trigger;
|
||||
// don't keep focus
|
||||
button.blur();
|
||||
// flash "checked"
|
||||
button.classList.add('code-copy-button-checked');
|
||||
var currentTitle = button.getAttribute("title");
|
||||
button.setAttribute("title", "Copied!");
|
||||
let tooltip;
|
||||
if (window.bootstrap) {
|
||||
button.setAttribute("data-bs-toggle", "tooltip");
|
||||
button.setAttribute("data-bs-placement", "left");
|
||||
button.setAttribute("data-bs-title", "Copied!");
|
||||
tooltip = new bootstrap.Tooltip(button,
|
||||
{ trigger: "manual",
|
||||
customClass: "code-copy-button-tooltip",
|
||||
offset: [0, -8]});
|
||||
tooltip.show();
|
||||
}
|
||||
setTimeout(function() {
|
||||
if (tooltip) {
|
||||
tooltip.hide();
|
||||
button.removeAttribute("data-bs-title");
|
||||
button.removeAttribute("data-bs-toggle");
|
||||
button.removeAttribute("data-bs-placement");
|
||||
}
|
||||
button.setAttribute("title", currentTitle);
|
||||
button.classList.remove('code-copy-button-checked');
|
||||
}, 1000);
|
||||
// clear code selection
|
||||
e.clearSelection();
|
||||
});
|
||||
function tippyHover(el, contentFn) {
|
||||
const config = {
|
||||
allowHTML: true,
|
||||
content: contentFn,
|
||||
maxWidth: 500,
|
||||
delay: 100,
|
||||
arrow: false,
|
||||
appendTo: function(el) {
|
||||
return el.parentElement;
|
||||
},
|
||||
interactive: true,
|
||||
interactiveBorder: 10,
|
||||
theme: 'quarto',
|
||||
placement: 'bottom-start'
|
||||
};
|
||||
window.tippy(el, config);
|
||||
}
|
||||
const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
|
||||
for (var i=0; i<noterefs.length; i++) {
|
||||
const ref = noterefs[i];
|
||||
tippyHover(ref, function() {
|
||||
// use id or data attribute instead here
|
||||
let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
|
||||
try { href = new URL(href).hash; } catch {}
|
||||
const id = href.replace(/^#\/?/, "");
|
||||
const note = window.document.getElementById(id);
|
||||
return note.innerHTML;
|
||||
});
|
||||
}
|
||||
const findCites = (el) => {
|
||||
const parentEl = el.parentElement;
|
||||
if (parentEl) {
|
||||
const cites = parentEl.dataset.cites;
|
||||
if (cites) {
|
||||
return {
|
||||
el,
|
||||
cites: cites.split(' ')
|
||||
};
|
||||
} else {
|
||||
return findCites(el.parentElement)
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
|
||||
for (var i=0; i<bibliorefs.length; i++) {
|
||||
const ref = bibliorefs[i];
|
||||
const citeInfo = findCites(ref);
|
||||
if (citeInfo) {
|
||||
tippyHover(citeInfo.el, function() {
|
||||
var popup = window.document.createElement('div');
|
||||
citeInfo.cites.forEach(function(cite) {
|
||||
var citeDiv = window.document.createElement('div');
|
||||
citeDiv.classList.add('hanging-indent');
|
||||
citeDiv.classList.add('csl-entry');
|
||||
var biblioDiv = window.document.getElementById('ref-' + cite);
|
||||
if (biblioDiv) {
|
||||
citeDiv.innerHTML = biblioDiv.innerHTML;
|
||||
}
|
||||
popup.appendChild(citeDiv);
|
||||
});
|
||||
return popup.innerHTML;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<nav class="page-navigation">
|
||||
<div class="nav-page nav-page-previous">
|
||||
<a href="./ch2.html" class="pagination-link">
|
||||
<i class="bi bi-arrow-left-short"></i> <span class="nav-page-text"><span class="chapter-number">2</span> <span class="chapter-title">Data Acquisition</span></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="nav-page nav-page-next">
|
||||
<a href="./ch4.html" class="pagination-link">
|
||||
<span class="nav-page-text"><span class="chapter-number">4</span> <span class="chapter-title">Application Development</span></span> <i class="bi bi-arrow-right-short"></i>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</div> <!-- /content -->
|
||||
|
||||
|
||||
|
||||
</body></html>
|
||||
485
docs/ch4.html
@@ -1,485 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="quarto-1.2.269">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
|
||||
|
||||
<title>Google Earth Engine for OSINT - 4 Application Development</title>
|
||||
<style>
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||
div.column{flex: auto; overflow-x: auto;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
ul.task-list{list-style: none;}
|
||||
ul.task-list li input[type="checkbox"] {
|
||||
width: 0.8em;
|
||||
margin: 0 0.8em 0.2em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script src="site_libs/quarto-nav/quarto-nav.js"></script>
|
||||
<script src="site_libs/quarto-nav/headroom.min.js"></script>
|
||||
<script src="site_libs/clipboard/clipboard.min.js"></script>
|
||||
<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
|
||||
<script src="site_libs/quarto-search/fuse.min.js"></script>
|
||||
<script src="site_libs/quarto-search/quarto-search.js"></script>
|
||||
<meta name="quarto:offset" content="./">
|
||||
<link href="./SyriaNTL.html" rel="next">
|
||||
<link href="./ch3.html" rel="prev">
|
||||
<script src="site_libs/quarto-html/quarto.js"></script>
|
||||
<script src="site_libs/quarto-html/popper.min.js"></script>
|
||||
<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
|
||||
<script src="site_libs/quarto-html/anchor.min.js"></script>
|
||||
<link href="site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||||
<link href="site_libs/quarto-html/quarto-syntax-highlighting.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||||
<link href="site_libs/quarto-html/quarto-syntax-highlighting-dark.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||||
<script src="site_libs/bootstrap/bootstrap.min.js"></script>
|
||||
<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||
<link href="site_libs/bootstrap/bootstrap.min.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||||
<link href="site_libs/bootstrap/bootstrap-dark.min.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
|
||||
<script id="quarto-search-options" type="application/json">{
|
||||
"location": "sidebar",
|
||||
"copy-button": false,
|
||||
"collapse-after": 3,
|
||||
"panel-placement": "start",
|
||||
"type": "textbox",
|
||||
"limit": 20,
|
||||
"language": {
|
||||
"search-no-results-text": "No results",
|
||||
"search-matching-documents-text": "matching documents",
|
||||
"search-copy-link-title": "Copy link to search",
|
||||
"search-hide-matches-text": "Hide additional matches",
|
||||
"search-more-match-text": "more match in this document",
|
||||
"search-more-matches-text": "more matches in this document",
|
||||
"search-clear-button-title": "Clear",
|
||||
"search-detached-cancel-button-title": "Cancel",
|
||||
"search-submit-button-title": "Submit"
|
||||
}
|
||||
}</script>
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body class="nav-sidebar floating">
|
||||
|
||||
<div id="quarto-search-results"></div>
|
||||
<header id="quarto-header" class="headroom fixed-top">
|
||||
<nav class="quarto-secondary-nav" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
|
||||
<div class="container-fluid d-flex justify-content-between">
|
||||
<h1 class="quarto-secondary-nav-title"><span class="chapter-number">4</span> <span class="chapter-title">Application Development</span></h1>
|
||||
<button type="button" class="quarto-btn-toggle btn" aria-label="Show secondary navigation">
|
||||
<i class="bi bi-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<!-- content -->
|
||||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article">
|
||||
<!-- sidebar -->
|
||||
<nav id="quarto-sidebar" class="sidebar collapse sidebar-navigation floating overflow-auto">
|
||||
<div class="pt-lg-2 mt-2 text-left sidebar-header sidebar-header-stacked">
|
||||
<a href="./index.html" class="sidebar-logo-link">
|
||||
<img src="./logo_white.png" alt="" class="sidebar-logo py-0 d-lg-inline d-none">
|
||||
</a>
|
||||
<div class="sidebar-title mb-0 py-0">
|
||||
<a href="./">Google Earth Engine for OSINT</a>
|
||||
<div class="sidebar-tools-main tools-wide">
|
||||
<a href="https://github.com/oballinger/GEE_OSINT/" title="Source Code" class="sidebar-tool px-1"><i class="bi bi-github"></i></a>
|
||||
<a href="" title="Download" id="sidebar-tool-dropdown-0" class="sidebar-tool dropdown-toggle px-1" data-bs-toggle="dropdown" aria-expanded="false"><i class="bi bi-download"></i></a>
|
||||
<ul class="dropdown-menu" aria-labelledby="sidebar-tool-dropdown-0">
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="./Google-Earth-Engine-for-OSINT.pdf">
|
||||
<i class="bi bi-bi-file-pdf pe-1"></i>
|
||||
Download PDF
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="./Google-Earth-Engine-for-OSINT.epub">
|
||||
<i class="bi bi-bi-journal pe-1"></i>
|
||||
Download ePub
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a href="" title="Share" id="sidebar-tool-dropdown-1" class="sidebar-tool dropdown-toggle px-1" data-bs-toggle="dropdown" aria-expanded="false"><i class="bi bi-share"></i></a>
|
||||
<ul class="dropdown-menu" aria-labelledby="sidebar-tool-dropdown-1">
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="https://twitter.com/intent/tweet?url=|url|">
|
||||
<i class="bi bi-bi-twitter pe-1"></i>
|
||||
Twitter
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item sidebar-tools-main-item" href="https://www.facebook.com/sharer/sharer.php?u=|url|">
|
||||
<i class="bi bi-bi-facebook pe-1"></i>
|
||||
Facebook
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a href="" class="quarto-color-scheme-toggle sidebar-tool" onclick="window.quartoToggleColorScheme(); return false;" title="Toggle dark mode"><i class="bi"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 flex-shrink-0 align-items-center">
|
||||
<div class="sidebar-search">
|
||||
<div id="quarto-search" class="" title="Search"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-menu-container">
|
||||
<ul class="list-unstyled mt-1">
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./index.html" class="sidebar-item-text sidebar-link">Introduction</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
<div class="sidebar-item-container">
|
||||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-1" aria-expanded="true">Learning</a>
|
||||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-1" aria-expanded="true">
|
||||
<i class="bi bi-chevron-right ms-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
<ul id="quarto-sidebar-section-1" class="collapse list-unstyled sidebar-section depth1 show">
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch1.html" class="sidebar-item-text sidebar-link"><span class="chapter-number">1</span> <span class="chapter-title">Remote Sensing</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch2.html" class="sidebar-item-text sidebar-link"><span class="chapter-number">2</span> <span class="chapter-title">Data Acquisition</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch3.html" class="sidebar-item-text sidebar-link"><span class="chapter-number">3</span> <span class="chapter-title">Algorithms</span></a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./ch4.html" class="sidebar-item-text sidebar-link active"><span class="chapter-number">4</span> <span class="chapter-title">Application Development</span></a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="sidebar-item sidebar-item-section">
|
||||
<div class="sidebar-item-container">
|
||||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-2" aria-expanded="true">Case Studies</a>
|
||||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-2" aria-expanded="true">
|
||||
<i class="bi bi-chevron-right ms-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
<ul id="quarto-sidebar-section-2" class="collapse list-unstyled sidebar-section depth1 show">
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./SyriaNTL.html" class="sidebar-item-text sidebar-link">War at Night</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<div class="sidebar-item-container">
|
||||
<a href="./RojavaRefineries.html" class="sidebar-item-text sidebar-link">Refinery Detection</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- margin-sidebar -->
|
||||
<div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
|
||||
|
||||
</div>
|
||||
<!-- main -->
|
||||
<main class="content" id="quarto-document-content">
|
||||
|
||||
<header id="title-block-header" class="quarto-title-block default">
|
||||
<div class="quarto-title">
|
||||
<h1 class="title d-none d-lg-block"><span class="chapter-number">4</span> <span class="chapter-title">Application Development</span></h1>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="quarto-title-meta">
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
|
||||
</main> <!-- /main -->
|
||||
<script id="quarto-html-after-body" type="application/javascript">
|
||||
window.document.addEventListener("DOMContentLoaded", function (event) {
|
||||
const toggleBodyColorMode = (bsSheetEl) => {
|
||||
const mode = bsSheetEl.getAttribute("data-mode");
|
||||
const bodyEl = window.document.querySelector("body");
|
||||
if (mode === "dark") {
|
||||
bodyEl.classList.add("quarto-dark");
|
||||
bodyEl.classList.remove("quarto-light");
|
||||
} else {
|
||||
bodyEl.classList.add("quarto-light");
|
||||
bodyEl.classList.remove("quarto-dark");
|
||||
}
|
||||
}
|
||||
const toggleBodyColorPrimary = () => {
|
||||
const bsSheetEl = window.document.querySelector("link#quarto-bootstrap");
|
||||
if (bsSheetEl) {
|
||||
toggleBodyColorMode(bsSheetEl);
|
||||
}
|
||||
}
|
||||
toggleBodyColorPrimary();
|
||||
const disableStylesheet = (stylesheets) => {
|
||||
for (let i=0; i < stylesheets.length; i++) {
|
||||
const stylesheet = stylesheets[i];
|
||||
stylesheet.rel = 'prefetch';
|
||||
}
|
||||
}
|
||||
const enableStylesheet = (stylesheets) => {
|
||||
for (let i=0; i < stylesheets.length; i++) {
|
||||
const stylesheet = stylesheets[i];
|
||||
stylesheet.rel = 'stylesheet';
|
||||
}
|
||||
}
|
||||
const manageTransitions = (selector, allowTransitions) => {
|
||||
const els = window.document.querySelectorAll(selector);
|
||||
for (let i=0; i < els.length; i++) {
|
||||
const el = els[i];
|
||||
if (allowTransitions) {
|
||||
el.classList.remove('notransition');
|
||||
} else {
|
||||
el.classList.add('notransition');
|
||||
}
|
||||
}
|
||||
}
|
||||
const toggleColorMode = (alternate) => {
|
||||
// Switch the stylesheets
|
||||
const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate');
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', false);
|
||||
if (alternate) {
|
||||
enableStylesheet(alternateStylesheets);
|
||||
for (const sheetNode of alternateStylesheets) {
|
||||
if (sheetNode.id === "quarto-bootstrap") {
|
||||
toggleBodyColorMode(sheetNode);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
disableStylesheet(alternateStylesheets);
|
||||
toggleBodyColorPrimary();
|
||||
}
|
||||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||||
// Switch the toggles
|
||||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||||
for (let i=0; i < toggles.length; i++) {
|
||||
const toggle = toggles[i];
|
||||
if (toggle) {
|
||||
if (alternate) {
|
||||
toggle.classList.add("alternate");
|
||||
} else {
|
||||
toggle.classList.remove("alternate");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Hack to workaround the fact that safari doesn't
|
||||
// properly recolor the scrollbar when toggling (#1455)
|
||||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||||
manageTransitions("body", false);
|
||||
window.scrollTo(0, 1);
|
||||
setTimeout(() => {
|
||||
window.scrollTo(0, 0);
|
||||
manageTransitions("body", true);
|
||||
}, 40);
|
||||
}
|
||||
}
|
||||
const isFileUrl = () => {
|
||||
return window.location.protocol === 'file:';
|
||||
}
|
||||
const hasAlternateSentinel = () => {
|
||||
let styleSentinel = getColorSchemeSentinel();
|
||||
if (styleSentinel !== null) {
|
||||
return styleSentinel === "alternate";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const setStyleSentinel = (alternate) => {
|
||||
const value = alternate ? "alternate" : "default";
|
||||
if (!isFileUrl()) {
|
||||
window.localStorage.setItem("quarto-color-scheme", value);
|
||||
} else {
|
||||
localAlternateSentinel = value;
|
||||
}
|
||||
}
|
||||
const getColorSchemeSentinel = () => {
|
||||
if (!isFileUrl()) {
|
||||
const storageValue = window.localStorage.getItem("quarto-color-scheme");
|
||||
return storageValue != null ? storageValue : localAlternateSentinel;
|
||||
} else {
|
||||
return localAlternateSentinel;
|
||||
}
|
||||
}
|
||||
let localAlternateSentinel = 'alternate';
|
||||
// Dark / light mode switch
|
||||
window.quartoToggleColorScheme = () => {
|
||||
// Read the current dark / light value
|
||||
let toAlternate = !hasAlternateSentinel();
|
||||
toggleColorMode(toAlternate);
|
||||
setStyleSentinel(toAlternate);
|
||||
};
|
||||
// Ensure there is a toggle, if there isn't float one in the top right
|
||||
if (window.document.querySelector('.quarto-color-scheme-toggle') === null) {
|
||||
const a = window.document.createElement('a');
|
||||
a.classList.add('top-right');
|
||||
a.classList.add('quarto-color-scheme-toggle');
|
||||
a.href = "";
|
||||
a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; };
|
||||
const i = window.document.createElement("i");
|
||||
i.classList.add('bi');
|
||||
a.appendChild(i);
|
||||
window.document.body.appendChild(a);
|
||||
}
|
||||
// Switch to dark mode if need be
|
||||
if (hasAlternateSentinel()) {
|
||||
toggleColorMode(true);
|
||||
} else {
|
||||
toggleColorMode(false);
|
||||
}
|
||||
const icon = "";
|
||||
const anchorJS = new window.AnchorJS();
|
||||
anchorJS.options = {
|
||||
placement: 'right',
|
||||
icon: icon
|
||||
};
|
||||
anchorJS.add('.anchored');
|
||||
const clipboard = new window.ClipboardJS('.code-copy-button', {
|
||||
target: function(trigger) {
|
||||
return trigger.previousElementSibling;
|
||||
}
|
||||
});
|
||||
clipboard.on('success', function(e) {
|
||||
// button target
|
||||
const button = e.trigger;
|
||||
// don't keep focus
|
||||
button.blur();
|
||||
// flash "checked"
|
||||
button.classList.add('code-copy-button-checked');
|
||||
var currentTitle = button.getAttribute("title");
|
||||
button.setAttribute("title", "Copied!");
|
||||
let tooltip;
|
||||
if (window.bootstrap) {
|
||||
button.setAttribute("data-bs-toggle", "tooltip");
|
||||
button.setAttribute("data-bs-placement", "left");
|
||||
button.setAttribute("data-bs-title", "Copied!");
|
||||
tooltip = new bootstrap.Tooltip(button,
|
||||
{ trigger: "manual",
|
||||
customClass: "code-copy-button-tooltip",
|
||||
offset: [0, -8]});
|
||||
tooltip.show();
|
||||
}
|
||||
setTimeout(function() {
|
||||
if (tooltip) {
|
||||
tooltip.hide();
|
||||
button.removeAttribute("data-bs-title");
|
||||
button.removeAttribute("data-bs-toggle");
|
||||
button.removeAttribute("data-bs-placement");
|
||||
}
|
||||
button.setAttribute("title", currentTitle);
|
||||
button.classList.remove('code-copy-button-checked');
|
||||
}, 1000);
|
||||
// clear code selection
|
||||
e.clearSelection();
|
||||
});
|
||||
function tippyHover(el, contentFn) {
|
||||
const config = {
|
||||
allowHTML: true,
|
||||
content: contentFn,
|
||||
maxWidth: 500,
|
||||
delay: 100,
|
||||
arrow: false,
|
||||
appendTo: function(el) {
|
||||
return el.parentElement;
|
||||
},
|
||||
interactive: true,
|
||||
interactiveBorder: 10,
|
||||
theme: 'quarto',
|
||||
placement: 'bottom-start'
|
||||
};
|
||||
window.tippy(el, config);
|
||||
}
|
||||
const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
|
||||
for (var i=0; i<noterefs.length; i++) {
|
||||
const ref = noterefs[i];
|
||||
tippyHover(ref, function() {
|
||||
// use id or data attribute instead here
|
||||
let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
|
||||
try { href = new URL(href).hash; } catch {}
|
||||
const id = href.replace(/^#\/?/, "");
|
||||
const note = window.document.getElementById(id);
|
||||
return note.innerHTML;
|
||||
});
|
||||
}
|
||||
const findCites = (el) => {
|
||||
const parentEl = el.parentElement;
|
||||
if (parentEl) {
|
||||
const cites = parentEl.dataset.cites;
|
||||
if (cites) {
|
||||
return {
|
||||
el,
|
||||
cites: cites.split(' ')
|
||||
};
|
||||
} else {
|
||||
return findCites(el.parentElement)
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
|
||||
for (var i=0; i<bibliorefs.length; i++) {
|
||||
const ref = bibliorefs[i];
|
||||
const citeInfo = findCites(ref);
|
||||
if (citeInfo) {
|
||||
tippyHover(citeInfo.el, function() {
|
||||
var popup = window.document.createElement('div');
|
||||
citeInfo.cites.forEach(function(cite) {
|
||||
var citeDiv = window.document.createElement('div');
|
||||
citeDiv.classList.add('hanging-indent');
|
||||
citeDiv.classList.add('csl-entry');
|
||||
var biblioDiv = window.document.getElementById('ref-' + cite);
|
||||
if (biblioDiv) {
|
||||
citeDiv.innerHTML = biblioDiv.innerHTML;
|
||||
}
|
||||
popup.appendChild(citeDiv);
|
||||
});
|
||||
return popup.innerHTML;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<nav class="page-navigation">
|
||||
<div class="nav-page nav-page-previous">
|
||||
<a href="./ch3.html" class="pagination-link">
|
||||
<i class="bi bi-arrow-left-short"></i> <span class="nav-page-text"><span class="chapter-number">3</span> <span class="chapter-title">Algorithms</span></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="nav-page nav-page-next">
|
||||
<a href="./SyriaNTL.html" class="pagination-link">
|
||||
<span class="nav-page-text">War at Night</span> <i class="bi bi-arrow-right-short"></i>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</div> <!-- /content -->
|
||||
|
||||
|
||||
|
||||
</body></html>
|
||||
|
Before Width: | Height: | Size: 8.4 MiB |
|
Before Width: | Height: | Size: 791 KiB |
|
Before Width: | Height: | Size: 3.9 MiB |
|
Before Width: | Height: | Size: 625 KiB |
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 2.3 MiB |
|
Before Width: | Height: | Size: 6.1 MiB |
|
Before Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 262 KiB |
|
Before Width: | Height: | Size: 609 KiB |
|
Before Width: | Height: | Size: 511 KiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 6.4 MiB |
|
Before Width: | Height: | Size: 746 KiB |
|
Before Width: | Height: | Size: 2.5 MiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 232 KiB |
|
Before Width: | Height: | Size: 4.0 MiB |
|
Before Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 384 KiB |
|
Before Width: | Height: | Size: 184 KiB |
|
Before Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 924 KiB |
|
Before Width: | Height: | Size: 1014 KiB |
|
Before Width: | Height: | Size: 877 KiB |
|
Before Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 72 KiB |
135
docs/search.json
@@ -63,6 +63,15 @@ ul.task-list li input[type="checkbox"] {
|
||||
"search-submit-button-title": "Submit"
|
||||
}
|
||||
}</script>
|
||||
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-RK9ZLZQ6GL"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-RK9ZLZQ6GL', { 'anonymize_ip': true});
|
||||
</script>
|
||||
|
||||
|
||||
</head>
|
||||
@@ -199,6 +208,7 @@ ul.task-list li input[type="checkbox"] {
|
||||
<ul>
|
||||
<li><a href="#introduction" id="toc-introduction" class="nav-link active" data-scroll-target="#introduction">Introduction</a>
|
||||
<ul class="collapse">
|
||||
<li><a href="#table-of-contents" id="toc-table-of-contents" class="nav-link" data-scroll-target="#table-of-contents">Table of Contents</a></li>
|
||||
<li><a href="#what-is-google-earth-engine" id="toc-what-is-google-earth-engine" class="nav-link" data-scroll-target="#what-is-google-earth-engine">What is Google Earth Engine?</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
@@ -238,14 +248,25 @@ ul.task-list li input[type="checkbox"] {
|
||||
|
||||
<section id="introduction" class="level1 unnumbered">
|
||||
<h1 class="unnumbered">Introduction</h1>
|
||||
<p>The analysis of satellite imagery is a foundational element of open source investigations. Though no-code platforms such as Sentinelhub have been invaluable in allowing the OSINT community to access and process satellite imagery, the analytical capabilities of these platforms are limited. <a href="https://earthengine.google.com/#intro">Google Earth Engine (GEE)</a> is a cloud-based platform that stores petabytes of satellite imagery from a variety of sources and allows users to perform advanced analyses on Google servers for free using a browser-based interface. This textbook is designed for investigators who want to perform more sophisticated analysis using geospatial data, and assumes no prior knowledge of coding or remote sensing (satellite imagery analysis). It is organized into four chapters:</p>
|
||||
<p>The analysis of satellite imagery is a foundational element of open source investigations. In the past decade, the quantity, quality, and availability thereof has increased dramatically. Capabilities and insights that were once only available to governments are now accessible to the general public. Satellite imagery is being used to collect evidence of genocide and other war crimes in <a href="https://www.nbcnews.com/science/science-news/ukraine-satellites-war-crimes-rcna26291">Ukraine</a>, <a href="https://www.amnesty.org/en/latest/news/2016/04/nigeria-military-cover-up-of-mass-slaughter-at-zaria-exposed/">Nigeria</a>, <a href="https://www.amnesty.org/en/latest/news/2016/01/burundi-satellite-evidence-supports-witness-accounts-of-mass-graves/">Burundi</a>, <a href="https://www.amnesty.org/en/latest/news/2021/07/cameroon-satellite-images-reveal-devastation-in-anglophone-regions-2/">Cameroon</a>, <a href="https://www.aaas.org/resources/satellite-imagery-assessment-forced-relocations-near-luiswishi-mine">the DRC</a>, <a href="https://gsp.yale.edu/case-studies/sudan/maps-satellite-images/other-darfur-satellite-imagery">South Sudan</a>, <a href="https://gsp.yale.edu/resources/maps-satellite-images/papua">Papua</a>, and <a href="https://www.hrw.org/report/2016/04/04/unchecked-power/police-and-military-raids-low-income-and-immigrant-communities">Venezuela</a>. It has been used to <a href="https://www.theguardian.com/environment/2016/mar/02/new-satellite-mapping-a-game-changer-against-illegal-logging">monitor environmental degradation</a> and hold extractive industries to account from <a href="https://www.bellingcat.com/resources/2021/04/15/what-oil-satellite-technology-and-iraq-can-tell-us-about-pollution/">Iraq</a> to <a href="https://www.planet.com/pulse/the-observatory-of-extractive-industries-oie-shines-a-light-on-the-mining-industry-using-planets-satellite-data/">Guatemala</a>. The ability to analyze satellite imagery is a critical skill for anyone interested in open source investigations.</p>
|
||||
<p>Though no-code platforms such as Sentinelhub have been invaluable in allowing the OSINT community to access and process satellite imagery, the analytical capabilities of these platforms are limited. <a href="https://earthengine.google.com/#intro">Google Earth Engine (GEE)</a> is a cloud-based platform that stores petabytes of satellite imagery from a variety of sources and allows users to perform advanced analyses on Google servers for free using a browser-based interface. This textbook is designed for investigators who want to perform more sophisticated analysis using geospatial data, and assumes no prior knowledge of coding or remote sensing (satellite imagery analysis). It is organized into two parts– an introduction to remote sensing and GEE, and a series of case studies that demonstrate how to use GEE for open source investigations:</p>
|
||||
<section id="table-of-contents" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="table-of-contents">Table of Contents</h2>
|
||||
<ul>
|
||||
<li>Learning
|
||||
<ol type="1">
|
||||
<li>Data Acquisition</li>
|
||||
<li>Getting Started</li>
|
||||
<li>Algorithms</li>
|
||||
<li>Application Development</li>
|
||||
<li>Case Studies</li>
|
||||
</ol>
|
||||
<li><a href="./ch1.html">Remote Sensing</a></li>
|
||||
<li><a href="./ch2.html">Data Acquisition</a></li>
|
||||
<li><a href="./ch3.html">Algorithms</a></li>
|
||||
<li><a href="./ch4.html">Application Development</a></li>
|
||||
</ol></li>
|
||||
<li>Case Studies
|
||||
<ol type="1">
|
||||
<li><a href="./SyriaNTL.html">War at Night</a></li>
|
||||
<li><a href="./RojavaRefineries.html">Refinery Detection</a></li>
|
||||
</ol></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="what-is-google-earth-engine" class="level2">
|
||||
<h2 class="anchored" data-anchor-id="what-is-google-earth-engine">What is Google Earth Engine?</h2>
|
||||
<p>As geospatial datasets—particularly satellite imagery collections—increase in size, researchers are increasingly relying on cloud computing platforms such as Google Earth Engine (GEE) to analyze vast quantities of data.</p>
|
||||
18
index.qmd
@@ -1,12 +1,18 @@
|
||||
# Introduction {.unnumbered}
|
||||
|
||||
The analysis of satellite imagery is a foundational element of open source investigations. Though no-code platforms such as Sentinelhub have been invaluable in allowing the OSINT community to access and process satellite imagery, the analytical capabilities of these platforms are limited. [Google Earth Engine (GEE)](https://earthengine.google.com/#intro) is a cloud-based platform that stores petabytes of satellite imagery from a variety of sources and allows users to perform advanced analyses on Google servers for free using a browser-based interface. This textbook is designed for investigators who want to perform more sophisticated analysis using geospatial data, and assumes no prior knowledge of coding or remote sensing (satellite imagery analysis). It is organized into four chapters:
|
||||
The analysis of satellite imagery is a foundational element of open source investigations. In the past decade, the quantity, quality, and availability thereof has increased dramatically. Capabilities and insights that were once only available to governments are now accessible to the general public. Satellite imagery is being used to collect evidence of genocide and other war crimes in [Ukraine](https://www.nbcnews.com/science/science-news/ukraine-satellites-war-crimes-rcna26291), [Nigeria](https://www.amnesty.org/en/latest/news/2016/04/nigeria-military-cover-up-of-mass-slaughter-at-zaria-exposed/), [Burundi](https://www.amnesty.org/en/latest/news/2016/01/burundi-satellite-evidence-supports-witness-accounts-of-mass-graves/), [Cameroon](https://www.amnesty.org/en/latest/news/2021/07/cameroon-satellite-images-reveal-devastation-in-anglophone-regions-2/), [the DRC](https://www.aaas.org/resources/satellite-imagery-assessment-forced-relocations-near-luiswishi-mine), [South Sudan](https://gsp.yale.edu/case-studies/sudan/maps-satellite-images/other-darfur-satellite-imagery), [Papua](https://gsp.yale.edu/resources/maps-satellite-images/papua), and [Venezuela](https://www.hrw.org/report/2016/04/04/unchecked-power/police-and-military-raids-low-income-and-immigrant-communities). It has been used to [monitor environmental degradation](https://www.theguardian.com/environment/2016/mar/02/new-satellite-mapping-a-game-changer-against-illegal-logging) and hold extractive industries to account from [Iraq](https://www.bellingcat.com/resources/2021/04/15/what-oil-satellite-technology-and-iraq-can-tell-us-about-pollution/) to [Guatemala](https://www.planet.com/pulse/the-observatory-of-extractive-industries-oie-shines-a-light-on-the-mining-industry-using-planets-satellite-data/). The ability to analyze satellite imagery is a critical skill for anyone interested in open source investigations.
|
||||
|
||||
1. Data Acquisition
|
||||
2. Getting Started
|
||||
3. Algorithms
|
||||
4. Application Development
|
||||
5. Case Studies
|
||||
Though no-code platforms such as Sentinelhub have been invaluable in allowing the OSINT community to access and process satellite imagery, the analytical capabilities of these platforms are limited. [Google Earth Engine (GEE)](https://earthengine.google.com/#intro) is a cloud-based platform that stores petabytes of satellite imagery from a variety of sources and allows users to perform advanced analyses on Google servers for free using a browser-based interface. This textbook is designed for investigators who want to perform more sophisticated analysis using geospatial data, and assumes no prior knowledge of coding or remote sensing (satellite imagery analysis). It is organized into two parts-- an introduction to remote sensing and GEE, and a series of case studies that demonstrate how to use GEE for open source investigations:
|
||||
|
||||
## Table of Contents
|
||||
- Learning
|
||||
1. [Remote Sensing](ch1.qmd)
|
||||
2. [Data Acquisition](ch2.qmd)
|
||||
3. [Algorithms](ch3.qmd)
|
||||
4. [Application Development](ch4.qmd)
|
||||
- Case Studies
|
||||
1. [War at Night](SyriaNTL.qmd)
|
||||
2. [Refinery Detection](RojavaRefineries.qmd)
|
||||
|
||||
## What is Google Earth Engine?
|
||||
|
||||
|
||||
1704
site_libs/bootstrap/bootstrap-icons.css
vendored
Normal file
BIN
site_libs/bootstrap/bootstrap-icons.woff
Normal file
7
site_libs/bootstrap/bootstrap.min.js
vendored
Normal file
7
site_libs/clipboard/clipboard.min.js
vendored
Normal file
9
site_libs/quarto-html/anchor.min.js
vendored
Normal file
6
site_libs/quarto-html/popper.min.js
vendored
Normal file
171
site_libs/quarto-html/quarto-syntax-highlighting.css
Normal file
@@ -0,0 +1,171 @@
|
||||
/* quarto syntax highlight colors */
|
||||
:root {
|
||||
--quarto-hl-ot-color: #003B4F;
|
||||
--quarto-hl-at-color: #657422;
|
||||
--quarto-hl-ss-color: #20794D;
|
||||
--quarto-hl-an-color: #5E5E5E;
|
||||
--quarto-hl-fu-color: #4758AB;
|
||||
--quarto-hl-st-color: #20794D;
|
||||
--quarto-hl-cf-color: #003B4F;
|
||||
--quarto-hl-op-color: #5E5E5E;
|
||||
--quarto-hl-er-color: #AD0000;
|
||||
--quarto-hl-bn-color: #AD0000;
|
||||
--quarto-hl-al-color: #AD0000;
|
||||
--quarto-hl-va-color: #111111;
|
||||
--quarto-hl-bu-color: inherit;
|
||||
--quarto-hl-ex-color: inherit;
|
||||
--quarto-hl-pp-color: #AD0000;
|
||||
--quarto-hl-in-color: #5E5E5E;
|
||||
--quarto-hl-vs-color: #20794D;
|
||||
--quarto-hl-wa-color: #5E5E5E;
|
||||
--quarto-hl-do-color: #5E5E5E;
|
||||
--quarto-hl-im-color: #00769E;
|
||||
--quarto-hl-ch-color: #20794D;
|
||||
--quarto-hl-dt-color: #AD0000;
|
||||
--quarto-hl-fl-color: #AD0000;
|
||||
--quarto-hl-co-color: #5E5E5E;
|
||||
--quarto-hl-cv-color: #5E5E5E;
|
||||
--quarto-hl-cn-color: #8f5902;
|
||||
--quarto-hl-sc-color: #5E5E5E;
|
||||
--quarto-hl-dv-color: #AD0000;
|
||||
--quarto-hl-kw-color: #003B4F;
|
||||
}
|
||||
|
||||
/* other quarto variables */
|
||||
:root {
|
||||
--quarto-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
}
|
||||
|
||||
pre > code.sourceCode > span {
|
||||
color: #003B4F;
|
||||
}
|
||||
|
||||
code span {
|
||||
color: #003B4F;
|
||||
}
|
||||
|
||||
code.sourceCode > span {
|
||||
color: #003B4F;
|
||||
}
|
||||
|
||||
div.sourceCode,
|
||||
div.sourceCode pre.sourceCode {
|
||||
color: #003B4F;
|
||||
}
|
||||
|
||||
code span.ot {
|
||||
color: #003B4F;
|
||||
}
|
||||
|
||||
code span.at {
|
||||
color: #657422;
|
||||
}
|
||||
|
||||
code span.ss {
|
||||
color: #20794D;
|
||||
}
|
||||
|
||||
code span.an {
|
||||
color: #5E5E5E;
|
||||
}
|
||||
|
||||
code span.fu {
|
||||
color: #4758AB;
|
||||
}
|
||||
|
||||
code span.st {
|
||||
color: #20794D;
|
||||
}
|
||||
|
||||
code span.cf {
|
||||
color: #003B4F;
|
||||
}
|
||||
|
||||
code span.op {
|
||||
color: #5E5E5E;
|
||||
}
|
||||
|
||||
code span.er {
|
||||
color: #AD0000;
|
||||
}
|
||||
|
||||
code span.bn {
|
||||
color: #AD0000;
|
||||
}
|
||||
|
||||
code span.al {
|
||||
color: #AD0000;
|
||||
}
|
||||
|
||||
code span.va {
|
||||
color: #111111;
|
||||
}
|
||||
|
||||
code span.pp {
|
||||
color: #AD0000;
|
||||
}
|
||||
|
||||
code span.in {
|
||||
color: #5E5E5E;
|
||||
}
|
||||
|
||||
code span.vs {
|
||||
color: #20794D;
|
||||
}
|
||||
|
||||
code span.wa {
|
||||
color: #5E5E5E;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
code span.do {
|
||||
color: #5E5E5E;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
code span.im {
|
||||
color: #00769E;
|
||||
}
|
||||
|
||||
code span.ch {
|
||||
color: #20794D;
|
||||
}
|
||||
|
||||
code span.dt {
|
||||
color: #AD0000;
|
||||
}
|
||||
|
||||
code span.fl {
|
||||
color: #AD0000;
|
||||
}
|
||||
|
||||
code span.co {
|
||||
color: #5E5E5E;
|
||||
}
|
||||
|
||||
code span.cv {
|
||||
color: #5E5E5E;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
code span.cn {
|
||||
color: #8f5902;
|
||||
}
|
||||
|
||||
code span.sc {
|
||||
color: #5E5E5E;
|
||||
}
|
||||
|
||||
code span.dv {
|
||||
color: #AD0000;
|
||||
}
|
||||
|
||||
code span.kw {
|
||||
color: #003B4F;
|
||||
}
|
||||
|
||||
.prevent-inlining {
|
||||
content: "</";
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=debc5d5d77c3f9108843748ff7464032.css.map */
|
||||
1
site_libs/quarto-html/tippy.css
Normal file
@@ -0,0 +1 @@
|
||||
.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}
|
||||