reconnect moved files to git repo
This commit is contained in:
106
templates/index.html
Executable file
106
templates/index.html
Executable file
@ -0,0 +1,106 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Time Series Analysis</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.form-check-label {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</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">Time Series Analysis</h1>
|
||||
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">{{ error }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" enctype="multipart/form-data" action="/upload">
|
||||
<div class="mb-3">
|
||||
<label for="file" class="form-label">Upload CSV or Excel File</label>
|
||||
<input type="file" class="form-control" id="file" name="file" accept=".csv,.xls,.xlsx" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<h5>Analysis Options</h5>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="decomposition" name="decomposition">
|
||||
<label class="form-check-label" for="decomposition">Perform Decomposition</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="forecasting" name="forecasting" checked>
|
||||
<label class="form-check-label" for="forecasting">Perform Forecasting</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="acf_pacf" name="acf_pacf">
|
||||
<label class="form-check-label" for="acf_pacf">Generate ACF/PACF Plots</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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="80" 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="20" 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="12" 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">ARIMA</option>
|
||||
<option value="Exponential Smoothing">Exponential Smoothing</option>
|
||||
<option value="Prophet">Prophet</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Analyze</button>
|
||||
</form>
|
||||
</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);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
238
templates/results.html
Executable file
238
templates/results.html
Executable file
@ -0,0 +1,238 @@
|
||||
<!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>
|
||||
Reference in New Issue
Block a user