diff --git a/peas/weather.py b/peas/weather.py index 6044cf382..a21dd0e48 100755 --- a/peas/weather.py +++ b/peas/weather.py @@ -18,9 +18,9 @@ from .PID import PID -def get_mongodb(): +def get_db(db_type='file'): from pocs.utils.database import PanDB - return PanDB() + return PanDB(db_type=db_type) def movingaverage(interval, window_size): @@ -101,7 +101,7 @@ class AAGCloudSensor(object): """ - def __init__(self, serial_address=None, store_result=True): + def __init__(self, serial_address=None, store_result=True, db_type='file'): self.config = load_config(config_files='peas') self.logger = get_root_logger() @@ -112,7 +112,7 @@ def __init__(self, serial_address=None, store_result=True): self.db = None if store_result: - self.db = get_mongodb() + self.db = get_db(db_type=db_type) self.messaging = None @@ -249,18 +249,6 @@ def __init__(self, serial_address=None, store_result=True): self.logger.warning(' Failed to get Serial Number') sys.exit(1) - def get_reading(self): - """ Calls commands to be performed each time through the loop """ - weather_data = dict() - - if self.db is None: - self.db = get_mongodb() - else: - weather_data = self.update_weather() - self.calculate_and_set_PWM() - - return weather_data - def send(self, send, delay=0.100): found_command = False @@ -606,7 +594,12 @@ def get_wind_speed(self, n=3): def send_message(self, msg, topic='weather'): if self.messaging is None: - self.messaging = PanMessaging.create_publisher(6510) + try: + msg_port = self.config['messaging']['msg_port'] + except KeyError: + return + + self.messaging = PanMessaging.create_publisher(msg_port) self.messaging.send_message(topic, msg) diff --git a/scripts/plot_weather.py b/scripts/plot_weather.py index ec405c176..15084c4a7 100755 --- a/scripts/plot_weather.py +++ b/scripts/plot_weather.py @@ -1,31 +1,35 @@ #!/usr/bin/env python3 -import numpy as np import os -import pandas as pd import sys import warnings from datetime import datetime as dt from datetime import timedelta as tdelta +from dateutil.parser import parse as date_parser -from astropy.table import Table -from astropy.time import Time - -from astroplan import Observer -from astropy.coordinates import EarthLocation - -from pocs.utils.config import load_config -from pocs.utils import serializers as json_util +import numpy as np +import pandas as pd +from pandas.plotting import register_matplotlib_converters -import matplotlib as mpl -mpl.use('Agg') from matplotlib import pyplot as plt from matplotlib.dates import DateFormatter from matplotlib.dates import HourLocator from matplotlib.dates import MinuteLocator from matplotlib.ticker import FormatStrFormatter from matplotlib.ticker import MultipleLocator + +from astropy.table import Table +from astropy.time import Time + +from pocs.utils.config import load_config +from pocs.utils.logger import get_root_logger +from pocs.utils import serializers as json_util +from pocs.utils.location import create_location_from_config + +logger = get_root_logger() + +register_matplotlib_converters() plt.ioff() plt.style.use('classic') @@ -43,9 +47,8 @@ def __init__(self, date_string=None, data_file=None, *args, **kwargs): self.args = args self.kwargs = kwargs - config = load_config(config_files=['peas']) + config = load_config(config_files=['pocs', 'peas']) self.cfg = config['weather']['plot'] - location_cfg = config.get('location', None) self.thresholds = config['weather'].get('aag_cloud', None) @@ -60,41 +63,45 @@ def __init__(self, date_string=None, data_file=None, *args, **kwargs): else: self.today = False - self.date = dt.strptime('{} 23:59:59'.format(date_string), - '%Y%m%dUT %H:%M:%S') + self.date = date_parser(f'{date_string} 23:59:59') self.date_string = date_string self.start = dt(self.date.year, self.date.month, self.date.day, 0, 0, 0, 0) self.end = dt(self.date.year, self.date.month, self.date.day, 23, 59, 59, 0) - print('Creating weather plotter for {}'.format(self.date_string)) + logger.info(f'Creating weather plotter for {self.date_string}') - self.twilights = self.get_twilights(location_cfg) + self.location = create_location_from_config(config) + self.twilights = self.get_twilights() self.table = self.get_table_data(data_file) + logger.debug(f'Found {len(self.table)} weather entries.') + + # Filter by date + logger.debug(f'Filtering table rows for {self.date_string}') + self.table = self.table.loc[self.start:self.end] if self.table is None: warnings.warn("No data") sys.exit(0) - self.time = pd.to_datetime(self.table['date']) - first = self.time[0].isoformat() - last = self.time[-1].isoformat() - print(' Retrieved {} entries between {} and {}'.format( - len(self.table), first, last)) - - if self.today: - self.current_values = self.table[-1] - else: - self.current_values = None + self.time = self.table.index + self.date_format = '%Y-%m-%d %H:%m:%S' + first = f'{self.time[0]:{self.date_format}}' + last = f'{self.time[-1]:{self.date_format}}' + logger.debug(f'Retrieved {len(self.table)} entries between {first} and {last}') def make_plot(self, output_file=None): # ------------------------------------------------------------------------- # Plot a day's weather # ------------------------------------------------------------------------- - print(' Setting up plot for time range: {} to {}'.format( - self.start.isoformat(), self.end.isoformat())) + start_time = f'{self.start:{self.date_format}}' + end_time = f'{self.end:{self.date_format}}' + + logger.debug(f'Setting up plot for time range: {start_time} to {end_time}') if self.today: - print(' Will generate last hour plot for time range: {} to {}'.format( - self.lhstart.isoformat(), self.lhend.isoformat())) + start_hour = f'{self.lhstart:{self.date_format}}' + end_hour = f'{self.lhend:{self.date_format}}' + logger.debug(f'Will generate last hour plot: {start_hour} to {end_hour}') + self.dpi = self.kwargs.get('dpi', 72) self.fig = plt.figure(figsize=(20, 12), dpi=self.dpi) # self.axes = plt.gca() @@ -116,6 +123,8 @@ def make_plot(self, output_file=None): self.plot_safety_vs_time() self.plot_pwm_vs_time() self.save_plot(plot_filename=output_file) + # Close all figures to free memory. + plt.close('all') def get_table_data(self, data_file): """ Get the table data @@ -142,23 +151,26 @@ def get_table_data(self, data_file): weather_entries = list() with open(data_file) as df: for entry in df: - rec0 = json_util.loads(entry) - weather_entries.append({**rec0['data']}) + try: + rec0 = json_util.loads(entry) + weather_entries.append({**rec0['data']}) + except Exception: + # Skip invalid entries. + pass table = pd.DataFrame(weather_entries) # Fix bad dtype conversion table.rain_sensor_temp_C = pd.to_numeric(table.rain_sensor_temp_C) - table = Table.from_pandas(table) else: - table = Table.from_pandas(pd.read_csv(data_file, parse_dates=True)) + table = pd.read_csv(data_file, parse_dates=True) else: # ------------------------------------------------------------------------- # Grab data from Mongo # ------------------------------------------------------------------------- import pymongo - from pocs.utils.database import PanDB + from panoptes.utils.database import PanDB - print(' Retrieving data from Mongo database') + logger.debug('Retrieving data from Mongo database') db = PanDB() entries = [x for x in db.weather.find( {'date': {'$gt': self.start, '$lt': self.end}}).sort([ @@ -176,24 +188,14 @@ def get_table_data(self, data_file): table.add_row(data) - table.sort('date') + table.index = pd.to_datetime(table['date']) return table - def get_twilights(self, config=None): + def get_twilights(self): """ Determine sunrise and sunset times """ - print(' Determining sunrise, sunset, and twilight times') - - if config is None: - from pocs.utils.config import load_config as pocs_config - config = pocs_config()['location'] + logger.debug('Determining sunrise, sunset, and twilight times') - location = EarthLocation( - lat=config['latitude'], - lon=config['longitude'], - height=config['elevation'], - ) - obs = Observer(location=location, name='PANOPTES', - timezone=config['timezone']) + obs = self.location['observer'] sunset = obs.sun_set_time(Time(self.start), which='next').datetime sunrise = obs.sun_rise_time(Time(self.start), which='next').datetime @@ -225,28 +227,27 @@ def get_twilights(self, config=None): def plot_ambient_vs_time(self): """ Ambient Temperature vs Time """ - print('Plot Ambient Temperature vs. Time') + logger.debug('Plot Ambient Temperature vs. Time') - t_axes = plt.axes(self.plot_positions[0][0]) + t_axes = self.fig.add_axes(self.plot_positions[0][0]) if self.today: time_title = self.date else: time_title = self.end - plt.title('Weather for {} at {}'.format(self.date_string, - time_title.strftime('%H:%M:%S UT'))) + t_axes.set_title(f'Weather for {self.date_string} at {time_title:%H:%M:%S}') amb_temp = self.table['ambient_temp_C'] - plt.plot_date(self.time, amb_temp, 'ko', - markersize=2, markeredgewidth=0, drawstyle="default") + t_axes.plot_date(self.time, amb_temp, 'ko', + markersize=2, markeredgewidth=0, drawstyle="default") try: max_temp = max(amb_temp) min_temp = min(amb_temp) label_time = self.end - tdelta(0, 6 * 60 * 60) label_temp = label_pos(self.cfg['amb_temp_limits']) - plt.annotate('Low: {:4.1f} $^\circ$C, High: {:4.1f} $^\circ$C'.format( + t_axes.annotate('Low: {:4.1f} $^\circ$C, High: {:4.1f} $^\circ$C'.format( min_temp, max_temp), xy=(label_time, max_temp), xytext=(label_time, label_temp), @@ -255,27 +256,27 @@ def plot_ambient_vs_time(self): except Exception: pass - plt.ylabel("Ambient Temp. (C)") - plt.grid(which='major', color='k') - plt.yticks(range(-100, 100, 10)) - plt.xlim(self.start, self.end) - plt.ylim(self.cfg['amb_temp_limits']) + t_axes.set_ylabel("Ambient Temp. (C)") + t_axes.grid(which='major', color='k') + t_axes.set_yticks(range(-100, 100, 10)) + t_axes.set_xlim(self.start, self.end) + t_axes.set_ylim(self.cfg['amb_temp_limits']) t_axes.xaxis.set_major_locator(self.hours) t_axes.xaxis.set_major_formatter(self.hours_fmt) for i, twi in enumerate(self.twilights): if i > 0: - plt.axvspan(self.twilights[i - 1][0], self.twilights[i][0], - ymin=0, ymax=1, color='blue', alpha=twi[2]) + t_axes.axvspan(self.twilights[i - 1][0], self.twilights[i][0], + ymin=0, ymax=1, color='blue', alpha=twi[2]) if self.today: - tlh_axes = plt.axes(self.plot_positions[0][1]) - plt.title('Last Hour') - plt.plot_date(self.time, amb_temp, 'ko', - markersize=4, markeredgewidth=0, - drawstyle="default") - plt.plot_date([self.date, self.date], self.cfg['amb_temp_limits'], - 'g-', alpha=0.4) + tlh_axes = self.fig.add_axes(self.plot_positions[0][1]) + tlh_axes.set_title('Last Hour') + tlh_axes.plot_date(self.time, amb_temp, 'ko', + markersize=4, markeredgewidth=0, + drawstyle="default") + tlh_axes.plot_date([self.date, self.date], self.cfg['amb_temp_limits'], + 'g-', alpha=0.4) try: current_amb_temp = self.current_values['data']['ambient_temp_C'] current_time = self.current_values['date'] @@ -289,18 +290,18 @@ def plot_ambient_vs_time(self): except Exception: pass - plt.grid(which='major', color='k') - plt.yticks(range(-100, 100, 10)) + tlh_axes.grid(which='major', color='k') + tlh_axes.set_yticks(range(-100, 100, 10)) tlh_axes.xaxis.set_major_locator(self.mins) tlh_axes.xaxis.set_major_formatter(self.mins_fmt) tlh_axes.yaxis.set_ticklabels([]) - plt.xlim(self.lhstart, self.lhend) - plt.ylim(self.cfg['amb_temp_limits']) + tlh_axes.set_xlim(self.lhstart, self.lhend) + tlh_axes.set_ylim(self.cfg['amb_temp_limits']) def plot_cloudiness_vs_time(self): """ Cloudiness vs Time """ - print('Plot Temperature Difference vs. Time') - td_axes = plt.axes(self.plot_positions[1][0]) + logger.debug('Plot Temperature Difference vs. Time') + td_axes = self.fig.add_axes(self.plot_positions[1][0]) sky_temp_C = self.table['sky_temp_C'] ambient_temp_C = self.table['ambient_temp_C'] @@ -308,55 +309,55 @@ def plot_cloudiness_vs_time(self): temp_diff = np.array(sky_temp_C) - np.array(ambient_temp_C) - plt.plot_date(self.time, temp_diff, 'ko-', label='Cloudiness', - markersize=2, markeredgewidth=0, - drawstyle="default") + td_axes.plot_date(self.time, temp_diff, 'ko-', label='Cloudiness', + markersize=2, markeredgewidth=0, + drawstyle="default") - wclear = [(x.strip() == 'Clear') for x in sky_condition.data] - plt.fill_between(self.time, -60, temp_diff, where=wclear, color='green', alpha=0.5) + wclear = [(x.strip() == 'Clear') for x in sky_condition] + td_axes.fill_between(self.time, -60, temp_diff, where=wclear, color='green', alpha=0.5) - wcloudy = [(x.strip() == 'Cloudy') for x in sky_condition.data] - plt.fill_between(self.time, -60, temp_diff, where=wcloudy, color='yellow', alpha=0.5) + wcloudy = [(x.strip() == 'Cloudy') for x in sky_condition] + td_axes.fill_between(self.time, -60, temp_diff, where=wcloudy, color='yellow', alpha=0.5) - wvcloudy = [(x.strip() == 'Very Cloudy') for x in sky_condition.data] - plt.fill_between(self.time, -60, temp_diff, where=wvcloudy, color='red', alpha=0.5) + wvcloudy = [(x.strip() == 'Very Cloudy') for x in sky_condition] + td_axes.fill_between(self.time, -60, temp_diff, where=wvcloudy, color='red', alpha=0.5) if self.thresholds: st = self.thresholds.get('threshold_very_cloudy', None) if st: - plt.plot_date([self.start, self.end], [st, st], 'r-', - markersize=2, markeredgewidth=0, alpha=0.3, - drawstyle="default") - - plt.ylabel("Cloudiness") - plt.grid(which='major', color='k') - plt.yticks(range(-100, 100, 10)) - plt.xlim(self.start, self.end) - plt.ylim(self.cfg['cloudiness_limits']) + td_axes.plot_date([self.start, self.end], [st, st], 'r-', + markersize=2, markeredgewidth=0, alpha=0.3, + drawstyle="default") + + td_axes.set_ylabel("Cloudiness") + td_axes.grid(which='major', color='k') + td_axes.set_yticks(range(-100, 100, 10)) + td_axes.set_xlim(self.start, self.end) + td_axes.set_ylim(self.cfg['cloudiness_limits']) td_axes.xaxis.set_major_locator(self.hours) td_axes.xaxis.set_major_formatter(self.hours_fmt) td_axes.xaxis.set_ticklabels([]) if self.today: - tdlh_axes = plt.axes(self.plot_positions[1][1]) + tdlh_axes = self.fig.add_axes(self.plot_positions[1][1]) tdlh_axes.plot_date(self.time, temp_diff, 'ko-', label='Cloudiness', markersize=4, markeredgewidth=0, drawstyle="default") - plt.fill_between(self.time, -60, temp_diff, where=wclear, - color='green', alpha=0.5) - plt.fill_between(self.time, -60, temp_diff, where=wcloudy, - color='yellow', alpha=0.5) - plt.fill_between(self.time, -60, temp_diff, where=wvcloudy, - color='red', alpha=0.5) - plt.plot_date([self.date, self.date], self.cfg['cloudiness_limits'], - 'g-', alpha=0.4) + tdlh_axes.fill_between(self.time, -60, temp_diff, where=wclear, + color='green', alpha=0.5) + tdlh_axes.fill_between(self.time, -60, temp_diff, where=wcloudy, + color='yellow', alpha=0.5) + tdlh_axes.fill_between(self.time, -60, temp_diff, where=wvcloudy, + color='red', alpha=0.5) + tdlh_axes.plot_date([self.date, self.date], self.cfg['cloudiness_limits'], + 'g-', alpha=0.4) if self.thresholds: st = self.thresholds.get('threshold_very_cloudy', None) if st: - plt.plot_date([self.start, self.end], [st, st], 'r-', - markersize=2, markeredgewidth=0, alpha=0.3, - drawstyle="default") + tdlh_axes.plot_date([self.start, self.end], [st, st], 'r-', + markersize=2, markeredgewidth=0, alpha=0.3, + drawstyle="default") try: current_cloudiness = self.current_values['data']['sky_condition'] @@ -371,10 +372,10 @@ def plot_cloudiness_vs_time(self): except Exception: pass - plt.grid(which='major', color='k') - plt.yticks(range(-100, 100, 10)) - plt.ylim(self.cfg['cloudiness_limits']) - plt.xlim(self.lhstart, self.lhend) + tdlh_axes.grid(which='major', color='k') + tdlh_axes.set_yticks(range(-100, 100, 10)) + tdlh_axes.set_ylim(self.cfg['cloudiness_limits']) + tdlh_axes.set_xlim(self.lhstart, self.lhend) tdlh_axes.xaxis.set_major_locator(self.mins) tdlh_axes.xaxis.set_major_formatter(self.mins_fmt) tdlh_axes.xaxis.set_ticklabels([]) @@ -382,8 +383,8 @@ def plot_cloudiness_vs_time(self): def plot_windspeed_vs_time(self): """ Windspeed vs Time """ - print('Plot Wind Speed vs. Time') - w_axes = plt.axes(self.plot_positions[2][0]) + logger.debug('Plot Wind Speed vs. Time') + w_axes = self.fig.add_axes(self.plot_positions[2][0]) wind_speed = self.table['wind_speed_KPH'] wind_mavg = moving_average(wind_speed, 9) @@ -399,27 +400,27 @@ def plot_windspeed_vs_time(self): linewidth=3, alpha=0.5, drawstyle="default") w_axes.plot_date([self.start, self.end], [0, 0], 'k-', ms=1) - wcalm = [(x.strip() == 'Calm') for x in wind_condition.data] + wcalm = [(x.strip() == 'Calm') for x in wind_condition] w_axes.fill_between(self.time, -5, wind_speed, where=wcalm, color='green', alpha=0.5) - wwindy = [(x.strip() == 'Windy') for x in wind_condition.data] + wwindy = [(x.strip() == 'Windy') for x in wind_condition] w_axes.fill_between(self.time, -5, wind_speed, where=wwindy, color='yellow', alpha=0.5) - wvwindy = [(x.strip() == 'Very Windy') for x in wind_condition.data] + wvwindy = [(x.strip() == 'Very Windy') for x in wind_condition] w_axes.fill_between(self.time, -5, wind_speed, where=wvwindy, color='red', alpha=0.5) if self.thresholds: st = self.thresholds.get('threshold_very_windy', None) if st: - plt.plot_date([self.start, self.end], [st, st], 'r-', - markersize=2, markeredgewidth=0, alpha=0.3, - drawstyle="default") + w_axes.plot_date([self.start, self.end], [st, st], 'r-', + markersize=2, markeredgewidth=0, alpha=0.3, + drawstyle="default") st = self.thresholds.get('threshold_very_gusty', None) if st: - plt.plot_date([self.start, self.end], [st, st], 'r-', - markersize=2, markeredgewidth=0, alpha=0.3, - drawstyle="default") + w_axes.plot_date([self.start, self.end], [st, st], 'r-', + markersize=2, markeredgewidth=0, alpha=0.3, + drawstyle="default") try: max_wind = max(wind_speed) @@ -432,12 +433,12 @@ def plot_windspeed_vs_time(self): ) except Exception: pass - plt.ylabel("Wind (km/h)") - plt.grid(which='major', color='k') -# plt.yticks(range(0, 200, 10)) + w_axes.set_ylabel("Wind (km/h)") + w_axes.grid(which='major', color='k') +# w_axes.yticks(range(0, 200, 10)) - plt.xlim(self.start, self.end) - plt.ylim(self.cfg['wind_limits']) + w_axes.set_xlim(self.start, self.end) + w_axes.set_ylim(self.cfg['wind_limits']) w_axes.xaxis.set_major_locator(self.hours) w_axes.xaxis.set_major_formatter(self.hours_fmt) w_axes.xaxis.set_ticklabels([]) @@ -446,7 +447,7 @@ def plot_windspeed_vs_time(self): w_axes.yaxis.set_minor_locator(MultipleLocator(10)) if self.today: - wlh_axes = plt.axes(self.plot_positions[2][1]) + wlh_axes = self.fig.add_axes(self.plot_positions[2][1]) wlh_axes.plot_date(self.time, wind_speed, 'ko', alpha=0.7, markersize=4, markeredgewidth=0, drawstyle="default") @@ -462,20 +463,20 @@ def plot_windspeed_vs_time(self): color='yellow', alpha=0.5) wlh_axes.fill_between(self.time, -5, wind_speed, where=wvwindy, color='red', alpha=0.5) - plt.plot_date([self.date, self.date], self.cfg['wind_limits'], - 'g-', alpha=0.4) + wlh_axes.plot_date([self.date, self.date], self.cfg['wind_limits'], + 'g-', alpha=0.4) if self.thresholds: st = self.thresholds.get('threshold_very_windy', None) if st: - plt.plot_date([self.start, self.end], [st, st], 'r-', - markersize=2, markeredgewidth=0, alpha=0.3, - drawstyle="default") + wlh_axes.plot_date([self.start, self.end], [st, st], 'r-', + markersize=2, markeredgewidth=0, alpha=0.3, + drawstyle="default") st = self.thresholds.get('threshold_very_gusty', None) if st: - plt.plot_date([self.start, self.end], [st, st], 'r-', - markersize=2, markeredgewidth=0, alpha=0.3, - drawstyle="default") + wlh_axes.plot_date([self.start, self.end], [st, st], 'r-', + markersize=2, markeredgewidth=0, alpha=0.3, + drawstyle="default") try: current_wind = self.current_values['data']['wind_speed_KPH'] @@ -489,10 +490,10 @@ def plot_windspeed_vs_time(self): ) except Exception: pass - plt.grid(which='major', color='k') -# plt.yticks(range(0, 200, 10)) - plt.xlim(self.lhstart, self.lhend) - plt.ylim(self.cfg['wind_limits']) + wlh_axes.grid(which='major', color='k') +# wlh_axes.yticks(range(0, 200, 10)) + wlh_axes.set_xlim(self.lhstart, self.lhend) + wlh_axes.set_ylim(self.cfg['wind_limits']) wlh_axes.xaxis.set_major_locator(self.mins) wlh_axes.xaxis.set_major_formatter(self.mins_fmt) wlh_axes.xaxis.set_ticklabels([]) @@ -504,8 +505,8 @@ def plot_windspeed_vs_time(self): def plot_rain_freq_vs_time(self): """ Rain Frequency vs Time """ - print('Plot Rain Frequency vs. Time') - rf_axes = plt.axes(self.plot_positions[3][0]) + logger.debug('Plot Rain Frequency vs. Time') + rf_axes = self.fig.add_axes(self.plot_positions[3][0]) rf_value = self.table['rain_frequency'] rain_condition = self.table['rain_condition'] @@ -514,33 +515,33 @@ def plot_rain_freq_vs_time(self): markersize=2, markeredgewidth=0, drawstyle="default") - wdry = [(x.strip() == 'Dry') for x in rain_condition.data] + wdry = [(x.strip() == 'Dry') for x in rain_condition] rf_axes.fill_between(self.time, 0, rf_value, where=wdry, color='green', alpha=0.5) - wwet = [(x.strip() == 'Wet') for x in rain_condition.data] + wwet = [(x.strip() == 'Wet') for x in rain_condition] rf_axes.fill_between(self.time, 0, rf_value, where=wwet, color='orange', alpha=0.5) - wrain = [(x.strip() == 'Rain') for x in rain_condition.data] + wrain = [(x.strip() == 'Rain') for x in rain_condition] rf_axes.fill_between(self.time, 0, rf_value, where=wrain, color='red', alpha=0.5) if self.thresholds: st = self.thresholds.get('threshold_wet', None) if st: - plt.plot_date([self.start, self.end], [st, st], 'r-', - markersize=2, markeredgewidth=0, alpha=0.3, - drawstyle="default") - - plt.ylabel("Rain Sensor") - plt.grid(which='major', color='k') - plt.ylim(self.cfg['rain_limits']) - plt.xlim(self.start, self.end) + rf_axes.plot_date([self.start, self.end], [st, st], 'r-', + markersize=2, markeredgewidth=0, alpha=0.3, + drawstyle="default") + + rf_axes.set_ylabel("Rain Sensor") + rf_axes.grid(which='major', color='k') + rf_axes.set_ylim(self.cfg['rain_limits']) + rf_axes.set_xlim(self.start, self.end) rf_axes.xaxis.set_major_locator(self.hours) rf_axes.xaxis.set_major_formatter(self.hours_fmt) rf_axes.xaxis.set_ticklabels([]) if self.today: - rflh_axes = plt.axes(self.plot_positions[3][1]) + rflh_axes = self.fig.add_axes(self.plot_positions[3][1]) rflh_axes.plot_date(self.time, rf_value, 'ko-', label='Rain', markersize=4, markeredgewidth=0, drawstyle="default") @@ -550,12 +551,12 @@ def plot_rain_freq_vs_time(self): color='orange', alpha=0.5) rflh_axes.fill_between(self.time, 0, rf_value, where=wrain, color='red', alpha=0.5) - plt.plot_date([self.date, self.date], self.cfg['rain_limits'], - 'g-', alpha=0.4) + rflh_axes.plot_date([self.date, self.date], self.cfg['rain_limits'], + 'g-', alpha=0.4) if st: - plt.plot_date([self.start, self.end], [st, st], 'r-', - markersize=2, markeredgewidth=0, alpha=0.3, - drawstyle="default") + rflh_axes.plot_date([self.start, self.end], [st, st], 'r-', + markersize=2, markeredgewidth=0, alpha=0.3, + drawstyle="default") try: current_rain = self.current_values['data']['rain_condition'] @@ -569,9 +570,9 @@ def plot_rain_freq_vs_time(self): ) except Exception: pass - plt.grid(which='major', color='k') - plt.ylim(self.cfg['rain_limits']) - plt.xlim(self.lhstart, self.lhend) + rflh_axes.grid(which='major', color='k') + rflh_axes.set_ylim(self.cfg['rain_limits']) + rflh_axes.set_xlim(self.lhstart, self.lhend) rflh_axes.xaxis.set_major_locator(self.mins) rflh_axes.xaxis.set_major_formatter(self.mins_fmt) rflh_axes.xaxis.set_ticklabels([]) @@ -580,8 +581,8 @@ def plot_rain_freq_vs_time(self): def plot_safety_vs_time(self): """ Plot Safety Values """ - print('Plot Safe/Unsafe vs. Time') - safe_axes = plt.axes(self.plot_positions[4][0]) + logger.debug('Plot Safe/Unsafe vs. Time') + safe_axes = self.fig.add_axes(self.plot_positions[4][0]) safe_value = [int(x) for x in self.table['safe']] @@ -589,34 +590,34 @@ def plot_safety_vs_time(self): markersize=2, markeredgewidth=0, drawstyle="default") safe_axes.fill_between(self.time, -1, safe_value, - where=(self.table['safe'].data), + where=(self.table['safe']), color='green', alpha=0.5) safe_axes.fill_between(self.time, -1, safe_value, - where=(~self.table['safe'].data), + where=(~self.table['safe']), color='red', alpha=0.5) - plt.ylabel("Safe") - plt.xlim(self.start, self.end) - plt.ylim(-0.1, 1.1) - plt.yticks([0, 1]) - plt.grid(which='major', color='k') + safe_axes.set_ylabel("Safe") + safe_axes.set_xlim(self.start, self.end) + safe_axes.set_ylim(-0.1, 1.1) + safe_axes.set_yticks([0, 1]) + safe_axes.grid(which='major', color='k') safe_axes.xaxis.set_major_locator(self.hours) safe_axes.xaxis.set_major_formatter(self.hours_fmt) safe_axes.xaxis.set_ticklabels([]) safe_axes.yaxis.set_ticklabels([]) if self.today: - safelh_axes = plt.axes(self.plot_positions[4][1]) + safelh_axes = self.fig.add_axes(self.plot_positions[4][1]) safelh_axes.plot_date(self.time, safe_value, 'ko-', markersize=4, markeredgewidth=0, drawstyle="default") safelh_axes.fill_between(self.time, -1, safe_value, - where=(self.table['safe'].data), + where=(self.table['safe']), color='green', alpha=0.5) safelh_axes.fill_between(self.time, -1, safe_value, - where=(~self.table['safe'].data), + where=(~self.table['safe']), color='red', alpha=0.5) - plt.plot_date([self.date, self.date], [-0.1, 1.1], - 'g-', alpha=0.4) + safelh_axes.plot_date([self.date, self.date], [-0.1, 1.1], + 'g-', alpha=0.4) try: safe = self.current_values['data']['safe'] current_safe = {True: 'Safe', False: 'Unsafe'}[safe] @@ -630,10 +631,10 @@ def plot_safety_vs_time(self): ) except Exception: pass - plt.ylim(-0.1, 1.1) - plt.yticks([0, 1]) - plt.grid(which='major', color='k') - plt.xlim(self.lhstart, self.lhend) + safelh_axes.set_ylim(-0.1, 1.1) + safelh_axes.set_yticks([0, 1]) + safelh_axes.grid(which='major', color='k') + safelh_axes.set_xlim(self.lhstart, self.lhend) safelh_axes.xaxis.set_major_locator(self.mins) safelh_axes.xaxis.set_major_formatter(self.mins_fmt) safelh_axes.xaxis.set_ticklabels([]) @@ -642,16 +643,16 @@ def plot_safety_vs_time(self): def plot_pwm_vs_time(self): """ Plot Heater values """ - print('Plot PWM Value vs. Time') - pwm_axes = plt.axes(self.plot_positions[5][0]) - plt.ylabel("Heater (%)") - plt.ylim(self.cfg['pwm_limits']) - plt.yticks([0, 25, 50, 75, 100]) - plt.xlim(self.start, self.end) - plt.grid(which='major', color='k') + logger.debug('Plot PWM Value vs. Time') + pwm_axes = self.fig.add_axes(self.plot_positions[5][0]) + pwm_axes.set_ylabel("Heater (%)") + pwm_axes.set_ylim(self.cfg['pwm_limits']) + pwm_axes.set_yticks([0, 25, 50, 75, 100]) + pwm_axes.set_xlim(self.start, self.end) + pwm_axes.grid(which='major', color='k') rst_axes = pwm_axes.twinx() - plt.ylim(-1, 21) - plt.xlim(self.start, self.end) + rst_axes.set_ylim(-1, 21) + rst_axes.set_xlim(self.start, self.end) pwm_value = self.table['pwm_value'] rst_delta = self.table['rain_sensor_temp_C'] - self.table['ambient_temp_C'] @@ -673,14 +674,14 @@ def plot_pwm_vs_time(self): pwm_axes.legend(loc='best') if self.today: - pwmlh_axes = plt.axes(self.plot_positions[5][1]) - plt.ylim(self.cfg['pwm_limits']) - plt.yticks([0, 25, 50, 75, 100]) - plt.xlim(self.lhstart, self.lhend) - plt.grid(which='major', color='k') + pwmlh_axes = self.fig.add_axes(self.plot_positions[5][1]) + pwmlh_axes.set_ylim(self.cfg['pwm_limits']) + pwmlh_axes.set_yticks([0, 25, 50, 75, 100]) + pwmlh_axes.set_xlim(self.lhstart, self.lhend) + pwmlh_axes.grid(which='major', color='k') rstlh_axes = pwmlh_axes.twinx() - plt.ylim(-1, 21) - plt.xlim(self.lhstart, self.lhend) + rstlh_axes.set_ylim(-1, 21) + rstlh_axes.set_xlim(self.lhstart, self.lhend) rstlh_axes.plot_date(self.time, rst_delta, 'ro-', alpha=0.5, label='RST Delta (C)', markersize=4, markeredgewidth=0, @@ -710,10 +711,9 @@ def save_plot(self, plot_filename=None): plot_filename = os.path.abspath(plot_filename) plot_dir = os.path.dirname(plot_filename) - if not os.path.exists(plot_dir): - os.makedirs(plot_dir) + os.makedirs(plot_dir, exist_ok=True) - print('Saving Figure: {}'.format(plot_filename)) + logger.info(f'Saving weather plot: {plot_filename}') self.fig.savefig( plot_filename, dpi=self.dpi, @@ -754,15 +754,7 @@ def moving_averagexy(x, y, window_size): help="Filename for data file") parser.add_argument("-o", "--plot_file", type=str, dest="plot_file", default=None, help="Filename for generated plot") - parser.add_argument('--plotly-user', help="Username for plotly publishing") - parser.add_argument('--plotly-api-key', help="API for plotly publishing") args = parser.parse_args() wp = WeatherPlotter(date_string=args.date, data_file=args.data_file) wp.make_plot(args.plot_file) - - if args.plotly_user and args.plotly_api_key: - from plotly import plotly - plotly.sign_in(args.plotly_user, args.plotly_api_key) - url = plotly.plot_mpl(wp.fig) - print('Plotly url: {}'.format(url)) diff --git a/scripts/plot_weather.sh b/scripts/plot_weather.sh deleted file mode 100755 index b68ae142d..000000000 --- a/scripts/plot_weather.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -# Runs scripts/plog_weather.py, which will generate an image in -# $PANDIR/weather_plots/. - -# We need the shell to have the the PANOPTES environment setup. - -echo "Running ${BASH_SOURCE[0]} at $(date)" - -if [[ -z "$PANDIR" || -z "$POCS" || -z "$PANLOG" ]] ; then - echo "The PANOPTES environment variables must be set." - echo "This script should be run from a login shell." - exit 1 -fi - -echo "Setting up logging..." - -# Setup a directory for the log file from this script and from those -# it invokes. By creating a unique directory per startup, we make it -# easier to view the group of files from a single reboot. -export LOG_DIR_SLASH="${PANLOG}/per-run/$(basename "${BASH_SOURCE[0]}" .sh)/" -mkdir -p "${LOG_DIR_SLASH}" - -LOG_NAME="$(basename "${BASH_SOURCE[0]}" .sh).$(date +%Y%m%d-%H%M%S-%Z).log" -LOG_FILE="${LOG_DIR_SLASH}${LOG_NAME}" - -echo "Will log to ${LOG_FILE}" - -exec 2> "${LOG_FILE}" # send stderr to a log file -exec 1>&2 # send stdout to the same log file -set +x - -# Record a bunch of environment variables into the log file. This -# helps us later if we need to debug the execution of this script -# and those it invokes. -echo "Running ${BASH_SOURCE[0]} at $(date)" -echo "Current dir: $(pwd)" -echo "Current user: $(whoami)" -echo "USER: ${USER}" -echo "LOGNAME: ${LOGNAME}" -echo "PATH: ${PATH}" -echo "PANUSER: ${PANUSER}" -echo "PANDIR: ${PANDIR}" -echo "PANLOG: ${PANLOG}" -echo "POCS: ${POCS}" -echo "PAWS: ${PAWS}" -echo "PIAA: ${PIAA}" - -set -x - -"${POCS}/scripts/plot_weather.py"