diff --git a/.gitignore b/.gitignore index ae210bce3..c95fdb4b1 100644 --- a/.gitignore +++ b/.gitignore @@ -132,4 +132,10 @@ docs/examples-rendered/*.py *.tex *.aux *.log -*.pdf \ No newline at end of file +*.pdf + +# test output +tests/datafile/par_*.par +tests/datafile/fake_toas.tim +tests/datafile/*.converted.par +tests/datafile/_test_pintempo.out diff --git a/CHANGELOG-unreleased.md b/CHANGELOG-unreleased.md index d0d57b171..5ac8acfd0 100644 --- a/CHANGELOG-unreleased.md +++ b/CHANGELOG-unreleased.md @@ -42,4 +42,5 @@ the released changes. - Consistent naming in `TimingModel.get_params_mapping()` - Better exceptions for unsupported/unimplemented binary models (BTX, MSS, etc.) - Emit warnings when `WaveX`/`DMWaveX` is used together with other representations of red/DM noise +- `get_observatory()` no longer overwrites `include_gps` and `include_bipm` of `Observatory` objects unless explicitly stated (BIPM and GPS clock corrections no longer incorrectly applied to BAT TOAs). ### Removed diff --git a/src/pint/observatory/__init__.py b/src/pint/observatory/__init__.py index 17d32856d..895d46411 100644 --- a/src/pint/observatory/__init__.py +++ b/src/pint/observatory/__init__.py @@ -21,6 +21,7 @@ necessary. """ +from copy import deepcopy import os import textwrap from collections import defaultdict @@ -143,24 +144,6 @@ class Observatory: # standard name. _alias_map = {} - def __new__(cls, name, *args, **kwargs): - # Generates a new Observatory object instance, and adds it - # it the registry, using name as the key. Name must be unique, - # a new instance with a given name will over-write the existing - # one only if overwrite=True - obs = super().__new__(cls) - if name.lower() in cls._registry: - if "overwrite" not in kwargs or not kwargs["overwrite"]: - raise ValueError( - f"Observatory {name.lower()} already present and overwrite=False" - ) - log.warning(f"Observatory '{name.lower()}' already present; overwriting...") - - cls._register(obs, name) - return obs - cls._register(obs, name) - return obs - def __init__( self, name, @@ -171,6 +154,10 @@ def __init__( bipm_version=bipm_default, overwrite=False, ): + self._name = name.lower() + self._aliases = ( + list(set(map(str.lower, aliases))) if aliases is not None else [] + ) if aliases is not None: Observatory._add_aliases(self, aliases) self.fullname = fullname if fullname is not None else name @@ -178,6 +165,15 @@ def __init__( self.include_bipm = include_bipm self.bipm_version = bipm_version + if name.lower() in Observatory._registry: + if not overwrite: + raise ValueError( + f"Observatory {name.lower()} already present and overwrite=False" + ) + log.warning(f"Observatory '{name.lower()}' already present; overwriting...") + + Observatory._register(self, name) + @classmethod def _register(cls, obs, name): """Add an observatory to the registry using the specified name @@ -186,7 +182,6 @@ def _register(cls, obs, name): The Observatory instance's name attribute will be updated for consistency.""" cls._registry[name.lower()] = obs - obs._name = name.lower() @classmethod def _add_aliases(cls, obs, aliases): @@ -199,10 +194,6 @@ def _add_aliases(cls, obs, aliases): to ensure consistency.""" for a in aliases: cls._alias_map[a.lower()] = obs.name - for o in cls._registry.values(): - o._aliases = [ - alias for alias, name in cls._alias_map.items() if name == o.name - ] @staticmethod def gps_correction(t, limits="warn"): @@ -460,7 +451,7 @@ def posvel(self, t, ephem, group=None): def get_observatory( - name, include_gps=True, include_bipm=True, bipm_version=bipm_default + name, include_gps=None, include_bipm=None, bipm_version=bipm_default ): """Convenience function to get observatory object with options. @@ -474,10 +465,10 @@ def get_observatory( ---------- name : str The name of the observatory - include_gps : bool, optional - Set False to disable UTC(GPS)->UTC clock correction. - include_bipm : bool, optional - Set False to disable TAI TT(BIPM) clock correction. + include_gps : bool or None, optional + Override UTC(GPS)->UTC clock correction. + include_bipm : bool or None, optional + Override TAI TT(BIPM) clock correction. bipm_version : str, optional Set the version of TT BIPM clock correction files. @@ -485,11 +476,19 @@ def get_observatory( file switches/options are added at a public API level. """ - site = Observatory.get(name) - site.include_gps = include_gps - site.include_bipm = include_bipm - site.bipm_version = bipm_version - return site + if include_bipm is not None or include_gps is not None: + site = deepcopy(Observatory.get(name)) + + if include_gps is not None: + site.include_gps = include_gps + + if include_bipm is not None: + site.include_bipm = include_bipm + site.bipm_version = bipm_version + + return site + + return Observatory.get(name) def earth_location_distance(loc1, loc2): @@ -533,8 +532,8 @@ def compare_t2_observatories_dat(t2dir=None): for line in interesting_lines(f, comments="#"): try: x, y, z, full_name, short_name = line.split() - except ValueError: - raise ValueError(f"unrecognized line '{line}'") + except ValueError as e: + raise ValueError(f"unrecognized line '{line}'") from e x, y, z = float(x), float(y), float(z) full_name, short_name = full_name.lower(), short_name.lower() topo_obs_entry = textwrap.dedent( @@ -831,10 +830,7 @@ def find_clock_file( """ # Avoid import loop from pint.observatory.clock_file import ClockFile, GlobalClockFile - from pint.observatory.global_clock_corrections import ( - Index, - get_clock_correction_file, - ) + from pint.observatory.global_clock_corrections import Index if name == "": raise ValueError("No filename supplied to find_clock_file") diff --git a/src/pint/observatory/satellite_obs.py b/src/pint/observatory/satellite_obs.py index 2021c0b48..38d0c031b 100644 --- a/src/pint/observatory/satellite_obs.py +++ b/src/pint/observatory/satellite_obs.py @@ -311,7 +311,6 @@ def __init__( overwrite=False, ): super().__init__( - self, name, include_gps=include_gps, include_bipm=include_bipm, @@ -444,4 +443,5 @@ def get_satellite_observatory(name, ft2name, **kwargs): # values as new observatories are added. if "maxextrap" not in kwargs: kwargs["maxextrap"] = 2 + return SatelliteObs(name, ft2name, **kwargs) diff --git a/src/pint/observatory/topo_obs.py b/src/pint/observatory/topo_obs.py index c1e800dea..1d7fe8868 100644 --- a/src/pint/observatory/topo_obs.py +++ b/src/pint/observatory/topo_obs.py @@ -502,7 +502,8 @@ def load_observatories(filename=observatories_json, overwrite=False): def load_observatories_from_usual_locations(clear=False): """Load observatories from the default JSON file as well as ``$PINT_OBS_OVERRIDE``, optionally clearing the registry - Running with ``clear=True`` will return PINT to the state it is on import. Running with ``clear=False`` may result in conflicting definitions if observatories have already been imported. + Running with ``clear=True`` will return PINT to the state it is on import. + Running with ``clear=False`` may result in conflicting definitions if observatories have already been imported. Parameters ---------- diff --git a/tests/test_eventstats.py b/tests/test_eventstats.py old mode 100755 new mode 100644 diff --git a/tests/test_fermiphase.py b/tests/test_fermiphase.py index 1be357cb5..b5f9437c4 100644 --- a/tests/test_fermiphase.py +++ b/tests/test_fermiphase.py @@ -12,7 +12,6 @@ import pint.models import pint.scripts.fermiphase as fermiphase -import pint.toa as toa from pint.fermi_toas import get_Fermi_TOAs, _default_uncertainty from pint.observatory.satellite_obs import get_satellite_observatory from pinttestdata import datadir diff --git a/tests/test_observatory.py b/tests/test_observatory.py index e126b02d8..050b1be0a 100644 --- a/tests/test_observatory.py +++ b/tests/test_observatory.py @@ -276,9 +276,11 @@ def test_json_observatory_output(sandbox): gbt_reload = get_observatory("gbt") for p in gbt_orig.__dict__: - if p not in ["_clock"]: + if p not in ["_clock", "_aliases"]: assert getattr(gbt_orig, p) == getattr(gbt_reload, p) + assert set(gbt_orig._aliases) == set(gbt_reload._aliases) + def test_json_observatory_input_latlon(sandbox): gbt_orig = get_observatory("gbt") @@ -336,3 +338,16 @@ def test_compare_t2_observatories_dat(): def test_compare_tempo_obsys_dat(): s = compare_tempo_obsys_dat(testdatadir / "observatory") assert isinstance(s, defaultdict) + + +def test_ssb_obs(): + ssb = Observatory.get("@") + assert not ssb.include_bipm and not ssb.include_gps + + ssb = get_observatory("@") + assert not ssb.include_bipm and not ssb.include_gps + + # get_observatory changes the state of the registered + # Observatory objects. So this needs to be repeated. + ssb = Observatory.get("@") + assert not ssb.include_bipm and not ssb.include_gps