test_gfz.test_not_avail()   A
last analyzed

Complexity

Conditions 5

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nop 2
dl 0
loc 13
rs 9.3333
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
# vim:fileencoding=utf-8
3
#
4
# Copyright (c) 2024 Stefan Bender
5
#
6
# This module is part of pyspaceweather.
7
# pyspaceweather is free software: you can redistribute it or modify
8
# it under the terms of the GNU General Public License as published
9
# by the Free Software Foundation, version 2.
10
# See accompanying COPYING.GPLv2 file or http://www.gnu.org/licenses/gpl-2.0.html.
11
"""Space weather index read tests for GFZ formats
12
13
Parsing tests for the GFZ file formats.
14
"""
15
import os
16
17
import numpy as np
18
import pandas as pd
19
import requests
20
21
import pytest
22
23
from spaceweather import (
24
	gfz_3h, gfz_daily, get_gfz_age, update_gfz,
25
)
26
from spaceweather.gfz import GFZ_URL_30D, HP30_URL_30D, HP60_URL_30D
27
28
GFZ_PATH_ALL = os.path.join("tests", "Kp_ap_Ap_SN_F107_since_2024.txt")
29
GFZ_PATH_30D = os.path.join("tests", "Kp_ap_Ap_SN_F107_nowcast.txt")
30
31
HP30_PATH_ALL = os.path.join("tests", "Hp30_ap30_complete_series.txt")
32
HP30_PATH_30D = os.path.join("tests", "Hp30_ap30_nowcast.txt")
33
34
HP60_PATH_ALL = os.path.join("tests", "Hp60_ap60_complete_series.txt")
35
HP60_PATH_30D = os.path.join("tests", "Hp60_ap60_nowcast.txt")
36
37
38
@pytest.fixture(scope="module")
39
def df_3h():
40
	return gfz_3h(gfzpath_all=GFZ_PATH_ALL, gfzpath_30d=GFZ_PATH_30D)
41
42
43
def test_age():
44
	now = pd.Timestamp.utcnow()
45
	for p in [GFZ_PATH_ALL, GFZ_PATH_30D]:
46
		assert os.path.exists(p)
47
		fage0 = get_gfz_age(p)
48
		fage1 = now - get_gfz_age(p, relative=False)
49
		assert (fage0 > pd.Timedelta("3h")) == (fage1 > pd.Timedelta("3h"))
50
		assert (fage0 > pd.Timedelta("1d")) == (fage1 > pd.Timedelta("1d"))
51
52
53
def test_update(mocker):
54
	mocker.patch("requests.get")
55
	update_gfz(min_age="1d", gfzpath_all=GFZ_PATH_ALL, gfzpath_30d=GFZ_PATH_30D)
56
	requests.get.assert_called_with(GFZ_URL_30D, stream=True)
57
58
59
def test_auto_update(mocker, tmpdir):
60
	# test with non-existent file
61
	mocker.patch("requests.get")
62
	tmpdir = str(tmpdir)
63
	update_gfz(gfzpath_30d=os.path.join(tmpdir, "foo.dat"))
64
	requests.get.assert_called_with(GFZ_URL_30D, stream=True)
65
	# Should update the last-5-year data
66
	gfz_daily(
67
		gfzpath_all=GFZ_PATH_ALL, gfzpath_30d=GFZ_PATH_30D,
68
		update=True, update_interval="1d",
69
	)
70
	requests.get.assert_called_with(GFZ_URL_30D, stream=True)
71
	with pytest.warns(UserWarning):
72
		gfz_daily(
73
			gfzpath_all=GFZ_PATH_ALL, gfzpath_30d=GFZ_PATH_30D,
74
			update=False, update_interval="0h",
75
		)
76
77
78
def test_not_avail(mocker, tmpdir):
79
	# test with non-existent file
80
	mocker.patch("requests.get")
81
	tmpdir = str(tmpdir)
82
	tmpfile = os.path.join(tmpdir, "foo.dat")
83
	# daily
84
	with pytest.raises(IOError):
85
		with pytest.warns(UserWarning):
86
			gfz_daily(update=False, update_interval="0h", gfzpath_30d=tmpfile)
87
	# 3h data
88
	with pytest.raises(IOError):
89
		with pytest.warns(UserWarning):
90
			gfz_3h(update=False, update_interval="0h", gfzpath_30d=tmpfile)
91
92
93
def test_daily():
94
	df = gfz_daily(gfzpath_all=GFZ_PATH_ALL, gfzpath_30d=GFZ_PATH_30D)
95
	np.testing.assert_allclose(
96
		df.loc["2024-01-01"].values,
97
		np.array([
98
			2.024e+03, 1.000e+00, 1.000e+00,
99
			3.36030e+04, 3.36035e+04, 2.596e+03, 2.500e+01,
100
			6.670e-01, 3.330e-01, 6.670e-01, 1.333e+00,
101
			2.000e+00, 3.000e+00, 3.333e+00, 4.000e+00, 1.5333e+01,
102
			3.000e+00, 2.000e+00, 3.000e+00, 5.000e+00,
103
			7.000e+00, 1.500e+01, 1.800e+01, 2.700e+01, 1.000e+01,
104
			5.400e+01, 1.357e+02, 1.312e+02, 1.000e+00,
105
		], dtype=np.float64),
106
		rtol=1e-6,
107
	)
108
109
110
@pytest.mark.parametrize(
111
	"name, result",
112
	[
113
		("Ap", [3, 2, 3, 5, 7, 15, 18, 27]),
114
		("Kp", [0.667, 0.333, 0.667, 1.333, 2.0, 3.0, 3.333, 4.0]),
115
	]
116
)
117
def test_3hourly_index(name, result, df_3h):
118
	df = df_3h
119
	np.testing.assert_allclose(
120
		df.loc[
121
			pd.date_range(
122
				"2024-01-01 01:30", "2024-01-01 23:30", freq="3h"
123
			)
124
		][name].values,
125
		np.array(result, dtype=np.float64),
126
		rtol=1e-6,
127
	)
128
129
130
@pytest.mark.parametrize(
131
	"fpall, fp30d, url",
132
	[
133
		(HP30_PATH_ALL, HP30_PATH_30D, HP30_URL_30D),
134
		(HP60_PATH_ALL, HP60_PATH_30D, HP60_URL_30D),
135
	],
136
	ids=["Hp30", "Hp60"],
137
)
138
def test_auto_update_hp(fpall, fp30d, url, mocker, request):
139
	mocker.patch("requests.get")
140
	_gfz_fmt = request.node.callspec.id.lower()
141
	# Should update the last-5-year data
142
	gfz_daily(
143
		gfzpath_all=fpall, gfzpath_30d=fp30d,
144
		update=True, update_interval="1d",
145
		gfz_format=_gfz_fmt,
146
	)
147
	requests.get.assert_called_with(url, stream=True)
148
149
150
@pytest.mark.parametrize(
151
	"fpall, fp30d, index, expected",
152
	[
153
		(
154
			HP30_PATH_ALL, HP30_PATH_30D, "2025-07-01 00:15",
155
			[2025, 7, 1, 0, 0.25, 34150.0, 34150.01042, 3.000, 15, 0],
156
		),
157
		(
158
			HP60_PATH_ALL, HP60_PATH_30D, "2025-07-01 00:30",
159
			[2025, 7, 1, 0, 0.50, 34150.0, 34150.02083, 3.333, 18, 0],
160
		),
161
	],
162
	ids=["Hp30", "Hp60"],
163
)
164
def test_daily_hp(fpall, fp30d, index, expected, request):
165
	_gfz_fmt = request.node.callspec.id.lower()
166
	df = gfz_daily(
167
		gfzpath_all=fpall,
168
		gfzpath_30d=fp30d,
169
		gfz_format=_gfz_fmt,
170
	)
171
	np.testing.assert_allclose(
172
		df.loc[index].values,
173
		np.array(expected, dtype=np.float64),
174
		rtol=1e-6,
175
	)
176