GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — archive method for OptimizationResult and total_sims attribute, updat… · PRMS-Python/PRMS-Python@41aeb2b

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • prms_python
    • optimizer.py
    • util.py
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎prms_python/optimizer.py‎

Copy file name to clipboardExpand all lines: prms_python/optimizer.py
+110-6Lines changed: 110 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import numpy as np
77
import matplotlib.pyplot as plt
88
import datetime as dt
9-
import os, sys, json, re
9+
import os, sys, json, re, shutil
1010
import multiprocessing as mp
1111

1212
from copy import copy
@@ -497,7 +497,8 @@ class OptimizationResult:
497497
def __init__(self, working_dir, stage):
498498
self.working_dir = working_dir
499499
self.stage = stage
500-
self.metadata_json_paths = self._get_optr_jsons(working_dir, stage)
500+
self.metadata_json_paths = self._get_optr_jsons(working_dir, stage)
501+
self.total_sims = self._count_total_sims()
501502
self.statvar_name = self._get_statvar_name(stage)
502503
self.measured = self._get_measured(stage)
503504
self.input_dir = self._get_input_dir(stage)
@@ -511,6 +512,15 @@ def __init__(self, working_dir, stage):
511512
params with their corresponding output sims.""".format(stage))
512513
print('\nThis optimization stage used the\
513514
following input parameter files:\n{}'.format('\n'.join(self.input_params)))
515+
516+
def _count_total_sims(self):
517+
# total number of simulations of given stage in working directory
518+
tracked_dirs = []
519+
for f in self.metadata_json_paths[self.stage]:
520+
with open(f) as fh:
521+
json_data = json.load(fh)
522+
tracked_dirs.extend(json_data.get('sim_dirs'))
523+
return len(tracked_dirs)
514524

515525
def _get_optr_jsons(self, work_dir, stage):
516526
"""
@@ -591,7 +601,7 @@ def _get_statvar_name(self, stage):
591601

592602
return var_name
593603

594-
def result_table(self, freq='daily', top_n=5, latex=False):
604+
def result_table(self, freq='daily', top_n=5, latex=False):
595605
##TODO: add stats for freq options annual (means or sum)
596606

597607
sim_dirs = self._get_sim_dirs(self.stage)
@@ -619,8 +629,12 @@ def result_table(self, freq='daily', top_n=5, latex=False):
619629
orig_mo = orig_statvar.groupby(orig_statvar.index.month).mean()
620630

621631
for i, sim in enumerate(sim_dirs):
622-
sim_out = load_statvar(OPJ(sim, 'outputs', 'statvar.dat'))\
632+
try:
633+
sim_out = load_statvar(OPJ(sim, 'outputs', 'statvar.dat'))\
623634
['{}'.format(statvar_name)]
635+
except: # simulation might have been removed or missing
636+
continue
637+
624638
sim_out = sim_out[idx]
625639
if freq == 'daily':
626640
result_df.loc[sim_names[i]] = [\
@@ -668,9 +682,9 @@ def get_top_ranked_sims(self, sorted_df):
668682
'params_adjusted' : []
669683
}
670684

671-
json_paths = self.metadata_json_paths[self.stage]
685+
json_paths = self.metadata_json_paths[self.stage]
672686

673-
for i,el in enumerate(sorted_df.index):
687+
for el in sorted_df.drop('orig_params').index:
674688
ret['dir_name'].append(el)
675689
ret['param_path'].append(OPJ(self.working_dir,el,'inputs',\
676690
'parameters'))
@@ -685,4 +699,94 @@ def get_top_ranked_sims(self, sorted_df):
685699

686700
return ret
687701

702+
def archive(self, remove_sims=True, metric_freq='daily'):
703+
"""
704+
Create archive directory to hold json files that contain
705+
information of adjusted parameters, model output, and performance
706+
metrics for each Optimizer simulation of the
707+
OptimizationResult.stage in the OptimizationResult.working_dir.
708+
709+
Arguments:
710+
remove_sims (bool) : If True recursively delete all folders
711+
and files associated with original simulations of the
712+
OptimizationResult.stage in the
713+
OptimizationResult.working_dir, if False do not delete
714+
simulations.
715+
metric_freq (Str) : Frequency of output metric computation
716+
for recording of model performance. Can be 'daily'
717+
(default) or 'monthly'. Note, new results can be computed
718+
later with archived results.
719+
Returns:
720+
None
721+
"""
722+
# create output archive directory
723+
archive_dir = OPJ(self.working_dir,"{}_archived".format(self.stage))
724+
if not os.path.isdir(archive_dir):
725+
os.mkdir(archive_dir)
688726

727+
# create table and used to make mapping dic
728+
table = self.result_table(freq=metric_freq,\
729+
top_n=self.total_sims, latex=False)
730+
map_dic = self.get_top_ranked_sims(table)
731+
732+
# get measured optimization variable path
733+
first_json = self.metadata_json_paths[self.stage][0]
734+
735+
with open(first_json) as json_file:
736+
json_data = json.load(json_file)
737+
measured_path = json_data.get('measured')
738+
739+
# record info for each simulation and archive to JSONs
740+
# pandas series and numpy arrays are converted to Python lists
741+
# for JSON serialization
742+
for i, sim in enumerate(map_dic.get('dir_name')):
743+
json_path = OPJ(archive_dir, '{sim}.json'.format(sim=sim))
744+
try:
745+
output_series = load_statvar(OPJ(self.working_dir, sim,\
746+
'outputs', 'statvar.dat'))\
747+
[self.statvar_name]
748+
except: # simulation directory was already removed
749+
continue
750+
json_data = {
751+
'param_names' : [],
752+
'param_values' : [],
753+
'original_param_path' : self.input_params,
754+
'measured_path' : measured_path,
755+
'output_name' : self.statvar_name,
756+
'output_date_index' : output_series.\
757+
index.astype(str).tolist(),
758+
'output_values' : output_series.values.tolist(),
759+
'metric_freq' : metric_freq,
760+
'NSE' : table.loc[sim, 'NSE'],
761+
'RMSE' : table.loc[sim, 'RMSE'],
762+
'PBIAS' : table.loc[sim, 'PBIAS'],
763+
'COEF_DET' : table.loc[sim, 'COEF_DET']
764+
}
765+
766+
for param in map_dic.get('params_adjusted')[i]:
767+
json_data['param_names'].append(param)
768+
json_data['param_values'].append(Parameters(\
769+
map_dic.get('param_path')[i])[param]\
770+
.tolist())
771+
# save JSON file into archive directory
772+
with open(json_path, 'w') as outf:
773+
json.dump(json_data, outf, sort_keys = True, indent = 4,\
774+
ensure_ascii = False)
775+
776+
# recursively delete all simulation directories after archiving
777+
if remove_sims:
778+
path = OPJ(self.working_dir, sim)
779+
for dirpath, dirnames, filenames in os.walk(path,\
780+
topdown=False):
781+
shutil.rmtree(dirpath, ignore_errors=True)
782+
else:
783+
continue
784+
785+
# after archiving all simulations delete the original JSON metadata
786+
for meta_file in self.metadata_json_paths[self.stage]:
787+
try:
788+
os.remove(meta_file)
789+
except:
790+
continue
791+
792+
Collapse file

‎prms_python/util.py‎

Copy file name to clipboardExpand all lines: prms_python/util.py
+32-24Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,30 @@
66
import numpy as np
77
import pandas as pd
88

9-
from .optimizer import OptimizationResult
10-
11-
def remove_all_optimization_sims_of_other_stage(work_directory,stage):
12-
"""
13-
9+
def remove_all_optimization_sims_of_other_stage(work_directory, stage):
1410
"""
15-
result = OptimizationResult(work_directory,stage=stage)
16-
17-
tracked_dirs = []
11+
Track number of simulation directories not tracked by a specific stage
12+
and recursively delete them and their contents. This was created to avoid
13+
having nutracked simulations in an optimizer working directory for example
14+
when an optimization method was interupted before data was saved to a meta
15+
data file.
1816
17+
Arguments:
18+
work_directory (str) : Directory to look for Optimization metadata
19+
json files and simulation directories to keep or remove.
20+
stage (str) : Optimization stage that will not have its simulation
21+
data deleted. All other stages if any are found in metadata files
22+
will have their associated simulation directories deleted.
23+
Returns:
24+
None
25+
"""
26+
from .optimizer import OptimizationResult # avoid circular import
27+
result = OptimizationResult(work_directory,stage=stage)
28+
tracked_dirs = []
1929
for f in result.metadata_json_paths[stage]:
2030
with open(f) as fh:
2131
json_data = json.load(fh)
2232
tracked_dirs.extend(json_data.get('sim_dirs'))
23-
24-
# track number of simulation directories not tracked by certain stage
25-
# and recursively delete them and their contents
2633
count = 0
2734
for d in os.listdir(result.working_dir):
2835
path = os.path.join(result.working_dir, d)
@@ -31,24 +38,23 @@ def remove_all_optimization_sims_of_other_stage(work_directory,stage):
3138
elif os.path.isdir(path):
3239
count+=1
3340
for dirpath, dirnames, filenames in os.walk(path, topdown=False):
34-
shutil.rmtree(dirpath, ignore_errors=True)
35-
41+
shutil.rmtree(dirpath, ignore_errors=True)
3642
print('deleted {} simulations that were either not tracked by a JSON file'\
3743
.format(count) + ' or were not part of {} optimization stage'\
3844
.format(stage))
3945

4046
def delete_files(work_directory, file_name=''):
4147
"""
42-
Recursively delete all files of a certain name from PRMS simulations.
43-
Can be useful because files can be large and may not be being used.
44-
For example initial condition output files are often large and not
45-
always used, similarly animation, data, control, ... files may
46-
no longer be needed.
48+
Recursively delete all files of a certain name from multiple PRMS
49+
simulations that are within a given directory. Can be useful to removw
50+
large files that are no longer needed. For example initial condition
51+
output files are often large and not always used, similarly animation,
52+
data, control, ... files may no longer be needed.
4753
4854
Arguments:
49-
work_directory (str): path to directory with simulations.
50-
file_name (str) = Name of the PRMS input or output file(s) to be
51-
removed, default='' empty string- nothing will be deleted.
55+
work_directory (str) : path to directory with simulations.
56+
file_name (str) : Name of the PRMS input or output file(s) to be
57+
removed, default = '' empty string- nothing will be deleted.
5258
5359
e.g. if you have several simulation directories:
5460
@@ -136,11 +142,13 @@ def load_statvar(statvar_file):
136142

137143
def load_data_file(data_file):
138144
"""
139-
Read the data file and load into a datetime indexed Pandas dataframe object
145+
Read the data file and load into a datetime indexed Pandas dataframe object.
146+
140147
Arguments:
141-
data_file (string): data file path
148+
data_file (str): data file path
142149
Returns:
143-
df (pandas.DataFrame): Pandas dataframe of input time series data from data file with datetime index
150+
df (pandas.DataFrame): Pandas dataframe of input time series data
151+
from data file with datetime index
144152
"""
145153
# valid input time series that can be put into a data file
146154
valid_input_variables = ('gate_ht',

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.