diff --git a/tools/autotest/test_isone.glm b/tools/autotest/test_isone.glm index 20fb36441..44f01ba43 100644 --- a/tools/autotest/test_isone.glm +++ b/tools/autotest/test_isone.glm @@ -1,4 +1,4 @@ -#python -m isone -d=smd/ME -s=2020-03-01 -e=2020-03-01 -c=test_isone.csv -g=test_isone_opt.glm +#python -m isone -D=smd/ME -s=2020-03-01 -e=2020-03-01 -c=test_isone.csv -g=test_isone_opt.glm module tape { csv_header_type NAME; diff --git a/tools/isone.py b/tools/isone.py index f7b8b71a8..e93f8c44c 100644 --- a/tools/isone.py +++ b/tools/isone.py @@ -1,9 +1,25 @@ +# Syntax: isone [OPTIONS ...] """ISO New England data access module -Syntax: gridlabd isone OPTIONS ... +Syntax +------ -Options: - -d|--dataset=DATASET/SUBSET Download data from the specified dataset +Shell: + +~~~ +gridlabd isone [OPTIONS ...] +~~~ + +GLM: + +~~~ +#python -m isone [OPTIONS ...] +~~~ + +Options +------- + -d|-debug Enable traceback output on exceptions + -D|--dataset=DATASET/SUBSET Download data from the specified dataset (and subset, default is `smd/ISO NE CA`) -c|--csv=FILENAME Save CSV data to the specified file (default is /dev/stdout) @@ -14,17 +30,37 @@ -f|--freshen Freshen the data cache -g|--glm=FILENAME Save GLM data to the specified file (default is /dev/null) + -h|--help|help Output the help documentation -l|--list Output a list of available sheets in dataset -N|--NAME=OBJECTNAME Specify the GLM object name (default is `isone`) + -q|--quiet Suppress error output messages -s|--start=YEAR|STARTDATE Download data starting on the specified year or date (last month by default) + -v|--verbose Enable verbose output -y|--year[=YEAR] Download data for the specified year (current year by default) Currently the only supported dataset is `smd`. The valid subsets depend on the dataset and year. See https://www.iso-ne.com/isoexpress/web/reports/load-and-demand/-/tree/zone-info for more information. + +Example +------- + +The following generates the wholesale market data New Hampshire for May 2023: + +~~~ +sh$ gridlabd isone -D=smd/NH -f -s=2023-05-01 -e=2023-06-01 +timestamp,DA_Demand,RT_Demand,DA_LMP,DA_EC,DA_CC,DA_MLC,RT_LMP,RT_EC,RT_CC,RT_MLC,Dry_Bulb,Dew_Point +2023-05-01 00:00:00,801.30,924.94,24.63,24.64,-0.05,0.04,18.96,18.75,0.18,0.03,53,51 +2023-05-01 01:00:00,807.90,899.31,20.61,20.59,-0.03,0.05,18.88,18.70,0.18,0.00,54,53 +2023-05-01 02:00:00,765.20,885.84,20.56,20.57,-0.03,0.02,18.12,17.73,0.41,-0.02,54,53 +... +2023-06-01 21:00:00,1753.00,1594.43,58.33,57.55,0.00,0.78,41.90,41.65,0.00,0.25,75,61 +2023-06-01 22:00:00,1495.20,1425.32,50.57,50.31,0.00,0.26,35.95,35.82,0.00,0.13,77,59 +2023-06-01 23:00:00,1269.60,1283.86,53.36,52.86,0.00,0.50,36.52,36.40,0.00,0.12,77,59 +~~~ """ import sys, os @@ -34,7 +70,7 @@ import traceback EXECNAME = os.path.splitext(os.path.basename(sys.argv[0]))[0] -DATASET = "smd" +DATASET = "smd/ISO NE CA" CSVFILE = "/dev/stdout" GLMFILE = None CLASSNAME = "isone" @@ -55,7 +91,12 @@ E_INVALID = 2 E_FAILED = 3 +class IsoneException(Exception): + pass + def error(msg,code=None): + if DEBUG: + raise IsoneException(msg) if not QUIET: print(f"ERROR [{EXECNAME}]: {msg}",flush=True,file=sys.stderr) if not code is None: @@ -79,6 +120,9 @@ def get_year(year=None,dataset=None): dataset = DATASET verbose(f"setting to default dataset '{dataset}'") specs = dataset.split("/") + if len(specs) != 2: + error(f"dataset {dataset} is not valid",E_INVALID) + cachefile = os.path.join(CACHEDIR,f"{specs[0]}_{year}.xlsx") if FRESHEN or not os.path.exists(cachefile): verbose(f"creating cache directory '{CACHEDIR}'") @@ -95,12 +139,8 @@ def get_year(year=None,dataset=None): error(f"unable to download data from '{url}' (HTTP code {req.status_code})",E_FAILED) except Exception as err: error(f"unable to get data from '{url}' ({err})",E_FAILED) - if len(specs) > 1: - verbose(f"loading '{specs[1]}' from '{cachefile}'") - return pandas.read_excel(cachefile,sheet_name=specs[1],index_col=[0,1],parse_dates=[0]) - else: - verbose(f"loading data from '{cachefile}'") - return pandas.read_excel(cachefile,sheet_name=None) + verbose(f"loading '{specs[1]}' from '{cachefile}'") + return pandas.read_excel(cachefile,sheet_name=specs[1],index_col=[0,1],parse_dates=[0]) def get_data(startdate=None,stopdate=None,dataset=None): """Get data from a date range @@ -110,10 +150,10 @@ def get_data(startdate=None,stopdate=None,dataset=None): :return: pandas.DataFrame - the requested data """ if startdate == None: - startdate = datetime.datetime(year=datetime.datetime.now().year) + startdate = datetime.datetime(year=datetime.datetime.now().year,month=1,day=1) else: startdate = datetime.datetime.strptime(startdate,DATEFORMAT) - if startdate == None: + if stopdate == None: stopdate = datetime.datetime.now() else: stopdate = datetime.datetime.strptime(stopdate,DATEFORMAT) @@ -159,12 +199,12 @@ def fix_timestamps(df): VERBOSE = True elif token in ["-q","--quiet"]: QUIET = True - elif token in ["--debug"]: + elif token in ["-d","--debug"]: DEBUG = True - # -d|--dataset=DATASET/SUBSET Download data from the specified dataset + # -D|--dataset=DATASET/SUBSET Download data from the specified dataset # (and subset, default is `smd/ISO NE CA`) - elif token in ["-d","--dataset"]: + elif token in ["-D","--dataset"]: if value: DATASET = value else: