Published
Edited
Sep 1, 2020
10 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
advisoryTrackShp = fetchArchiveFile(ADVISORY_TRACK_SHP_URL)
Insert cell
advisoryTrack = {
const data = await shpToGeoJSON(advisoryTrackShp);

const keys = Object.keys(data);

// the layer names annoyingly change with each advisory, so we have to hunt for them
const points = data[keys.find(key => key.endsWith('5day_pts'))];
const line = data[keys.find(key => key.endsWith('5day_lin'))];
const watches = data[keys.find(key => key.endsWith('ww_wwlin'))];
console.log(points);

// ADVDATE: "700 PM CDT Wed Aug 26 2020"
// FLDATELBL: "2020-08-26 4:00 PM Wed CDT"
points.features.forEach((point, idx) => {
const properties = point.properties;
const stormType = properties.STORMTYPE;

let STORM_LABEL;

switch (stormType) {
case 'MH':
case 'HU':
STORM_LABEL = properties.SSNUM;
break;
case 'TS':
STORM_LABEL = 'S';
break;
case 'TD':
STORM_LABEL = 'D';
break;
case 'STD':
case 'STS':
STORM_LABEL = 'P';
break;
}

let parsedDate;

// first point
if (idx === 0) {
const rawDate = properties.ADVDATE.replace(' CDT', '');
parsedDate = DateTime.fromFormat(rawDate, 'hmm a EEE MMM dd yyyy', {
zone: 'America/Chicago'
});
} else {
const rawDate = properties.FLDATELBL.replace(' CDT', '');
parsedDate = DateTime.fromFormat(rawDate, 'yyyy-MM-dd h:mm a EEE', {
zone: 'America/Chicago'
});
}

const options = {
weekday: 'short',
hour: 'numeric'
};

if (parsedDate.minute > 0) {
options.minute = 'numeric';
}

if (idx === 0) {
options.timeZoneName = 'short';
}

properties.STORM_LABEL = STORM_LABEL;
properties.FORMATTED_DATE = parsedDate.toLocaleString(options);
});

const firstPoint = points.features[0].geometry.coordinates;

return {
points,
line,
watches,
firstPoint
};
}
Insert cell
Insert cell
Insert cell
preliminaryBestTrackShp = fetchArchiveFile(PRELIMINARY_BEST_TRACK_SHP_URL)
Insert cell
preliminaryTrack = {
const data = await shpToGeoJSON(preliminaryBestTrackShp);

const points = data[`${NOAA_HURRICANE_ID}_pts`];
const line = data[`${NOAA_HURRICANE_ID}_lin`];
const windSwath = data[`${NOAA_HURRICANE_ID}_windswath`];

const lastPoint =
points.features[points.features.length - 1].geometry.coordinates;
const connectionLine = turf.lineString([lastPoint, advisoryTrack.firstPoint]);

line.features.push(connectionLine);

return {
points,
line,
windSwath
};
}
Insert cell
Insert cell
Insert cell
advisoryWindFieldShp = fetchArchiveFile(ADVISORY_WIND_FIELD_SHP_URL)
Insert cell
advisoryWindField = {
const data = await shpToGeoJSON(advisoryWindFieldShp);
const keys = Object.keys(data);
const initial = data[keys.find(key => key.endsWith('initialradii'))];
return initial;
}
Insert cell
Insert cell
Insert cell
windSpeedProbabilitiesArchive = fetchArchiveFile(WIND_SPEED_PROBABILITIES_URL)
Insert cell
probabilities = ['50-60', '60-70', '70-80', '80-90', '>90%']
Insert cell
windSpeedProbabilities = {
const data = await kmzToGeoJSON(windSpeedProbabilitiesArchive);
const keys = Object.keys(data);
const knots34 = data[keys.find(key => key.endsWith('wsp34knt120hr_5km'))];
knots34.features = knots34.features.filter(({ properties }) => probabilities.includes(properties.name));
return knots34;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more