Geometry and frames

Positions, frames, terrain and the geomagnetic field: grand.geo.

grand.geo.coordinates

Terrestrial coordinate systems and the conversions between them.

grand.geo.topography

Topography wrapper for GRAND packages.

grand.geo.geomagnet

Geomagnetic field wrapper for GRAND packages

grand.geo.coordinates

Terrestrial coordinate systems and the conversions between them.

The frames are Geodetic, ECEF, LTP and GRANDCS; every conversion between a local frame and geodetic passes through ECEF. See Coordinates and conventions for the conventions, including the two that most often catch people out: every angle is in degrees, and GRANDCS \(x\) runs north where an ENU \(x\) runs east.

units:

  • energy: GeV

  • time : nanosecond

  • length: m

  • voltage: microVolt

  • Efield: microVolt/m

  • Bfield: nanoTesla

  • angles: degree

  • grammage: g/cm2

  • Density: g/cm3

  • frequency: Hz

  • resistance: Ohm.

class grand.geo.coordinates.Coordinates(n: int | None = None)[source]

Bases: ndarray

Generic container for a coordinates object.

This object created is a standard np.ndarray of size (3, n) where 3 is for 3D coordinates and n is the number of entries.

class grand.geo.coordinates.CartesianRepresentation(arg: Any = None, x: float | ndarray = None, y: float | ndarray = None, z: float | ndarray = None)[source]

Bases: Coordinates

Generic container for cartesian coordinates.

info()[source]

Prints a short description of the object, for interactive use.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

A short description of shape and range, for interactive use.

Return type:

str

property x

Cartesian \(x\) component, in meters.

Parameters:

v (float or ndarray) – Metres along the frame x axis.

Returns:

Metres along the frame x axis.

Return type:

float or ndarray

property y

Cartesian \(y\) component, in meters.

Parameters:

v (float or ndarray) – Metres along the frame y axis.

Returns:

Metres along the frame y axis.

Return type:

float or ndarray

property z

Cartesian \(z\) component, in meters.

Parameters:

v (float or ndarray) – Metres along the frame z axis.

Returns:

Metres along the frame z axis.

Return type:

float or ndarray

cartesian_to_spherical()[source]

Returns this vector as a SphericalRepresentation.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

Polar angle, azimuth and radius.

Return type:

SphericalRepresentation

cartesian_to_horizontal()[source]

Returns this vector as a HorizontalRepresentation.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

Azimuth, elevation and norm.

Return type:

HorizontalRepresentation

norm()[source]

Returns the Euclidean length of the vector, in meters.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

Euclidean length of each vector, in meters.

Return type:

ndarray

class grand.geo.coordinates.SphericalRepresentation(arg: Any = None, theta: float | int | ndarray = None, phi: float | int | ndarray = None, r: float | int | ndarray = None)[source]

Bases: Coordinates

Generic container for spherical coordinates.

property theta

Polar angle from the \(+z\) axis, in degrees.

Parameters:

v (float or ndarray) – Polar angle from +z, in degrees.

Returns:

Polar angle from +z, in degrees.

Return type:

float or ndarray

property phi

Azimuth from the \(+x\) axis, in degrees.

Parameters:

v (float or ndarray) – Azimuth from +x, in degrees.

Returns:

Azimuth from +x, in degrees.

Return type:

float or ndarray

property r

Radius, in meters.

Parameters:

v (float or ndarray) – Radius, in meters.

Returns:

Radius, in meters.

Return type:

float or ndarray

spherical_to_cartesian()[source]

Returns this vector as a CartesianRepresentation.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

Components x, y and z.

Return type:

CartesianRepresentation

spherical_to_horizontal()[source]

Returns this vector as a HorizontalRepresentation.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

Azimuth, elevation and norm.

Return type:

HorizontalRepresentation

class grand.geo.coordinates.HorizontalRepresentation(azimuth: float | int | ndarray = None, elevation: float | int | ndarray = None, norm: float | int | ndarray = 1.0)[source]

Bases: Coordinates

Generic container for horizontal coordinates.

property azimuth

Azimuth from geographic north toward east, in degrees.

Parameters:

v (float or ndarray) – Degrees from geographic north toward east.

Returns:

Degrees from north toward east.

Return type:

float or ndarray

property elevation

Elevation above the horizon, in degrees.

Parameters:

v (float or ndarray) – Degrees above the horizon.

Returns:

Degrees above the horizon.

Return type:

float or ndarray

property norm

Length of the vector, in meters.

Parameters:

v (float or ndarray) – Length of the vector, in meters.

Returns:

Length of the vector, in meters.

Return type:

float or ndarray

horizontal_to_cartesian()[source]

Returns this vector as a CartesianRepresentation.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

Components x, y and z.

Return type:

CartesianRepresentation

horizontal_to_spherical()[source]

Returns this vector as a SphericalRepresentation.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

Polar angle, azimuth and radius.

Return type:

SphericalRepresentation

class grand.geo.coordinates.Horizontal(arg: Any = None, azimuth: float | int | ndarray = None, elevation: float | int | ndarray = None, norm: float | int | ndarray = 1.0, location: Any = Geodetic([[38.88849], [92.28605], [2920.522]]), vector: bool = False)[source]

Bases: HorizontalRepresentation

Generic container for horizontal coordinates.

azimuth : angle (deg) starting from true North toward East. elevation: angle (deg) from horizontal plane toward zenith.

horizontal_to_ecef()[source]

Returns this direction in the ECEF frame.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The same direction, Earth-centred.

Return type:

ECEF

horizontal_to_geodetic()[source]

Returns this direction as a geodetic position.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The same direction, as a geodetic position.

Return type:

Geodetic

horizontal_to_grandcs()[source]

Returns this direction in the GRANDCS array frame.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The same direction, in the array frame.

Return type:

GRANDCS

class grand.geo.coordinates.HorizontalVector(*args, **kwargs)[source]

Bases: HorizontalRepresentation

Deprecated alias, merged into Horizontal.

by adding ‘vector’ attribute to reduce code duplication. It takes what Horizontal takes: location raised TypeError here.

class grand.geo.coordinates.ECEF(arg: Any = None, x: float | int | ndarray = None, y: float | int | ndarray = None, z: float | int | ndarray = None, *args, **kwargs)[source]

Bases: CartesianRepresentation

Earth-Centred, Earth-Fixed Cartesian coordinates, in meters.

A right-handed frame whose origin is the center of the Earth and which rotates with it. Every conversion between a local frame and geodetic coordinates passes through ECEF; it is the common pivot, so that the ellipsoid constants live in one place.

The axes are:

  • \(x\), through the equator at the prime meridian (latitude 0, longitude 0);

  • \(y\), through the equator 90 degrees east (latitude 0, longitude 90);

  • \(z\), through the north pole (latitude 90).

Examples

import numpy as np
from grand import Geodetic, ECEF

site = Geodetic(latitude=40.98, longitude=93.95, height=1200.0)
print(np.round(np.asarray(ECEF(site)).ravel(), 1))
[-332230.4 4811451.1 4161493.6]

See also

Geodetic

latitude, longitude and height.

LTP

a local tangent plane.

GRANDCS

the array frame.

ecef_to_geodetic(reference='GEOID')[source]

Returns this position as latitude, longitude and height.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

Latitude, longitude and height.

Return type:

Geodetic

Parameters:

reference (str or Reference, optional) – Surface the height is measured from.

ecef_to_grandcs(location=None)[source]

Returns this position in the GRANDCS array frame.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Parameters:

location (Geodetic, optional) – Origin of the array frame. Without it the default origin is used, with a warning.

Returns:

The same position, in the array frame.

Return type:

GRANDCS

ecef_to_ltp(ltp)[source]

Returns this position in a local tangent plane, LTP.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The same position, in the local frame.

Return type:

LTP

Parameters:

ltp (LTP or GRANDCS) – The frame to express the result in.

class grand.geo.coordinates.Geodetic(arg: Any = None, latitude: float | int | ndarray = None, longitude: float | int | ndarray = None, height: float | int | ndarray = None, *args, **kwargs)[source]

Bases: GeodeticRepresentation

A position as latitude, longitude and height.

Latitude

Degrees north of the equator, from -90 (South Pole) to +90 (North Pole); negative in the southern hemisphere.

Longitude

Degrees east of the prime meridian (Greenwich), between -360 and 360 (beyond that it is refused). A negative value is stored plus 360, so -10 becomes 350.

Height

Metres above the WGS-84 ellipsoid, the reference surface of these coordinates; not below -6400 km, the center of the Earth. The ellipsoid is not sea level: the geoid (mean sea level) lies up to about 100 m above or below it, 61 m below at Dunhuang. Heights from other sources – topography, site tables – may be measured from the geoid; see Reference and geoid_undulation().

Conversions to and from the local frames (LTP, GRANDCS) pass through ECEF, whose origin is the center of the Earth.

See also

grand.geo.coordinates.GRANDCS

The array frame.

grand.geo.topography.geoid_undulation

Between the ellipsoid and sea level.

Examples

Conversion to any local frame passes through ECEF, and the round trip is exact.

import numpy as np
from grand import Geodetic, ECEF

site = Geodetic(latitude=40.98, longitude=93.95, height=1200.0)
print("ECEF (m):", np.round(np.asarray(ECEF(site)).ravel(), 1))
print("round trip:", np.round(np.asarray(Geodetic(ECEF(site))).ravel(), 6))
ECEF (m): [-332230.4 4811451.1 4161493.6]
round trip: [  40.98   93.95 1200.  ]
geodetic_to_horizontal(location=None)[source]

Returns this position in horizontal coordinates, as seen from location.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Parameters:

location (Geodetic, ECEF, LTP or GRANDCS) – Where the direction is measured from.

Returns:

Azimuth, elevation and norm.

Return type:

Horizontal

geodetic_to_ecef()[source]

Returns this position in the ECEF frame.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The same position, Earth-centred.

Return type:

ECEF

geodetic_to_grandcs(location=None)[source]

Returns this position in the GRANDCS array frame.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Parameters:

location (Geodetic, optional) – Origin of the array frame. Without it the default origin is used, with a warning.

Returns:

The same position, in the array frame.

Return type:

GRANDCS

geodetic_to_ltp(ltp)[source]

Returns this position in a local tangent plane, LTP.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The same position, in the local frame.

Return type:

LTP

Parameters:

ltp (LTP or GRANDCS) – The frame to express the result in.

class grand.geo.coordinates.LTP(arg: Any = None, x: float | int | ndarray = None, y: float | int | ndarray = None, z: float | int | ndarray = None, *args, **kwargs)[source]

Bases: CartesianRepresentation

Calculates basis and orgin at a given latitude and longitude.

Basis and origin is calculated in ECEF frame. ‘location’ and ‘orientation’ are required.

See also

grand.geo.coordinates.GRANDCS

The array frame: north, west, up, from magnetic north.

Examples

The same three numbers name different places in different orientations: 1 km along x is east in 'ENU' and north in 'NWU':

import numpy as np
from grand import Geodetic, LTP

site = Geodetic(latitude=40.98, longitude=93.95, height=1200.0)
for orientation in ("ENU", "NWU"):
    point = LTP(x=1000.0, y=0.0, z=0.0, location=site,
                orientation=orientation, magnetic=False)
    print(orientation, np.round(np.asarray(Geodetic(point)).ravel()[:2], 5))
ENU [40.98    93.96188]
NWU [40.989 93.95 ]
ltp_to_ltp(ltp)[source]

Returns this vector in another local tangent plane.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The vector in the other local frame.

Return type:

LTP

Parameters:

ltp (LTP or GRANDCS) – The frame to express the result in.

ltp_to_grandcs(location=None)[source]

Returns this vector in the GRANDCS array frame.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Parameters:

location (Geodetic, optional) – Origin of the array frame. Without it the default origin is used, with a warning.

Returns:

The vector in the array frame.

Return type:

GRANDCS

ltp_to_ecef()[source]

Returns this vector in the ECEF frame.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The vector, Earth-centred.

Return type:

ECEF

ltp_to_geodetic(reference='GEOID')[source]

Returns this vector as a geodetic position.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The vector as a geodetic position.

Return type:

Geodetic

Parameters:

reference (str or Reference, optional) – Surface the height is measured from.

class grand.geo.coordinates.GRANDCS(arg: Any = None, x: float | int | ndarray = None, y: float | int | ndarray = None, z: float | int | ndarray = None, *args, **kwargs)[source]

Bases: LTP

Class for the GRANDCS coordinate system (cs). This class instantiate coordinates.

in GRANDCS’s coordinate frame. Input can be either x, y, z coordinates value in GRANDCS’s cs or coordinates in ECEF or Geodetic system.

If the input coordinates are in ECEF or Geodetic (or any coordinate system other than GRANDCS’s cs) following procedure is performed. Convert everything to ECEF frame to do all initial calculations and then finally project the positional vector from GRANDCS’s cs origin to it’s basis vectors. Basis for NWU GRANDCS’s cs is calculated based on GRANDCS’s origin. Basis forms a rotational matrix. Transpose of the rotational matrix is it’s inverse. Basis in this case are unit vectors in ECEF frame that describes the NWU direction from GRANDCS’s origin (also in ECEF frame). To convert other cs to GRANDCS’s cs, first transform the coordinates in ECEF frame, then shift the origin of coordinates from ECEF’s origin to GRANDCS’s origin. Now you get a positional vector from GRANDCS’s origin in ECEF frame. Take a dot product of this positional vector with the NWU basis unit vectors to get the coordinates in GRANDCS coordinate system.

Use inverse (transpose) of rotational matrix to convert from GRANDCS cs to ECEF. Then convert from ECEF to Geodetic.

See also

grand.geo.coordinates.LTP

A local frame with a chosen orientation.

grand.geo.coordinates.Geodetic

Latitude, longitude and height.

Examples

GRANDCS \(x\) runs north, while an ENU \(x\) runs east, so the same three numbers name different places. Neither call raises.

import numpy as np
from grand import Geodetic, GRANDCS, LTP, ECEF

site = Geodetic(latitude=40.98, longitude=93.95, height=1200.0)

a = ECEF(GRANDCS(x=1000.0, y=0.0, z=0.0, location=site))
b = ECEF(LTP(x=1000.0, y=0.0, z=0.0, location=site,
             orientation="ENU", magnetic=False))

print("%.1f m apart" % np.linalg.norm(np.asarray(a).ravel()
                                      - np.asarray(b).ravel()))
1410.6 m apart
grandcs_to_ecef()[source]

Returns this vector in the ECEF frame.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The vector, Earth-centred.

Return type:

ECEF

grandcs_to_geodetic(reference='GEOID')[source]

Returns this vector as a geodetic position.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The vector as a geodetic position.

Return type:

Geodetic

Parameters:

reference (str or Reference, optional) – Surface the height is measured from.

grandcs_to_ltp(ltp)[source]

Returns this vector in a local tangent plane, LTP.

Every conversion between a local frame and geodetic passes through ECEF; see Coordinates and conventions.

Returns:

The vector in a local frame.

Return type:

LTP

Parameters:

ltp (LTP or GRANDCS) – The frame to express the result in.

class grand.geo.coordinates.Reference(*values)[source]

Bases: IntEnum

Reference surface for a height in the geodetic system.

A geodetic height is meaningless without saying what it is measured from. ELLIPSOID measures from the WGS-84 ellipsoid, the smooth mathematical figure; GEOID measures from mean sea level, which departs from the ellipsoid by up to about 100 m. Confusing the two is a common source of vertical errors at the array.

Added in version 0.1.0.

Notes

The same enumeration is defined in grand.geo.topography. It is repeated here because importing it would make the two modules circular.

Examples

A height of 1200 m means two different places depending on which surface it is measured from.

from grand.geo.coordinates import Reference, geoid_undulation

print(list(Reference))
print("geoid - ellipsoid at Dunhuang: %.2f m"
      % geoid_undulation(latitude=40.98, longitude=93.95))
[<Reference.ELLIPSOID: 1>, <Reference.GEOID: 2>]
geoid - ellipsoid at Dunhuang: -61.04 m
ELLIPSOID = 1
GEOID = 2
grand.geo.coordinates.geoid_undulation(coordinates=None, latitude=None, longitude=None)[source]

Returns the height of the geoid above the ellipsoid, in meters.

The geoid undulation is what converts between the two references of Reference: a height above mean sea level plus the undulation at that location is the height above the ellipsoid. Values are read from the EGM96 model shipped in data/egm96.png.

Parameters:
  • coordinates (Geodetic, ECEF, LTP, GRANDCS or float, optional) – The position; or, as a number, the latitude, with the longitude as the second argument: geoid_undulation(40.98, 93.95).

  • latitude (float or ndarray, optional) – Geodetic latitude, in degrees.

  • longitude (float or ndarray, optional) – Geodetic longitude, in degrees.

Returns:

  • float or ndarray – Undulation in meters, positive where the geoid lies above the ellipsoid.

  • A missing angle gives NaN, with a warning.

Examples

from grand.geo.coordinates import geoid_undulation

# The GRANDProto300 site at Dunhuang.
print("%.2f m" % geoid_undulation(latitude=40.98, longitude=93.95))
print("%.2f m" % geoid_undulation(40.98, 93.95))
-61.04 m
-61.04 m

Notes

grand.geo.topography.geoid_undulation() has the same signature and gives the same values; it is repeated here to avoid a circular import.

grand.geo.topography

Topography wrapper for GRAND packages.

grand.geo.topography.elevation(coordinates, reference: str | None = 'GEOID')[source]

Get the topography elevation, w.r.t. sea level or w.r.t. the ellipsoid.

Parameters:
  • coordinates (Geodetic, ECEF, LTP or GRANDCS) – Position or positions to evaluate at.

  • reference (str or Reference, optional) – Surface the height is measured from: the ellipsoid or the geoid.

Returns:

Ground elevation, in meters.

Return type:

float or ndarray

grand.geo.topography.distance(position: Any, direction: CartesianRepresentation, maximum_distance: float = None, frame: Any = None)[source]

Get the signed intersection distance with the topography.

Parameters:
  • position (Geodetic, ECEF, LTP or GRANDCS) – Starting point.

  • direction (CartesianRepresentation or ECEF) – Direction to travel in, in ECEF unless frame says otherwise.

  • maximum_distance (float, optional) – Give up beyond this distance, in meters.

  • frame (LTP, GRANDCS or "ENU", optional) – Frame direction is given in: the axes of an LTP or GRANDCS, or "ENU" for east, north and up at the (single) starting point. By default it is ECEF.

Returns:

Distance to the ground, in meters, or NaN if it was not reached.

Return type:

float or ndarray

grand.geo.topography.geoid_undulation(coordinates=None, latitude=None, longitude=None)[source]

Get the geoid undulation: the height of the geoid above the ellipsoid.

Same signature and values as grand.geo.coordinates.geoid_undulation().

Parameters:
  • coordinates (Geodetic, ECEF, LTP, GRANDCS or float, optional) – Position or positions to evaluate at; or, as a number, the latitude, with the longitude as the second argument.

  • latitude (float or ndarray, optional) – Degrees north, instead of coordinates.

  • longitude (float or ndarray, optional) – Degrees east, instead of coordinates.

Returns:

  • float or ndarray – Height of the geoid above the ellipsoid, in meters.

  • A missing angle gives NaN, with a warning.

Examples

Negative here: at Dunhuang the geoid lies below the ellipsoid, so a point 1200 m above the ellipsoid is about 1261 m above sea level.

from grand.geo.topography import geoid_undulation

print("%.2f m" % geoid_undulation(latitude=40.98, longitude=93.95))
-61.04 m
grand.geo.topography.update_data(coordinates=None, clear: bool = False, radius: float = None)[source]

Updates the cache of topography data.

Tiles are published at https://github.com/grand-mother/store/releases and saved locally as grand/data/topography/*.hgt, one file per one-degree square. They are not in version control.

Parameters:
  • coordinates (Geodetic, ECEF, LTP or GRANDCS) – Position or positions to evaluate at.

  • clear (bool, optional) – Remove the cached tiles first.

  • radius (float, optional) – Fetch tiles within this radius, in meters.

grand.geo.topography.cachedir() → Path[source]

Get the location of the topography data cache.

Returns:

Directory the downloaded elevation tiles are cached in.

Return type:

Path

grand.geo.topography.model() → str[source]

Get the default model for topographic data.

Returns:

Name of the elevation model in use, such as SRTM.

Return type:

str

class grand.geo.topography.Reference(*values)[source]

Bases: IntEnum

Reference level for topography data

ELLIPSOID = 1
GEOID = 2
LOCAL = 3
class grand.geo.topography.Topography(path: Path | str = PosixPath('/home/runner/work/grand/grand/data/topography'))[source]

Bases: object

Proxy to topography data.

elevation(coordinates, reference: str | None = 'GEOID')[source]

Get the topography elevation, w.r.t. sea level, w.r.t the ellipsoid or in local coordinates. The default reference is w.r.t sea level (GEOID).

Parameters:
  • coordinates (Geodetic, ECEF, LTP or GRANDCS) – Position or positions to evaluate at.

  • reference (str or Reference, optional) – Surface the height is measured from: the ellipsoid or the geoid.

Returns:

Ground elevation, in meters.

Return type:

float or ndarray

distance(position: Any, direction: CartesianRepresentation, maximum_distance: float = None, frame: Any = None)[source]

Get the signed intersection distance with the topography.

Parameters:
  • position (Geodetic, ECEF, LTP or GRANDCS) – Starting point.

  • direction (CartesianRepresentation or ECEF) – Direction to travel in, in ECEF unless frame says otherwise. A local (east, north, up) vector passed without frame is read as ECEF and gives a wrong distance.

  • maximum_distance (float, optional) – Give up beyond this distance, in meters.

  • frame (LTP, GRANDCS or "ENU", optional) – Frame direction is given in: the axes of an LTP or GRANDCS, or "ENU" for east, north and up at the (single) starting point. By default it is ECEF.

Returns:

Distance to the ground, in meters.

Return type:

float or ndarray

grand.geo.geomagnet

Geomagnetic field wrapper for GRAND packages

grand.geo.geomagnet.field(coordinates: ECEF | Geodetic | GRANDCS | LTP) → CartesianRepresentation[source]

Get the default geo-magnetic field at the given coordinates.

Parameters:

coordinates (Geodetic, ECEF, LTP or GRANDCS) – Where to evaluate the field.

Returns:

The geomagnetic field vector, in tesla, in the local east-north-up frame at the location, whatever frame coordinates is given in. GRAND data use north-west-up: there, x is this y and y is minus this x. About 5.6e-5 T at Dunhuang.

Return type:

CartesianRepresentation

Examples

The field drives the radio emission, so its direction at the site enters every simulated shower.

import numpy as np
from grand import Geodetic
from grand.geo.geomagnet import field

site = Geodetic(latitude=40.98, longitude=93.95, height=1200.0)
b = np.asarray(field(site)).ravel()
print("B at Dunhuang (T):", np.round(b, 7))
print("magnitude: %.1f microtesla" % (np.linalg.norm(b) * 1e6))
B at Dunhuang (T): [ 1.00e-07  2.67e-05 -4.97e-05]
magnitude: 56.4 microtesla
class grand.geo.geomagnet.Geomagnet(model: str = None, latitude: float | ndarray = None, longitude: float | ndarray = None, height: float | ndarray = None, location: ECEF | Geodetic | LTP | GRANDCS = None, obstime: str | date = None)[source]

Bases: object

The geomagnetic field of a model (‘IGRF13’ by default) at a place and time.

Give the location as latitude (deg), longitude (deg) and height (m), or as an ECEF, Geodetic, LTP or GRANDCS position; a missing location raises TypeError. Give the time as an ISO date (‘2020-01-19’) or a datetime.date; the default is ‘2020-01-01’.

field

The field in tesla, in the local east-north-up frame at the location, whatever frame the location was given in. GRAND data use north-west-up: there, x is this y and y is minus this x.

Type:

CartesianRepresentation

declination

Angle of the horizontal field from geographic north, in degrees, positive toward east.

Type:

float or ndarray

inclination

Angle of the field below the horizontal, in degrees (positive in the northern hemisphere).

Type:

float or ndarray

location

Where the field was evaluated.

Type:

Geodetic