Skip to content

Commit

Permalink
Implemented Planned Changed and New Stacked Basemap
Browse files Browse the repository at this point in the history
  • Loading branch information
rell committed Aug 10, 2023
1 parent b7c17ec commit 9aa73ab
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 126 deletions.
61 changes: 37 additions & 24 deletions chart.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export function drawGraph(data, canvas)
{
export function drawGraph(data, canvas) {
const ctx = canvas.getContext('2d');
const average = data.reduce((sum, d) => sum + d.y, 0) / data.length;
// canvas.width = 400;
// canvas.height = 600;
return new Chart(ctx, {
type: 'line',
data: {
Expand All @@ -18,34 +19,38 @@ export function drawGraph(data, canvas)
data: [{ x: data[0].x, y: average }, { x: data[data.length - 1].x, y: average }],
borderColor: 'red',
borderWidth: 1,
// Configure the borderDash option to display the line as a dotted line
borderDash: [5, 5],
fill: false,
// Display the average line behind the main data
order: 0,
// Do not display the average line in the legend
showLine: false,
}
],
},
options: {
maintainAspectRatio: false,
animation: {
duration: 0,
easing: 'linear',
animateRotate: false,
animateScale: false,
animateDraw: false,
},
hover: {
animationDuration: 0,
},
responsiveAnimationDuration: 0,
legend: {
display: false,
},
tooltips: {
callbacks:{
callbacks: {
title: function(tooltipItem, data) {
// Get the index of the hovered point
const index = tooltipItem[0].index;
// Get the corresponding data point
const dataPoint = data.datasets[0].data[index];
// Format the date string
const date = formatDate(data.labels[index], true);
// Return the title with the full date string and AOD value
return `${date}\nAverage AOD Value: ${dataPoint}`;
},
label: function(tooltipItem)
{
label: function(tooltipItem) {
return '';
}
}
Expand All @@ -54,36 +59,44 @@ export function drawGraph(data, canvas)
yAxes: [
{
ticks: {
fontColor: 'black',
beginAtZero: true,
stepSize: 1,
maxTickLimit: 4
maxTickLimit: 4,
},
},
],
xAxes: [
{
ticks: {
fontColor: 'black',
maxTicksLimit: 15,
autoSkip: true,
// max: parseFloat(data.datasets[0].data.toFixed(2)),
maxRotation: 150,
minRotation: 0,
callback: function(value, index, values) {
return formatDate(value);
}
}
}
]
},
},
},
],
},
elements: {
line: {
borderColor: 'rgba(0, 0, 0, 1)',
},
point: {
borderColor: 'rgba(0, 0, 0, 1)',
},
},
backgroundColor: 'rgba(255, 255, 255, 1)',
responsive: true,
onCreate: function (chart) {
// Calculate the max value based on the chart data
responsive: false,
onCreated: function(chart) {
const max = Math.max(...chart.data.datasets[0].data);
// Update the max option of the y-axis ticks
chart.options.scales.yAxes[0].ticks.max = parseFloat(max.toFixed(2));
chart.update();
}
}
},
},
});
}
function formatDate(dateString, full=false) {
Expand Down
31 changes: 26 additions & 5 deletions components.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Function to create a color scale for mapping data values to colors
function setColorScale()
function setColorScale()
{
return d3.scaleLinear()
.domain([0, (1/6), ((1/6)*2), ((1/6)*3), ((1/6)*4), ((1/6)*5), 1])
Expand Down Expand Up @@ -83,7 +83,6 @@ export function updateTime(dateTime, daily = false) {
{
[year, month, day] = dateTime[0].map(Number);
[previousHr, hour, bufferHr, minute] = dateTime[1];

}
else if (dateTime.length === 3)
{
Expand All @@ -99,8 +98,8 @@ export function updateTime(dateTime, daily = false) {
year: 'numeric'
});

const timeString = `${previousHr}:${minute} — ${hour}:${minute} UTC`;
currentTimeDiv.innerHTML = `${dateString} (${timeString})`;
const timeString = `${previousHr}:${minute} — ${hour}:${minute}`;
currentTimeDiv.innerHTML = `${dateString} (${timeString}) <strong>UTC</strong>`;
} else if (daily) {
const dateString = new Date(Date.UTC(year, month-1, day+1)).toLocaleString('en-US', {
month: 'long',
Expand All @@ -124,7 +123,7 @@ export function updateAOD(optical_dep)
}


export function getStartEndDateTime(dateTime = null, hourTolerance = 1)
export function getStartEndDateTime(dateTime = null, hourTolerance = 1, daily = null, previousDateTime=null)
{
let yesterday;
let year, month, day, previousYear, previousMonth, previousDay, previousHr, hour, bufferHr, minute;
Expand All @@ -142,6 +141,28 @@ export function getStartEndDateTime(dateTime = null, hourTolerance = 1)
previousMonth = (yesterday.getUTCMonth() + 1).toString().padStart(2, '0');
previousDay = (yesterday.getUTCDate()).toString().padStart(2, '0');
}
else if (dateTime && daily)
{
const setTime = new Date(Date.parse(dateTime))
yesterday = new Date(Date.parse(dateTime))
yesterday.setDate(setTime.getDate() - 1)
year = setTime.getUTCFullYear().toString().padStart(4, '0');
month = (setTime.getUTCMonth() + 1).toString().padStart(2, '0');
day = (setTime.getUTCDate()).toString().padStart(2, '0');
previousYear = yesterday.getUTCFullYear().toString().padStart(4, '0');
previousMonth = (yesterday.getUTCMonth() + 1).toString().padStart(2, '0');
previousDay = (yesterday.getUTCDate()).toString().padStart(2, '0');
if (previousDateTime.length === 3)
{
hour = previousDateTime[2][1];
minute = previousDateTime[2][3];
}
else if (previousDateTime.length === 2)
{
hour = previousDateTime[1][1];
minute = previousDateTime[1][3];
}
}
else if (dateTime)
{
const setTime = new Date(Date.parse(dateTime))
Expand Down
1 change: 1 addition & 0 deletions data.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export async function getAllSites(year)

const data = response.split(`,${year}`)[1] // CSV
const objs = await Papa.parse(data, config) // Avg for building js objects was ~7 ms
console.log(objs.data)
return objs.data
} catch (error) {
console.error(error);
Expand Down
72 changes: 49 additions & 23 deletions fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,29 @@ export class FieldInitializer {
});

// Sort siteFieldData alphabetically in descending order.
const sitenames = this.allSiteData.map(obj => obj['Site_Name']);
this.siteFieldData = sitenames.map(element => ({ value: element, label: element}))
.sort((a, b) => a.value.localeCompare(b.value));
// const siteNames = this.allSiteData.map(obj => `${obj['Site_Name']} (${obj['Latitude(decimal_degrees)']}, ${obj['Longitude(decimal_degrees)']})`);
// const siteValues = this.allSiteData.map(obj => `${obj['Site_Name']}`);

this.siteFieldData = this.allSiteData.map(obj => ({ value: `${obj['Site_Name']}`, label:`${obj['Site_Name']}`}))
.sort((a, b) => a.value.localeCompare(b.value));
// this.siteFieldData = this.allSiteData.map(obj => ({ value: `${obj['Site_Name']}`, label: `${obj['Site_Name']} (${obj['Latitude(decimal_degrees)']}, ${obj['Longitude(decimal_degrees)']})`}))
// .sort((a, b) => a.value.localeCompare(b.value));
console.log(this.siteFieldData)
// Initialize dropdown menus for selecting data type and AERONET site.
let placeholder = '500';
const aodDisc = 'Select wavelength';
toolTipContent = 'Select a preferred wavelength for the aerosol optical depth.'
toolTipContent = 'Select a preferred wavelength of aerosol optical depth.'
const dropdownAOD = initDropdown('optical-depth-dropdown', this.aodFieldData, aodDisc, placeholder, false, 'aod-fields', toolTipContent);

placeholder = 'Select'
const siteDisc = 'Site';
toolTipContent = 'This option allows you to select an AERONET site of interest, and you will be directed to that specific point.'
const dropdownSite = initDropdown('site-drop-down', this.siteFieldData, siteDisc, placeholder, true, 'site-fields', toolTipContent);
toolTipContent = 'This option allows you to select and goto an AERONET site of interest.'
const dropdownSite = initDropdown('site-drop-down', this.siteFieldData, siteDisc, placeholder, true, 'site-fields', toolTipContent,);


const datatypeOpt = [{value: 10, label: 'Realtime'}, {value: 20, label: 'Daily'}];
const datatypeOpt = [{value: 10, label: 'Real-time'}, {value: 20, label: 'Daily'}];
const dataTypeDisc = 'Select mode';
toolTipContent = '<strong>Realtime:</strong> the points displayed on the legend are the most recent within a selected window.</p>\n' +
toolTipContent = '<strong>Real-time:</strong> the points displayed on the legend are the most recent within a selected window.</p>\n' +
'<p><strong>Daily:</strong> the average value displayed for the date set within the window.'
placeholder = 'realtime'
const dropdownData = initDropdown('data-type-dropdown', datatypeOpt, dataTypeDisc, placeholder, false, 'avg-fields', toolTipContent);
Expand All @@ -84,7 +88,7 @@ export class FieldInitializer {

// Initialize toggle for toggling inactive stations.
const inactiveOff = `<div class="tooltip-container">
<div id='row'> <label for="toggle-inactive">Inactive Sites</label>
<div id='row'> <label for="toggle-inactive">Show Inactive Sites</label>
<div class="tooltip-trigger-container">
<span class="tooltip-trigger">?</span>
<div class="tooltip-content">
Expand All @@ -101,7 +105,8 @@ export class FieldInitializer {
// Set the HTML for the fields container.
const fieldsContainer = document.getElementById('fields');
const header = document.createElement("h2");
header.textContent = "Filters";
header.textContent = "Data Filters";
header.style.textAlign = 'center';

// Insert the header before the form element
fieldsContainer.insertBefore(header, fieldsContainer.firstChild);
Expand Down Expand Up @@ -145,7 +150,7 @@ export class FieldInitializer {
this.normalizeMarkers()
}else {

this.map.setView([0,0],3);
this.map.setView([50,0],3.50);
}
this.recentlySetInactive = true;
this.setToggleValue(this.recentlySetInactive)
Expand Down Expand Up @@ -232,6 +237,22 @@ export class FieldInitializer {
defaultDate: new Date(year, month-1, day),
});
} else {
let newDate = new Date(this.dateString)
if(this.dateString.split('T')[1] === '04:00:00.000Z')
{
newDate = new Date(this.dateString)

if(this.dateTime.length === 2)
{
newDate.setHours(this.dateTime[1][1]);
newDate.setMinutes(this.dateTime[1][3]);
}
else if (this.dateTime.length === 3)
{
newDate.setHours(this.dateTime[2][1]);
newDate.setMinutes(this.dateTime[2][3]);
}
}
fp = flatpickr('#date-input', {
utc: true,
enableTime: !daily,
Expand All @@ -240,7 +261,7 @@ export class FieldInitializer {
altFormat: 'Y-m-d h:i K',
minDate: new Date(1993, 0, 1),
maxDate: now,
defaultDate: new Date(this.dateString),
defaultDate: newDate,
});
}
}
Expand All @@ -250,7 +271,7 @@ export class FieldInitializer {
document.getElementById('submitButton').addEventListener('click', async (event) => {
// Get the selected date from Flatpickr
this.dateString = document.getElementById('date-input').value;
this.dateTime = getStartEndDateTime(this.dateString, this.hourTolerance)
this.dateTime = getStartEndDateTime(this.dateString, this.hourTolerance, this.daily, this.dateTime)
this.updateApiArgs();
this.markerLayer.endDate = this.dateTime.length === 3 ? this.dateTime[1] : this.dateTime[0];
this.markerLayer.startDate = this.setChartStart(this.dateTime)
Expand Down Expand Up @@ -278,28 +299,33 @@ export class FieldInitializer {
const tooltipTrigger = document.querySelector('.tooltip-trigger');
const tooltip = document.querySelector('.tooltip');

tooltipTrigger.addEventListener('mouseover', () => {
tooltip.style.top = `${tooltipTrigger.offsetTop + tooltipTrigger.offsetHeight}px`;
tooltip.style.left = `${tooltipTrigger.offsetLeft}px`;
});
if (tooltip && tooltipTrigger) {
tooltipTrigger.addEventListener('mouseover', () => {
tooltip.style.top = `${tooltipTrigger.offsetTop + tooltipTrigger.offsetHeight}px`;
tooltip.style.left = `${tooltipTrigger.offsetLeft}px`;
});

tooltipTrigger.addEventListener('mouseout', () => {
tooltip.style.top = null;
tooltip.style.left = null;
});
tooltipTrigger.addEventListener('mouseout', () => {
tooltip.style.top = null;
tooltip.style.left = null;
});
} else {
console.error('Tooltip elements not found in the DOM');
}
}

setToggleValue(value) {
this.toggleInactive.checked = value;
}
setChartStart() {
const daysToAvg = this.markerLayer.chartTimeLength
let date;
let startYear,startMonth,startDay,year,month,day;
if (this.dateTime.length === 3)
{
[year, month, day] = this.dateTime[1].map(Number);
date = new Date(year, month - 1, day);
date.setDate(date.getDate()-30);
date.setDate(date.getDate()-daysToAvg);
startYear = date.getUTCFullYear();
startMonth = date.getUTCMonth();
startDay = date.getUTCDate();
Expand All @@ -308,7 +334,7 @@ export class FieldInitializer {
{
[year, month, day] = this.dateTime[0].map(Number);
date = new Date(year, month - 1, day);
date.setDate(date.getDate()-30);
date.setDate(date.getDate()-daysToAvg);
startYear = date.getUTCFullYear();
startMonth = date.getUTCMonth()+1;
startDay = date.getUTCDate();
Expand Down
18 changes: 12 additions & 6 deletions forms.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

h2
{
margin: 0;
font-family: 'Open Sans', sans-serif;
padding: 0;
margin-top: 10px;
margin-bottom: 0;
width: 100%;
background-color: rgba(0, 123, 200, 1);
color: white;
padding: 10px;
}
form{
font-family: 'Open Sans', sans-serif;
Expand All @@ -22,9 +24,13 @@ body
overflow-y: hidden;
}
#fields {
width: 30%;
min-height: 300px;
min-width: 327px;
width: 10%;
float: left;
margin-left: 20px;
/* Adjust later */
overflow: hidden;

}

label {
Expand Down Expand Up @@ -72,7 +78,7 @@ button {
display: inline-block;
border-radius: 0.25rem;
padding: 0.5rem 1rem;
font-size: 1rem;
font-size: 1em;
font-weight: bold;
color: #fff;
background-color: #007bff;
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<title>Visualization</title>
<title>AERONET Data Explorer</title>
<link rel='stylesheet' type='text/css' href='./map.css'/>
<link rel='stylesheet' type='text/css' href='./forms.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css'>
Expand Down
Loading

0 comments on commit 9aa73ab

Please sign in to comment.