Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
254b479
Initial commit: fire/api/geodetic_levelling added.
Oct 15, 2025
ce6276f
Grid-filer til brug for geodætisk korrektion af nivellement tilføjet.
Oct 15, 2025
7f87c27
New environment file environment-dev-geod-lev.yml with packages neces…
Oct 15, 2025
8aaf04e
Imports in modules in fire/api/geodetic_levelling updated.
Oct 15, 2025
1493fbd
Function apply_geodetic_corrections_to_height_diffs modified to take …
Nov 5, 2025
67240e8
Parametre-attribut tilføjet regnemotorer.
Nov 6, 2025
1a92374
Regnemotoren GeodætiskRegn(GamaRegn) defineret.
Nov 10, 2025
f317e69
Function apply_geodetic_corrections_to_height_diffs() slightly modifi…
Nov 14, 2025
85502db
Function convert_geopotential_heights_to_metric_heights() modified to…
Nov 14, 2025
fef1a99
environment-dev-geod-lev.yml opdateret som følge af rebase
Nov 21, 2025
b6cd656
Functions apply_geodetic_corrections_to_height_diffs() and convert_ge…
Nov 24, 2025
a924b9e
Funktionalitet til geodætisk korrektion af nivellement samt konverter…
Dec 5, 2025
a8d0708
Funktionalitet til skrivning af excel-fil med anvendte geodætiske kor…
Dec 12, 2025
4db624a
Kontroller af parametre vedr. geodætiske korrektioner tilføjet til re…
Dec 16, 2025
fe1b962
Function decimalyear_to_datetime() added to module histogram.py.
Dec 18, 2025
9bc19ee
Diverse mangler vedr. tolkning af regneparametre fra kommandolinjen o…
Dec 18, 2025
b0a87e1
Ny regnemotor DVR90Regn tilføjet.
Dec 19, 2025
c1b5d04
Dokumentation/docstring vedr. regnemotorerne GeodætiskRegn og DVR90Re…
Dec 23, 2025
b6e31dd
Optional use of approx formulas (instead of rigorous formulas) for ti…
Feb 12, 2026
0a4aeb4
Function calculate_perm_tidal_deformation_geoid() modified: now gravi…
Feb 18, 2026
7242b18
Koden vedr. fortolkning af regneparametre er flyttet til en særskilt …
Feb 18, 2026
4636f28
Metoden læs_gama_outputfil(self) let modificeret: Nord og øst kopiere…
Feb 19, 2026
bc47ac8
Functions for interpolation/calculation of gravity etc. moved to new …
Feb 20, 2026
a0edee1
Minor improvements to module metric_to_gpu_transformation.py regardin…
Feb 23, 2026
37480d8
Module contour_plot.py removed from tracking.
Mar 18, 2026
49651e3
Module histogram.py removed from tracking and as a consequence hereof…
Mar 18, 2026
fc3ebcb
Koden vedr. initialisering af parametre til regnemotorerne GeodætiskR…
Mar 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions environment-dev-geod-lev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: fire-dev-geod-lev
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vi skal ikke have dette miljø ind i repo'et. Meningen med at have et separat miljø fire-dev-geod-lev som dette var at det kan være lettere i udviklingsfasen af skifte imellem miljøer hvor man arbejder på forskellige tilføjelser til FIRE.
Men ift. denne pull request vil det være nok at tilføje de nye afhængigheder i environment-dev.yml og environment.yml filerne.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, det er implementeret.

channels:
- conda-forge
dependencies:
- black
- click
- fiona
- gama
- graphviz
- matplotlib
- numpy
- openpyxl
- oracledb
- pandas
- pyarrow
- pip
- pre-commit
- pylint
- pyproj
- pytest-cov
- pytest-freezegun
- pytest-mock
- pytest
- python=
- rich
- scipy
- shapely
- sphinx-click
- sphinx
- sphinx_rtd_theme
- sphinxcontrib-programoutput
- sqlalchemy
- xmltodict
- astropy
- jplephem
- cartopy
- networkx
- pyerfa
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ version = {attr = "fire.__version__"}
# Bruges i `fire ts analyse-gnss`. Grid indholdende absolut uplift-rate (DTU 2016).
# Dækker området 54.1-58° N, 7.7-13.1° E.
"dtu2016_abs.tif",
# Grid-filer, der bruges i `fire niv regn`, se README.md i fire.data
"absg_DTU2016_PK.tif",
"DKup24geo_DTU2024_PK.tif",
"NKG2016_lev.tif",
"dk-g-direkte-fra-gri-thokn.tif",
]

[tool.flake8]
Expand Down
12 changes: 12 additions & 0 deletions src/fire/api/geodetic_levelling/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""
geodetic_levelling
"""

import fire.api.geodetic_levelling.geodetic_correction_levelling_obs
import fire.api.geodetic_levelling.gravity
import fire.api.geodetic_levelling.metric_to_gpu_transformation
import fire.api.geodetic_levelling.tidal_transformation
import fire.api.geodetic_levelling.time_propagation
import fire.api.geodetic_levelling.geophysical_parameters

__version__ = "1.0.0"
221 changes: 221 additions & 0 deletions src/fire/api/geodetic_levelling/geodetic_correction_levelling_obs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
"""This module contains functions for geodetic correction of height differences/levelling observations."""

from pathlib import Path
import copy

import pandas as pd

from fire.api.geodetic_levelling.tidal_transformation import (
apply_tidal_corrections_to_height_diff,
)

from fire.api.geodetic_levelling.time_propagation import (
propagate_height_diff_from_epoch_to_epoch,
)

from fire.api.geodetic_levelling.metric_to_gpu_transformation import (
convert_metric_height_diff_to_geopotential_height_diff,
)

from fire.api.niv.datatyper import (
NivObservation,
NivKote,
)


def apply_geodetic_corrections_to_height_diffs(
height_diff_objects: list[NivObservation],
height_objects: list[NivKote],
height_diff_unit: str = "metric",
epoch_target: pd.Timestamp = None,
tidal_system: str = None,
use_approx_tidal_formulas: bool = False,
grid_inputfolder: Path = None,
deformationmodel: str = None,
gravitymodel: str = None,
) -> tuple[list[NivObservation], pd.DataFrame]:
"""Apply geodetic corrections to metric height differences.

Applies various geodetic corrections to the metric height differences in a list of
NivObservation objects.

The metric height differences are tidally corrected if and only if the function is called
with an argument for parameter tidal_system.

The metric height differences are propagated to a target epoch if and only if
the function is called with arguments for all three parameters epoch_target, deformationmodel
and grid_inputfolder.

The metric height differences are converted to geopotential units if and only
if the function is called with argument "gpu" for parameter height_diff_unit and with arguments
for both parameter gravitymodel and grid_inputfolder.

Args:
height_diff_objects: list[NivObservation], list of NivObservation objects with
metric height differences to be corrected/converted
height_objects: list[NivKote], list of NivKote objects with geographic coordinates of from/to points
height_diff_unit: str = "metric", optional parameter, determines whether or not metric
input height differences are converted to geopotential units, "metric" for no conversion,
"gpu" for conversion to gpu, default value is "metric"
epoch_target: pd.Timestamp = None, optional parameter, target epoch for the propagation
of metric height differences (format: yyyy-mm-dd hh:mm:ss)
tidal_system: str = None, optional parameter, system for tidal corrections of metric height
differences, "non", "mean" or "zero" for non-tidal, mean tide or zero tide
use_approx_tidal_formulas: bool = False, optional parameter, determines whether approx or
rigorous formulas are used for tidal transformation of height differences and gravity.
By default rigorous formulas are used.
grid_inputfolder: Path = None, optional parameter, folder for input grid, i.e. deformation model
and/or gravity model
deformationmodel: str = None, optional parameter, deformation model used for the propagation
of metric height differences, must be in GeoTIFF or GTX file format, e.g. "NKG2016_lev.tif"
gravitymodel: str = None, optional parameter, gravity model used for the conversion of metric
height differences to gpu, must be in GeoTIFF or GTX file format, e.g. "dk-g-direkte-fra-gri-thokn.tif"

Returns:
tuple[list[NivObservation], pd.DataFrame], a tuple containing a list of NivObservation
objects with corrected/converted height differences (generated from deep copies of the
inputted NivObservation objects) and a DataFrame with the corrections themselves.

Raises:
? Hvis input mappe eller filer ikke findes, hvis der mangler punkter i points?
"""
# Output list for corrected/converted height differences
height_diff_objects_corrected = []

# Output DataFrame for applied corrections
index = []

for height_diff_object in height_diff_objects:
index.append(height_diff_object.id)

corrections_df = pd.DataFrame(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generelt: Prøv at få alt hvad der hedder dataframe ud af geodetic_levelling-pakken. De ting der skal til dataframe kan vi flytte over til dedikerede steder, enten et sted i regnemotor, eller andetsteds. :) Kan prøve at vise et eksempel på hvordan det kan se ud, men det er lidt for meget til at vise på github oven i de andre kommentarer.

columns=[
"From point",
"To point",
f"ΔH tidal correction (tidal system: {tidal_system}) [m]",
f"ΔH epoch correction (target epoch: {epoch_target}) [m]",
f"ΔH m2gpu multiplication factor (tidal system: {tidal_system}) [10 m/s^2]",
],
index=index,
)

for height_diff_object in height_diff_objects:
height_diff = height_diff_object.deltaH
point_from = height_diff_object.fra
point_to = height_diff_object.til
epoch_obs = height_diff_object.dato

# Geographic coordinates of point_from and point_to
(point_from_lat, point_from_long) = [
(height_object.nord, height_object.øst)
for height_object in height_objects
if height_object.punkt == point_from
][0]
(point_to_lat, point_to_long) = [
(height_object.nord, height_object.øst)
for height_object in height_objects
if height_object.punkt == point_to
][0]

# Point from and point to are written to DataFrame for applied corrections
corrections_df.at[height_diff_object.id, "From point"] = point_from
corrections_df.at[height_diff_object.id, "To point"] = point_to

# The metric height differences are tidally corrected if the
# function apply_geodetic_corrections_to_height_diffs is called with an argument for
# parameter tidal_system
if tidal_system is not None:
(height_diff, tidal_corr) = apply_tidal_corrections_to_height_diff(
height_diff,
point_from_lat,
point_from_long,
point_to_lat,
point_to_long,
epoch_obs,
tidal_system,
use_approx_tidal_formulas,
grid_inputfolder=grid_inputfolder,
gravitymodel=gravitymodel,
)

corrections_df.at[
height_diff_object.id,
f"ΔH tidal correction (tidal system: {tidal_system}) [m]",
] = tidal_corr

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Da funktionen ikke skal gøre mere herefter hvis grid_inputfolder er None kunne man her indsætte :

Suggested change
if grid_inputfolder is None:
return height_diff, corrections

hvilket gør at man nedenunder kan fjerne tjek for om grid_inputfolder er None

# The metric height differences are propagated to a target epoch if
# the function apply_geodetic_corrections_to_height_diffs is called with arguments for
# all three parameters epoch_target, deformationmodel and grid_inputfolder
if (
(epoch_target is not None)
and (deformationmodel is not None)
and (grid_inputfolder is not None)
):
(height_diff, epoch_corr) = propagate_height_diff_from_epoch_to_epoch(
height_diff,
point_from_lat,
point_from_long,
point_to_lat,
point_to_long,
epoch_obs,
epoch_target,
grid_inputfolder,
deformationmodel,
)

corrections_df.at[
height_diff_object.id,
f"ΔH epoch correction (target epoch: {epoch_target}) [m]",
] = epoch_corr

elif epoch_target is not None:
exit(
"Function apply_geodetic_corrections_to_height_diffs: Wrong arguments for\n\
parameter epoch_target and/or deformationmodel and/or grid_inputfolder."
)
Comment on lines +171 to +175
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er det nødvendigt at smide den her fejl? Vi ender kun hernede hvis fx epoch_target = 1990 og de andre to er None. Men hvis fx deformationmodel = PK_2016.tif og epoch_target=None, så fortsætter funktionen uden fejl.

Som jeg forstår det, så skal der kun laves uplift-korrektion hvis både epoch_target, deformationmodel og grid_inputfolder er givet. Hvis bare én af disse er None, så skal der ikke laves uplift-korrektion, og vi kan fortsætte til næste trin.

Suggested change
elif epoch_target is not None:
exit(
"Function apply_geodetic_corrections_to_height_diffs: Wrong arguments for\n\
parameter epoch_target and/or deformationmodel and/or grid_inputfolder."
)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jeg har lavet det således aht. brugeren. Hvis brugeren har angivet en epoke, må det antages, at brugeren ønsker at tidspropagere observationerne, og at det derfor er en fejl, at deformationmodel og/eller grid_inputfolder ikke er angivet.


# The metric height differences are converted to geopotential units if
# the function apply_geodetic_corrections_to_height_diffs is called with argument "gpu"
# for parameter height_diff_unit and with arguments for both parameter gravitymodel
# and grid_inputfolder
if (
height_diff_unit == "gpu"
and (gravitymodel is not None)
and (grid_inputfolder is not None)
):
(height_diff, m2gpu_factor) = (
convert_metric_height_diff_to_geopotential_height_diff(
height_diff,
point_from_lat,
point_from_long,
point_to_lat,
point_to_long,
grid_inputfolder,
gravitymodel,
tidal_system,
use_approx_tidal_formulas,
)
)

corrections_df.at[
height_diff_object.id,
f"ΔH m2gpu multiplication factor (tidal system: {tidal_system}) [10 m/s^2]",
] = m2gpu_factor

elif height_diff_unit == "metric":
pass

else:
exit(
"Function apply_geodetic_corrections_to_height_diffs: Wrong arguments for\n\
parameter height_diff_unit and/or gravitymodel and/or grid_inputfolder."
)
Comment on lines +205 to +212
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Samme som ovenfor. Det er tilstrækkeligt at hoppe ud af if-else-blokken efter vi har konstateret at der ikke skal foretages konvertering til gpu.

Suggested change
elif height_diff_unit == "metric":
pass
else:
exit(
"Function apply_geodetic_corrections_to_height_diffs: Wrong arguments for\n\
parameter height_diff_unit and/or gravitymodel and/or grid_inputfolder."
)


# Update of height_diff_object_corrected and height_diff_objects_corrected
height_diff_object_corrected = copy.deepcopy(height_diff_object)
height_diff_object_corrected.deltaH = height_diff
height_diff_objects_corrected.append(height_diff_object_corrected)

corrections_df = corrections_df.reset_index().rename(columns={"index": "Journal"})

return (height_diff_objects_corrected, corrections_df)
53 changes: 53 additions & 0 deletions src/fire/api/geodetic_levelling/geophysical_parameters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""This module contains various geophysical parameters and constants required
for tidal correction and transformation of gravity and height etc.
"""

from math import pi

# Inclination of the ecliptic/the lunar orbit in radians
epsilon = (23 + (27 / 60)) * (1 / 360) * 2 * pi

# Geocentric distance to the Moon in units of m
moon_dist = 3.84399 * 1e8

# Mass of the Moon in units of kg
moon_mass = 7.346 * 1e22

# Mean radius of the Earth in units of m
radius_earth = 6371000

# Love numbers
h = 0.62
k = 0.30

# Tilt factor
gamma = 1 + k - h

# Gravimetric factor
delta = 1 + h - (3 / 2) * k

# Defining constants for Geodetic Reference System 1980 (GRS80)
# Major semi-axis of the reference ellipsoid in units of m
a_GRS80 = 6378137

# Gravitational mass constant of the Earth in units of m^3/s^2
GM_GRS80 = 3986005 * 1e8

# Dynamic form factor
J2_GRS80 = 108263 * 1e-8

# Angular velocity of the Earth’s rotation in units of rad/s
omega_GRS80 = 7292115 * 1e-11

# Derived constants for Geodetic Reference System 1980 (GRS80)
# Minor semi-axis of the reference ellipsoid in units of m
b_GRS80 = 6356752.3141

# Flattening of the reference ellipsoid
f_GRS80 = 0.00335281068118

# m = (normal_gravity^2*a^2*b)/(G*M)
m_GRS80 = 0.00344978600308

# Normal gravity at equator in units of m/s^2
normal_gravity_equator_GRS80 = 9.7803267715
Loading
Loading