def _validate_input(self): """Validate entry when unfocusing text input.""" if not self.text_input.focus: try: input_value = float(self.text_input.text) except ValueError: # No text entered. input_value = self.param_slider.value self.text_input.text = str(input_value) return if input_value > self.param_max or input_value < self.param_min: # If input value is out of range. popup = WarningPopup() popup.popup_text.text = '{param_name} must be between {param_min} and {param_max} (got {input_val}).'.format( param_name=self.name.text[:1].upper() + self.name.text[1:], param_min=self.param_min, param_max=self.param_max, input_val=input_value) popup.open() input_value = self.param_slider.value self.text_input.text = str(input_value) else: # Set slider value to input value. anim = Animation(transition='out_expo', duration=SLIDER_DUR, value=input_value) anim.start(self.param_slider)
def get_inputs(self): try: params = self._validate_inputs() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: return params
def next_screen(self): try: self.get_selections() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: self.manager.current = self.manager.next()
def get_selections(self): """Retrieves screen's selections.""" try: load_profile_selected = self._validate_inputs() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: return load_profile_selected
def next_screen(self): """Check if all input data is valid before proceeding to the net metering screen.""" try: self._validate_inputs() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: self.manager.current = self.manager.next()
def get_selections(self): """Retrieves screen's selections.""" try: params, params_desc = self._validate_inputs() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: return params, params_desc
def get_selections(self): """Retrieves UI selections.""" try: peak_kw_min, peak_kw_max, net_metering_type, sell_price = self._validate_inputs( ) except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: return peak_kw_min, peak_kw_max, net_metering_type, sell_price
def get_selections(self): """Retrieves UI selections.""" try: weekday_schedule, weekend_schedule, tou_rates_dict, flat_rates_dict = self._validate_inputs( ) except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: return weekday_schedule.tolist(), weekend_schedule.tolist( ), tou_rates_dict, flat_rates_dict
def launch_btm(self): """""" data_manager = App.get_running_app().data_manager try: data_manager.scan_btm_data_bank() except FileNotFoundError: # 'data' directory does not exist. no_data_popup = WarningPopup() no_data_popup.popup_text.text = "Looks like you haven't downloaded any data yet. Try using QuESt Data Manager to get some data before returning here!" no_data_popup.open() else: self.current = 'btm_home'
def on_enter(self): # change the navigation bar title ab = self.manager.nav_bar ab.build_valuation_advanced_nav_bar() ab.set_title('Single Run: Set Parameters') data_manager = App.get_running_app().data_manager MODEL_PARAMS = data_manager.get_valuation_model_params(self.iso) if not MODEL_PARAMS: popup = WarningPopup() popup.bind(on_dismiss=partial(ab.go_to_screen, 'load_data')) popup.dismiss_button.text = 'Go back' popup.popup_text.text = 'We need a market area in the "Select Data" screen selected first to populate this area.' popup.open()
def _next_screen(self): if not self.manager.has_screen('summary'): screen = CostSavingsWizardSummary(name='summary') self.manager.add_widget(screen) try: self.get_selections() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: self.manager.transition.duration = BASE_TRANSITION_DUR self.manager.transition.direction = 'left' self.manager.current = 'summary'
def execute_query(self): """Executes the PVWatts query using the given parameters.""" try: api_key, pv_params = self.get_inputs() self.api_key = api_key except ValueError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: # Reset screen. self.reset_screen() self.save_button.disabled = True # Form query. api_query = URL_PVWATTS query_segs = [] for k, v in pv_params.items(): query_segs.append('{key}={value}'.format(key=k, value=v)) api_query += '&'.join(query_segs) # print(api_query) try: self._query_api(api_query) except requests.ConnectionError: popup = ConnectionErrorPopup() popup.popup_text.text = 'There was an issue connecting to the API. Check your connection settings and try again.' popup.open()
def run_batch(self): try: requests = self._generate_requests() except ValueError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: solver_name = App.get_running_app().config.get('optimization', 'solver') handler = self.manager.get_screen('valuation_home').handler handler.solver_name = solver_name try: _, handler_status = handler.process_requests(requests) except BadParameterException as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: self.completion_popup = BatchRunCompletePopup() self.completion_popup.view_results_button.bind(on_release=self._go_to_view_results) if not handler_status: self.completion_popup.title = "Success!*" self.completion_popup.popup_text.text = "Your specified batch runs have been completed.\n\n*At least one model (month) had issues being built and/or solved. Any such model will be omitted from the results." self.completion_popup.open()
def finalize_selections(self): """Validates the specified data based on the selected columns using a validation function. Returns ------- Pandas DataFrame Dataframe with the data series str Name of the data column """ try: import_df, data_column_name = self._validate_columns_selected() except ValueError as e: exception_popup = WarningPopup() exception_popup.popup_text.text = e.args[0] exception_popup.open() else: logging.info("DataImporter: Data format validation completed without issues.") completion_popup = self.manager.completion_popup completion_popup.open() return import_df, data_column_name
def execute_single_run(self, *args): try: requests = self._generate_requests() except ValueError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() except BadParameterException as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: solver_name = App.get_running_app().config.get( 'optimization', 'solver') handler = self.manager.get_screen('valuation_home').handler handler.solver_name = solver_name try: _, handler_status = handler.process_requests(requests) except BadParameterException as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: self.completion_popup = ValuationSingleRunCompletePopup() self.completion_popup.view_results_button.bind( on_release=self._go_to_view_results) if not handler_status: self.completion_popup.title = "Oops!" self.completion_popup.popup_text.text = "The optimization model had issues being built and/or solved. This is most likely due to bad data. No results have been recorded." self.completion_popup.open()
def run_batch(self): try: requests = self._generate_requests() except ValueError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: solver_name = App.get_running_app().config.get( 'optimization', 'solver') handler = self.manager.get_screen('valuation_home').handler handler.solver_name = solver_name try: solved_ops, handler_status = handler.process_requests(requests) except BadParameterException as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: self.completion_popup = BatchRunCompletePopup() self.completion_popup.view_results_button.bind( on_release=self._go_to_view_results) if len(handler_status) > 0: if solved_ops: # At least one model solved successfully. self.completion_popup.title = "Success!*" self.completion_popup.popup_text.text = '\n'.join([ 'All finished, but we found these issues:', ] + list(handler_status)) else: # No models solved successfully. self.completion_popup.title = "Hmm..." self.completion_popup.popup_text.text = '\n'.join([ 'Unfortunately, none of the models were able to be solved. We found these issues:', ] + list(handler_status)) self.completion_popup.open()
def execute_search(self): """Executes the utility search using the given parameters.""" try: api_key, search_query, search_type = self.get_inputs() self.api_key = api_key except ValueError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() except InputError as e: popup = WarningPopup() popup.popup_text.text = str(e) popup.open() else: # Reset screen. self.reset_screen() self.search_button.disabled = True def _execute_search(): # Open loading screen. # self.loading_screen = LoadingModalView() # self.loading_screen.loading_text.text = 'Retrieving rate structures...' # self.loading_screen.open() if self.utility_ref_table.empty: try: self._download_utility_ref_table() except requests.ConnectionError: popup = ConnectionErrorPopup() popup.popup_text.text = 'There was an issue connecting to and downloading the lists of utilities. Check your connection settings and try again.' popup.open() return finally: self.search_button.disabled = False # Filter DataFrame by search type/query and drop duplicate entries. if search_type == 'state': utility_data_filtered = self.utility_ref_table.loc[ self.utility_ref_table['state'].str.lower( ).str.contains(search_query) | self.utility_ref_table['state name'].str.lower( ).str.contains(search_query)] elif search_type == 'zip': utility_data_filtered = self.utility_ref_table.loc[ self.utility_ref_table[search_type] == search_query] else: utility_data_filtered = self.utility_ref_table.loc[ self.utility_ref_table[search_type].str.lower( ).str.contains(search_query)] utility_data_filtered = utility_data_filtered[[ 'eiaid', 'utility_name', 'state', 'ownership' ]] utility_data_filtered.drop_duplicates(inplace=True) logging.info( 'RateStructureDM: Utility table filter completed.') self.search_button.disabled = False if utility_data_filtered.empty: logging.warning( 'RateStructureDM: No results matched the query.') popup = WarningPopup() popup.popup_text.text = 'No results matched your query.' popup.open() # Enable search results selector. fade_in_animation(self.utility_select_bx) self._populate_utility_selector(utility_data_filtered) # Animation.stop_all(self.loading_screen.logo, 'opacity') # self.loading_screen.dismiss() thread_query = threading.Thread(target=_execute_search) thread_query.start()
def save_rate_structure(self): """Saves the rate structure details to an object on disk.""" # Retrieve selections from other screens. utility_search_screen = self.manager.get_screen('start') utility_selected, rate_structure_selected = utility_search_screen.get_selections( ) energy_rate_screen = self.manager.get_screen('energy_rate_structure') energy_weekday_schedule, energy_weekend_schedule, energy_rates_dict = energy_rate_screen.get_selections( ) demand_rate_screen = self.manager.get_screen('demand_rate_structure') demand_weekday_schedule, demand_weekend_schedule, demand_tou_rates_dict, demand_flat_rates_dict = demand_rate_screen.get_selections( ) try: peak_kw_min, peak_kw_max, net_metering_type, sell_price = self.get_selections( ) except TypeError: return # Form dictionary object for saving. rate_structure_object = {} if not self.save_name_field.text: popup = WarningPopup() popup.popup_text.text = 'Please specify a name to save the rate structure as.' popup.open() return else: rate_structure_object['name'] = self.save_name_field.text rate_structure_object['utility'] = { 'utility name': utility_selected['utility_name'], 'rate structure name': rate_structure_selected['name'] } rate_structure_object['energy rate structure'] = { 'weekday schedule': energy_weekday_schedule, 'weekend schedule': energy_weekend_schedule, 'energy rates': energy_rates_dict } rate_structure_object['demand rate structure'] = { 'weekday schedule': demand_weekday_schedule, 'weekend schedule': demand_weekend_schedule, 'time of use rates': demand_tou_rates_dict, 'flat rates': demand_flat_rates_dict, 'minimum peak demand': peak_kw_min, 'maximum peak demand': peak_kw_max } rate_structure_object['net metering'] = { 'type': net_metering_type, 'energy sell price': sell_price } # Save to JSON. # Strip non-alphanumeric chars from given name for filename. delchars = ''.join(c for c in map(chr, range(256)) if not c.isalnum()) fname = rate_structure_object['name'].translate( {ord(i): None for i in delchars}) destination_dir = os.path.join(DATA_HOME, 'rate_structures') os.makedirs(destination_dir, exist_ok=True) destination_file = os.path.join(destination_dir, fname + '.json') if not os.path.exists(destination_file): with open(destination_file, 'w') as outfile: json.dump(rate_structure_object, outfile) popup = WarningPopup() popup.title = 'Success!' popup.popup_text.text = 'Rate structure data successfully saved.' popup.open() else: # File already exists with same name. popup = WarningPopup() popup.popup_text.text = 'A rate structure with the provided name already exists. Please specify a new name.' popup.open()
def _query_api(self, api_query): """Uses PVWatts API to query for a PV profile.""" ssl_verify, proxy_settings = check_connection_settings() try: with requests.Session() as req: http_request = req.get(api_query, proxies=proxy_settings, timeout=10, verify=ssl_verify, stream=True) if http_request.status_code != requests.codes.ok: http_request.raise_for_status() except requests.HTTPError as e: logging.error('PVProfileDM: {0}'.format(repr(e))) raise requests.ConnectionError except requests.exceptions.ProxyError: logging.error('PVProfileDM: Could not connect to proxy.') raise requests.ConnectionError except requests.ConnectionError as e: logging.error( 'PVProfileDM: Failed to establish a connection to the host server.' ) raise requests.ConnectionError except requests.Timeout as e: logging.error('PVProfileDM: The connection timed out.') raise requests.ConnectionError except requests.RequestException as e: logging.error('PVProfileDM: {0}'.format(repr(e))) raise requests.ConnectionError except Exception as e: # Something else went wrong. logging.error( 'PVProfileDM: An unexpected error has occurred. ({0})'.format( repr(e))) raise requests.ConnectionError else: request_content = http_request.json() if not self.save_name_field.text: popup = WarningPopup() popup.popup_text.text = 'Please specify a name to save the PV profile as.' popup.open() return else: outname = self.save_name_field.text # Strip non-alphanumeric chars from given name for filename. delchars = ''.join(c for c in map(chr, range(256)) if not c.isalnum()) outname = outname.translate({ord(i): None for i in delchars}) # Save. destination_dir = os.path.join(DATA_HOME, 'pv') os.makedirs(destination_dir, exist_ok=True) destination_file = os.path.join(destination_dir, outname + '.json') if not os.path.exists(destination_file): with open(destination_file, 'w') as outfile: json.dump(request_content, outfile) logging.info('PVProfileDM: Profile successfully saved.') popup = WarningPopup() popup.title = 'Success!' popup.popup_text.text = 'PV profile successfully saved.' popup.open() else: # File already exists with same name. popup = WarningPopup() popup.popup_text.text = 'A PV profile with the provided name already exists. Please specify a new name.' popup.open() finally: self.save_button.disabled = False
def save_load_data(self): """Saves the data for the building type selected.""" try: csv_link = self._validate_selections() except Exception as e: print(e) else: ssl_verify, proxy_settings = check_connection_settings() attempt_download = True n_tries = 0 self.connection_error_occurred = False while attempt_download: n_tries += 1 if n_tries >= MAX_WHILE_ATTEMPTS: logging.warning('LoadProfileDM: Hit download retry limit.') attempt_download = False self.connection_error_occurred = True break if App.get_running_app().root.stop.is_set(): return try: with requests.Session() as req: page = req.get(csv_link, timeout=10, verify=ssl_verify, proxies=proxy_settings) if page.status_code != requests.codes.ok: page.raise_for_status() else: attempt_download = False except requests.HTTPError as e: logging.error('LoadProfileDM: {0}'.format(repr(e))) except requests.exceptions.ProxyError: logging.error('LoadProfileDM: Could not connect to proxy.') except requests.ConnectionError as e: logging.error( 'LoadProfileDM: Failed to establish a connection to the host server.' ) except requests.Timeout as e: logging.error('LoadProfileDM: The connection timed out.') except requests.RequestException as e: logging.error('LoadProfileDM: {0}'.format(repr(e))) except Exception as e: # Something else went wrong. logging.error( 'LoadProfileDM: An unexpected error has occurred. ({0})' .format(repr(e))) else: data_down = page.content.decode(page.encoding) csv_data = pd.read_csv(io.StringIO(data_down)) electricity_data = csv_data[[ 'Date/Time', 'Electricity:Facility [kW](Hourly)' ]] # Save to persistent object on disk. url_split = csv_link.split('/') destination_dir = os.path.join(DATA_HOME, 'load', 'residential', url_split[-2]) os.makedirs(destination_dir, exist_ok=True) destination_file = os.path.join(destination_dir, url_split[-1]) electricity_data.to_csv(destination_file, sep=',', index=False) popup = WarningPopup() popup.title = 'Success!' popup.popup_text.text = 'Load data successfully saved.' popup.open() logging.info( 'LoadProfileDM: Load data successfully saved.')