diff --git a/setup.py b/setup.py index a7880e0..ec2f459 100755 --- a/setup.py +++ b/setup.py @@ -32,7 +32,8 @@ 'Topic :: Scientific/Engineering :: Information Analysis', ], entry_points={ - 'console_scripts': ['hillmaker=hillmaker.hills:main'], + 'console_scripts': + ['hillmaker=hillmaker.hills:main', 'hill_gui=hillmaker.gui:main'], }, project_urls={ 'Source': 'http://github.com/misken/hillmaker', diff --git a/src/hillmaker/gui.py b/src/hillmaker/gui.py new file mode 100644 index 0000000..24a4c05 --- /dev/null +++ b/src/hillmaker/gui.py @@ -0,0 +1,178 @@ +# Copyright 2022 Mark Isken, Jacob Norman + +from datetime import datetime as dt +import os +import sys +import json +from gooey import Gooey, GooeyParser + + +@Gooey(program_name='Hillmaker Occupancy Analysis', + target='hillmaker.exe', + default_size=(610, 610), + required_cols=2, + optional_cols=2, + tabbed_groups=True, + use_events='VALIDATE_FORM' + ) +def get_user_input(argv=None): + """ + Adds GUI to hillmaker function make_hills. + + Use GooeyParser to get user-defined inputs for use with the + hillmaker function make_hills. Saves the arguments in a + default json file so that the most recent selections are the + preselected values for subsequent runs. + + Returns + ---------- + args : GooeyParser + Used to retrieve user inputs. + """ + + stored_args = {} + # get the script name without the extension and use it to build up + # the json filename + script_name = os.path.splitext(os.path.basename(__file__))[0] + args_file = f'{script_name}-args.json' + + # read in the prior arguments as a dictionary + if os.path.isfile(args_file): + with open(args_file) as data_file: + stored_args = json.load(data_file) + + test = "user_input.lower().endswith('.csv')" + message = 'Must be .csv file' + today = str(int(dt.now().strftime('%Y%m%d'))) + + parser = GooeyParser(description='Computes occupancy statistics based on a list of start and stop times.') + + parser.add_argument('scenario', + metavar='Scenario', + action='store', + default=stored_args.get('scenario'), + help='Specify a scenario name for output files', + gooey_options={ + 'validator': { + 'test': 'len(user_input) > 0 ', + 'message': 'Must be a valid year in integer form' + } + }) + + parser.add_argument('stop_data_csv', + metavar='Timestamps Filename', + action='store', + default=stored_args.get('stops_fn'), + help='Select file containing start and stop times', + widget='FileChooser', + gooey_options={ + 'validator': { + 'test': test, + 'message': message + } + }) + + parser.add_argument('in_field', + metavar='In Time Field Name', + action='store', + default=stored_args.get('in_fld_name'), + help='Set the time in field name', + gooey_options={ + 'validator': { + 'test': 'len(user_input) > 0 ', + 'message': 'Must be a valid year in integer form' + } + }) + + parser.add_argument('out_field', + metavar='Out Time Field Name', + action='store', + default=stored_args.get('out_fld_name'), + help='Set the time out field name', + gooey_options={ + 'validator': { + 'test': 'len(user_input) > 0 ', + 'message': 'Must be a valid year in integer form' + } + }) + + parser.add_argument('start_analysis_dt', + metavar='Start Date', + action='store', + default=stored_args.get('start_ts'), + help='Set the time out field name', + widget='DateChooser', + gooey_options={ + 'validator': { + 'test': 'int(user_input.replace("-", "")) <= ' + today, + 'message': 'Must be a valid date up to and including today' + } + }) + + parser.add_argument('end_analysis_dt', + metavar='End Date', + action='store', + default=stored_args.get('end_ts'), + help='Set the time out field name', + widget='DateChooser', + gooey_options={ + 'validator': { + 'test': 'int(user_input.replace("-", "")) <= ' + today, + 'message': 'Must be a valid date up to and including today' + } + }) + + parser.add_argument('--cat_field', + metavar='Category', + action='store', + #default=stored_args.get('cat_fld_name'), + help='Select a category to separate analysis by' + ) + + parser.add_argument('--bin_size_mins', + metavar='Bin Size', + action='store', + widget='Slider', + default=60, + help='The size of the time bins in minutes', + type=int, + gooey_options={'min': 0, 'max': 60} + ) + + parser.add_argument('--output_path', + metavar='Output Directory', + action='store', + widget='DirChooser', + default=stored_args.get('output_dir'), + help='Select output directory to save files', + ) + + parser.add_argument('--verbosity', + metavar='Verbosity', + action='store', + widget='Slider', + default=0, + help='0=logging.WARNING, 1=logging.INFO, 2=logging.DEBUG', + type=int, + gooey_options={'min': 0, 'max': 2} + ) + + args = parser.parse_args() + # store the values of the args to be defaults on next run + with open(args_file, 'w') as data_file: + # using vars(args) returns the data as a dictionary + json.dump({i: vars(args)[i] for i in vars(args) if i != 'db_pwd'}, data_file) + return args + + +def main(argv=None): + """ + :param argv: Input arguments + :return: No return value + """ + # launch gui and get user input + inputs = get_user_input() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/hillmaker/hills.py b/src/hillmaker/hills.py index a9cd330..b73fba4 100755 --- a/src/hillmaker/hills.py +++ b/src/hillmaker/hills.py @@ -1,18 +1,6 @@ """Hillmaker""" -# Copyright 2015, 2022 Mark Isken, Jacob Norman -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright 2022 Mark Isken, Jacob Norman import sys from pathlib import Path @@ -391,32 +379,32 @@ def process_command_line(argv=None): # Add arguments required.add_argument( - '--scenario', type=str, + 'scenario', type=str, help="Used in output filenames" ) required.add_argument( - '--stop_data_csv', type=str, + 'stop_data_csv', type=str, help="Path to csv file containing the stop data to be processed" ) required.add_argument( - '--in_field', type=str, + 'in_field', type=str, help="Column name corresponding to the arrival times" ) required.add_argument( - '--out_field', type=str, + 'out_field', type=str, help="Column name corresponding to the departure times" ) required.add_argument( - '--start_analysis_dt', type=str, + 'start_analysis_dt', type=str, help="Starting datetime for the analysis (must be convertible to pandas Timestamp)" ) required.add_argument( - '--end_analysis_dt', type=str, + 'end_analysis_dt', type=str, help="Ending datetime for the analysis (must be convertible to pandas Timestamp)" ) @@ -489,7 +477,7 @@ def process_command_line(argv=None): # Do the parsing and return the populated namespace with the input arg values # If argv == None, then ``parse_args`` will use ``sys.argv[1:]``. - args = parser.parse_args(argv) + args, unknown = parser.parse_known_args(argv) return args def update_args(args, toml_config): diff --git a/src/hillmaker/plotting.py b/src/hillmaker/plotting.py index 03f1f15..be3b049 100644 --- a/src/hillmaker/plotting.py +++ b/src/hillmaker/plotting.py @@ -1,16 +1,4 @@ # Copyright 2022 Mark Isken, Jacob Norman -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import pandas as pd import matplotlib.pyplot as plt