geomagnetism
Advanced tools
Comparing version 0.1.1 to 0.2.0
@@ -21,3 +21,3 @@ var fs = require('fs'); | ||
//get parser by input file extension | ||
// get parser by input file extension | ||
var ext = path.extname(input_filename).toLowerCase().substr(1); | ||
@@ -24,0 +24,0 @@ var parser; |
68
index.js
@@ -1,34 +0,54 @@ | ||
var Model = require('./lib/model.js'); | ||
var geomagnetism = module.exports = {}; | ||
const Model = require('./lib/model.js'); | ||
const geomagnetism = module.exports = {}; | ||
var models = null; | ||
var modelData = [ | ||
require('./data/wmm-2020.json'), | ||
require('./data/wmm-2015v2.json'), | ||
require('./data/wmm-2015.json'), | ||
const modelData = [ | ||
{ | ||
file: require('./data/wmm-2025.json'), | ||
startDate: new Date("2024-11-13T03:00:00.000Z"), | ||
endDate: new Date("2029-11-13T03:00:00.000Z") | ||
}, | ||
{ | ||
file: require('./data/wmm-2020.json'), | ||
startDate: new Date("2019-12-10T08:00:00.000Z"), | ||
endDate: new Date("2024-12-10T08:00:00.000Z") | ||
}, | ||
{ | ||
file: require('./data/wmm-2015v2.json'), | ||
startDate: new Date("2018-09-18T06:00:00.000Z"), | ||
endDate: new Date("2023-09-18T06:00:00.000Z") | ||
}, | ||
{ | ||
file: require('./data/wmm-2015.json'), | ||
startDate: new Date("2014-12-15T07:00:00.000Z"), | ||
endDate: new Date("2019-12-15T07:00:00.000Z") | ||
} | ||
]; | ||
var base_model; | ||
geomagnetism.model = function(date) { | ||
geomagnetism.model = function (date, options = {}) { | ||
date = date || new Date(); | ||
if (!models) { | ||
models = modelData.map(function(data) { | ||
return new Model(data); | ||
}); | ||
const ts = date.getTime(); | ||
const allowOutOfBoundsModel = (options && options.allowOutOfBoundsModel) || false; | ||
// Get the latest matching model | ||
let matchingModelData = modelData.find((model) => { | ||
return ts >= model.startDate.getTime() && ts <= model.endDate.getTime(); | ||
}); | ||
// Get if the date is before the first model or after the last model | ||
if (!matchingModelData && ts < modelData[modelData.length - 1].startDate.getTime()) { | ||
matchingModelData = modelData[modelData.length - 1]; | ||
} else if (!matchingModelData && ts > modelData[0].endDate.getTime()) { | ||
matchingModelData = modelData[0]; | ||
} | ||
var ts = date.getTime(); | ||
var matchingModel; | ||
for (var i = 0, n = models.length; i < n; ++i) { | ||
if (models[i].start_date.getTime() > ts) continue; | ||
if (models[i].end_date.getTime() < ts) continue; | ||
matchingModel = models[i]; | ||
break; | ||
// If no matching model found, use the latest | ||
if (!matchingModelData) { | ||
matchingModelData = modelData[0]; // latest (will throw error if allowOutOfBoundsModel is true) | ||
} | ||
if (!matchingModel) { | ||
matchingModel = models[0]; // latest (will throw error) | ||
} | ||
return matchingModel.getTimedModel(date); | ||
const matchingModel = new Model(matchingModelData.file); | ||
return matchingModel.getTimedModel(date, allowOutOfBoundsModel); | ||
}; |
var GeodeticCoord = require('./coords/geodetic.js'); | ||
var Ellipsoid = require('./ellipsoid.js'); | ||
var MagneticElements = require('./magnetic_elements.js'); | ||
@@ -22,6 +21,5 @@ var MagneticVector = require('./magnetic_vector.js'); | ||
Model.prototype.getTimedModel = function(date){ | ||
var year_int = date.getFullYear(); | ||
var year_start = new Date(year_int, 0, 1); | ||
var fractional_year = (date.valueOf() - year_start.valueOf()) / (1000*3600*24*365); | ||
Model.prototype.getTimedModel = function(date, allowOutOfBoundsModel = false){ | ||
var year_int = date.getUTCFullYear(); | ||
var fractional_year = (date.valueOf() - Date.UTC(year_int)) / (1000*3600*24*365); | ||
var year = year_int + fractional_year; | ||
@@ -31,3 +29,7 @@ var dyear = year - this.epoch; | ||
if(date < this.start_date || date > this.end_date){ | ||
throw new RangeError("Model is only valid from "+this.start_date.toDateString()+" to "+this.end_date.toDateString()); | ||
if(allowOutOfBoundsModel) { | ||
console.error("Model is only valid from "+this.start_date.toDateString()+" to "+this.end_date.toDateString()); | ||
} else { | ||
throw new Error("Model is only valid from "+this.start_date.toDateString()+" to "+this.end_date.toDateString()); | ||
} | ||
} | ||
@@ -39,3 +41,5 @@ | ||
n_max_sec_var: this.n_max_sec_var, | ||
name: this.name | ||
name: this.name, | ||
start_date: this.start_date, | ||
end_date: this.end_date, | ||
}); | ||
@@ -121,12 +125,10 @@ var a = model.n_max_sec_var; | ||
/* | ||
Model.prototype.getSecVarSummation = function(sph_variables, coord_spherical){ | ||
//TODO | ||
} | ||
*/ | ||
Model.prototype.point = function(coords) { | ||
// Extract altitude if provided, otherwise default to 0 | ||
var altitude = (coords.length > 2 && typeof coords[2] === 'number') ? coords[2] : 0; | ||
Model.prototype.point = function(coords) { | ||
var coord_geodetic = new GeodeticCoord({ | ||
lat: coords[0], | ||
lon: coords[1] | ||
lon: coords[1], | ||
height_above_ellipsoid: altitude | ||
}); | ||
@@ -133,0 +135,0 @@ var coord_spherical = coord_geodetic.toSpherical(); |
{ | ||
"name": "geomagnetism", | ||
"version": "0.1.1", | ||
"types": "geomagnetism.d.ts", | ||
"version": "0.2.0", | ||
"description": "Computes geomagnetic field information", | ||
@@ -5,0 +6,0 @@ "main": "index.js", |
# geomagnetism | ||
[![NPM version](http://img.shields.io/npm/v/geomagnetism.svg?style=flat)](https://www.npmjs.org/package/geomagnetism) | ||
[![Build Status](http://img.shields.io/travis/naturalatlas/geomagnetism/master.svg?style=flat)](https://travis-ci.org/naturalatlas/geomagnetism) | ||
[![Coverage Status](http://img.shields.io/coveralls/naturalatlas/geomagnetism/master.svg?style=flat)](https://coveralls.io/r/naturalatlas/geomagnetism) | ||
Get magnetic declination for given time and place. It's an adaptation of the [World Magnetic Model](http://www.ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml) by the [NOAA National Geophysical Data Center](https://www.ngdc.noaa.gov/). | ||
`geomagnetism` provides a convenient interface for retrieving the Earth's magnetic declination (variation between magnetic north and true north) at a given location and date. It leverages NOAA's [World Magnetic Model (WMM)](https://www.ngdc.noaa.gov/geomag/WMM/) to compute properties such as declination, inclination, horizontal intensity, and more. | ||
@@ -14,18 +13,79 @@ ``` sh | ||
The main entry point is the `model()` function. If you pass it a Date object, it will compute results for that specific date. If you do **not** pass a date, it will default to the current date. Once you have a model, you can query it using the `point()` method, which expects an array representing latitude and longitude. Optionally, you can provide an altitude as a third element in the array. | ||
- Latitude and longitude are required: `[lat, lon]` | ||
- Altitude (optional) can be provided: `[lat, lon, altitude_in_kilometers]` | ||
**Example: Current Date** | ||
```js | ||
const geomagnetism = require('geomagnetism'); | ||
// information for "right now" | ||
const info = geomagnetism.model().point([44.53461, -109.05572]); | ||
console.log('declination:', info.decl); | ||
// If no date is passed, the current date is used | ||
const currentModel = geomagnetism.model(); | ||
const info = currentModel.point([44.53461, -109.05572]); // only lat/lon | ||
console.log('Declination (current date):', info.decl, 'degrees'); | ||
``` | ||
// use a specific date | ||
const model = geomagnetism.model(new Date('12/25/2017')); | ||
const info = model.point([44.53461, -109.05572]); | ||
console.log('declination:', info.decl); | ||
**Example: Specific Date** | ||
```js | ||
const geomagnetism = require('geomagnetism'); | ||
// If a date is passed, that specific date is used | ||
const specificDateModel = geomagnetism.model(new Date('2020-10-05')); | ||
const info = specificDateModel.point([44.53461, -109.05572]); | ||
console.log('Declination on 2020-10-05:', info.decl, 'degrees'); | ||
``` | ||
**Example: Including Altitude** | ||
```js | ||
const geomagnetism = require('geomagnetism'); | ||
// Provide altitude as the third array item (in kilometers above mean sea level) | ||
const model = geomagnetism.model(new Date('2022-01-01')); | ||
const infoWithAltitude = model.point([44.53461, -109.05572, 1.5]); | ||
console.log('Declination at altitude:', infoWithAltitude.decl, 'degrees'); | ||
``` | ||
## Handling Out-of-Range Dates | ||
The `geomagnetism.model()` function determines the best available World Magnetic Model for the date you provide. If the given date falls outside the known range of the WMM data files, by default (`allowOutOfBoundsModel = false`), the function will throw an error indicating that no suitable model is found for the given date. | ||
If you would prefer that the library "fall back" to the closest available model rather than throwing an error, you can explicitly pass true to allowOutOfBoundsModel option. | ||
```js | ||
geomagnetism.model(date, { allowOutOfBoundsModel: true }); | ||
``` | ||
- `date`: *(optional)* A JavaScript Date object. Defaults to the current date if not specified. | ||
- `allowOutOfBoundsModel`: *(optional)* A boolean. If not specified or false, throws an error if the date is out of range. If true, falls back to the nearest available model. | ||
**Examples:** | ||
```js | ||
const geomagnetism = require('geomagnetism'); | ||
// Strict behavior (default): If the date is out of range, an error is thrown | ||
try { | ||
let model = geomagnetism.model(new Date('1900-01-01')); // allowOutOfBoundsModel defaults to false | ||
let info = model.point([44.53461, -109.05572]); | ||
} catch (err) { | ||
console.error('Error (strict mode):', err.message); | ||
} | ||
// Fallback behavior: If the date is out of range, it uses the closest model | ||
let fallbackModel = geomagnetism.model(new Date('1900-01-01'), { allowOutOfBoundsModel: true }); | ||
let fallbackInfo = fallbackModel.point([44.53461, -109.05572]); | ||
console.log('Declination using fallback model:', fallbackInfo.decl); | ||
``` | ||
## Available Data & Models | ||
`geomagnetism` ships with multiple versions of the WMM data, each valid for a certain time range. The library automatically picks the correct model based on the date you supply. Older models are included to gracefully handle historical dates when using the fallback behavior. | ||
## License | ||
Copyright © 2015–2021 [Natural Atlas, Inc.](https://naturalatlas.com/) & [Contributors](https://github.com/naturalatlas/geomagnetism/graphs/contributors) | ||
Copyright © 2015–2024 [Natural Atlas, Inc.](https://naturalatlas.com/) & [Contributors](https://github.com/naturalatlas/geomagnetism/graphs/contributors) | ||
@@ -32,0 +92,0 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0 |
var geomagnetism = require('../index.js'); | ||
var assert = require('chai').assert; | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
@@ -51,7 +50,6 @@ | ||
values.forEach(function(test){ | ||
if(test.alt > 0) return; | ||
var model = getModel(test); | ||
var info = model.point([test.lat, test.lon]); | ||
assert.closeTo(info.incl, test.incl, tolerances.incl, 'inclination'); | ||
assert.closeTo(info.decl, test.decl, tolerances.decl, 'declination'); | ||
var info = model.point([test.lat, test.lon, test.alt]); | ||
assert.closeTo(info.incl, test.incl, tolerances.incl, 'inclination ' + test.date); | ||
assert.closeTo(info.decl, test.decl, tolerances.decl, 'declination ' + test.date); | ||
assert.closeTo(info.x, test.x, tolerances.x, 'x'); | ||
@@ -66,15 +64,24 @@ assert.closeTo(info.y, test.y, tolerances.y, 'y'); | ||
var date = new Date(); | ||
var info = geomagnetism.model(date).point([44.53461, -109.05572]); | ||
geomagnetism.model(date).point([44.53461, -109.05572]); | ||
}); | ||
it("should return value for current date + 1 year", function(){ | ||
var date = new Date(Date.now() + 1000 * 3600 * 24 * 365); | ||
var info = geomagnetism.model(date).point([44.53461, -109.05572]); | ||
var date = new Date(); | ||
date.setFullYear(date.getFullYear() + 1); | ||
geomagnetism.model(date).point([44.53461, -109.05572]); | ||
}); | ||
}); | ||
describe("getTimedModel()", function(){ | ||
it("should throw if date is outside of valid range", function(){ | ||
it("should throw error if date is outside of valid range and allowOutOfBoundsModel is false", function(){ | ||
assert.throws(function(){ | ||
geomagnetism.model(new Date("1/1/1999")); | ||
}, RangeError); | ||
}, Error); | ||
}); | ||
it("should log error if date is outside of valid range below and allowOutOfBoundsModel is true", function(){ | ||
var model = geomagnetism.model(new Date("1/1/1999"), { allowOutOfBoundsModel: true }); | ||
assert.equal(model.start_date.getFullYear(), 2014); | ||
}); | ||
it("should log error if date is outside of valid range above and allowOutOfBoundsModel is true", function(){ | ||
var model = geomagnetism.model(new Date("1/1/2030"), { allowOutOfBoundsModel: true }); | ||
assert.equal(model.start_date.getFullYear(), 2024); | ||
}); | ||
it("should get a different model for a different date", function(){ | ||
@@ -81,0 +88,0 @@ var pt = [44.53461, -109.05572]; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
72885
23
2250
94
1