diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..02137753
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,52 @@
+dist: xenial # required for Python >= 3.7
+language: python
+sudo: false # if false, use TravisCI's container based build
+
+python:
+ - "3.6"
+ - "3.7"
+
+addons:
+ apt:
+ packages:
+ - ccache
+
+cache:
+ directories:
+ - $HOME/.ccache
+
+before_script:
+ - "export DISPLAY=:99.0"
+ - "sh -e /etc/init.d/xvfb start"
+ - sleep 3 # give xvfb some time to start
+
+# setup miniconda for numpy, scipy, pandas
+before_install:
+ - echo "before install"
+ - export PATH=/usr/lib/ccache:$PATH
+ - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh;
+ - bash miniconda.sh -b -p $HOME/miniconda
+ - export PATH="$HOME/miniconda/bin:$PATH"
+ - hash -r
+ - conda config --set always_yes yes --set changeps1 no
+ - conda update -q conda
+ - conda info -a
+
+install:
+ - echo "install"
+ - conda env create python=$TRAVIS_PYTHON_VERSION --file ci/environment.yml
+ - source activate test_env
+ - conda list
+ - echo $PATH
+ - ls -l /home/travis/miniconda/envs/test_env/lib
+ - pip install git+https://github.com/PyUtilib/pyutilib.git
+ - pip install git+https://github.com/Pyomo/pyomo.git
+ - conda install kivy -c conda-forge
+ - conda install -c conda-forge glpk
+ - python setup.py develop
+
+script:
+ - python -m unittest -v
+
+after_success:
+coveralls
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 04b87644..b2c549e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,29 @@
# Master branch changelog
+## Patch 1.2.d
+### QuESt
+* Removed "id" property for NavigationButton(ActionButton) widgets to address deprecation warnings.
+* Added files to repository for Travis CI. We will be implementing continuous integration and unit tests over the next few updates.
+
+#### QuESt Data Manager
+* PV profiles that are obtained using PVWatts now use the "TMY3" dataset instead of the default "NSRDB" dataset.
+ * This is to maintain consistency with the load profiles obtained from OpenEI.org which are based on TMY3.
+
+#### QuESt Valuation
+* The "Single Run" mode in QuESt Valuation has been deprecated and removed from the GUI.
+ * The functionality of the "Single Run" mode is already duplicated by the "Batch Run" mode.
+
+### Resolved issues
+* Various issues due to Kivy v1.11.0 update. Backwards compatibility with Kivy v1.10.1 should be maintained.
+* An issue where the settings for the QuESt BTM data management system were not respected.
+* An issue where the wrong navigation bar was loaded upon entering QuESt BTM.
+* An issue where attempting to start the QuESt Valuation Wizard (on the second screen) or QuESt Valuation Batch Runs (when selecting a market area) after a fresh or install or with no `/data/` directory resulted in a fatal crash.
+
## Patch 1.2.c
### Resolved issues
* An issue where attempting to download ISO/RTO market data for ERCOT resulted in a fatal crash.
## Patch 1.2.b
-
### Resolved issues
* An issue where attempting to export a PNG from a results viewer when solved models were selected but no plot had yet been drawn resulted in a fatal crash.
diff --git a/QuESt.kv b/QuESt.kv
index ade2be26..52ba1ce7 100644
--- a/QuESt.kv
+++ b/QuESt.kv
@@ -15,11 +15,8 @@
#:include es_gui/apps/data_manager/pv.kv
#:include es_gui/apps/valuation/home.kv
-#:include es_gui/apps/valuation/valuationscreen.kv
#:include es_gui/apps/valuation/batchrunscreen.kv
#:include es_gui/apps/valuation/results_viewer.kv
-#:include es_gui/apps/valuation/setparametersscreen.kv
-#:include es_gui/apps/valuation/loaddatascreen.kv
#:include es_gui/apps/valuation/wizard.kv
#:include es_gui/apps/valuation/reporting.kv
diff --git a/README.md b/README.md
index 6e037306..32fb7808 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
# QuESt: Optimizing Energy Storage
-Current release version: 1.2.c
+Current release version: 1.2.d
-Release date: 05/03/19
+Release date: 06/04/19
## Table of contents
- [Introduction](#intro)
@@ -53,23 +53,36 @@ The software is designed to be used by anyone with an interest in performing ana
## Getting started
-### Installing from executable
+### Installing from executable (recommended)
+Running QuESt from an executable is the most straightforward way to get started with QuESt. You do not require any Python installation to install QuESt with this method; simply run the executable. What is required:
-#### Windows 10
-For Windows 10 users, we will offer an executable version of QuESt. This version comes pre-packaged with its own Python environment (including Kivy) so no Python installation is required. Until further notice, you will still need to install a solver for Pyomo in order to solve optimization problems such as those in QuESt Valuation and QuESt BTM.
+* QuESt executable package
+* Solver compatible with Pyomo
-You can find the executable version with each release in the **Releases** section:
-https://github.com/rconcep/snl-quest/releases
+We are currently looking into packaging a basic solver to simplify the installation process further.
+
+#### Windows 10
+You can find the executable version with each release in the [**Releases**](https://github.com/rconcep/snl-quest/releases) section.
-1. Download and extract the `.zip` that is *not* labeled "Source code."
+1. Download and extract the `.zip` that is *not* labeled "Source code." Its name will be `snl-quest-v{version number}-win10.zip`.
2. Inside the extracted folder, there will be a lot of files and folders. Locate the `snl-quest-v{version number}.exe` file and run it.
3. A command prompt should open along with the QuESt GUI.
-### Installing from source code
+#### OSX, Linux
+Currently, we do not offer executable packages of QuESt for OSX or Linux operating systems. They are possible to package but we have not implemented those packaging processes yet. Installing from source code is an option.
+
+#### Solvers compatible with Pyomo
+When running the executable version of QuESt, a solver compatible for Pyomo is required to be installed and on your system path. Here are a few examples:
+
+##### Installing GLPK (for Windows)
+1. Download and extract the executables for Windows linked [here](http://winglpk.sourceforge.net/).
+2. The glpk.dll and glpsol.exe files are in the `w32` and `w64` subdirectories for 32-Bit and 64-Bit Windows, respectively. These files need to be in the system path for Windows. The easiest way to do this is to move those files to the `C:\windows\system32` directory. You can also place them in the same directory as the QuESt executable.
+3. (When placing the files in your system path) Try running the command ``glpsol`` in the command prompt (Windows) or terminal (OSX). If you receive a message other than something like "command not found," it means the solver is successfully installed.
+### Installing from source code (advanced)
For all platforms, you can instead install QuESt using the codebase in this repository.
-You will want to obtain the codebase for QuESt. You can do that by downloading a release version in a compressed archive from the "releases" tab on the GitHub repository page. Alternatively, you can clone this repository or download a compressed archive of it by clicking the "Clone or download" button on this page. We recommend keeping the QuESt files in a location where you have read/write permission. Once you have the codebase, follow the appropriate set of instructions for your operating system.
+You will want to obtain the codebase for QuESt. You can do that by downloading a release version in a compressed archive from the "releases" tab on the GitHub repository page labeled as "Source code". Alternatively, you can clone this repository or download a compressed archive of it by clicking the "Clone or download" button on this page. We recommend keeping the QuESt files in a location where you have read/write permission. Once you have the codebase, follow the appropriate set of instructions for your operating system.
**Requirements**
* Python 3.6+
@@ -106,10 +119,11 @@ If you've installed Python using Anaconda, you may be able to install several so
#### Installing GLPK (for OSX)
You will need to either build GLPK from source or install it using the [homebrew](https://brew.sh/) package manager. This [blog post](http://arnab-deka.com/posts/2010/02/installing-glpk-on-a-mac/) may be useful.
-#### Installing GLPK (for OSX via Anaconda)
+#### Installing GLPK or CBC (for OSX via Anaconda)
If you've installed Python using Anaconda, you may be able to install several solvers through Anaconda's package manager with the following (according to Pyomo's [installation instructions](https://pyomo.readthedocs.io/en/latest/installation.html)):
``conda install -c conda-forge glpk``
+``conda install -c conda-forge coincbc``
##### Installing IPOPT (for Windows)
1. Download and extract the pre-compiled binaries linked [here](https://www.coin-or.org/download/binary/Ipopt/). Select the latest version appropriate for your system and OS.
diff --git a/ci/environment.yml b/ci/environment.yml
new file mode 100644
index 00000000..3ad13eb3
--- /dev/null
+++ b/ci/environment.yml
@@ -0,0 +1,17 @@
+name: test_env
+channels:
+- conda-forge
+- defaults
+dependencies:
+- numpy
+- scipy
+- pandas
+- six
+- matplotlib
+- xlrd
+- jinja2
+- bs4
+- requests
+- urllib3
+- holidays
+
diff --git a/es_gui/apps/btm/home.py b/es_gui/apps/btm/home.py
index 8a896b0e..fa3ee221 100644
--- a/es_gui/apps/btm/home.py
+++ b/es_gui/apps/btm/home.py
@@ -19,11 +19,10 @@ class BehindTheMeterHomeScreen(Screen):
def __init__(self, **kwargs):
super(BehindTheMeterHomeScreen, self).__init__(**kwargs)
- # # Initialize data management system.
+ # Initialize data management system.
self.dms = BtmDMS(
- # max_memory=App.get_running_app().config.getint('valuation', 'valuation_dms_size')*1000,
- # save_data=bool(App.get_running_app().config.getint('valuation', 'valuation_dms_save')),
- save_data = True,
+ max_memory=App.get_running_app().config.getint('btm', 'btm_dms_size')*1000,
+ save_data=bool(App.get_running_app().config.getint('btm', 'btm_dms_save')),
save_name='btm_dms.p',
home_path='data',
)
@@ -34,7 +33,6 @@ def on_enter(self):
ab = self.manager.nav_bar
ab.reset_nav_bar()
ab.set_title('Behind-the-Meter Applications')
- ab.build_data_manager_nav_bar()
# data_manager = App.get_running_app().data_manager
diff --git a/es_gui/apps/data_manager/data_manager.py b/es_gui/apps/data_manager/data_manager.py
index 543b5429..10483320 100644
--- a/es_gui/apps/data_manager/data_manager.py
+++ b/es_gui/apps/data_manager/data_manager.py
@@ -246,7 +246,12 @@ def get_markets(self):
"""Returns a keys view of all of the markets for valuation available."""
# self.scan_valuation_data_bank()
- return self.data_bank['valuation'].keys()
+ try:
+ valuation_data_bank = self.data_bank['valuation']
+ except KeyError:
+ return []
+ else:
+ return self.data_bank['valuation'].keys()
def scan_valuation_data_bank(self):
"""Scans the valuation data bank to determine what data has been downloaded."""
diff --git a/es_gui/apps/data_manager/pv.kv b/es_gui/apps/data_manager/pv.kv
index ef1f6283..acd0a6d3 100644
--- a/es_gui/apps/data_manager/pv.kv
+++ b/es_gui/apps/data_manager/pv.kv
@@ -37,7 +37,7 @@
#password: True
write_tab: False
hint_text: 'API key'
- text: app.App.get_running_app().config.get('data_manager_openei', 'openei_key')
+ text: app.App.get_running_app().config.get('datamanager-openei', 'openei_key')
size_hint_x: 0.7
BoxLayout:
diff --git a/es_gui/apps/data_manager/pv.py b/es_gui/apps/data_manager/pv.py
index 57faf034..5f5747e9 100644
--- a/es_gui/apps/data_manager/pv.py
+++ b/es_gui/apps/data_manager/pv.py
@@ -96,6 +96,7 @@ def get_inputs(self):
api_key, pv_params = self._validate_inputs()
# Fixed values.
+ pv_params['dataset'] = 'tmy3'
pv_params['radius'] = '0'
pv_params['timeframe'] = 'hourly'
pv_params['api_key'] = api_key
diff --git a/es_gui/apps/data_manager/rate_structure.kv b/es_gui/apps/data_manager/rate_structure.kv
index aaee3030..6a97c5eb 100644
--- a/es_gui/apps/data_manager/rate_structure.kv
+++ b/es_gui/apps/data_manager/rate_structure.kv
@@ -60,7 +60,7 @@
#password: True
write_tab: False
hint_text: 'API key'
- text: app.App.get_running_app().config.get('data_manager_openei', 'openei_key')
+ text: app.App.get_running_app().config.get('datamanager-openei', 'openei_key')
size_hint_x: 0.7
BoxLayout:
diff --git a/es_gui/apps/data_manager/widgets.kv b/es_gui/apps/data_manager/widgets.kv
index 4b84adcb..7dfb0343 100644
--- a/es_gui/apps/data_manager/widgets.kv
+++ b/es_gui/apps/data_manager/widgets.kv
@@ -193,7 +193,7 @@
#password: True
write_tab: False
hint_text: 'Email Address'
- text: app.App.get_running_app().config.get('data_manager_iso-ne', 'iso-ne_api_username')
+ text: app.App.get_running_app().config.get('datamanager-isone', 'iso-ne_api_username')
BoxLayout:
orientation: 'horizontal'
@@ -1089,7 +1089,7 @@
#password: True
write_tab: False
hint_text: 'Subscription key'
- text: app.App.get_running_app().config.get('data_manager_pjm', 'pjm_subscription_key')
+ text: app.App.get_running_app().config.get('datamanager-pjm', 'pjm_subscription_key')
BoxLayout:
orientation: 'horizontal'
diff --git a/es_gui/apps/valuation/home.kv b/es_gui/apps/valuation/home.kv
index 544d5205..2b910217 100644
--- a/es_gui/apps/valuation/home.kv
+++ b/es_gui/apps/valuation/home.kv
@@ -31,10 +31,11 @@
orientation: 'horizontal'
spacing: 10
- MenuTileButton:
- background_color: C(hex_pms312)
- text: '[font=Modern Pictograms][size=80]r[/size][/font]\nSingle Run'
- on_release: root.manager.current = 'load_data'
+ # MenuTileButton:
+ # background_color: C(hex_pms312)
+ # text: '[font=Modern Pictograms][size=80]r[/size][/font]\nSingle Run'
+ # on_release: root.manager.current = 'load_data'
+ # disabled: True
MenuTileButton:
id: advanced_button
diff --git a/es_gui/apps/valuation/loaddatascreen.kv b/es_gui/apps/valuation/loaddatascreen.kv
index 2cf642c2..ee758990 100644
--- a/es_gui/apps/valuation/loaddatascreen.kv
+++ b/es_gui/apps/valuation/loaddatascreen.kv
@@ -1,6 +1,6 @@
#: kivy 1.10.0
-#: import ListAdapter kivy.adapters.listadapter.ListAdapter
-#: import ListItemButton kivy.uix.listview.ListItemButton
+# import ListAdapter kivy.adapters.listadapter.ListAdapter
+# import ListItemButton kivy.uix.listview.ListItemButton
:
@@ -14,10 +14,10 @@
# size: self.size
-:
- font_size: stnd_font
- selected_color: 1, 1, 1, 1
- deselected_color: 0, 0, 0, 1
+# :
+# font_size: stnd_font
+# selected_color: 1, 1, 1, 1
+# deselected_color: 0, 0, 0, 1
:
background_normal: 'es_gui/resources/images/button_normal.png'
diff --git a/es_gui/resources/settings/data_manager.json b/es_gui/resources/settings/data_manager.json
index 7719371f..c55519ac 100644
--- a/es_gui/resources/settings/data_manager.json
+++ b/es_gui/resources/settings/data_manager.json
@@ -7,7 +7,7 @@
"type": "string",
"title": "Subscription key",
"desc": "Key provided for PJM's Data Miner 2 API access.",
- "section": "data_manager_pjm",
+ "section": "datamanager-pjm",
"key": "pjm_subscription_key"
},
{
@@ -18,7 +18,7 @@
"type": "string",
"title": "API username",
"desc": "Username for ISO-NE Web Services API account.",
- "section": "data_manager_iso-ne",
+ "section": "datamanager-isone",
"key": "iso-ne_api_username"
},
{
@@ -29,7 +29,7 @@
"type": "string",
"title": "API key",
"desc": "Key for OpenEI, PVWatts, and other Data.gov developer network API access. Also referred to as NREL Developer Network API key.",
- "section": "data_manager_openei",
+ "section": "datamanager-openei",
"key": "openei_key"
}
]
\ No newline at end of file
diff --git a/main.py b/main.py
index 196783eb..4b2d526d 100644
--- a/main.py
+++ b/main.py
@@ -71,11 +71,8 @@
# Valuation
from es_gui.apps.valuation.home import ValuationHomeScreen
-from es_gui.apps.valuation.valuationscreen import ValuationScreen
from es_gui.apps.valuation.batchrunscreen import BatchRunScreen
from es_gui.apps.valuation.results_viewer import ValuationResultsViewer
-from es_gui.apps.valuation.setparametersscreen import SetParametersScreen
-from es_gui.apps.valuation.loaddatascreen import LoadDataScreen
from es_gui.apps.valuation.wizard import ValuationWizard
# Behind-the-meter
@@ -133,7 +130,7 @@ def _go_to_webpage(instance, value):
elif value == 'sandia':
webbrowser.open('http://sandia.gov/')
- version_statement = 'QuESt v1.2.c \n 2019.05.03'
+ version_statement = 'QuESt v1.2.d \n 2019.06.04'
developed_by = '{app_name} is developed by the {ess} and {espr} departments at {sandia}.'.format(app_name=APP_NAME, ess=_ref_link('Energy Storage Technology and Systems', 'sandia-ess'), espr=_ref_link('Electric Power Systems Research', 'sandia-espr'), sandia=_ref_link('Sandia National Laboratories', 'sandia'))
@@ -218,11 +215,8 @@ def __init__(self, **kwargs):
self.add_widget(PVwattsSearchScreen(name='data_manager_pvwatts'))
# Energy storage valuation.
- #self.add_widget(ValuationScreen(name='valuation_advanced'))
self.add_widget(ValuationHomeScreen(name='valuation_home'))
self.add_widget(BatchRunScreen(name='batch_run'))
- self.add_widget(SetParametersScreen(name='set_parameters'))
- self.add_widget(LoadDataScreen(name='load_data'))
self.add_widget(ValuationResultsViewer(name='valuation_results_viewer'))
self.add_widget(ValuationWizard(name='valuation_wizard'))
@@ -266,8 +260,6 @@ class NavigationBar(ActionBar):
'valuation_home': 'index',
'batch_run': 'valuation_home',
'valuation_results_viewer': 'valuation_home',
- 'set_parameters': 'load_data',
- 'load_data': 'valuation_home',
'valuation_wizard': 'valuation_home',
'valuation_advanced': 'valuation_home',
'data_manager_home': 'index',
@@ -293,7 +285,6 @@ def build_data_manager_nav_bar(self):
data_manager_home_button = NavigationButton(
text='data manager home',
on_release=partial(self.go_to_screen, 'data_manager_home'),
- id='data_manager_home_button'
)
self.reset_nav_bar()
@@ -305,25 +296,21 @@ def build_valuation_advanced_nav_bar(self):
view_results_button = NavigationButton(
text='view results',
on_release=partial(self.go_to_screen, 'valuation_results_viewer'),
- id='plot_button'
)
run_op_button = NavigationButton(
text='run optimization',
on_release=self.sm.get_screen('set_parameters').execute_single_run,
- id='run_op_button'
)
load_data_button = NavigationButton(
text='select data',
on_release=partial(self.go_to_screen, 'load_data'),
- id='load_data_button'
)
set_parameters_button = NavigationButton(
text='set parameters',
on_release=partial(self.go_to_screen, 'set_parameters'),
- id='set_parameters_button'
)
self.reset_nav_bar()
@@ -340,45 +327,15 @@ def build_valuation_results_nav_bar(self):
view_results_button = NavigationButton(
text='view results',
on_release=partial(self.go_to_screen, 'valuation_results_viewer'),
- id='plot_button'
)
- single_run_button = NavigationButton(
- text='single run',
- on_release=partial(self.go_to_screen, 'load_data'),
- id='single_run_button'
- )
-
- # run_op_button = NavigationButton(
- # text='run optimization',
- # on_release=self.sm.get_screen('valuation_advanced').open_valuation_run_menu,
- # id='run_op_button'
- # )
- #
- # load_data_button = NavigationButton(
- # text='load data',
- # on_release=partial(self.go_to_screen, 'load_data'),
- # id='load_data_button'
- # )
- #
- # set_parameters_button = NavigationButton(
- # text='set parameters',
- # on_release=partial(self.go_to_screen, 'set_parameters'),
- # id='set_parameters_button'
- # )
-
batch_processing_button = NavigationButton(
text='batch runs',
on_release=partial(self.go_to_screen, 'batch_run'),
- id='batch_processing_button'
)
self.reset_nav_bar()
- # self.action_view.add_widget(load_data_button)
- # self.action_view.add_widget(set_parameters_button)
- # self.action_view.add_widget(run_op_button)
- self.action_view.add_widget(single_run_button)
self.action_view.add_widget(view_results_button)
self.action_view.add_widget(batch_processing_button)
@@ -387,13 +344,11 @@ def build_valuation_batch_nav_bar(self):
view_results_button = NavigationButton(
text='view results',
on_release=partial(self.go_to_screen, 'valuation_results_viewer'),
- id='plot_button'
)
batch_processing_button = NavigationButton(
text='batch runs',
on_release=partial(self.go_to_screen, 'batch_run'),
- id='batch_processing_button'
)
self.reset_nav_bar()
@@ -418,19 +373,16 @@ def build_index_nav_bar(self):
home_button = NavigationButton(
text='home',
on_release=partial(self.go_to_screen, 'index'),
- id='home_button'
)
settings_button = NavigationButton(
text='settings',
on_release=self.sm.settings_screen.open,
- id='settings_button'
)
about_button = NavigationButton(
text='about',
on_release=self.sm.about_screen.open,
- id='about_button'
)
self.action_view.add_widget(home_button)
@@ -491,9 +443,9 @@ def build_config(self, config):
config.setdefaults('connectivity', {'use_proxy': 0, 'http_proxy': '', 'https_proxy': '', 'use_ssl_verify': 1})
config.setdefaults('valuation', {'valuation_dms_save': 1, 'valuation_dms_size': 20000})
config.setdefaults('btm', {'btm_dms_save': 1, 'btm_dms_size': 20000})
- config.setdefaults('data_manager_pjm', {'pjm_subscription_key': ''})
- config.setdefaults('data_manager_iso-ne', {'iso-ne_api_username': ''})
- config.setdefaults('data_manager_openei', {'openei_key': ''})
+ config.setdefaults('datamanager-pjm', {'pjm_subscription_key': ''})
+ config.setdefaults('datamanager-isone', {'iso-ne_api_username': ''})
+ config.setdefaults('datamanager-openei', {'openei_key': ''})
def build(self):
# Sets the window/application title.
diff --git a/setup.py b/setup.py
index b57a2163..5d520757 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@
from distutils.core import Extension
DISTNAME = 'QuESt'
-VERSION = '1.2'
+VERSION = '1.2.d'
EXTENSIONS = []
PYTHON_REQUIRES='>=36'
DESCRIPTION = 'Sandia National Laboratories application suite for energy storage analysis and evaluation tools.'