Shared TypeScript data models and utilities for radar-based rainfall analysis, used across all radartorain.com services.
raain-model is the foundational model library for the Raain ecosystem, providing type-safe data structures, coordinate transformations, and measurement utilities for converting weather radar data into actionable rainfall measurements.
npm install raain-model
# or
yarn add raain-model
import {RainNode, RadarNode, GaugeNode} from 'raain-model';
// Create a radar node
const radarNode = new RadarNode({
id: 'parisR',
latitude: 48.8566,
longitude: 2.3522,
name: 'Paris Radar',
team: null
});
// Create a rain gauge node
const gaugeNode = new GaugeNode({
id: 'parisG',
latitude: 48.8566,
longitude: 2.3522,
name: 'One Paris Gauge',
team: null
});
// Create a rain node
const rainNode = new RainNode({
id: 'parisZ',
name: 'Paris Rain Zone',
team: null,
radars: [radarNode],
gauges: [gaugeNode]
});
// ...
Visit documentation and API swagger.
⚠️ IMPORTANT: Keep this section up to date when adding new API endpoints or model classes. This mapping is critical for API consumers to understand which models to expect from each endpoint. Validation Rules:
- Every endpoint listed here MUST exist in Raain Api Routes
- Every model class MUST have the endpoint documented in its source file header (e.g.,
RainNode.ts)- Before adding an endpoint, verify it exists in both locations
The following table lists which REST API endpoints return or accept which model classes in this library:
| API endpoint (pattern) | Exposes model class | Notes |
|---|---|---|
/radars |
RadarNode[] |
Search for radars |
/radars/:radarId |
RadarNode |
Get a radar by ID |
/radars/:radarId/measures |
RadarMeasure[] |
Get radar measures |
/radars/:radarId/measures/:radarMeasureId |
RadarMeasure |
Get a radar measure by ID |
/gauges |
GaugeNode[] |
Search for gauges |
/gauges/:gaugeId |
GaugeNode |
Get a gauge by ID |
/gauges/:gaugeId?format=cartesian-map |
GaugeNodeMap |
Get a gauge by ID (format=cartesian-map) |
/gauges/:gaugeId/measures |
GaugeMeasure[] |
Get gauge measures |
/rains |
RainNode[] |
Search for rain zones |
/rains/:rainId |
RainNode |
Get a rain zone by ID |
/rains/:rainId/cumulatives/:rainComputationCumulativeId |
RainComputationCumulative |
Get a cumulative computation |
/rains/:rainId/cumulatives/:rainComputationCumulativeId?format=cartesian-map |
RainComputationMap |
Get a cumulative computation (format=cartesian-map) |
/rains/:rainId/cumulatives/:rainComputationCumulativeId/compares |
RainComputationQuality[] |
Get cumulative quality metrics |
/rains/:rainId/cumulatives/:rainComputationCumulativeId/cumulative/:cumulativeHours |
RainComputationCumulative |
Get cumulative computation data |
/notifications |
EventNode[] |
Get all notifications |
/notifications/:notificationId |
EventNode |
Get a notification by ID |
/teams |
TeamNode[] |
Search for teams |
/teams/:teamId |
TeamNode |
Get a team by ID |
Note: All endpoints are prefixed with the API version (e.g., /v3/...).
api/)The api/ directory provides TypeScript interfaces for API request and response contracts, enabling type-safe API
integration.
Contract Types:
| Suffix | Purpose | Example |
|---|---|---|
*Request |
Query parameters (GET) | RaainApiGaugesFindMeasuresRequest |
*RequestBody |
Request body (POST/PUT) | RaainApiGaugesUpsertMeasureRequestBody |
*Response |
Response body | RaainApiGaugesFindMeasuresResponse |
Common Types:
PaginationRequest: Standard pagination params (page, limit)PaginatedResponse<T>: Paginated list response (data, total, hasNext, etc.)ErrorResponse: Standard error format ({ error: string })Usage Example:
import {
RaainApiGaugesFindMeasuresRequest,
RaainApiGaugesFindMeasuresResponse,
PaginatedResponse,
GaugeNode
} from 'raain-model';
// Type-safe request parameters
const params: RaainApiGaugesFindMeasuresRequest = {
begin: '2024-01-01T00:00:00Z',
end: '2024-01-02T00:00:00Z'
};
// Type-safe response handling
const response: RaainApiGaugesFindMeasuresResponse = await fetch(
`/v3/gauges/${gaugeId}/measures?begin=${params.begin}&end=${params.end}`
).then(r => r.json());
// Paginated endpoints return PaginatedResponse<T>
const gauges: PaginatedResponse<GaugeNode> = await fetch('/v3/gauges').then(r => r.json());
Organization & Management
RainNode: Rain zone with radar(s) coverageRadarNode: Radar station metadata and configurationGaugeNode: Physical rain gauge stationTeamNode: Team/organization entityPeopleNode: User/person entity with rolesEventNode: Notification/event payloadMeasurements
RadarMeasure: Single radar measurement with polar dataGaugeMeasure: Single gauge measurementRainMeasure: Aggregated rain measurementRainComputation: Rain computation resultRainComputationCumulative: Cumulative rain computation over timeCoordinate Systems
CartesianMeasureValue: Cartesian (x, y) rain map dataPolarMeasureValue: Polar (azimuth, range) radar dataPolarMeasureValueMap: Collection of polar measurementsLatLng: Geographic coordinates (latitude/longitude)EarthMap: Singleton for earth coordinate mappingCartesianTools: Utilities for geographic calculationsData Visualization
RadarNodeMap: Radar coverage/map visualizationGaugeNodeMap: Gauge data over time windowRainComputationMap: Rain computation as cartesian mapQuality & Analysis
RainComputationQuality: Quality metrics comparing radar vs gaugeSpeedMatrix: Quality assessment matrix with multiple indicator methodsQualityIndicatorMethod: Enum for quality calculation strategiesRainSpeed / RainSpeedMap: Rain speed tracking and storageThe SpeedMatrixContainer.getQuality() method supports multiple methods to assess radar prediction quality against
gauge measurements:
import {QualityIndicatorMethod, SpeedMatrixContainer} from 'raain-model';
const container = new SpeedMatrixContainer({matrices: [...]});
// Default (NASH_SUTCLIFFE) - returns raw value (0 to 1)
const nse = container.getQuality();
// Use specific method - returns raw value
const delta = container.getQuality('m1', {
method: QualityIndicatorMethod.DELTA
});
// With normalize=true - returns 0-100 scale (0=bad, 100=best)
const normalizedDelta = container.getQuality('m1', {
method: QualityIndicatorMethod.DELTA,
normalize: true
});
// With custom threshold for SUCCESS_RATE
const success = container.getQuality('m1', {
method: QualityIndicatorMethod.SUCCESS_RATE,
successThreshold: 0.9 // 90% match required
});
// With custom normalization options
const customNormalized = container.getQuality('m1', {
method: QualityIndicatorMethod.RMSE,
normalize: true,
normalizationOptions: {rmseMaxRef: 20} // 20 mm/h as max reference
});
Nash-Sutcliffe Efficiency (NSE) is particularly useful for hydrology:
All methods:
| Method | Range | Perfect | Description |
|---|---|---|---|
NASH_SUTCLIFFE |
-∞ → 1 | 1 | Hydrology standard (default) |
DELTA |
0 → ∞ | 0 | Average absolute difference |
RATIO |
0 → 1 | 1 | Average of min/max ratio between values |
SUCCESS_RATE |
0 → 100 | 100 | Percentage of points meeting threshold |
RMSE |
0 → ∞ | 0 | Root Mean Square Error (penalizes large errors) |
MAPE |
0 → 100+ | 0 | Mean Absolute Percentage Error |
Normalizing Quality Indicators (0 = bad, 100 = best)
All quality methods can be normalized to a unified 0-100 scale for easier comparison.
| Method | Normalization Formula | Default Reference |
|---|---|---|
SUCCESS_RATE |
value (already 0-100) | - |
RATIO |
value × 100 | - |
NASH_SUTCLIFFE |
clamp(value, 0, 1) × 100 | min clamp: 0 |
DELTA |
100 - (value / maxRef) × 100 | maxRef: 10 mm/h |
RMSE |
100 - (value / maxRef) × 100 | maxRef: 10 mm/h |
MAPE |
100 - (value / maxRef) × 100 | maxRef: 100% |
Default reference values are available via QUALITY_NORMALIZATION_DEFAULTS.
The library supports two coordinate systems for different use cases:
Polar Coordinates (azimuth, range)
Cartesian Coordinates (x, y)
CartesianTools# Install dependencies
npm i
# ... Do your changes ...
# Linting and formatting
npm run bp:style:fix
# Run all tests
npm test
# (optional) Compile TypeScript
npm run build
# PR it :)
See CHANGELOG.md for version history and changes.
This project is licensed under the MIT License - see the LICENSE file for details.