Skip to content
Snippets Groups Projects
record.py 3.58 KiB
Newer Older
# coding=utf-8
from datetime import datetime, timedelta

import numpy

Bruce Flynn's avatar
Bruce Flynn committed
from .time import hhmm_to_offset

symbols = {
    'TIME': {'type': numpy.int32},
    'ACCURAIN': {'type': numpy.float32},
}


class LineParseError(BaseException):
    """Error parsing line of record data.
    """
    @classmethod
    def raise_wrapped(cls, exception, msg=None):
        import sys
        traceback = sys.exc_info()[2]
        msg = msg or str(exception)
        raise cls(msg), None, traceback


def parse_v0_record(line):
    """
    Key/Value (Before June 2 2012)
    ==============================
    TIME:       Seconds since Jan 1, 1970
    ACCURAIN:   Accumulated precipitation (mm)
    TEMP107_4:  Auxillary temperature*
    LI200X:     Solar Flux (w/m^2)
    TEMP107_1:  Box temperature*
    RH41372:    Relative humidity (%)
    TEMP107_5:  Auxillary temperature*
    CS105:      Box pressure*
    PAROSCI:    Pressure (hPa)
    WSPD05305:  Wind speed (m/s)
    TEMP107_3:  Axullary temperature*
    CS10162:    Box relative humidity*
    RAIN380M:   Precipitation (0.01in)
    TEMP107_2:  Outside box temperature*
    TEMP41372:  Air temperature (ºC)
    WDIR05305:  Wind direction (degrees)
    """
    parts = line.split()
    if len(parts) != 32:
        msg = "Expected 32 line parts, got {:d}".format(len(parts))
        raise LineParseError(msg)
Bruce Flynn's avatar
Bruce Flynn committed
    raw_data = {k: v for k, v in zip(parts[0::2], parts[1::2])}
    time_str = raw_data['TIME']
    try:
        unix_time = int(time_str)
    except ValueError as err:
        msg = "Could not parse unix time from {}".format(time_str)
        LineParseError.raise_wrapped(err, msg)
Bruce Flynn's avatar
Bruce Flynn committed
    else:
        stamp = datetime.utcfromtimestamp(unix_time)
        return stamp, raw_data


class RecordV1(dict):
    """
    CSV (June 2 2012 to ...)
    ============================
    StationId*
    Year
    Day of year
    HourMinute
    Seconds
    Box Presure*
    ParoSci Air Temperature period*
    ParoSci Pressure period*
    ParoSci Air Temperature*
    Pressure (hPa)
    ParoSci Calc. Sig.*
    Box relative humidity*
    Box air temperature*
    Auxillary Air Temp2*
    Auxillary Air Temp3*
    Auxillary Air Temp4*
    Wind Speed (m/s)
    Wind Direction (degrees)
    RH Shield Freq.*
    Relative Humidity (%)
    Air Temperature 6.3m (ºC)
    Dewpoint (ºC)
    RTD Shield Freq.*
    Air temperature (ºC)
    Solar Flux (w/m^s)
    Precipitation (.01in)
    Acumulated Precip (mm) *reset at 0z
    Altimeter (inHg)
    """
    names = ['station_id', 'year', 'doy', 'hhmm', 'sec', 'box_pressure',
             'paro_air_temp_period', 'paro_pressure_period', 'paro_air_temp',
             'pressure', 'paro_cal_sig', 'box_rh', 'box_air_temp',
             'air_temp_2', 'air_temp_3', 'air_temp_4', 'wind_speed', 'wind_dir',
             'rh_shield_freq', 'rh', 'air_temp_6-3m', 'dewpoint',
             'rtd_shield_freq', 'air_temp', 'solar_flux', 'precip',
             'accum_precip', 'altimeter']

    def __init__(self, line):
        super(self.__class__, self).__init__()
        parts = line.split(',')
        if len(parts) != 29:
            raise LineParseError("Expected 29 parts, got {:d}".format(len(parts)))
        self.update({k: v for k, v in zip(self.names, parts)})

    def __getattr__(self, name, default=None):
        return self.get(name, default)

    def get_stamp(self):
        year = int(self['year'])
        doy = int(self['doy'])
        dt = datetime.strptime('{:d}.{:03d}'.format(int(year), int(doy)), '%Y.%j')
Bruce Flynn's avatar
Bruce Flynn committed
        secs = hhmm_to_offset(self['hhmm'])
        secs += float(self['sec'])
        secs -= (secs % 5)
        dt += timedelta(seconds=secs)
        return dt