Source code for metloom.pointdata.csas
"""
Data reader for the Center for Snow and Avalanche Studies
"""
from metloom.pointdata import CSVPointData, StationInfo
from metloom.variables import CSASVariables
import os
from datetime import datetime, timedelta
[docs]
class InvalidDateRange(Exception):
"""
Exception to indicate there is no know data for the available date range
"""
[docs]
class CSASStationInfo(StationInfo):
# Name, id, lat, long, elevation, http path
SENATOR_BECK = ("Senator Beck Study Plot", "SBSP", 37.90688, -107.72627, 12186,
"2023/11/SBSP_1hr_2003-2009.csv")
SWAMP_ANGEL = ("Swamp Angel Study Plot", "SASP", 37.90691, -107.71132, 11060,
"2023/11/SASP_1hr_2003-2009.csv")
PUTNEY = ("Putney Study Plot", "PTSP", 37.89233, -107.69577, 12323,
"2025/05/PTSP_1hr.csv")
SENATOR_BECK_STREAM_GAUGE = ("Senator Beck Stream Gauge", "SBSG", 37.90678,
-107.70943, 11030, "2025/05/SBSG_1hr.csv")
[docs]
class CSASMet(CSVPointData):
"""
"""
CURRENT_AVAILABLE_YEAR = 2024
ALLOWED_VARIABLES = CSASVariables
ALLOWED_STATIONS = CSASStationInfo
# Data is in Mountain time
UTC_OFFSET_HOURS = -7
URL = "https://snowstudies.org/wp-content/uploads/"
DATASOURCE = "CSAS"
DOI = ""
def _file_urls(self, station_id, start, end):
"""
Navigate the system using dates. Data for SASP and SBSP is stored in
two csvs. 2003-2009 and 2010-2023. Not sure what happens when the
next year is made available. This function will grab the necessary urls
depending on the requested data
"""
urls = []
if station_id in ['SASP', 'SBSP']:
current_available_year = self.CURRENT_AVAILABLE_YEAR
if start.year <= 2009:
urls.append(os.path.join(self.URL, self._station_info.path))
# Account for later file use or even straddling thge data
if start.year > 2009 or end.year > 2009: # TODO: add to the info enum?
partial = str(self._station_info.path).replace("2003", "2010")
partial = partial.replace('2009', str(current_available_year))
# Change the subdirectory in the url
filename = partial.replace('2023/11/', '2025/05/')
urls.append(os.path.join(self.URL, filename))
if start.year < 2003 or end.year > current_available_year:
raise InvalidDateRange(f"CSAS data is only available from 2003-"
f"{current_available_year}")
else:
urls.append(os.path.join(self.URL, self._station_info.path))
return urls
@staticmethod
def _parse_datetime(row):
# Julian day is not zero based Jan 1 == DOY 1
dt = timedelta(days=int(row['DOY']) - 1, hours=int(row['Hour'] / 100))
return datetime(int(row['Year']), 1, 1) + dt
def _assign_datetime(self, resp_df):
resp_df['datetime'] = resp_df.apply(lambda row: self._parse_datetime(row),
axis=1)
return resp_df.set_index('datetime')