Skip to content

Commit

Permalink
per #344, move more functions out of met_util into a more appropriate…
Browse files Browse the repository at this point in the history
… util file
  • Loading branch information
georgemccabe committed Oct 28, 2022
1 parent 867eb4a commit 23679ff
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 171 deletions.
108 changes: 0 additions & 108 deletions internal/tests/pytests/util/met_util/test_met_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,19 +211,6 @@ def test_get_lead_sequence_init_min_10(metplus_config):
assert test_seq == [relativedelta(hours=lead) for lead in lead_seq]


@pytest.mark.parametrize(
'value, expected_result', [
(3.3, 3.5),
(3.1, 3.0),
(-3.2, -3.0),
(-3.8, -4.0),
]
)
@pytest.mark.util
def test_round_0p5(value, expected_result):
assert util.round_0p5(value) == expected_result


@pytest.mark.parametrize(
'int_string, expected_result', [
('4', [4]),
Expand Down Expand Up @@ -261,101 +248,6 @@ def test_subset_list(subset_definition, expected_result):
assert result == expected_result


@pytest.mark.parametrize(
'filename, expected_result', [
# file does not exist
('filedoesnotexist.tcst', []),
# file is empty
('empty_filter.tcst', []),
# file has STORM_ID column with 4 values
('fake_filter_20141214_00.tcst', ['ML1201072014',
'ML1221072014',
'ML1241072014',
'ML1251072014']),
# file does not have STORM_ID column
('test_20190101.stat', []),
]
)
@pytest.mark.util
def test_get_storm_ids(metplus_config, filename, expected_result):
config = metplus_config
filepath = os.path.join(config.getdir('METPLUS_BASE'),
'internal', 'tests',
'data',
'stat_data',
filename)

assert util.get_storms(filepath, id_only=True) == expected_result


@pytest.mark.parametrize(
'filename, expected_result', [
# file does not exist
('filedoesnotexist.tcst', []),
# file is empty
('empty_filter.tcst', []),
# file has STORM_ID column with 4 values
('fake_filter_20141214_00.tcst', ['header',
'ML1201072014',
'ML1221072014',
'ML1241072014',
'ML1251072014']),
# file does not have STORM_ID column
('test_20190101.stat', []),
]
)
@pytest.mark.util
def test_get_storms(metplus_config, filename, expected_result):
storm_id_index = 4
config = metplus_config
filepath = os.path.join(config.getdir('METPLUS_BASE'),
'internal', 'tests',
'data',
'stat_data',
filename)

storm_dict = util.get_storms(filepath)
print(storm_dict)
assert list(storm_dict.keys()) == expected_result
for storm_id in expected_result[1:]:
for storm_line in storm_dict[storm_id]:
# ensure storm_id_index matches storm ID
assert storm_line.split()[storm_id_index] == storm_id

# ensure header matches expected format
if storm_dict:
assert storm_dict['header'].split()[storm_id_index] == 'STORM_ID'


@pytest.mark.util
def test_get_storms_mtd(metplus_config):
index = 23
expected_result = [
'header',
'CF001',
'CO001'
]
sort_column = 'OBJECT_CAT'
config = metplus_config
filepath = os.path.join(config.getdir('METPLUS_BASE'),
'internal', 'tests',
'data',
'mtd',
'fake_mtd_2d.txt')

storm_dict = util.get_storms(filepath, sort_column=sort_column)
print(storm_dict)
assert list(storm_dict.keys()) == expected_result
for storm_id in expected_result[1:]:
for storm_line in storm_dict[storm_id]:
# ensure index matches storm ID
assert storm_line.split()[index] == storm_id

# ensure header matches expected format
if storm_dict:
assert storm_dict['header'].split()[index] == sort_column


@pytest.mark.parametrize(
'level, expected_result', [
('level', 'level'),
Expand Down
13 changes: 13 additions & 0 deletions internal/tests/pytests/util/string_manip/test_util_string_manip.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@
from metplus.util.string_manip import _fix_list


@pytest.mark.parametrize(
'value, expected_result', [
(3.3, 3.5),
(3.1, 3.0),
(-3.2, -3.0),
(-3.8, -4.0),
]
)
@pytest.mark.util
def test_round_0p5(value, expected_result):
assert round_0p5(value) == expected_result


@pytest.mark.parametrize(
'key, value', [
({"gt2.3", "gt5.5"}, True),
Expand Down
99 changes: 99 additions & 0 deletions internal/tests/pytests/util/system_util/test_system_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env python3

import pytest

from metplus.util.system_util import *

@pytest.mark.parametrize(
'filename, expected_result', [
# file does not exist
('filedoesnotexist.tcst', []),
# file is empty
('empty_filter.tcst', []),
# file has STORM_ID column with 4 values
('fake_filter_20141214_00.tcst', ['ML1201072014',
'ML1221072014',
'ML1241072014',
'ML1251072014']),
# file does not have STORM_ID column
('test_20190101.stat', []),
]
)
@pytest.mark.util
def test_get_storm_ids(metplus_config, filename, expected_result):
config = metplus_config
filepath = os.path.join(config.getdir('METPLUS_BASE'),
'internal', 'tests',
'data',
'stat_data',
filename)

assert get_storms(filepath, id_only=True) == expected_result


@pytest.mark.parametrize(
'filename, expected_result', [
# file does not exist
('filedoesnotexist.tcst', []),
# file is empty
('empty_filter.tcst', []),
# file has STORM_ID column with 4 values
('fake_filter_20141214_00.tcst', ['header',
'ML1201072014',
'ML1221072014',
'ML1241072014',
'ML1251072014']),
# file does not have STORM_ID column
('test_20190101.stat', []),
]
)
@pytest.mark.util
def test_get_storms(metplus_config, filename, expected_result):
storm_id_index = 4
config = metplus_config
filepath = os.path.join(config.getdir('METPLUS_BASE'),
'internal', 'tests',
'data',
'stat_data',
filename)

storm_dict = get_storms(filepath)
print(storm_dict)
assert list(storm_dict.keys()) == expected_result
for storm_id in expected_result[1:]:
for storm_line in storm_dict[storm_id]:
# ensure storm_id_index matches storm ID
assert storm_line.split()[storm_id_index] == storm_id

# ensure header matches expected format
if storm_dict:
assert storm_dict['header'].split()[storm_id_index] == 'STORM_ID'


@pytest.mark.util
def test_get_storms_mtd(metplus_config):
index = 23
expected_result = [
'header',
'CF001',
'CO001'
]
sort_column = 'OBJECT_CAT'
config = metplus_config
filepath = os.path.join(config.getdir('METPLUS_BASE'),
'internal', 'tests',
'data',
'mtd',
'fake_mtd_2d.txt')

storm_dict = get_storms(filepath, sort_column=sort_column)
print(storm_dict)
assert list(storm_dict.keys()) == expected_result
for storm_id in expected_result[1:]:
for storm_line in storm_dict[storm_id]:
# ensure index matches storm ID
assert storm_line.split()[index] == storm_id

# ensure header matches expected format
if storm_dict:
assert storm_dict['header'].split()[index] == sort_column
59 changes: 0 additions & 59 deletions metplus/util/met_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,65 +293,6 @@ def get_lead_sequence_groups(config):

return lead_seq_dict

def round_0p5(val):
"""! Round to the nearest point five (ie 3.3 rounds to 3.5, 3.1
rounds to 3.0) Take the input value, multiply by two, round to integer
(no decimal places) then divide by two. Expect any input value of n.0,
n.1, or n.2 to round down to n.0, and any input value of n.5, n.6 or
n.7 to round to n.5. Finally, any input value of n.8 or n.9 will
round to (n+1).0
Args:
@param val : The number to be rounded to the nearest .5
Returns:
pt_five: The n.0, n.5, or (n+1).0 value as
a result of rounding the input value, val.
"""

return round(val * 2) / 2


def get_storms(filter_filename, id_only=False, sort_column='STORM_ID'):
"""! Get each storm as identified by a column in the input file.
Create dictionary storm ID as the key and a list of lines for that
storm as the value.
@param filter_filename name of tcst file to read and extract storm id
@param sort_column column to use to sort and group storms. Default
value is STORM_ID
@returns 2 item tuple - 1)dictionary where key is storm ID and value
is list of relevant lines from tcst file, 2) header line from tcst
file. Item with key 'header' contains the header of the tcst file
"""
# Initialize a set because we want unique storm ids.
storm_id_list = set()

try:
with open(filter_filename, "r") as file_handle:
header, *lines = file_handle.readlines()

storm_id_column = header.split().index(sort_column)
for line in lines:
storm_id_list.add(line.split()[storm_id_column])
except (ValueError, FileNotFoundError):
if id_only:
return []
return {}

# sort the unique storm ids, copy the original
# set by using sorted rather than sort.
sorted_storms = sorted(storm_id_list)
if id_only:
return sorted_storms

if not sorted_storms:
return {}

storm_dict = {'header': header}
# for each storm, get all lines for that storm
for storm in sorted_storms:
storm_dict[storm] = [line for line in lines if storm in line]

return storm_dict

def get_files(filedir, filename_regex, logger=None):
"""! Get all the files (with a particular
Expand Down
14 changes: 14 additions & 0 deletions metplus/util/string_manip.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,17 @@ def validate_thresholds(thresh_list):
"optionally combined with && or ||")
return False
return True


def round_0p5(val):
"""! Round to the nearest point five (ie 3.3 rounds to 3.5, 3.1
rounds to 3.0) Take the input value, multiply by two, round to integer
(no decimal places) then divide by two. Expect any input value of n.0,
n.1, or n.2 to round down to n.0, and any input value of n.5, n.6 or
n.7 to round to n.5. Finally, any input value of n.8 or n.9 will
round to (n+1).0
@param val : The number to be rounded to the nearest .5
@returns n.0, n.5, or (n+1).0 value as a result of rounding
"""
return round(val * 2) / 2
44 changes: 44 additions & 0 deletions metplus/util/system_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,47 @@ def write_list_to_file(filename, output_list):
with open(filename, 'w+') as f:
for line in output_list:
f.write(f"{line}\n")


def get_storms(filter_filename, id_only=False, sort_column='STORM_ID'):
"""! Get each storm as identified by a column in the input file.
Create dictionary storm ID as the key and a list of lines for that
storm as the value.
@param filter_filename name of tcst file to read and extract storm id
@param sort_column column to use to sort and group storms. Default
value is STORM_ID
@returns 2 item tuple - 1)dictionary where key is storm ID and value
is list of relevant lines from tcst file, 2) header line from tcst
file. Item with key 'header' contains the header of the tcst file
"""
# Initialize a set because we want unique storm ids.
storm_id_list = set()

try:
with open(filter_filename, "r") as file_handle:
header, *lines = file_handle.readlines()

storm_id_column = header.split().index(sort_column)
for line in lines:
storm_id_list.add(line.split()[storm_id_column])
except (ValueError, FileNotFoundError):
if id_only:
return []
return {}

# sort the unique storm ids, copy the original
# set by using sorted rather than sort.
sorted_storms = sorted(storm_id_list)
if id_only:
return sorted_storms

if not sorted_storms:
return {}

storm_dict = {'header': header}
# for each storm, get all lines for that storm
for storm in sorted_storms:
storm_dict[storm] = [line for line in lines if storm in line]

return storm_dict
Loading

0 comments on commit 23679ff

Please sign in to comment.