Files
Time-Series-Analysis/templates/results.html
2025-08-01 04:33:03 -04:00

238 lines
11 KiB
HTML
Executable File

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Analysis Results</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/plotly@2.27.0/dist/plotly.min.js"></script>
<style>
body {
background-color: #f8f9fa;
}
.container {
max-width: 1200px;
margin-top: 20px;
}
.collapsible-section {
margin-bottom: 15px;
}
.collapsible-section .btn-toggle {
background-color: #007bff;
color: white;
width: 100%;
text-align: left;
padding: 10px;
border-radius: 5px;
}
.collapsible-section .btn-toggle:hover {
background-color: #0056b3;
}
.collapsible-section .collapse {
margin-top: 10px;
}
.plotly-container {
width: 100%;
max-width: none;
margin: 0;
}
</style>
</head>
<body>
<div class="container">
<!-- Warning Message -->
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>Warning:</strong> This app does not save files or outputs. All work will be lost when the page is closed.
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<h1 class="text-center mb-4">Analysis Results</h1>
<!-- Summary Statistics -->
<div class="collapsible-section">
<button class="btn btn-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-summary" aria-expanded="true" aria-controls="collapse-summary">
Summary Statistics
</button>
<div class="collapse show" id="collapse-summary">
<div class="card card-body">
<h5>Summary Statistics</h5>
<table class="table">
{% for key, value in summary.items() %}
<tr>
<td>{{ key }}</td>
<td>{{ value | round(2) }}</td>
</tr>
{% endfor %}
</table>
<a href="{{ url_for('download_file', filename=filename) }}" class="btn btn-secondary">Download Processed Data</a>
</div>
</div>
</div>
<!-- Decomposition -->
{% if do_decomposition and plot_html %}
<div class="collapsible-section">
<button class="btn btn-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-decomposition" aria-expanded="false" aria-controls="collapse-decomposition">
Decomposition
</button>
<div class="collapse" id="collapse-decomposition">
<div class="card card-body">
<h5>Decomposition</h5>
<div class="plotly-container" style="width: 1200px; height: 800px;">{{ plot_html | safe }}</div>
</div>
</div>
</div>
{% endif %}
<!-- ACF/PACF Plots -->
{% if do_acf_pacf and acf_pacf_html %}
<div class="collapsible-section">
<button class="btn btn-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-acf-pacf" aria-expanded="false" aria-controls="collapse-acf-pacf">
ACF/PACF Plots
</button>
<div class="collapse" id="collapse-acf-pacf">
<div class="card card-body">
<h5>ACF/PACF Plots</h5>
<div class="plotly-container" style="width: 1200px; height: 800px;">{{ acf_pacf_html | safe }}</div>
</div>
</div>
</div>
{% endif %}
<!-- Forecasting -->
{% if do_forecasting and forecast_html %}
<div class="collapsible-section">
<button class="btn btn-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-forecasting" aria-expanded="{{ 'true' if scroll_to_forecast else 'false' }}" aria-controls="collapse-forecasting">
Forecasting
</button>
<div class="collapse {{ 'show' if scroll_to_forecast else '' }}" id="collapse-forecasting">
<div class="card card-body">
<h5>Forecast Plot</h5>
<p><strong>Model:</strong> {{ model_type }}</p>
{% if model_params %}
<p><strong>Model Parameters:</strong> {{ model_params }}</p>
{% endif %}
{% if metrics %}
<p><strong>Test Set Metrics:</strong></p>
<ul>
<li>MAE: {{ metrics.MAE | round(2) }}</li>
<li>MSE: {{ metrics.MSE | round(2) }}</li>
<li>RMSE: {{ metrics.RMSE | round(2) }}</li>
</ul>
{% endif %}
<div class="plotly-container" style="width: 1200px; height: 400px;">{{ forecast_html | safe }}</div>
{% if forecast_history %}
<h5 class="mt-4">Forecast History</h5>
<form method="post" action="{{ url_for('compare_forecasts') }}">
<table class="table">
<thead>
<tr>
<th>Select</th>
<th>Run</th>
<th>Train Percent (%)</th>
<th>Test Percent (%)</th>
<th>Forecast Periods</th>
<th>MAE</th>
<th>MSE</th>
<th>RMSE</th>
<th>Model</th>
</tr>
</thead>
<tbody>
{% for entry in forecast_history %}
<tr>
<td><input type="checkbox" name="selected_forecasts" value="{{ loop.index0 }}" {{ 'checked' if loop.index0 in selected_indices else '' }}></td>
<td>{{ loop.index }}</td>
<td>{{ entry.train_percent | round(2) }}</td>
<td>{{ entry.test_percent | round(2) }}</td>
<td>{{ entry.forecast_periods }}</td>
<td>{{ entry.mae | round(2) if entry.mae else '-' }}</td>
<td>{{ entry.mse | round(2) if entry.mse else '-' }}</td>
<td>{{ entry.rmse | round(2) if entry.rmse else '-' }}</td>
<td>{{ entry.model_type }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<button type="submit" class="btn btn-primary">Compare Selected Forecasts</button>
</form>
<a href="{{ url_for('download_forecast_history') }}" class="btn btn-secondary mt-2">Download Forecast History</a>
{% endif %}
<h5 class="mt-4">Re-forecast</h5>
<form method="post" action="{{ url_for('reforecast') }}">
<div class="mb-3">
<label for="train_percent" class="form-label">Train Percentage</label>
<input type="number" class="form-control" id="train_percent" name="train_percent" value="{{ train_percent }}" min="1" max="99" required>
</div>
<div class="mb-3">
<label for="test_percent" class="form-label">Test Percentage</label>
<input type="number" class="form-control" id="test_percent" name="test_percent" value="{{ test_percent }}" min="1" max="99" required>
</div>
<div class="mb-3">
<label for="forecast_periods" class="form-label">Forecast Periods</label>
<input type="number" class="form-control" id="forecast_periods" name="forecast_periods" value="{{ forecast_periods }}" min="1" required>
</div>
<div class="mb-3">
<label for="model_type" class="form-label">Forecast Model</label>
<select class="form-control" id="model_type" name="model_type">
<option value="ARIMA" {{ 'selected' if model_type == 'ARIMA' else '' }}>ARIMA</option>
<option value="Exponential Smoothing" {{ 'selected' if model_type == 'Exponential Smoothing' else '' }}>Exponential Smoothing</option>
<option value="Prophet" {{ 'selected' if model_type == 'Prophet' else '' }}>Prophet</option>
</select>
</div>
<div class="form-check mb-3">
<input type="checkbox" class="form-check-input" id="add_to_existing" name="add_to_existing">
<label class="form-check-label" for="add_to_existing">Add to Existing Plots</label>
</div>
<button type="submit" class="btn btn-primary">Run Re-forecast</button>
</form>
</div>
</div>
</div>
{% endif %}
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Sync Train and Test Percentage inputs
const trainInput = document.getElementById('train_percent');
const testInput = document.getElementById('test_percent');
function syncPercentages(source, target) {
source.addEventListener('input', () => {
const value = parseFloat(source.value);
if (!isNaN(value) && value >= 1 && value <= 99) {
target.value = (100 - value).toFixed(0);
} else {
target.value = '';
}
});
}
syncPercentages(trainInput, testInput);
syncPercentages(testInput, trainInput);
// Scroll to and expand forecasting section if scroll_to_forecast is true
{% if scroll_to_forecast %}
document.addEventListener('DOMContentLoaded', function() {
const forecastingSection = document.querySelector('#collapse-forecasting');
if (forecastingSection) {
forecastingSection.classList.add('show');
forecastingSection.scrollIntoView({ behavior: 'smooth' });
}
});
{% endif %}
// Resize Plotly plots on section expand
document.querySelectorAll('.collapse').forEach(collapse => {
collapse.addEventListener('shown.bs.collapse', () => {
if (typeof Plotly !== 'undefined') {
Plotly.Plots.resize(collapse.querySelector('.plotly-container'));
}
});
});
</script>
</body>
</html>