Skip to content

Commit 322190a

Browse files
authored
integrate sensor position schema detection and parsing (NEONScience#59)
1 parent fed76af commit 322190a

17 files changed

+962
-226
lines changed

lib/components/TimeSeriesViewer/TimeSeriesViewerContext.js

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ var _NeonApi = _interopRequireDefault(require("../NeonApi/NeonApi"));
1818
var _NeonGraphQL = _interopRequireDefault(require("../NeonGraphQL/NeonGraphQL"));
1919
var _NeonEnvironment = _interopRequireDefault(require("../NeonEnvironment/NeonEnvironment"));
2020
var _rxUtil = require("../../util/rxUtil");
21+
var _typeUtil = require("../../util/typeUtil");
2122
var _parseTimeSeriesData = _interopRequireDefault(require("../../workers/parseTimeSeriesData"));
23+
var _DataPackageParser = _interopRequireDefault(require("../../parser/DataPackageParser"));
2224
var _NeonSignInButtonState = _interopRequireDefault(require("../NeonSignInButton/NeonSignInButtonState"));
2325
var _StateStorageService = _interopRequireDefault(require("../../service/StateStorageService"));
2426
var _StateStorageConverter = require("./StateStorageConverter");
@@ -614,6 +616,10 @@ var parseSiteVariables = function parseSiteVariables(previousVariables, siteCode
614616
variablesObject: newStateVariables
615617
};
616618
};
619+
var parsePosition = function parsePosition(position) {
620+
if (!(0, _typeUtil.exists)(position)) return position;
621+
return _DataPackageParser.default.parseSensorPosition(position);
622+
};
617623

618624
/**
619625
* Build an object for state.product.sites[{site}] from a product/site positions fetch response
@@ -627,22 +633,25 @@ var parseSitePositions = function parseSitePositions(site, csv) {
627633
var newSite = _extends({}, site);
628634
var positions = parseCSV(csv, true); // Duplicated lines have been unintentionally seen here!
629635
positions.data.forEach(function (position) {
630-
var posId = position['HOR.VER'];
631-
if (!newSite.positions[posId]) {
632-
newSite.positions[posId] = {
633-
data: {},
634-
history: []
635-
};
636+
var parsedPosition = parsePosition(position);
637+
if ((0, _typeUtil.exists)(parsedPosition)) {
638+
var posId = parsedPosition.horVer;
639+
if (!newSite.positions[posId]) {
640+
newSite.positions[posId] = {
641+
data: {},
642+
history: []
643+
};
644+
}
645+
newSite.positions[posId].history.push(parsedPosition);
636646
}
637-
newSite.positions[posId].history.push(position);
638647
});
639648
// Sort position history by start/end time descending
640649
Object.keys(newSite.positions).forEach(function (posId) {
641650
newSite.positions[posId].history.sort(function (a, b) {
642-
if (!a.end) {
651+
if (!a.sensorEndDateTime) {
643652
return 1;
644653
}
645-
return a.end < b.start ? -1 : 1;
654+
return a.sensorEndDateTime < b.sensorStartDateTime ? -1 : 1;
646655
});
647656
});
648657
return newSite;

lib/components/TimeSeriesViewer/TimeSeriesViewerSites.d.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,20 @@ declare namespace PositionHistoryButton {
3636
const position: PropTypes.Validator<string>;
3737
const fullWidth: PropTypes.Requireable<boolean>;
3838
const history: PropTypes.Validator<(PropTypes.InferProps<{
39-
'HOR.VER': PropTypes.Validator<string>;
40-
azimuth: PropTypes.Validator<string>;
41-
pitch: PropTypes.Validator<string>;
42-
roll: PropTypes.Validator<string>;
43-
start: PropTypes.Requireable<string>;
44-
end: PropTypes.Requireable<string>;
45-
xOffset: PropTypes.Validator<string>;
46-
yOffset: PropTypes.Validator<string>;
47-
zOffset: PropTypes.Validator<string>;
48-
referenceStart: PropTypes.Requireable<string>;
49-
referenceEnd: PropTypes.Requireable<string>;
50-
referenceLatitude: PropTypes.Validator<string>;
51-
referenceLongitude: PropTypes.Validator<string>;
52-
referenceElevation: PropTypes.Validator<string>;
39+
horVer: PropTypes.Validator<string>;
40+
azimuth: PropTypes.Requireable<number>;
41+
pitch: PropTypes.Requireable<number>;
42+
roll: PropTypes.Requireable<number>;
43+
sensorStartDateTime: PropTypes.Requireable<string>;
44+
sensorEndDateTime: PropTypes.Requireable<string>;
45+
xOffset: PropTypes.Requireable<number>;
46+
yOffset: PropTypes.Requireable<number>;
47+
zOffset: PropTypes.Requireable<number>;
48+
referenceLocationStartDateTime: PropTypes.Requireable<string>;
49+
referenceLocationEndDateTime: PropTypes.Requireable<string>;
50+
referenceLocationLatitude: PropTypes.Requireable<number>;
51+
referenceLocationLongitude: PropTypes.Requireable<number>;
52+
referenceLocationElevation: PropTypes.Requireable<number>;
5353
}> | null | undefined)[]>;
5454
}
5555
namespace defaultProps {

lib/components/TimeSeriesViewer/TimeSeriesViewerSites.js

Lines changed: 66 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -386,52 +386,59 @@ function PositionHistoryButton(props) {
386386
}, "z"), /*#__PURE__*/_react.default.createElement(_TableCell.default, {
387387
align: "right"
388388
}, "Elevation"))), /*#__PURE__*/_react.default.createElement(_TableBody.default, null, history.map(function (row, idx) {
389-
var _row$start = row.start,
390-
start = _row$start === void 0 ? '' : _row$start,
391-
_row$end = row.end,
392-
rawEnd = _row$end === void 0 ? '' : _row$end,
389+
var _row$sensorStartDateT = row.sensorStartDateTime,
390+
sensorStartDateTime = _row$sensorStartDateT === void 0 ? '' : _row$sensorStartDateT,
391+
_row$sensorEndDateTim = row.sensorEndDateTime,
392+
rawEnd = _row$sensorEndDateTim === void 0 ? '' : _row$sensorEndDateTim,
393393
xOffset = row.xOffset,
394394
yOffset = row.yOffset,
395395
zOffset = row.zOffset,
396-
referenceElevation = row.referenceElevation;
397-
var hasReferenceElevation = (0, _typeUtil.exists)(referenceElevation) && referenceElevation !== '';
398-
var hasZOffset = (0, _typeUtil.exists)(zOffset) && zOffset !== '';
399-
var parsedReferenceElevation = hasReferenceElevation ? parseFloat(referenceElevation, 10) : NaN;
400-
var parsedZOffset = hasZOffset ? parseFloat(zOffset, 10) : NaN;
396+
referenceLocationElevation = row.referenceLocationElevation;
397+
var hasReferenceElevation = (0, _typeUtil.exists)(referenceLocationElevation) && !isNaN(referenceLocationElevation);
398+
var hasXOffset = (0, _typeUtil.exists)(xOffset) && !isNaN(xOffset);
399+
var hasYOffset = (0, _typeUtil.exists)(yOffset) && !isNaN(yOffset);
400+
var hasZOffset = (0, _typeUtil.exists)(zOffset) && !isNaN(zOffset);
401+
var parsedReferenceElevation = hasReferenceElevation ? referenceLocationElevation : NaN;
402+
var parsedXOffset = hasXOffset ? xOffset : NaN;
403+
var parsedYOffset = hasYOffset ? yOffset : NaN;
404+
var parsedZOffset = hasZOffset ? zOffset : NaN;
401405
var elevation = 'unknown';
402406
if (!isNaN(parsedReferenceElevation)) {
403-
if (!isNaN(hasZOffset)) {
407+
if (!isNaN(parsedZOffset)) {
404408
elevation = "".concat((parsedReferenceElevation + parsedZOffset).toFixed(2).toString(), "m");
405409
} else {
406410
elevation = "".concat(parsedReferenceElevation, "m");
407411
}
408412
}
413+
var displayXOffset = hasXOffset ? "".concat(xOffset, "m") : '--';
414+
var displayYOffset = hasYOffset ? "".concat(yOffset, "m") : '--';
415+
var displayZOffset = hasZOffset ? "".concat(zOffset, "m") : '--';
409416
var end = rawEnd === '' ? 'Current' : rawEnd;
410417
var cellStyle = idx !== history.length - 1 ? {} : {
411418
fontWeight: '600',
412419
borderBottom: 'none'
413420
};
414-
var key = "".concat(start).concat(end).concat(xOffset).concat(yOffset).concat(zOffset);
421+
var key = "".concat(sensorStartDateTime).concat(end).concat(parsedXOffset).concat(parsedYOffset).concat(parsedZOffset);
415422
return /*#__PURE__*/_react.default.createElement(_TableRow.default, {
416423
key: key
417424
}, /*#__PURE__*/_react.default.createElement(_TableCell.default, {
418425
component: "th",
419426
scope: "row",
420427
style: cellStyle
421-
}, start), /*#__PURE__*/_react.default.createElement(_TableCell.default, {
428+
}, sensorStartDateTime), /*#__PURE__*/_react.default.createElement(_TableCell.default, {
422429
component: "th",
423430
scope: "row",
424431
style: cellStyle
425432
}, end), /*#__PURE__*/_react.default.createElement(_TableCell.default, {
426433
align: "right",
427434
style: cellStyle
428-
}, "".concat(xOffset, "m")), /*#__PURE__*/_react.default.createElement(_TableCell.default, {
435+
}, displayXOffset), /*#__PURE__*/_react.default.createElement(_TableCell.default, {
429436
align: "right",
430437
style: cellStyle
431-
}, "".concat(yOffset, "m")), /*#__PURE__*/_react.default.createElement(_TableCell.default, {
438+
}, displayYOffset), /*#__PURE__*/_react.default.createElement(_TableCell.default, {
432439
align: "right",
433440
style: cellStyle
434-
}, "".concat(zOffset, "m")), /*#__PURE__*/_react.default.createElement(_TableCell.default, {
441+
}, displayZOffset), /*#__PURE__*/_react.default.createElement(_TableCell.default, {
435442
align: "right",
436443
style: cellStyle
437444
}, elevation));
@@ -448,20 +455,20 @@ PositionHistoryButton.propTypes = {
448455
position: _propTypes.default.string.isRequired,
449456
fullWidth: _propTypes.default.bool,
450457
history: _propTypes.default.arrayOf(_propTypes.default.shape({
451-
'HOR.VER': _propTypes.default.string.isRequired,
452-
azimuth: _propTypes.default.string.isRequired,
453-
pitch: _propTypes.default.string.isRequired,
454-
roll: _propTypes.default.string.isRequired,
455-
start: _propTypes.default.string,
456-
end: _propTypes.default.string,
457-
xOffset: _propTypes.default.string.isRequired,
458-
yOffset: _propTypes.default.string.isRequired,
459-
zOffset: _propTypes.default.string.isRequired,
460-
referenceStart: _propTypes.default.string,
461-
referenceEnd: _propTypes.default.string,
462-
referenceLatitude: _propTypes.default.string.isRequired,
463-
referenceLongitude: _propTypes.default.string.isRequired,
464-
referenceElevation: _propTypes.default.string.isRequired
458+
horVer: _propTypes.default.string.isRequired,
459+
azimuth: _propTypes.default.number,
460+
pitch: _propTypes.default.number,
461+
roll: _propTypes.default.number,
462+
sensorStartDateTime: _propTypes.default.string,
463+
sensorEndDateTime: _propTypes.default.string,
464+
xOffset: _propTypes.default.number,
465+
yOffset: _propTypes.default.number,
466+
zOffset: _propTypes.default.number,
467+
referenceLocationStartDateTime: _propTypes.default.string,
468+
referenceLocationEndDateTime: _propTypes.default.string,
469+
referenceLocationLatitude: _propTypes.default.number,
470+
referenceLocationLongitude: _propTypes.default.number,
471+
referenceLocationElevation: _propTypes.default.number
465472
})).isRequired
466473
};
467474
PositionHistoryButton.defaultProps = {
@@ -532,25 +539,26 @@ function PositionDetail(props) {
532539
var history = state.product.sites[siteCode].positions[position].history;
533540
var current = history.length - 1 || 0;
534541
var _ref2 = history[current] || {},
535-
name = _ref2.name,
536-
description = _ref2.description,
537-
referenceName = _ref2.referenceName,
538-
referenceDescription = _ref2.referenceDescription,
539-
_ref2$referenceElevat = _ref2.referenceElevation,
540-
referenceElevation = _ref2$referenceElevat === void 0 ? '--' : _ref2$referenceElevat,
541-
_ref2$xOffset = _ref2.xOffset,
542-
xOffset = _ref2$xOffset === void 0 ? '--' : _ref2$xOffset,
543-
_ref2$yOffset = _ref2.yOffset,
544-
yOffset = _ref2$yOffset === void 0 ? '--' : _ref2$yOffset,
545-
_ref2$zOffset = _ref2.zOffset,
546-
zOffset = _ref2$zOffset === void 0 ? '--' : _ref2$zOffset;
547-
var hasReferenceElevation = (0, _typeUtil.exists)(referenceElevation) && referenceElevation !== '';
548-
var hasZOffset = (0, _typeUtil.exists)(zOffset) && zOffset !== '' && zOffset !== '--';
549-
var parsedReferenceElevation = hasReferenceElevation ? parseFloat(referenceElevation, 10) : NaN;
550-
var parsedZOffset = hasZOffset ? parseFloat(zOffset, 10) : NaN;
542+
sensorName = _ref2.sensorName,
543+
sensorDescription = _ref2.sensorDescription,
544+
referenceLocationName = _ref2.referenceLocationName,
545+
referenceLocationDescription = _ref2.referenceLocationDescription,
546+
referenceLocationElevation = _ref2.referenceLocationElevation,
547+
xOffset = _ref2.xOffset,
548+
yOffset = _ref2.yOffset,
549+
zOffset = _ref2.zOffset;
550+
var hasReferenceElevation = (0, _typeUtil.exists)(referenceLocationElevation) && !isNaN(referenceLocationElevation);
551+
var hasXOffset = (0, _typeUtil.exists)(xOffset) && !isNaN(xOffset);
552+
var hasYOffset = (0, _typeUtil.exists)(yOffset) && !isNaN(yOffset);
553+
var hasZOffset = (0, _typeUtil.exists)(zOffset) && !isNaN(zOffset);
554+
var parsedReferenceElevation = hasReferenceElevation ? referenceLocationElevation : NaN;
555+
var parsedZOffset = hasZOffset ? zOffset : NaN;
556+
var displayXOffset = hasXOffset ? "".concat(xOffset, "m") : '--';
557+
var displayYOffset = hasYOffset ? "".concat(yOffset, "m") : '--';
558+
var displayZOffset = hasZOffset ? "".concat(zOffset, "m") : '--';
551559
var elevation = '--';
552560
if (!isNaN(parsedReferenceElevation)) {
553-
if (!isNaN(hasZOffset)) {
561+
if (!isNaN(parsedZOffset)) {
554562
elevation = "".concat((parsedReferenceElevation + parsedZOffset).toFixed(2).toString(), "m");
555563
} else {
556564
elevation = "".concat(parsedReferenceElevation, "m");
@@ -564,15 +572,15 @@ function PositionDetail(props) {
564572
fontWeight: 600
565573
};
566574
var renderDescription = function renderDescription() {
567-
var hasName = (0, _typeUtil.isStringNonEmpty)(name);
568-
var hasDescription = (0, _typeUtil.isStringNonEmpty)(description);
569-
var hasReferenceName = (0, _typeUtil.isStringNonEmpty)(referenceName);
570-
var hasReferenceDescription = (0, _typeUtil.isStringNonEmpty)(referenceDescription);
571-
var appliedName = hasName ? name : 'N/A';
572-
var appliedDescription = hasDescription ? description : 'N/A';
575+
var hasName = (0, _typeUtil.isStringNonEmpty)(sensorName);
576+
var hasDescription = (0, _typeUtil.isStringNonEmpty)(sensorDescription);
577+
var hasReferenceName = (0, _typeUtil.isStringNonEmpty)(referenceLocationName);
578+
var hasReferenceDescription = (0, _typeUtil.isStringNonEmpty)(referenceLocationDescription);
579+
var appliedName = hasName ? sensorName : 'N/A';
580+
var appliedDescription = hasDescription ? sensorDescription : 'N/A';
573581
var includeReference = hasReferenceName || hasReferenceDescription;
574-
var appliedReferenceName = hasReferenceName ? referenceName : 'N/A';
575-
var appliedReferenceDescription = hasReferenceDescription ? referenceDescription : 'N/A';
582+
var appliedReferenceName = hasReferenceName ? referenceLocationName : 'N/A';
583+
var appliedReferenceDescription = hasReferenceDescription ? referenceLocationDescription : 'N/A';
576584
return wide ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
577585
className: classes.startFlex,
578586
style: _extends({}, fadeStyle, {
@@ -681,7 +689,7 @@ function PositionDetail(props) {
681689
variant: "body2"
682690
}, /*#__PURE__*/_react.default.createElement("span", {
683691
style: _extends({}, axisStyle)
684-
}, "x / y / z:"), "".concat(xOffset, "m / ").concat(yOffset, "m / ").concat(zOffset, "m"))), renderDescription()) : /*#__PURE__*/_react.default.createElement("div", {
692+
}, "x / y / z:"), "".concat(displayXOffset, " / ").concat(displayYOffset, " / ").concat(displayZOffset))), renderDescription()) : /*#__PURE__*/_react.default.createElement("div", {
685693
ref: containerRef,
686694
className: classes.startFlex,
687695
style: positionContainerStyle
@@ -725,11 +733,11 @@ function PositionDetail(props) {
725733
variant: "body2"
726734
}, /*#__PURE__*/_react.default.createElement("span", {
727735
style: _extends({}, axisStyle)
728-
}, "x:"), "".concat(xOffset, "m"), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("span", {
736+
}, "x:"), "".concat(displayXOffset), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("span", {
729737
style: _extends({}, axisStyle)
730-
}, "y:"), "".concat(yOffset, "m"), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("span", {
738+
}, "y:"), "".concat(displayYOffset), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("span", {
731739
style: _extends({}, axisStyle)
732-
}, "z:"), "".concat(zOffset, "m")))), renderDescription()), /*#__PURE__*/_react.default.createElement("div", {
740+
}, "z:"), "".concat(displayZOffset)))), renderDescription()), /*#__PURE__*/_react.default.createElement("div", {
733741
style: historyButtonContainerStyle
734742
}, /*#__PURE__*/_react.default.createElement(PositionHistoryButton, {
735743
siteCode: siteCode,

lib/parser/DataPackageParser.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Nullable, UnknownRecord } from '../types/core';
2+
import { SensorPosition } from '../types/internal';
3+
export interface IDataPackageParser {
4+
/**
5+
* Parse a data package sensor position record into an
6+
* internal shape based on detected schema version.
7+
* @param position The position to parse
8+
* @returns The parsed position to an internal, normalized shape.
9+
*/
10+
parseSensorPosition: (position: Nullable<UnknownRecord>) => Nullable<SensorPosition>;
11+
}
12+
declare const DataPackageParser: IDataPackageParser;
13+
export default DataPackageParser;

lib/parser/DataPackageParser.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"use strict";
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
exports.default = void 0;
7+
var _typeUtil = require("../util/typeUtil");
8+
var _neonDataPackage = require("../types/neonDataPackage");
9+
var DataPackageParser = {
10+
parseSensorPosition: function parseSensorPosition(position) {
11+
if (!(0, _typeUtil.exists)(position)) {
12+
return null;
13+
}
14+
var result = null;
15+
var resultV2 = _neonDataPackage.sensorPositionV2Schema.safeParse(position);
16+
if (!resultV2.success) {
17+
// Check for v1 schema
18+
var resultV1 = _neonDataPackage.sensorPositionV1Schema.safeParse(position);
19+
if (!resultV1.success) {
20+
var v2ErrorFormat = resultV2.error.format();
21+
var v1ErrorFormat = resultV1.error.format();
22+
// eslint-disable-next-line no-console
23+
console.error('Failed to detect sensor position schema', v2ErrorFormat, v1ErrorFormat);
24+
} else {
25+
var parsedV1 = resultV1.data;
26+
result = {
27+
horVer: parsedV1['HOR.VER'],
28+
sensorName: (0, _typeUtil.isStringNonEmpty)(parsedV1.name) ? parsedV1.name : 'N/A',
29+
sensorDescription: parsedV1.description,
30+
sensorStartDateTime: parsedV1.start,
31+
sensorEndDateTime: parsedV1.end,
32+
referenceLocationName: parsedV1.referenceName,
33+
referenceLocationDescription: parsedV1.referenceDescription,
34+
referenceLocationStartDateTime: parsedV1.referenceStart,
35+
referenceLocationEndDateTime: parsedV1.referenceEnd,
36+
xOffset: parsedV1.xOffset,
37+
yOffset: parsedV1.yOffset,
38+
zOffset: parsedV1.zOffset,
39+
pitch: parsedV1.pitch,
40+
roll: parsedV1.roll,
41+
azimuth: parsedV1.azimuth,
42+
referenceLocationLatitude: parsedV1.referenceLatitude,
43+
referenceLocationLongitude: parsedV1.referenceLongitude,
44+
referenceLocationElevation: parsedV1.referenceElevation,
45+
eastOffset: parsedV1.eastOffset,
46+
northOffset: parsedV1.northOffset,
47+
xAzimuth: parsedV1.xAzimuth,
48+
yAzimuth: parsedV1.yAzimuth
49+
};
50+
}
51+
} else {
52+
var parsedV2 = resultV2.data;
53+
result = {
54+
horVer: parsedV2['HOR.VER'],
55+
sensorName: parsedV2.sensorLocationID,
56+
sensorDescription: parsedV2.sensorLocationDescription,
57+
sensorStartDateTime: parsedV2.positionStartDateTime,
58+
sensorEndDateTime: parsedV2.positionEndDateTime,
59+
referenceLocationName: parsedV2.referenceLocationID,
60+
referenceLocationDescription: parsedV2.referenceLocationIDDescription,
61+
referenceLocationStartDateTime: parsedV2.referenceLocationIDStartDateTime,
62+
referenceLocationEndDateTime: parsedV2.referenceLocationIDEndDateTime,
63+
xOffset: parsedV2.xOffset,
64+
yOffset: parsedV2.yOffset,
65+
zOffset: parsedV2.zOffset,
66+
pitch: parsedV2.pitch,
67+
roll: parsedV2.roll,
68+
azimuth: parsedV2.azimuth,
69+
referenceLocationLatitude: parsedV2.locationReferenceLatitude,
70+
referenceLocationLongitude: parsedV2.locationReferenceLongitude,
71+
referenceLocationElevation: parsedV2.locationReferenceElevation,
72+
eastOffset: parsedV2.eastOffset,
73+
northOffset: parsedV2.northOffset,
74+
xAzimuth: parsedV2.xAzimuth,
75+
yAzimuth: parsedV2.yAzimuth
76+
};
77+
}
78+
return result;
79+
}
80+
};
81+
Object.freeze(DataPackageParser);
82+
var _default = DataPackageParser;
83+
exports.default = _default;

0 commit comments

Comments
 (0)