v0.20.0 -- Full s3 event parse and PDF creation. #28

Merged
serversdown merged 46 commits from dev into main 2026-05-28 17:54:34 -04:00
2 changed files with 40 additions and 2 deletions
Showing only changes of commit 5d5441604b - Show all commits
+17
View File
@@ -629,6 +629,22 @@ function renderWaveform(data) {
return (Number.isInteger(v) ? String(v) : v.toFixed(1)) + xAxisUnit; return (Number.isInteger(v) ? String(v) : v.toFixed(1)) + xAxisUnit;
}; };
// Y-axis bounds. Geophone waveforms render symmetric around zero
// (seismograph convention — zero line in the middle, signal goes
// up AND down). Mic + histograms keep default auto-scale (always
// positive values; zero at the bottom).
let yBounds = {};
const isGeoWaveform = !isHistogram && ch !== 'MicL';
if (isGeoWaveform) {
let absMax = 0;
for (const v of values) {
const a = Math.abs(v);
if (a > absMax) absMax = a;
}
const padded = (absMax || 1) * 1.10;
yBounds = { min: -padded, max: padded };
}
const chart = new Chart(canvas, { const chart = new Chart(canvas, {
type: isHistogram ? 'bar' : 'line', type: isHistogram ? 'bar' : 'line',
data: { data: {
@@ -677,6 +693,7 @@ function renderWaveform(data) {
grid: { color: isPrintMode ? '#e0e0e0' : '#21262d', drawTicks: showXAxis }, grid: { color: isPrintMode ? '#e0e0e0' : '#21262d', drawTicks: showXAxis },
}, },
y: { y: {
...yBounds,
ticks: { color: isPrintMode ? '#666' : '#484f58', maxTicksLimit: 5 }, ticks: { color: isPrintMode ? '#666' : '#484f58', maxTicksLimit: 5 },
grid: { color: isPrintMode ? '#e0e0e0' : '#21262d' }, grid: { color: isPrintMode ? '#e0e0e0' : '#21262d' },
title: { display: true, text: unit, title: { display: true, text: unit,
+23 -2
View File
@@ -2670,6 +2670,24 @@ function _renderScWaveform(data) {
return String(v) + xAxisLabel; return String(v) + xAxisLabel;
}; };
// Y-axis bounds. Convention:
// - Geophones (Tran/Vert/Long) on waveform-mode events:
// symmetric around zero so the zero line sits in the middle and
// positive/negative excursions are visually balanced.
// - Mic (always positive sound pressure) + histograms (per-interval
// peaks, always positive): default auto-scale, zero at the bottom.
let yBounds = {};
const isGeoWaveform = !isHistogram && ch !== 'MicL';
if (isGeoWaveform) {
let absMax = 0;
for (const v of values) {
const a = Math.abs(v);
if (a > absMax) absMax = a;
}
const padded = (absMax || 1) * 1.10;
yBounds = { min: -padded, max: padded };
}
_scCharts[ch] = new Chart(canvas, { _scCharts[ch] = new Chart(canvas, {
type: isHistogram ? 'bar' : 'line', type: isHistogram ? 'bar' : 'line',
data: { data: {
@@ -2709,6 +2727,7 @@ function _renderScWaveform(data) {
grid: { color: '#21262d', drawTicks: showX }, grid: { color: '#21262d', drawTicks: showX },
}, },
y: { y: {
...yBounds,
ticks: { color: '#484f58', maxTicksLimit: 4 }, ticks: { color: '#484f58', maxTicksLimit: 4 },
grid: { color: '#21262d' }, grid: { color: '#21262d' },
title: { display: true, text: chData.unit || '', color: '#484f58', font: { size: 9 } }, title: { display: true, text: chData.unit || '', color: '#484f58', font: { size: 9 } },
@@ -3072,7 +3091,8 @@ if (currentSection === 'db') {
<h4>Event</h4> <h4>Event</h4>
<dl class="sc-grid"> <dl class="sc-grid">
<dt>Serial</dt> <dd id="sc-f-serial"></dd> <dt>Serial</dt> <dd id="sc-f-serial"></dd>
<dt>Timestamp</dt> <dd id="sc-f-ts"></dd> <dt title="When the seismograph recorded this event (from the BW report's Event Time field)">Recorded at</dt>
<dd id="sc-f-ts"></dd>
<dt>Record type</dt> <dd id="sc-f-rt"></dd> <dt>Record type</dt> <dd id="sc-f-rt"></dd>
<dt>Sample rate</dt> <dd id="sc-f-sr"></dd> <dt>Sample rate</dt> <dd id="sc-f-sr"></dd>
<dt>Waveform key</dt> <dd id="sc-f-key"></dd> <dt>Waveform key</dt> <dd id="sc-f-key"></dd>
@@ -3104,7 +3124,8 @@ if (currentSection === 'db') {
<dt id="sc-l-bwsize">File size</dt> <dd id="sc-f-bwsize"></dd> <dt id="sc-l-bwsize">File size</dt> <dd id="sc-f-bwsize"></dd>
<dt id="sc-l-sha">File sha256</dt> <dd id="sc-f-sha"></dd> <dt id="sc-l-sha">File sha256</dt> <dd id="sc-f-sha"></dd>
<dt>Source kind</dt> <dd id="sc-f-src"></dd> <dt>Source kind</dt> <dd id="sc-f-src"></dd>
<dt>Captured at</dt> <dd id="sc-f-cap"></dd> <dt title="When our server received and stored this event (sfm-db insert time, not the recording time)">Received by server at</dt>
<dd id="sc-f-cap"></dd>
</dl> </dl>
</div> </div>
<div class="sc-section"> <div class="sc-section">