Skip to content

Commit

Permalink
Merge pull request #701 from royagrace/test_update
Browse files Browse the repository at this point in the history
Test update
  • Loading branch information
jlmaurer authored Feb 3, 2025
2 parents 1fd248f + eb3cb1f commit 8259b14
Show file tree
Hide file tree
Showing 13 changed files with 816 additions and 286 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

[Unreleased]
### Changed
* [701](https://github.com/dbekaert/RAiDER/pull/701) - Fixed a few path typos and handle some edge cases, add unit tests, lint project
* [672](https://github.com/dbekaert/RAiDER/pull/672) - Linted the project with `ruff`.
* [683](https://github.com/dbekaert/RAiDER/pull/683) - Fixed a naive datetime and added default template to template generation argument

### Fixed
* [700](https://github.com/dbekaert/RAiDER/pull/700) - Fixed a few path typos and handle some edge cases
* [679](https://github.com/dbekaert/RAiDER/pull/679) - Fixed a bug causing test_updateTrue to falsely pass.
* [685](https://github.com/dbekaert/RAiDER/pull/679) - Fixed a global bbox bug in checkContainment

Expand Down
41 changes: 19 additions & 22 deletions test/test_gnss.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
from pathlib import Path
from RAiDER.models.customExceptions import NoStationDataFoundError
from RAiDER.gnss.downloadGNSSDelays import (
get_stats_by_llh, get_station_list, download_tropo_delays,
filterToBBox
)
from RAiDER.gnss.processDelayFiles import (
addDateTimeToFiles,
getDateTime,
concatDelayFiles
)
import datetime
import os
import pytest
from pathlib import Path

import pandas as pd
import pytest

from RAiDER.gnss.downloadGNSSDelays import download_tropo_delays, filterToBBox, get_station_list, get_stats_by_llh
from RAiDER.gnss.processDelayFiles import addDateTimeToFiles, concatDelayFiles, getDateTime
from RAiDER.models.customExceptions import NoStationDataFoundError
from test import TEST_DIR, pushd


from test import pushd, TEST_DIR
SCENARIO2_DIR = os.path.join(TEST_DIR, "scenario_2")


Expand Down Expand Up @@ -125,17 +120,19 @@ def test_download_tropo_delays2():


def test_download_tropo_delays2(tmp_path):
stations, output_file = get_station_list(
stationFile=os.path.join(SCENARIO2_DIR, 'stations.csv'))
with pushd(tmp_path):
stations, output_file = get_station_list(
stationFile=os.path.join(SCENARIO2_DIR, 'stations.csv')
)

# spot check a couple of stations
assert 'CAPE' in stations
assert 'FGNW' in stations
assert isinstance(output_file, str)
# spot check a couple of stations
assert 'CAPE' in stations
assert 'FGNW' in stations
assert isinstance(output_file, str)

# try downloading the delays
download_tropo_delays(stats=stations, years=[2022], writeDir=tmp_path)
assert True
# try downloading the delays
download_tropo_delays(stats=stations, years=[2022], writeDir=tmp_path)
assert True


def test_filterByBBox1():
Expand Down
2 changes: 1 addition & 1 deletion test/test_intersect.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def test_gnss_intersect(tmp_path, wm):
## run raider and intersect
calcDelays([str(cfg)])

gold = {"ERA5": 2.34514, "GMAO": np.nan, "HRRR": np.nan}
gold = {"ERA5": 2.34514, "GMAO": np.nan, "HRRR": np.nan}
df = pd.read_csv(
os.path.join(outdir, f'{wm}_Delay_{date}T{time.replace(":", "")}_ztd.csv')
)
Expand Down
106 changes: 51 additions & 55 deletions test/test_synthetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
from RAiDER.losreader import Raytracing, build_ray
from RAiDER.models.weatherModel import make_weather_model_filename
from RAiDER.utilFcns import lla2ecef, write_yaml
from test import ORB_DIR, WM_DIR, pushd
from test import ORB_DIR, TEST_DIR, WM_DIR, pushd


def update_model(wm_file: str, wm_eq_type: str, wm_dir: str = "weather_files_synth"):
"""Update weather model file by the equation to test, write it to disk
"""Update weather model file by the equation to test, write it to disk.
wm_eq_type is one of: [hydro, wet_linear, wet_nonlinear]
Hydro Refractivity = k1 * (Pressure/Temp), set Pressure = Temp
Expand All @@ -33,7 +33,7 @@ def update_model(wm_file: str, wm_eq_type: str, wm_dir: str = "weather_files_syn
), "Set wm_eq_type to hydro, wet_linear, or wet_nonlinear"
# initialize dummy wm to calculate constant delays
# any model will do as 1) all constants same 2) all equations same
model = op.basename(wm_file).split('_')[0].upper().replace("-", "")
model = os.path.basename(wm_file).split('_')[0].upper().replace("-", "")
Obj = get_wm_by_name(model)[1]()
ds = xr.open_dataset(wm_file)
t = ds["t"]
Expand Down Expand Up @@ -73,8 +73,8 @@ def update_model(wm_file: str, wm_eq_type: str, wm_dir: str = "weather_files_syn


def length_of_ray(target_xyz: list, model_zs, los, max_height):
"""Build rays at xy locations
"""Build rays at xy locations."""
"""
Target xyz is a list of lists (xpts, ypts, hgt_levels)
Model_zs are all the model levels over which ray is calculated
los in los object (has the orbit info)
Expand All @@ -99,7 +99,7 @@ def length_of_ray(target_xyz: list, model_zs, los, max_height):

@dataclass
class StudyArea(object):
"""Object with shared parameters related to the study area
"""Object with shared parameters related to the study area.
region the short name corresponding to a specific bounding box.
Choose from:
Expand Down Expand Up @@ -141,7 +141,7 @@ def __init__(self, region: str, wmName: str, path: str):
self.wm_dir_synth = op.join(self.wd, "weather_files_synth")

def setup_region(self):
"""Setup the bounding box and choose orbit file based on region name
"""Setup the bounding box and choose orbit file based on region name.
Possible regions are:
LA (Los Angeles, California; midlatitude)
Expand Down Expand Up @@ -193,7 +193,7 @@ def make_config_dict(self):
@pytest.mark.skip()
@pytest.mark.parametrize("region", "AK LA Fort".split())
def test_dl_real(tmp_path, region, mod="ERA5"):
"""Download the real weather model to overwrite
"""Download the real weather model to overwrite.
This 'golden dataset' shouldnt be changed
"""
Expand All @@ -216,7 +216,7 @@ def test_dl_real(tmp_path, region, mod="ERA5"):

@pytest.mark.parametrize("region", "AK LA Fort".split())
def test_hydrostatic_eq(tmp_path, region, mod="ERA-5"):
"""Test hydrostatic equation: Hydro Refractivity = k1 * (Pressure/Temp)
"""Test hydrostatic equation: Hydro Refractivity = k1 * (Pressure/Temp).
The hydrostatic delay reduces to an integral along the ray path when P=T.
However the constants k1 and scaling of 10^-6 will remain present leading
Expand All @@ -231,60 +231,57 @@ def test_hydrostatic_eq(tmp_path, region, mod="ERA-5"):
Ensure that normalized residual is not significantly different from 0
significantly different = 6 decimal places
"""
with pushd(tmp_path):
## setup the config files
SAobj = StudyArea(region, mod, tmp_path)
dct_cfg = SAobj.make_config_dict()
dct_cfg["runtime_group"]["weather_model_directory"] = SAobj.wm_dir_synth
dct_cfg["download_only"] = False
## setup the config files
SAobj = StudyArea(region, mod, TEST_DIR)
dct_cfg = SAobj.make_config_dict()
dct_cfg["runtime_group"]["weather_model_directory"] = SAobj.wm_dir_synth
dct_cfg["download_only"] = False

## update the weather model; t = p for hydrostatic
update_model(SAobj.path_wm_real, "hydro", SAobj.wm_dir_synth)

## run raider with the synthetic model
cfg = write_yaml(dct_cfg, 'temp.yaml')
calcDelays([str(cfg)])

# get the just created synthetic delays
wm_name = SAobj.wmName.replace("-", "") # incase of ERA-5
out_name = f'{SAobj.wd}/{wm_name}_tropo_{SAobj.dts.replace("_", "")}_ray.nc'
ds = xr.open_dataset(out_name)
da = ds["hydro"]
ds.close()
del ds

## update the weather model; t = p for hydrostatic
update_model(SAobj.path_wm_real, "hydro", SAobj.wm_dir_synth)
# now build the rays at the unbuffered wm nodes
max_tropo_height = SAobj.wmObj._zlevels[-1] - 1
targ_xyz = [da.x.data, da.y.data, da.z.data]
ray_length = length_of_ray(
targ_xyz, SAobj.wmObj._zlevels, SAobj.los, max_tropo_height
)

## run raider with the synthetic model
cfg = write_yaml(dct_cfg, 'temp.yaml')
calcDelays([str(cfg)])
# scale by constant (units K/Pa) to match raider (m K / Pa)
ray_data = ray_length * SAobj.wmObj._k1

# get the just created synthetic delays
wm_name = SAobj.wmName.replace("-", "") # incase of ERA-5
ds = xr.open_dataset(
f'{SAobj.wd}/{wm_name}_tropo_{SAobj.dts.replace("_", "")}_ray.nc'
)
da = ds["hydro"]
ds.close()
del ds
# actual raider data
# undo scaling of ppm; units are meters * K/Pa
raid_data = da.data * 1e6

# now build the rays at the unbuffered wm nodes
max_tropo_height = SAobj.wmObj._zlevels[-1] - 1
targ_xyz = [da.x.data, da.y.data, da.z.data]
ray_length = length_of_ray(
targ_xyz, SAobj.wmObj._zlevels, SAobj.los, max_tropo_height
)

# scale by constant (units K/Pa) to match raider (m K / Pa)
ray_data = ray_length * SAobj.wmObj._k1

# actual raider data
# undo scaling of ppm; units are meters * K/Pa
raid_data = da.data * 1e6

assert np.all(np.abs(ray_data) > 1)
assert np.all(np.abs(raid_data) > 1)
assert np.all(np.abs(ray_data) > 1)
assert np.all(np.abs(raid_data) > 1)

# normalize with the theoretical data and compare difference with 0
resid = (ray_data - raid_data) / ray_data
np.testing.assert_almost_equal(0, resid, decimal=6)
# normalize with the theoretical data and compare difference with 0
resid = (ray_data - raid_data) / ray_data
np.testing.assert_almost_equal(0, resid, decimal=6)

da.close()
del da
da.close()
del da


@pytest.mark.parametrize("region", "AK LA Fort".split())
def test_wet_eq_linear(tmp_path, region, mod="ERA-5"):
"""Test linear part of wet equation.
Wet Refractivity = k2 * (E/T) + k3 * (E/T^2)
E = relative humidty; T = temperature
E = relative humidty; T = temperature.
The wet delay reduces to an integral along the ray path when E=T and k3 = 0
However the constants k2 and scaling of 10^-6 will remain present, leading
Expand All @@ -297,9 +294,8 @@ def test_wet_eq_linear(tmp_path, region, mod="ERA-5"):
Check they are both large enough for meaningful numerical comparison (>1)
Compute residual and normalize by theoretical ray length (calculated here)
Ensure that normalized residual is not significantly different from 0
significantly different = 7 decimal places
significantly different = 7 decimal places
"""

with pushd(tmp_path):
# create temp directory for file that is created
dir_to_del = "tmp_dir"
Expand Down Expand Up @@ -359,8 +355,8 @@ def test_wet_eq_linear(tmp_path, region, mod="ERA-5"):

@pytest.mark.parametrize("region", "AK LA Fort".split())
def test_wet_eq_nonlinear(tmp_path, region, mod="ERA-5"):
"""Test the nonlinear part of the wet equation.
"""Test the nonlinear part of the wet equation."""
"""
Wet Refractivity = k2 * (E/T) + k3 * (E/T^2)
E = relative humidty; T = temperature
Expand Down
Loading

0 comments on commit 8259b14

Please sign in to comment.