def no_source(time: datetime, glat: float, glon: float, Nbins: int, Talt: float, Thot: float) -> xarray.Dataset: """ testing only, may give non-physical results""" idate, utsec = glowdate(time) ip = gi.get_indices([time - timedelta(days=1), time], 81) cmd = [ str(EXE), idate, utsec, str(glat), str(glon), str(ip["f107s"][1]), str(ip["f107"][1]), str(ip["f107"][0]), str(ip["Ap"][1]), "-nosource", str(Nbins), str(Talt), str(Thot), ] dat = subprocess.check_output(cmd, timeout=15, stderr=subprocess.DEVNULL, universal_newlines=True) return glowparse(dat, time, ip, glat, glon)
def no_precipitation(time: datetime, glat: float, glon: float, Nbins: int) -> xarray.Dataset: idate, utsec = glowdate(time) ip = gi.get_indices([time - timedelta(days=1), time], 81) cmd = [ str(EXE), idate, utsec, str(glat), str(glon), str(ip["f107s"][1]), str(ip["f107"][1]), str(ip["f107"][0]), str(ip["Ap"][1]), "-noprecip", str(Nbins), ] dat = subprocess.check_output(cmd, timeout=15, stderr=subprocess.DEVNULL, universal_newlines=True) return glowparse(dat, time, ip, glat, glon)
def test_multi_past(): dates = pandas.date_range(datetime(2017, 12, 31, 23), datetime(2018, 1, 1, 2), freq="3H") try: dat = gi.get_indices(dates) except ConnectionError as e: pytest.skip(f"possible timeout error {e}") assert (dat.index == [datetime(2017, 1, 1, 22, 30), datetime(2018, 1, 1, 1, 30)]).all
def test_farfuture(): t = date(2029, 12, 21) dat = gi.get_indices(t, 81) assert dat.shape == (1, 5) assert dat.index[0] == datetime(2030, 1, 1, 2, 37, 40, 799998) assert "Ap" in dat assert "f107" in dat assert "f107s" in dat assert "Aps" in dat
def test_past_and_future(): dates = [datetime(2017, 1, 1), datetime(2030, 3, 1)] try: dat = gi.get_indices(dates) except ConnectionError as e: pytest.skip(f"possible timeout error {e}") pasttime = datetime(2017, 1, 1) if dat["resolution"][0] == "d": pasttime += timedelta(hours=1, minutes=30) assert (dat.index == [pasttime, datetime(2030, 3, 2, 22, 55, 11, 999997)]).all()
def test_list(): t = [date(2018, 1, 1), datetime(2018, 1, 2)] try: dat = gi.get_indices(t) except ConnectionError as e: pytest.skip(f"possible timeout error {e}") assert dat.shape[0] == 2 assert dat.shape[1] in (3, 4) assert (dat.index == [datetime(2018, 1, 1, 1, 30), datetime(2018, 1, 2, 1, 30)]).all
def test_past(dt, hour, f107, f107s, ap, aps, kp): try: dat = gi.get_indices(dt, 81) except ConnectionError as e: pytest.skip(f"possible timeout error {e}") assert dat.shape[0] == 1 assert dat["f107"].iloc[0] == approx(f107, abs=0.1) assert dat["f107s"].iloc[0] == approx(f107s, abs=0.1) assert dat["Ap"].iloc[0] == ap assert dat["Aps"].iloc[0] == approx(aps, abs=0.1) if "Kp" in dat: assert dat["Kp"].iloc[0] == approx(kp, abs=0.1)
def ebins(time: datetime, glat: float, glon: float, Ebins: np.ndarray, Phitop: np.ndarray) -> xarray.Dataset: idate, utsec = glowdate(time) # %% Matlab compatible workaround (may change to use stdin in future) Efn = Path(tempfile.mkstemp(".dat")[1]) with Efn.open("wb") as f: Ebins.tofile(f) Phitop.tofile(f) tmpfile_size = Efn.stat().st_size expected_size = (Ebins.size + Phitop.size) * 4 if tmpfile_size != expected_size: raise OSError(f"{Efn} size {tmpfile_size} != {expected_size}") ip = gi.get_indices([time - timedelta(days=1), time], 81) cmd = [ str(EXE), idate, utsec, str(glat), str(glon), str(ip["f107s"][1]), str(ip["f107"][1]), str(ip["f107"][0]), str(ip["Ap"][1]), "-e", str(Ebins.size), str(Efn), ] ret = subprocess.run(cmd, timeout=15, universal_newlines=True, stdout=subprocess.PIPE) if ret.returncode: raise RuntimeError(f"GLOW failed at {time}") try: Efn.unlink() except PermissionError: # Windows sometimes does this if something else is holding the file open. # this is also why we don't use a tempfile context manager for this application. pass return glowparse(ret.stdout, time, ip, glat, glon)
def test_nearfuture(): t = datetime.today() + timedelta(days=3) try: dat = gi.get_indices(t) except ConnectionError as e: pytest.skip(f"possible timeout error {e}") assert dat.shape[0] == 1 if t.hour >= 12: assert dat.index[0] == datetime(t.year, t.month, t.day) + timedelta(days=1) else: assert dat.index[0] == datetime(t.year, t.month, t.day) assert "Ap" in dat assert "f107" in dat
def test_past(dt, hour, f107s, ap, aps, kp): try: dat = gi.get_indices(dt, 81) except ConnectionError as e: pytest.skip(f"possible timeout error {e}") assert dat.shape[0] == 1 if dat["resolution"].iloc[0] == "m": assert dat["f107"].iloc[0] == approx(73.5, abs=0.1) assert dat["f107s"].iloc[0] == approx(76.4, abs=0.1) assert dat["Ap"].iloc[0] == 9 assert dat["Aps"].iloc[0] == approx(9.66, abs=0.1) elif dat["resolution"].iloc[0] == "d": assert dat["f107"].iloc[0] == approx(76.4) assert dat["f107s"].iloc[0] == approx(f107s, abs=0.1) assert dat["Ap"].iloc[0] == ap assert dat["Aps"].iloc[0] == approx(aps, abs=0.1) assert dat["Kp"].iloc[0] == approx(kp, abs=0.1) else: raise ValueError(f"unknown resolution {dat.resolution}")
def rungtd1d( time: datetime, altkm: float, glat: float, glon: float, indices: dict[str, typing.Any] = None ) -> xarray.Dataset: """ This is the "atomic" function looped by other functions """ time = todatetime(time) # %% get solar parameters for date if not indices: indices = gi.get_indices(time, smoothdays=81).squeeze().to_dict() assert isinstance(indices, dict) # %% dimensions altkm = np.atleast_1d(altkm) if altkm.ndim != 1: raise ValueError("altitude read incorrectly") if not isinstance(glon, (int, float, np.int32, np.int64)): raise TypeError("single longitude only") if not isinstance(glat, (int, float, np.int32, np.int64)): raise TypeError("single latitude only") # %% doy = time.strftime("%j") altkm = np.atleast_1d(altkm) # %% dens = np.empty((altkm.size, len(species))) temp = np.empty((altkm.size, len(ttypes))) # %% build on run exe_name = "msise00_driver" if os.name == "nt": exe_name += ".exe" if not importlib.resources.is_resource(__package__, exe_name): # check for CMake here to avoid "generator didn't stop after throw() higher level raise" if not shutil.which("ctest"): raise FileNotFoundError( """ CMake not available. try installing CMake like: pip install cmake""" ) with importlib.resources.path(__package__, "setup.cmake") as setup_file: cmake(setup_file) if not importlib.resources.is_resource(__package__, exe_name): raise RuntimeError("could not build MSISE00 Fortran driver") # check inputs for error, especially unavailable indices if not np.isfinite(glat).all(): raise ValueError("glat is not finite.") if not np.isfinite(glon).all(): raise ValueError("glon is not finite.") f107s = indices["f107s"] if not np.isfinite(f107s): raise ValueError("f107s is not finite.") f107s = indices["f107s"] if not np.isfinite(f107s): raise ValueError("f107s is not finite.") f107 = indices["f107"] if not np.isfinite(f107): raise ValueError("f107 is not finite.") Ap = indices["Ap"] if not np.isfinite(Ap): raise ValueError("Ap is not finite.") with importlib.resources.path(__package__, exe_name) as exe: for i, a in enumerate(altkm): cmd = [ str(exe), doy, str(time.hour), str(time.minute), str(time.second), str(glat), str(glon), str(f107s), str(f107), str(Ap), str(a), ] logging.info(" ".join(cmd)) ret = subprocess.check_output(cmd, text=True) # different compilers throw in extra \n raw = list(map(float, ret.split())) if not len(raw) == 9 + 2: raise ValueError(ret) dens[i, :] = raw[:9] temp[i, :] = raw[9:] dsf = { k: (("time", "alt_km", "lat", "lon"), v[None, :, None, None]) for (k, v) in zip(species, dens.T) } dsf.update( { "Tn": (("time", "alt_km", "lat", "lon"), temp[:, 1][None, :, None, None]), "Texo": (("time", "alt_km", "lat", "lon"), temp[:, 0][None, :, None, None]), } ) atmos = xarray.Dataset( dsf, # type: ignore coords={"time": [time], "alt_km": altkm, "lat": [glat], "lon": [glon]}, attrs={ "species": species, "f107s": indices["f107s"], "f107": indices["f107"], "Ap": indices["Ap"], }, ) return atmos
from argparse import ArgumentParser p = ArgumentParser() p.add_argument( "start_stop", help="date or date range of observation yyyy-mm-dd (START, STOP)", nargs="+") a = p.parse_args() start = parse(a.start_stop[0]) if len(a.start_stop) > 1: end = parse(a.start_stop[1]) else: end = start + timedelta(days=1) dates = pandas.date_range(start, end, freq="3H") inds = gi.get_indices(dates) # %% plot fig = figure() ax = fig.gca() inds.plot(ax=ax) # , marker='.' ax.set_ylabel("index values") ax.set_xlabel("time [UTC]") ax.grid(True) # fig.savefig('2015.png', bbox_inches='tight') show()