Пример #1
0
    def get_series(obs_type,
                   timespan,
                   db_manager,
                   aggregate_type=None,
                   aggregate_interval=None):
        """Get a series, possibly with aggregation, for special 'wind vector' types. These are
        typically used for the wind vector plots.
        """

        # Check to see if the requested type is not 'windvec' or 'windgustvec'
        if obs_type not in WindVec.windvec_types:
            # The type is not one of the extended wind types. We can't handle it.
            raise weewx.UnknownType(obs_type)

        # It is an extended wind type. Prepare the lists that will hold the
        # final results.
        start_vec = list()
        stop_vec = list()
        data_vec = list()

        # Is aggregation requested?
        if aggregate_type:
            # Yes. Just use the regular series function. When it comes time to do the aggregation,
            # the specialized function WindVec.get_aggregate() (defined below), will be used.
            return ArchiveTable.get_series(obs_type, timespan, db_manager,
                                           aggregate_type, aggregate_interval)

        else:
            # No aggregation desired. However, we have will have to assemble the wind vector from
            # its flattened types. This SQL select string will select the proper wind types
            sql_str = 'SELECT dateTime, %s, %s, usUnits, `interval` FROM %s ' \
                      'WHERE dateTime >= ? AND dateTime <= ?' \
                      % (WindVec.windvec_types[obs_type][0], WindVec.windvec_types[obs_type][1],
                         db_manager.table_name)
            std_unit_system = None

            for record in db_manager.genSql(sql_str, timespan):
                ts, magnitude, direction, unit_system, interval = record
                if std_unit_system:
                    if std_unit_system != unit_system:
                        raise weewx.UnsupportedFeature(
                            "Unit type cannot change within a time interval.")
                else:
                    std_unit_system = unit_system

                value = weeutil.weeutil.to_complex(magnitude, direction)

                start_vec.append(ts - interval * 60)
                stop_vec.append(ts)
                data_vec.append(value)

            unit, unit_group = weewx.units.getStandardUnitType(
                std_unit_system, obs_type, aggregate_type)

        return (ValueTuple(start_vec, 'unix_epoch', 'group_time'),
                ValueTuple(stop_vec, 'unix_epoch',
                           'group_time'), ValueTuple(data_vec, unit,
                                                     unit_group))
Пример #2
0
    def get_series(obs_type, timespan, db_manager, aggregate_type=None, aggregate_interval=None):
        """Get a series, possibly with aggregation.
        """

        if obs_type not in [ 'pm2_5_aqi', 'pm2_5_aqi_color' ]:
            raise weewx.UnknownType(obs_type)

        log.debug('get_series(%s, %s, %s, aggregate:%s, aggregate_interval:%s)' % (
            obs_type, timestamp_to_string(timespan.start), timestamp_to_string(
            timespan.stop), aggregate_type, aggregate_interval))

        #  Prepare the lists that will hold the final results.
        start_vec = list()
        stop_vec = list()
        data_vec = list()

        # Is aggregation requested?
        if aggregate_type:
            # Yes. Just use the regular series function.
            return weewx.xtypes.ArchiveTable.get_series(obs_type, timespan, db_manager, aggregate_type,
                                           aggregate_interval)
        else:
            # No aggregation.
            sql_str = 'SELECT dateTime, usUnits, `interval`, pm2_5 FROM %s ' \
                      'WHERE dateTime >= ? AND dateTime <= ? AND pm2_5 IS NOT NULL' \
                      % db_manager.table_name
            std_unit_system = None

            for record in db_manager.genSql(sql_str, timespan):
                ts, unit_system, interval, pm2_5 = record
                if std_unit_system:
                    if std_unit_system != unit_system:
                        raise weewx.UnsupportedFeature(
                            "Unit type cannot change within a time interval.")
                else:
                    std_unit_system = unit_system

                if obs_type == 'pm2_5_aqi':
                    value = AQI.compute_pm2_5_aqi(pm2_5)
                if obs_type == 'pm2_5_aqi_color':
                    value = AQI.compute_pm2_5_aqi_color(AQI.compute_pm2_5_aqi(pm2_5))
                log.debug('get_series(%s): %s - %s - %s' % (obs_type,
                    timestamp_to_string(ts - interval * 60),
                    timestamp_to_string(ts), value))
                start_vec.append(ts - interval * 60)
                stop_vec.append(ts)
                data_vec.append(value)

            unit, unit_group = weewx.units.getStandardUnitType(std_unit_system, obs_type,
                                                               aggregate_type)

        return (ValueTuple(start_vec, 'unix_epoch', 'group_time'),
                ValueTuple(stop_vec, 'unix_epoch', 'group_time'),
                ValueTuple(data_vec, unit, unit_group))
Пример #3
0
    def get_series(obs_type, timespan, db_manager, aggregate_type=None, aggregate_interval=None):
        """Get a series, possibly with aggregation, for special 'wind' types."""

        # Check to see if the requested type is not 'windvec' or 'windgustvec'
        if obs_type not in Wind.windvec_types:
            # The type is not one of the extended wind types. We can't handle it.
            raise weewx.UnknownType(obs_type)

        # It is an extended wind type. Prepare the lists that will hold the
        # final results.
        start_vec = list()
        stop_vec = list()
        data_vec = list()

        # Is aggregation requested?
        if aggregate_type:
            # Yes. Just use the regular series function, but with the special wind aggregate type. It will
            # call the proper aggregation function.
            return SeriesArchive.get_series(obs_type, timespan, db_manager, aggregate_type, aggregate_interval)

        else:
            # No aggregation desired. However, we have will have to assemble the wind vector from its flattened types.
            # This SQL select string will select the proper wind types
            sql_str = 'SELECT dateTime, %s, %s, usUnits, `interval` FROM %s WHERE dateTime >= ? AND dateTime <= ?' \
                      % (Wind.windvec_types[obs_type][0], Wind.windvec_types[obs_type][1], db_manager.table_name)
            std_unit_system = None

            for record in db_manager.genSql(sql_str, timespan):
                start_vec.append(record[0] - record[4] * 60)
                stop_vec.append(record[0])
                if std_unit_system:
                    if std_unit_system != record[3]:
                        raise weewx.UnsupportedFeature("Unit type cannot change within a time interval.")
                else:
                    std_unit_system = record[3]
                # Break the mag and dir down into x- and y-components.
                (magnitude, direction) = record[1:3]
                if magnitude is None or direction is None:
                    data_vec.append(None)
                else:
                    x = magnitude * math.cos(math.radians(90.0 - direction))
                    y = magnitude * math.sin(math.radians(90.0 - direction))
                    if weewx.debug:
                        # There seem to be some little rounding errors that
                        # are driving my debugging crazy. Zero them out
                        if abs(x) < 1.0e-6: x = 0.0
                        if abs(y) < 1.0e-6: y = 0.0
                    data_vec.append(complex(x, y))
            unit, unit_group = weewx.units.getStandardUnitType(std_unit_system, obs_type, aggregate_type)

        return (ValueTuple(start_vec, 'unix_epoch', 'group_time'),
                ValueTuple(stop_vec, 'unix_epoch', 'group_time'),
                ValueTuple(data_vec, unit, unit_group))
Пример #4
0
    def get_vectors(self, stamps, csv_file_name, threshold_lo_t,
                    threshold_hi_t):

        (minstamp, maxstamp) = stamps
        threshold_lo = (threshold_lo_t)[ZERO]
        threshold_hi = (threshold_hi_t)[ZERO]
        result = {
            'date': ValueTuple([], 'unix_epoch', 'group_time'),
            'daily_max': ValueTuple([], 'degree_C', 'group_temperature'),
            'daily_min': ValueTuple([], 'degree_C', 'group_temperature'),
            'dd': ValueTuple([], 'degree_C_day', 'group_degree_day'),
            'dd_cumulative': ValueTuple([], 'degree_C_day',
                                        'group_degree_day'),
        }
        try:
            with open(csv_file_name) as csv_file:
                csv_dict = csv.DictReader(csv_file)
                recs = []
                for (ndx, rec) in enumerate(csv_dict):
                    try:
                        date_string = '%(YR)s/%(MO)s/%(DAY)s' % rec
                        stamp = time.mktime(
                            time.strptime(date_string, '%Y/%m/%d'))
                    except ValueError:
                        stamp = None
                    if stamp is None:
                        pass
                    else:
                        recs.append([stamp, rec])
                recs.sort()
                dd_cumulative = ZERO
                for (ndx, (stamp, rec)) in enumerate(recs):
                    if (minstamp <= stamp) and (stamp <= maxstamp):
                        result['date'][ZERO].append(stamp)
                        try:
                            daily_max = float(rec.get('TMPMAX_C'))
                            result['daily_max'][ZERO].append(daily_max)
                            daily_min = float(rec.get('TMPMIN_C'))
                            result['daily_min'][ZERO].append(daily_min)
                            dd = dd_clipped(daily_max, daily_min, threshold_lo,
                                            threshold_hi)
                            result['dd'][ZERO].append(dd)
                            dd_cumulative += dd
                            result['dd_cumulative'][ZERO].append(dd_cumulative)
                        except ValueError:
                            pass
                        except TypeError:
                            pass
        except IOError as e:
            log.info("Unable to read file '%s' %s:", csv_file_name, e)

        return result
Пример #5
0
    def get_vectors(self, stamps, csv_file_name, c_temp_base_t, c4_temp_t):

        (minstamp, maxstamp) = stamps
        c_temp_base = self.to_degree_f.convert(c_temp_base_t)[ZERO]
        c4_temp = self.to_degree_f.convert(c4_temp_t)[ZERO]
        result = {
            'date': ValueTuple([], 'unix_epoch', 'group_time'),
            'daily_max': ValueTuple([], 'degree_F', 'group_temperature'),
            'daily_min': ValueTuple([], 'degree_F', 'group_temperature'),
            'dd': ValueTuple([], 'count', 'group_count'),
            'dd_cumulative': ValueTuple([], 'count', 'group_count'),
        }
        try:
            with open(csv_file_name) as csv_file:
                csv_dict = csv.DictReader(csv_file)
                recs = []
                for (ndx, rec) in enumerate(csv_dict):
                    try:
                        date_string = '%(YR)s/%(MO)s/%(DAY)s' % rec
                        stamp = time.mktime(
                            time.strptime(date_string, '%Y/%m/%d'))
                    except ValueError:
                        stamp = None
                    if stamp is None:
                        pass
                    else:
                        recs.append([stamp, rec])
                recs.sort()
                dd_cumulative = ZERO
                for (ndx, (stamp, rec)) in enumerate(recs):
                    if (minstamp <= stamp) and (stamp <= maxstamp):
                        result['date'][ZERO].append(stamp)
                        try:
                            daily_max = float(rec.get('TMPMAX_F'))
                            result['daily_max'][ZERO].append(daily_max)
                            daily_min = float(rec.get('TMPMIN_F'))
                            result['daily_min'][ZERO].append(daily_min)
                            dd = get_growth10(daily_max, daily_min,
                                              c_temp_base, c4_temp)
                            result['dd'][ZERO].append(dd)
                            dd_cumulative += dd
                            result['dd_cumulative'][ZERO].append(dd_cumulative)
                        except ValueError:
                            pass
                        except TypeError:
                            pass
        except IOError as e:
            log.critical("growth10Generator: Unable to read file '%s' %s:",
                         csv_file_name, e)
        return result
Пример #6
0
    def get_series(obs_type,
                   timespan,
                   db_manager,
                   aggregate_type=None,
                   aggregate_interval=None,
                   **option_dict):
        """Get a series of an xtype, by using the main archive table. Works only for no
        aggregation. """

        start_vec = list()
        stop_vec = list()
        data_vec = list()

        if aggregate_type:
            # This version does not know how to do aggregations, although this could be
            # added in the future.
            raise weewx.UnknownAggregation(aggregate_type)

        else:
            # No aggregation

            std_unit_system = None

            # Hit the database.
            for record in db_manager.genBatchRecords(*timespan):

                if std_unit_system:
                    if std_unit_system != record['usUnits']:
                        raise weewx.UnsupportedFeature(
                            "Unit system cannot change "
                            "within a series.")
                else:
                    std_unit_system = record['usUnits']

                # Given a record, use the xtypes system to calculate a value:
                try:
                    value = get_scalar(obs_type, record, db_manager)
                    data_vec.append(value[0])
                except weewx.CannotCalculate:
                    data_vec.append(None)
                start_vec.append(record['dateTime'] - record['interval'] * 60)
                stop_vec.append(record['dateTime'])

            unit, unit_group = weewx.units.getStandardUnitType(
                std_unit_system, obs_type)

        return (ValueTuple(start_vec, 'unix_epoch', 'group_time'),
                ValueTuple(stop_vec, 'unix_epoch',
                           'group_time'), ValueTuple(data_vec, unit,
                                                     unit_group))
Пример #7
0
    def test_AggregateDaily(self):
        """Test special aggregates that can be used against the daily summaries."""
        with weewx.manager.open_manager_with_config(
                self.config_dict, 'wx_binding') as db_manager:
            month_start_tt = (2010, 3, 1, 0, 0, 0, 0, 0, -1)
            month_stop_tt = (2010, 4, 1, 0, 0, 0, 0, 0, -1)
            start_ts = time.mktime(month_start_tt)
            stop_ts = time.mktime(month_stop_tt)

            min_ge_vt = weewx.xtypes.DailySummaries.get_aggregate(
                'outTemp',
                TimeSpan(start_ts, stop_ts),
                'min_ge',
                db_manager,
                val=ValueTuple(15, 'degree_F', 'group_temperature'))
            self.assertEqual(min_ge_vt[0], 6)

            min_le_vt = weewx.xtypes.DailySummaries.get_aggregate(
                'outTemp',
                TimeSpan(start_ts, stop_ts),
                'min_le',
                db_manager,
                val=ValueTuple(0, 'degree_F', 'group_temperature'))
            self.assertEqual(min_le_vt[0], 2)

            minmax_vt = weewx.xtypes.DailySummaries.get_aggregate(
                'outTemp', TimeSpan(start_ts, stop_ts), 'minmax', db_manager)
            self.assertAlmostEqual(minmax_vt[0], 39.28, 2)

            max_wind_vt = weewx.xtypes.DailySummaries.get_aggregate(
                'wind', TimeSpan(start_ts, stop_ts), 'max', db_manager)
            self.assertAlmostEqual(max_wind_vt[0], 24.0, 2)

            avg_wind_vt = weewx.xtypes.DailySummaries.get_aggregate(
                'wind', TimeSpan(start_ts, stop_ts), 'avg', db_manager)
            self.assertAlmostEqual(avg_wind_vt[0], 10.21, 2)
            # Double check this last one against the average calculated from the archive
            avg_wind_vt = weewx.xtypes.ArchiveTable.get_aggregate(
                'windSpeed', TimeSpan(start_ts, stop_ts), 'avg', db_manager)
            self.assertAlmostEqual(avg_wind_vt[0], 10.21, 2)

            vecavg_wind_vt = weewx.xtypes.DailySummaries.get_aggregate(
                'wind', TimeSpan(start_ts, stop_ts), 'vecavg', db_manager)
            self.assertAlmostEqual(vecavg_wind_vt[0], 5.14, 2)

            vecdir_wind_vt = weewx.xtypes.DailySummaries.get_aggregate(
                'wind', TimeSpan(start_ts, stop_ts), 'vecdir', db_manager)
            self.assertAlmostEqual(vecdir_wind_vt[0], 88.77, 2)
Пример #8
0
 def calc_windGustDir(self, key, data, db_manager):
     """ Set windGustDir to None if windGust is zero. Otherwise, raise weewx.NoCalculate.If"""
     if 'windGust' not in data \
             or not self.force_null\
             or data['windGust']:
         raise weewx.NoCalculate
     return ValueTuple(None, 'degree_compass', 'group_direction')
Пример #9
0
 def temperature(self, input, item, event):
     system = event.packet['usUnits']
     unit_group = weewx.units.getStandardUnitType(system, item)
     temp_c = self.val(input) / 1000.0
     temp_v = ValueTuple(temp_c, "degree_C", "group_temperature")
     temp_u = weewx.units.convert(temp_v, unit_group[0])
     event.packet[item] = temp_u[0]
Пример #10
0
    def pressure(self, record, dbmanager):
        """Calculate the observation type 'pressure'."""

        # All of the following keys are required:
        if any(key not in record
               for key in ['usUnits', 'outTemp', 'barometer', 'outHumidity']):
            raise weewx.CannotCalculate('pressure')

        # Get the temperature in Fahrenheit from 12 hours ago
        temp_12h_vt = self._get_temperature_12h(record['dateTime'], dbmanager)
        if temp_12h_vt is None \
                or temp_12h_vt[0] is None \
                or record['outTemp'] is None \
                or record['barometer'] is None \
                or record['outHumidity'] is None:
            pressure = None
        else:
            # The following requires everything to be in US Customary units.
            # Rather than convert the whole record, just convert what we need:
            record_US = weewx.units.to_US({
                'usUnits': record['usUnits'],
                'outTemp': record['outTemp'],
                'barometer': record['barometer'],
                'outHumidity': record['outHumidity']
            })
            # Get the altitude in feet
            altitude_ft = weewx.units.convert(self.altitude_vt, "foot")
            # The outside temperature in F.
            temp_12h_F = weewx.units.convert(temp_12h_vt, "degree_F")
            pressure = weewx.uwxutils.uWxUtilsVP.SeaLevelToSensorPressure_12(
                record_US['barometer'], altitude_ft[0], record_US['outTemp'],
                temp_12h_F[0], record_US['outHumidity'])

        return ValueTuple(pressure, 'inHg', 'group_pressure')
Пример #11
0
 def pressure(self, input, item, event):
     system = event.packet['usUnits']
     unit_group = weewx.units.getStandardUnitType(system, item)
     pres_r = self.val(input)/10.0
     pres_p = ValueTuple(pres_r, "kPa", "group_pressure")
     pres_u = weewx.units.convert(pres_p, unit_group[0])
     event.packet[item] = pres_u[0]
Пример #12
0
def get_float_t(txt, unit_group):
    if txt is None:
        result = None
    elif isinstance(txt, str):
        if txt.lower() in [NULL, 'none']:
            result = None
    else:
        result = ValueTuple(float(txt[ZERO]), txt[1], unit_group)
    return result
Пример #13
0
 def calc_windGustDir(self, key, data, db_manager):
     # Return the current gust direction if windGust is non-zero, otherwise, None
     if 'windGust' not in data:
         raise weewx.CannotCalculate
     if self.ignore_zero_wind or data['windGust']:
         val = data.get('windGustDir')
     else:
         val = None
     return ValueTuple(val, 'degree_compass', 'group_direction')
Пример #14
0
 def calc_windDir(self, key, data, db_manager):
     # Return the current wind direction if windSpeed is non-zero, otherwise, None
     if 'windSpeed' not in data or 'windDir' not in data:
         raise weewx.CannotCalculate
     if self.force_null and data['windSpeed'] == 0:
         val = None
     else:
         val = data['windDir']
     return ValueTuple(val, 'degree_compass', 'group_direction')
Пример #15
0
    def __getattr__(self, obs_type):
        """Return the trend for the given observation type."""
        # This is to get around bugs in the Python version of Cheetah's namemapper:
        if obs_type in ['__call__', 'has_key']:
            raise AttributeError

        db_manager = self.db_lookup(self.data_binding)
        # Get the current record, and one "time_delta" ago:
        now_record = db_manager.getRecord(self.nowtime, self.time_grace_val)
        then_record = db_manager.getRecord(self.nowtime - self.time_delta_val,
                                           self.time_grace_val)

        # Do both records exist?
        if now_record is None or then_record is None:
            # No. One is missing.
            trend = ValueTuple(None, None, None)
        else:
            # Both records exist. Check to see if the observation type is known
            if obs_type not in now_record or obs_type not in then_record:
                # obs_type is unknown. Signal it
                trend = weewx.units.UnknownType(obs_type)
            else:
                # Both records exist, both types are known. We can proceed.
                now_vt = weewx.units.as_value_tuple(now_record, obs_type)
                then_vt = weewx.units.as_value_tuple(then_record, obs_type)
                # Do the unit conversion now, rather than lazily. This is because the temperature
                # conversion functions are not distributive. That is,
                #     F_to_C(68F - 50F)
                # is not equal to
                #     F_to_C(68F) - F_to_C(50F)
                # We want the latter, not the former, so we perform the conversion immediately.
                now_vtc = self.converter.convert(now_vt)
                then_vtc = self.converter.convert(then_vt)
                if now_vtc.value is None or then_vtc.value is None:
                    # One of the values is None, so the trend will be None.
                    trend = ValueTuple(None, now_vtc.unit, now_vtc.group)
                else:
                    # All good. Calculate the trend.
                    trend = now_vtc - then_vtc

        # Return the results as a ValueHelper. Use the formatting and labeling options from the
        # current time record. The user can always override these.
        return weewx.units.ValueHelper(trend, 'current', self.formatter,
                                       self.converter)
Пример #16
0
    def get_scalar(self, obs_type, record, db_manager):
        # We only know how to calculate 'vapor_p'. For everything else, raise an exception UnknownType
        if obs_type != 'vapor_p':
            raise weewx.UnknownType(obs_type)

        # We need outTemp in order to do the calculation.
        if 'outTemp' not in record or record['outTemp'] is None:
            raise weewx.CannotCalculate(obs_type)

        # We have everything we need. Start by forming a ValueTuple for the outside temperature.
        # To do this, figure out what unit and group the record is in ...
        unit_and_group = weewx.units.getStandardUnitType(
            record['usUnits'], 'outTemp')
        # ... then form the ValueTuple.
        outTemp_vt = ValueTuple(record['outTemp'], *unit_and_group)

        # Both algorithms need temperature in Celsius, so let's make sure our incoming temperature
        # is in that unit. Use function convert(). The results will be in the form of a ValueTuple
        outTemp_C_vt = weewx.units.convert(outTemp_vt, 'degree_C')
        # Get the first element of the ValueTuple. This will be in Celsius:
        outTemp_C = outTemp_C_vt[0]

        if self.algorithm == 'simple':
            # Use the "Simple" algorithm.
            # We need temperature in Kelvin.
            outTemp_K = weewx.units.CtoK(outTemp_C)
            # Now we can use the formula. Results will be in mmHg. Create a ValueTuple out of it:
            p_vt = ValueTuple(math.exp(20.386 - 5132.0 / outTemp_K), 'mmHg',
                              'group_pressure')
        elif self.algorithm == 'tetens':
            # Use Teten's algorithm.
            # Use the formula. Results will be in kPa:
            p_kPa = 0.61078 * math.exp(17.27 * outTemp_C_vt[0] /
                                       (outTemp_C_vt[0] + 237.3))
            # Form a ValueTuple
            p_vt = ValueTuple(p_kPa, 'kPa', 'group_pressure')
        else:
            # Don't recognize the exception. Fail hard:
            raise ValueError(self.algorithm)

        # We have the vapor pressure as a ValueTuple. Convert it back to the units used by
        # the incoming record and return it
        return weewx.units.convertStd(p_vt, record['usUnits'])
Пример #17
0
    def get_scalar(self, obs_type, record, db_manager):
        # We only know how to calculate some sun and moon related stuff. For everything else, raise an exception UnknownType
        if obs_type not in ('sun_altitude', 'sun_azimuth'):
            raise weewx.UnknownType(obs_type)

        # we only report sun values if the sun is above the horizon
        almanac = Almanac(record['dateTime'], self.lat, self.lng,
                          0)  # TODO convert alt  to meters
        sun_altitude = almanac.sun.alt
        if obs_type == 'sun_altitude':
            value = ValueTuple(sun_altitude if sun_altitude >= 0 else None,
                               'degree_compass', 'group_direction')
        elif obs_type == 'sun_azimuth':
            value = ValueTuple(almanac.sun.az if sun_altitude >= 0 else None,
                               'degree_compass', 'group_direction')

        # We have the calculated values as ValueTuples. Convert them back to the units used by
        # the incoming record and return it
        return weewx.units.convertStd(value, record['usUnits'])
Пример #18
0
    def __getattr__(self, obs_type):
        """Return the trend for the given observation type."""
        # This is to get around bugs in the Python version of Cheetah's namemapper:
        if obs_type in ['__call__', 'has_key']:
            raise AttributeError

        db_manager = self.db_lookup(self.data_binding)
        # Get the current record, and one "time_delta" ago:
        now_record = db_manager.getRecord(self.nowtime, self.time_grace_val)
        then_record = db_manager.getRecord(self.nowtime - self.time_delta_val,
                                           self.time_grace_val)

        # Do both records exist?
        if now_record is None or then_record is None:
            # No. One is missing.
            trend = ValueTuple(None, None, None)
        else:
            # Both records exist.
            # Check to see if the observation type is known
            if obs_type not in now_record or obs_type not in then_record:
                # obs_type is unknown. Signal it
                trend = weewx.units.UnknownType(obs_type)
            else:
                now_vt = weewx.units.as_value_tuple(now_record, obs_type)
                then_vt = weewx.units.as_value_tuple(then_record, obs_type)
                # Do the unit conversion now, rather than lazily. This is because,
                # in the case of temperature, the difference between two converted
                # values is not the same as the conversion of the difference
                # between two values. E.g., 20C - 10C is not equal to
                # F_to_C(68F - 50F). We want the former, not the latter.
                now_vtc = self.converter.convert(now_vt)
                then_vtc = self.converter.convert(then_vt)
                if now_vtc.value is None or then_vtc.value is None:
                    trend = ValueTuple(None, now_vtc.unit, now_vtc.group)
                else:
                    trend = now_vtc - then_vtc

        # Return the results as a ValueHelper. Use the formatting and labeling
        # options from the current time record. The user can always override
        # these.
        return weewx.units.ValueHelper(trend, 'current', self.formatter,
                                       self.converter)
Пример #19
0
 def calc_beaufort(key, data, db_manager=None):
     global first_time
     if first_time:
         print("Type beaufort has been deprecated. Use unit beaufort instead.")
         log.info("Type beaufort has been deprecated. Use unit beaufort instead.")
         first_time = False
     if 'windSpeed' not in data:
         raise weewx.CannotCalculate
     windspeed_vt = weewx.units.as_value_tuple(data, 'windSpeed')
     windspeed_kn = weewx.units.convert(windspeed_vt, 'knot')[0]
     return ValueTuple(weewx.wxformulas.beaufort(windspeed_kn), None, None)
Пример #20
0
    def get_scalar(self, obs_type, record, db_manager):
        # We only know how to calculate 'makkink'. For everything else, raise an exception UnknownType
        if obs_type != 'makkink':
            raise weewx.UnknownType(obs_type)

        # We need outTemp and the radiation in order to do the calculation.
        if 'outTemp' not in record or record['outTemp'] is None:
            raise weewx.CannotCalculate(obs_type)
        if 'radiation' not in record or record['radiation'] is None:
            raise weewx.CannotCalculate(obs_type)

        # We have everything we need. Start by forming a ValueTuple for the outside temperature.
        # To do this, figure out what unit and group the record is in ...
        unit_and_group = weewx.units.getStandardUnitType(
            record['usUnits'], 'outTemp')
        # ... then form the ValueTuple.
        outTemp_vt = ValueTuple(record['outTemp'], *unit_and_group)

        # same for radiation
        unit_and_group = weewx.units.getStandardUnitType(
            record['usUnits'], 'radiation')
        # ... then form the ValueTuple.
        radiation_vt = ValueTuple(record['radiation'], *unit_and_group)

        outTemp_C_vt = weewx.units.convert(outTemp_vt, 'degree_C')
        # Get the first element of the ValueTuple. This will be in Celsius:
        T = outTemp_C_vt[0]

        # just to make sure nothing fancy happens we do this for radiation as well
        # even though this is W/m2 in us as well as metric
        radiation_Wm2_vt = weewx.units.convert(radiation_vt,
                                               'watt_per_meter_squared')
        Kin = radiation_Wm2_vt[0]

        makkink = ValueTuple(
            self.Eref(T, Kin) * 3600, 'mm_per_hour',
            'group_rainrate')  # convert from kg/m2*s --> mm/hour

        # Convert it back to the units used by
        # the incoming record and return it
        return weewx.units.convertStd(makkink, record['usUnits'])
Пример #21
0
 def calc_humidex(key, data, db_manager=None):
     if 'outTemp' not in data or 'outHumidity' not in data:
         raise weewx.CannotCalculate(key)
     if data['usUnits'] == weewx.US:
         val = weewx.wxformulas.humidexF(data['outTemp'],
                                         data['outHumidity'])
         u = 'degree_F'
     else:
         val = weewx.wxformulas.humidexC(data['outTemp'],
                                         data['outHumidity'])
         u = 'degree_C'
     return ValueTuple(val, u, 'group_temperature')
Пример #22
0
 def calc_maxSolarRad(self, key, data, db_manager):
     altitude_m = weewx.units.convert(self.altitude_vt, 'meter')[0]
     if self.maxSolarRad_algo == 'bras':
         val = weewx.wxformulas.solar_rad_Bras(self.latitude_f, self.longitude_f, altitude_m,
                                               data['dateTime'], self.nfac)
     elif self.maxSolarRad_algo == 'rs':
         val = weewx.wxformulas.solar_rad_RS(self.latitude_f, self.longitude_f, altitude_m,
                                             data['dateTime'], self.atc)
     else:
         raise weewx.ViolatedPrecondition("Unknown solar algorithm '%s'"
                                          % self.maxSolarRad_algo)
     return ValueTuple(val, 'watt_per_meter_squared', 'group_radiation')
Пример #23
0
 def calc_inDewpoint(key, data, db_manager=None):
     if 'inTemp' not in data or 'inHumidity' not in data:
         raise weewx.CannotCalculate(key)
     if data['usUnits'] == weewx.US:
         val = weewx.wxformulas.dewpointF(data['inTemp'],
                                          data['inHumidity'])
         u = 'degree_F'
     else:
         val = weewx.wxformulas.dewpointC(data['inTemp'],
                                          data['inHumidity'])
         u = 'degree_C'
     return ValueTuple(val, u, 'group_temperature')
Пример #24
0
    def get_extension_list(self, timespan, db_lookup):
        """ Returns various tags.
          Returns:
          Easter:         A ValueHelper containing the date of the next Easter
                          Sunday. The time represented is midnight at the start
                          of Easter Sunday.
        """

        #
        # Easter. Calculate date for Easter Sunday this year
        #
        def calc_easter(year):
            """Calculate Easter date.
            Uses a modified version of Butcher's Algorithm.
            Refer New Scientist, 30 March 1961 pp 828-829
            https://books.google.co.uk/books?id=zfzhCoOHurwC&printsec=frontcover&source=gbs_ge_summary_r&cad=0#v=onepage&q&f=false
            """

            a = year % 19
            b = year // 100
            c = year % 100
            d = b // 4
            e = b % 4
            g = (8 * b + 13) // 25
            h = (19 * a + b - d - g + 15) % 30
            i = c // 4
            k = c % 4
            l = (2 * e + 2 * i - h - k + 32) % 7
            m = (a + 11 * h + 19 * l) // 433
            n = (h + l - 7 * m + 90) // 25
            p = (h + l - 7 * m + 33 * n + 19) % 32
            _dt = datetime.datetime(year=year, month=n, day=p)
            _ts = time.mktime(_dt.timetuple())
            return _ts

        _year = date.today().year
        easter_ts = calc_easter(_year)
        # check to see if we have past this calculated date, if so we want next
        # years date so increment year and recalculate
        if date.fromtimestamp(easter_ts) < date.today():
            easter_ts = calc_easter(_year + 1)
        easter_vt = ValueTuple(easter_ts, 'unix_epoch', 'group_time')
        easter_vh = ValueHelper(easter_vt,
                                formatter=self.generator.formatter,
                                converter=self.generator.converter)

        # Create a small dictionary with the tag names (keys) we want to use
        search_list_extension = {
            'Easter': easter_vh,
        }

        return [search_list_extension]
Пример #25
0
        def time_at(expression):
            """When an sql expression evaluated true"""
            db_manager = db_lookup()
            sql_stmt = "SELECT dateTime FROM %s WHERE %s AND dateTime <= %d ORDER BY dateTime DESC LIMIT 1" \
                       % (db_manager.table_name, expression, timespan.stop)

            row = db_manager.getSql(sql_stmt)
            val = row[0] if row else None
            vt = ValueTuple(val, 'unix_epoch', 'group_time')
            vh = ValueHelper(vt,
                             formatter=self.generator.formatter,
                             converter=self.generator.converter)
            return vh
Пример #26
0
 def calc_cloudbase(self, key, data, db_manager):
     if 'outTemp' not in data or 'outHumidity' not in data:
         raise weewx.CannotCalculate(key)
     # Convert altitude to the same unit system as the incoming record
     altitude = weewx.units.convertStd(self.altitude_vt, data['usUnits'])
     # Use the appropriate formula
     if data['usUnits'] == weewx.US:
         formula = weewx.wxformulas.cloudbase_US
         u = 'foot'
     else:
         formula = weewx.wxformulas.cloudbase_Metric
         u = 'meter'
     val = formula(data['outTemp'], data['outHumidity'], altitude[0])
     return ValueTuple(val, u, 'group_altitude')
Пример #27
0
        def time_since(expression):
            """Time since a sql expression evaluted true"""
            db_manager = db_lookup()
            sql_stmt = "SELECT dateTime FROM %s WHERE %s AND dateTime <= %d ORDER BY dateTime DESC LIMIT 1" \
                       % (db_manager.table_name, expression, timespan.stop)

            row = db_manager.getSql(sql_stmt)
            val = timespan.stop - row[0] if row else None
            vt = ValueTuple(val, 'second', 'group_deltatime')
            vh = ValueHelper(vt,
                             context="long_delta",
                             formatter=self.generator.formatter,
                             converter=self.generator.converter)
            return vh
Пример #28
0
 def zip_vectors(self):
     size = len(self.vectors['date'][ZERO])
     result = []
     while size:
         result.append({})
         size -= 1
     for key in [
             'date',
             'daily_max',
             'daily_min',
             'dd',
             'dd_cumulative',
     ]:
         (vals, units, unit_group) = self.vectors[key]
         for (ndx, val) in enumerate(vals):
             val_t = ValueTuple(val, units, unit_group)
             result[ndx][key] = weewx.units.ValueHelper(
                 val_t, 'day', self.formatter, self.converter)
     horizon_labels = [(cumulative_dd, horizon_label)
                       for ((cumulative_dd, dd_units, dd_group),
                            horizon_label) in self.plot.horizons]
     horizon_labels.sort()
     for rec in result:
         remarks = []
         while horizon_labels:
             (horizon_dd, horizon_event) = horizon_labels[ZERO]
             cydia_a = rec['dd_cumulative'].raw
             if cydia_a > horizon_dd:
                 remarks.append(horizon_event)
                 horizon_labels.pop(ZERO)
             else:
                 break
         val_t = ValueTuple('; '.join(remarks), None, None)
         rec['remark'] = weewx.units.ValueHelper(val_t, 'day',
                                                 self.formatter,
                                                 self.converter)
     return result
Пример #29
0
    def get_scalar(self, key, record, db_manager):
        """Calculate the rainRate"""
        if key != 'rainRate':
            raise weewx.UnknownType(key)

        if self.rain_events is None:
            self._setup(record['dateTime'], db_manager)

        # Sum the rain events within the time window...
        rainsum = sum(x[1] for x in self.rain_events
                      if x[0] > record['dateTime'] - self.rain_period)
        # ...then divide by the period and scale to an hour
        val = 3600 * rainsum / self.rain_period
        u, g = weewx.units.getStandardUnitType(record['usUnits'], 'rainRate')
        return ValueTuple(val, u, g)
Пример #30
0
    def testVT(self):
        a=ValueTuple(68.0, "degree_F", "group_temperature")
        b=ValueTuple(18.0, "degree_F", "group_temperature")
        c=ValueTuple(None, "degree_F", "group_temperature")
        d=ValueTuple(1020.0, "mbar", "group_pressure")

        self.assertEqual(a + b, ValueTuple(86.0, "degree_F", "group_temperature"))
        self.assertEqual(a - b, ValueTuple(50.0, "degree_F", "group_temperature"))
        self.assertRaises(TypeError, operator.add, a, c)
        self.assertRaises(TypeError, operator.add, a, d)