diff --git a/autotest/pst_from_tests.py b/autotest/pst_from_tests.py index a074fd175..2b6ca4c02 100644 --- a/autotest/pst_from_tests.py +++ b/autotest/pst_from_tests.py @@ -984,100 +984,6 @@ def mf6_freyberg_shortnames_test(): os.path.join(tmp_model_ws, "freyberg6.nam"), delr=m.dis.delr.array, delc=m.dis.delc.array) # set up PstFrom object - pf = PstFrom(original_d=tmp_model_ws, new_d=template_ws, - remove_existing=True, - longnames=False, spatial_reference=sr, - zero_based=False,start_datetime="1-1-2018") - - df = pd.read_csv(os.path.join(tmp_model_ws, "heads.csv"), index_col=0) - try: - pf.add_observations("heads.csv", insfile="heads.csv.ins", index_cols="time", use_cols=list(df.columns.values), - prefix="hds_too_long_tho") - except: - pass - else: - raise Exception("should have failed") - - pf = PstFrom(original_d=tmp_model_ws, new_d=template_ws, - remove_existing=True, - longnames=False, spatial_reference=sr, - zero_based=False, start_datetime="1-1-2018") - try: - pf.add_parameters(filenames="freyberg6.sfr_packagedata.txt", par_name_base="rhk_still_too_long", - pargp="sfr_rhk", index_cols=[0, 1, 2, 3], use_cols=[9], upper_bound=10., lower_bound=0.1, - par_type="grid") - except: - pass - else: - raise Exception("should have failed") - - pf = PstFrom(original_d=tmp_model_ws, new_d=template_ws, - remove_existing=True, - longnames=False, spatial_reference=sr, - zero_based=False, start_datetime="1-1-2018") - try: - pf.add_parameters(filenames="freyberg6.sfr_packagedata.txt", par_name_base="rhk_still_too_long", - pargp="sfr_rhk", index_cols=[0, 1, 2, 3], use_cols=[9], upper_bound=10., lower_bound=0.1, - par_type="grid", par_style="direct") - except: - pass - else: - raise Exception("should have failed") - - pf = PstFrom(original_d=tmp_model_ws, new_d=template_ws, - remove_existing=True, - longnames=False, spatial_reference=sr, - zero_based=False, start_datetime="1-1-2018") - try: - pf.add_parameters(filenames="freyberg6.ic_strt_layer1.txt", par_name_base="rhk_still_too_long", - pargp="sfr_rhk", upper_bound=10., lower_bound=0.1, - par_type="pilotpoints") - except: - pass - else: - raise Exception("should have failed") - - pf = PstFrom(original_d=tmp_model_ws, new_d=template_ws, - remove_existing=True, - longnames=False, spatial_reference=sr, - zero_based=False, start_datetime="1-1-2018") - try: - pf.add_parameters(filenames="freyberg6.ic_strt_layer1.txt", par_name_base="rhk_still_too_long", - pargp="sfr_rhk", upper_bound=10., lower_bound=0.1, - par_type="grid") - except: - pass - else: - raise Exception("should have failed") - - try: - pf.add_parameters(filenames="freyberg6.ic_strt_layer1.txt", par_name_base="rhk_still_too_long", - pargp="sfr_rhk", upper_bound=10., lower_bound=0.1, - par_type="grid",par_style="direct") - except: - pass - else: - raise Exception("should have failed") - - - try: - pf.add_parameters(filenames="freyberg6.ic_strt_layer1.txt", par_name_base="rhk_still_too_long", - pargp="sfr_rhk", upper_bound=10., lower_bound=0.1, - par_type="constant") - except: - pass - else: - raise Exception("should have failed") - - try: - pf.add_parameters(filenames="freyberg6.ic_strt_layer1.txt", par_name_base="rhk_still_too_long", - pargp="sfr_rhk", upper_bound=10., lower_bound=0.1, - par_type="zone") - except: - pass - else: - raise Exception("should have failed") - # obs # using tabular style model output # (generated by pyemu.gw_utils.setup_hds_obs()) @@ -1088,11 +994,10 @@ def mf6_freyberg_shortnames_test(): remove_existing=True, longnames=False, spatial_reference=sr, zero_based=False, start_datetime="1-1-2018") - df = pd.read_csv(os.path.join(tmp_model_ws,"heads.csv"),index_col=0) - pf.add_observations("heads.csv",insfile="heads.csv.ins",index_cols="time",use_cols=list(df.columns.values),prefix="hds") - df = pd.read_csv(os.path.join(tmp_model_ws, "sfr.csv"), index_col=0) - pf.add_observations("sfr.csv", insfile="sfr.csv.ins", index_cols="time", use_cols=list(df.columns.values)) - v = pyemu.geostats.ExpVario(contribution=1.0,a=1000) + df = pd.read_csv(os.path.join(tmp_model_ws,"heads.csv"), index_col=0) + pf.add_observations("heads.csv",insfile="heads.csv.ins", index_cols="time", + use_cols=list(df.columns.values), prefix="hds") + v = pyemu.geostats.ExpVario(contribution=1.0, a=1000) gr_gs = pyemu.geostats.GeoStruct(variograms=v) rch_temporal_gs = pyemu.geostats.GeoStruct(variograms=pyemu.geostats.ExpVario(contribution=1.0,a=60)) pf.extra_py_imports.append('flopy') @@ -1129,7 +1034,7 @@ def mf6_freyberg_shortnames_test(): pf.add_parameters(filenames=list_file,par_type="constant",par_name_base="w{0}".format(kper), pargp="wel_{0}".format(kper),index_cols=[0,1,2],use_cols=[3], upper_bound=1.5,lower_bound=0.5) - za = np.ones((3,40,20)) + za = np.ones((3, 40, 20)) df = pd.read_csv(os.path.join(m.model_ws, list_file), delim_whitespace=True, header=None) - 1 za[tuple(df.loc[0:2, [0, 1, 2]].values.T)] = [2,3,4] @@ -1140,9 +1045,6 @@ def mf6_freyberg_shortnames_test(): upper_bound=1.5, lower_bound=0.5, zone_array=za) assert len(pdf) == 4 - pf.add_parameters(filenames="freyberg6.sfr_packagedata.txt", par_name_base="rhk", - pargp="sfr_rhk", index_cols=[0, 1, 2, 3], use_cols=[9], upper_bound=10., lower_bound=0.1, - par_type="grid") # add model run command pf.mod_sys_cmds.append("mf6") @@ -1152,6 +1054,18 @@ def mf6_freyberg_shortnames_test(): # build pest pst = pf.build_pst('freyberg.pst') + # test update/rebuild + pf.add_parameters(filenames="freyberg6.sfr_packagedata.txt", + par_name_base="rhk", + pargp="sfr_rhk", index_cols=[0, 1, 2, 3], use_cols=[9], + upper_bound=10., lower_bound=0.1, + par_type="grid", rebuild_pst=True) + pf.add_parameters(filenames=arr_file, par_type="grid", par_name_base=pb + "g2", + pargp=pb + "g2", zone_array=ib, upper_bound=ub, lower_bound=lb, + geostruct=gr_gs, rebuild_pst=True) + df = pd.read_csv(os.path.join(tmp_model_ws, "sfr.csv"), index_col=0) + pf.add_observations("sfr.csv", insfile="sfr.csv.ins", index_cols="time", + use_cols=list(df.columns.values), rebuild_pst=True) assert pst.parameter_data.parnme.apply(lambda x: len(x)).max() <= 12 assert pst.observation_data.obsnme.apply(lambda x: len(x)).max() <= 20 @@ -1171,13 +1085,14 @@ def mf6_freyberg_shortnames_test(): os.chdir(b_d) raise Exception(str(e)) os.chdir(b_d) - + pst.try_parse_name_metadata() pst.control_data.noptmax = 0 pst.pestpp_options["additional_ins_delimiters"] = "," pst.write(os.path.join(pf.new_d, "freyberg.pst")) pyemu.os_utils.run("{0} freyberg.pst".format(ies_exe_path), cwd=pf.new_d) + pst = pyemu.Pst(os.path.join(pf.new_d, "freyberg.pst")) res_file = os.path.join(pf.new_d, "freyberg.base.rei") assert os.path.exists(res_file), res_file pst.set_res(res_file) @@ -1592,7 +1507,8 @@ def mf6_freyberg_direct_test(): cov.to_coo("prior.jcb") pst.try_parse_name_metadata() df = pd.read_csv(os.path.join(tmp_model_ws, "heads.csv"), index_col=0) - pf.add_observations("heads.csv", insfile="heads.csv.ins", index_cols="time", use_cols=list(df.columns.values), + pf.add_observations("heads.csv", insfile="heads.csv.ins", index_cols="time", + use_cols=list(df.columns.values), prefix="hds", rebuild_pst=True) # test par mults are working @@ -1992,8 +1908,13 @@ def mf6_freyberg_short_direct_test(): rch_temporal_gs = pyemu.geostats.GeoStruct(variograms=pyemu.geostats.ExpVario(contribution=1.0, a=60)) pf.extra_py_imports.append('flopy') ib = m.dis.idomain[0].array - tags = {"npf_k_": [0.1, 10.], "npf_k33_": [.1, 10], "sto_ss": [.1, 10], "sto_sy": [.9, 1.1], - "rch_recharge": [.5, 1.5]} + tags = { + "npf_k_": [0.1, 10.], + "npf_k33_": [.1, 10], + "sto_ss": [.1, 10], + "sto_sy": [.9, 1.1], + "rch_recharge": [.5, 1.5] + } dts = pd.to_datetime("1-1-2018") + pd.to_timedelta(np.cumsum(sim.tdis.perioddata.array["perlen"]), unit="d") print(dts) # setup from array style pars @@ -2064,7 +1985,7 @@ def mf6_freyberg_short_direct_test(): pargp="wel_{0}_direct".format(kper), index_cols=[0, 1, 2], use_cols=[3], upper_bound=0.0, lower_bound=-1000, geostruct=gr_gs, par_style="direct", transform="none") - # Adding dummy list pars with different file structures + # # Adding dummy list pars with different file structures list_file = "new_freyberg6.wel_stress_period_data_1.txt" # with a header pf.add_parameters(filenames=list_file, par_type="grid", par_name_base='nw', pargp='nwell_mult', index_cols=['k', 'i', 'j'], use_cols='flx', @@ -2116,7 +2037,8 @@ def mf6_freyberg_short_direct_test(): cov.to_coo("prior.jcb") pst.try_parse_name_metadata() df = pd.read_csv(os.path.join(tmp_model_ws, "heads.csv"), index_col=0) - pf.add_observations("heads.csv", insfile="heads.csv.ins", index_cols="time", use_cols=list(df.columns.values), + pf.add_observations("heads.csv", insfile="heads.csv.ins", index_cols="time", + use_cols=list(df.columns.values), prefix="hds", rebuild_pst=True) # test par mults are working @@ -2166,13 +2088,16 @@ def mf6_freyberg_short_direct_test(): # turn direct recharge to min and direct wel to min and # check that the model results are consistent par = pst.parameter_data - rch_par = par.loc[par.pargp.apply( - lambda x: "rch_gr" in x and "direct" in x), "parnme"] - wel_par = par.loc[par.pargp.apply( - lambda x: "wel_" in x and "direct" in x), "parnme"] - par.loc[rch_par,"parval1"] = par.loc[rch_par, "parlbnd"] + rch_par = par.loc[(par.pname == 'rch') & + (par.ptype == 'gr') & + (par.pstyle == 'd'), + "parnme"] + wel_par = par.loc[(par.pname.str.contains('wel')) & + (par.pstyle == 'd'), + "parnme"] + par.loc[rch_par, "parval1"] = par.loc[rch_par, "parlbnd"] # this should set wells to zero since they are negative values in the control file - par.loc[wel_par,"parval1"] = par.loc[wel_par, "parubnd"] + par.loc[wel_par, "parval1"] = par.loc[wel_par, "parubnd"] pst.write(os.path.join(pf.new_d, "freyberg.pst")) pyemu.os_utils.run("{0} freyberg.pst".format(ies_exe_path), cwd=pf.new_d) lst = flopy.utils.Mf6ListBudget(os.path.join(pf.new_d, "freyberg6.lst")) @@ -2853,7 +2778,7 @@ def mf6_freyberg_arr_obs_and_headerless_test(): os.mkdir(tmp_model_ws) sim = flopy.mf6.MFSimulation.load(sim_ws=org_model_ws) # sim.set_all_data_external() - sim.simulation_data.mfpath.set_sim_path(tmp_model_ws) + sim.set_sim_path(tmp_model_ws) # sim.set_all_data_external() m = sim.get_model("freyberg6") sim.set_all_data_external(check_data=False) @@ -3688,6 +3613,7 @@ def mf6_subdir_test(): # assert np.abs(float(df.upper_bound.min()) - 30.) < 1.0e-6,df.upper_bound.min() # assert np.abs(float(df.lower_bound.max()) - -0.3) < 1.0e-6,df.lower_bound.max() + if __name__ == "__main__": #mf6_freyberg_pp_locs_test() # invest() @@ -3695,12 +3621,12 @@ def mf6_subdir_test(): #freyberg_prior_build_test() # mf6_freyberg_test() #$mf6_freyberg_da_test() - #mf6_freyberg_shortnames_test() + # mf6_freyberg_shortnames_test() #mf6_freyberg_direct_test() #mf6_freyberg_varying_idomain() # xsec_test() - # mf6_freyberg_short_direct_test() + mf6_freyberg_short_direct_test() # mf6_add_various_obs_test() # mf6_subdir_test() tpf = TestPstFrom() diff --git a/pyemu/pst/pst_handler.py b/pyemu/pst/pst_handler.py index 6533e7718..ec034c16f 100644 --- a/pyemu/pst/pst_handler.py +++ b/pyemu/pst/pst_handler.py @@ -1243,8 +1243,28 @@ def load(self, filename): ) self._load_version2(filename) + self._try_load_longnames() self.try_parse_name_metadata() + def _try_load_longnames(self): + from pathlib import Path + d = Path(self.filename).parent + for df, fnme in ((self.parameter_data, "parlongname.map"), + (self.observation_data, "obslongname.map")): + try: + mapr = pd.read_csv(Path(d, fnme), index_col=0)['longname'] + df['longname'] = df.index.map(mapr.to_dict()) + except Exception: + pass + if hasattr(self, "parameter_groups"): + df, fnme = (self.parameter_groups, "pglongname.map") + try: + mapr = pd.read_csv(Path(d, fnme), index_col=0)['longname'] + df['longname'] = df.index.map(mapr.to_dict()) + except Exception: + pass + + def _parse_pestpp_line(self, line): # args = line.replace('++','').strip().split() args = line.replace("++", "").strip().split(")") @@ -3751,8 +3771,17 @@ def try_parse_name_metadata(self): par_cols = pst_utils.pst_config["par_fieldnames"] obs_cols = pst_utils.pst_config["obs_fieldnames"] + if "longname" in par.columns: + partg = "longname" + else: + partg = "parnme" + if "longname" in obs.columns: + obstg = "longname" + else: + obstg = "obsnme" + for df, name, fieldnames in zip( - [par, obs], ["parnme", "obsnme"], [par_cols, obs_cols] + [par, obs], [partg, obstg], [par_cols, obs_cols] ): try: meta_dict = df.loc[:, name].apply( @@ -3817,9 +3846,12 @@ def rename_parameters(self, name_dict, pst_path="."): eq = eq.replace(old, new) self.prior_information.loc[idx, "equation"] = eq + # pad for putting to tpl + name_dict = {k: v.center(12) for k, v in name_dict.items()} for tpl_file in self.model_input_data.pest_file: sys_tpl_file = os.path.join( - pst_path, tpl_file.replace("/", os.path.sep).replace("\\", os.path.sep) + pst_path, + str(tpl_file).replace("/", os.path.sep).replace("\\", os.path.sep) ) if not os.path.exists(sys_tpl_file): warnings.warn( @@ -3869,7 +3901,7 @@ def rename_observations(self, name_dict, pst_path="."): for ins_file in self.model_output_data.pest_file: sys_ins_file = os.path.join( - pst_path, ins_file.replace("/", os.path.sep).replace("\\", os.path.sep) + pst_path, str(ins_file).replace("/", os.path.sep).replace("\\", os.path.sep) ) if not os.path.exists(sys_ins_file): warnings.warn( diff --git a/pyemu/pst/pst_utils.py b/pyemu/pst/pst_utils.py index 3c2f97569..743b8ae6e 100644 --- a/pyemu/pst/pst_utils.py +++ b/pyemu/pst/pst_utils.py @@ -1036,7 +1036,6 @@ def csv_to_ins_file( includes_header=True, includes_index=True, prefix="", - longnames=False, head_lines_len=0, sep=",", gpname=False, @@ -1103,10 +1102,7 @@ def csv_to_ins_file( for rname_org in df.index: rname = str(rname_org).strip().lower() if rname in row_visit: - if longnames: - rsuffix = "_" + str(int(row_visit[rname] + 1)) - else: - rsuffix = str(int(row_visit[rname] + 1)) + rsuffix = "_" + str(int(row_visit[rname] + 1)) row_visit[rname] += 1 else: row_visit[rname] = 1 @@ -1124,10 +1120,7 @@ def csv_to_ins_file( for cname_org in df.columns: cname = str(cname_org).strip().lower() if cname in col_visit: - if longnames: - csuffix = "_" + str(int(col_visit[cname] + 1)) - else: - csuffix = str(int(col_visit[cname] + 1)) + csuffix = "_" + str(int(col_visit[cname] + 1)) col_visit[cname] += 1 else: col_visit[cname] = 1 @@ -1185,26 +1178,11 @@ def csv_to_ins_file( nprefix = prefix[c_count] else: nprefix = prefix - if longnames: - if len(nprefix) > 0: - nname = f"{nprefix}_usecol:{clabel}" - else: - nname = f"usecol:{clabel}" - oname = f"{nname}_{rlabel}" + if len(nprefix) > 0: + nname = f"{nprefix}_usecol:{clabel}" else: - nname = nprefix + clabel.replace(" ", "").replace("_", "") - oname = ( - nprefix - + rlabel.replace(" ", "").replace("_", "") - + clabel.replace(" ", "").replace("_", "") - ) - if len(oname) > 20: - raise Exception( - "csv_to_ins_file(): cant form observation name " - + " for prefix '{0}' , row '{1}', col '{2}' in less than 20 chars".format( - nprefix, rlabel, clabel - ) - ) + nname = f"usecol:{clabel}" + oname = f"{nname}_{rlabel}" onames.append(oname) # append list of obs ovals.append(vals[i, j]) # store current obs val # defin group name diff --git a/pyemu/utils/pp_utils.py b/pyemu/utils/pp_utils.py index 24222925e..d053904b1 100644 --- a/pyemu/utils/pp_utils.py +++ b/pyemu/utils/pp_utils.py @@ -33,7 +33,6 @@ def setup_pilotpoints_grid( pp_dir=".", tpl_dir=".", shapename="pp.shp", - longnames=False, pp_filename_dict={}, ): """setup a regularly-spaced (gridded) pilot point parameterization @@ -59,7 +58,6 @@ def setup_pilotpoints_grid( tpl_dir (`str`, optional): directory to write pilot point template file to. Default is '.' shapename (`str`, optional): name of shapefile to write that contains pilot point information. Default is "pp.shp" - longnames (`bool`): flag to use parameter names longer than 12 chars. Default is False pp_filename_dict (`dict`): optional dict of prefix-pp filename pairs. prefix values must match the values in `prefix_dict`. If None, then pp filenames are based on the key values in `prefix_dict`. Default is None @@ -240,7 +238,7 @@ def setup_pilotpoints_grid( tpl_filename = os.path.join(tpl_dir, base_filename + ".tpl") # write the tpl file pilot_points_to_tpl( - pp_df, tpl_filename, name_prefix=prefix, longnames=longnames + pp_df, tpl_filename, name_prefix=prefix, ) pp_df.loc[:, "tpl_filename"] = tpl_filename pp_df.loc[:, "pp_filename"] = pp_filename @@ -490,7 +488,7 @@ def write_pp_file(filename, pp_df): ) -def pilot_points_to_tpl(pp_file, tpl_file=None, name_prefix=None, longnames=False): +def pilot_points_to_tpl(pp_file, tpl_file=None, name_prefix=None): """write a template file for a pilot points file Args: @@ -502,8 +500,6 @@ def pilot_points_to_tpl(pp_file, tpl_file=None, name_prefix=None, longnames=Fals pilot point parameters will be named "hk_0001","hk_0002", etc. If None, parameter names from `pp_df.name` are used. Default is None. - longnames (`bool`): flag to use parameter names longer than 12 chars. - Default is False Returns: `pandas.DataFrame`: a dataframe with pilot point information @@ -512,7 +508,7 @@ def pilot_points_to_tpl(pp_file, tpl_file=None, name_prefix=None, longnames=Fals Example:: - pyemu.pp_utils.pilot_points_to_tpl("my_pps.dat",name_prefix="my_pps",longnames=True) + pyemu.pp_utils.pilot_points_to_tpl("my_pps.dat",name_prefix="my_pps") """ @@ -527,82 +523,45 @@ def pilot_points_to_tpl(pp_file, tpl_file=None, name_prefix=None, longnames=Fals if tpl_file is None: tpl_file = pp_file + ".tpl" - if longnames: - if name_prefix is not None: - if "i" in pp_df.columns and "j" in pp_df.columns: - pp_df.loc[:, "parnme"] = pp_df.apply( - lambda x: "{0}_i:{1}_j:{2}".format(name_prefix, int(x.i), int(x.j)), - axis=1, - ) - elif "x" in pp_df.columns and "y" in pp_df.columns: - pp_df.loc[:, "parnme"] = pp_df.apply( - lambda x: "{0}_x:{1:0.2f}_y:{2:0.2f}".format(name_prefix, x.x, x.y), - axis=1, - ) - else: - pp_df.loc[:, "idx"] = np.arange(pp_df.shape[0]) - pp_df.loc[:, "parnme"] = pp_df.apply( - lambda x: "{0}_ppidx:{1}".format(name_prefix, x.idx), - axis=1, - ) - if "zone" in pp_df.columns: - pp_df.loc[:, "parnme"] = pp_df.apply( - lambda x: x.parnme + "_zone:{0}".format(x.zone), axis=1 - ) - pp_df.loc[:, "tpl"] = pp_df.parnme.apply( - lambda x: "~ {0} ~".format(x) + if name_prefix is not None: + if "i" in pp_df.columns and "j" in pp_df.columns: + pp_df.loc[:, "parnme"] = pp_df.apply( + lambda x: "{0}_i:{1}_j:{2}".format(name_prefix, int(x.i), int(x.j)), + axis=1, ) - else: - names = pp_df.name.copy() - pp_df.loc[:, "parnme"] = pp_df.name - pp_df.loc[:, "tpl"] = pp_df.parnme.apply( - lambda x: "~ {0} ~".format(x) + elif "x" in pp_df.columns and "y" in pp_df.columns: + pp_df.loc[:, "parnme"] = pp_df.apply( + lambda x: "{0}_x:{1:0.2f}_y:{2:0.2f}".format(name_prefix, x.x, x.y), + axis=1, ) - _write_df_tpl( - tpl_file, - pp_df.loc[:, ["name", "x", "y", "zone", "tpl"]], - sep=" ", - index_label="index", - header=False, - index=False, - quotechar=" ", - quoting=2, - ) - else: - if name_prefix is not None: - digits = str(len(str(pp_df.shape[0]))) - fmt = "{0:0" + digits + "d}" - if len(name_prefix) + 1 + int(digits) > 12: - warnings.warn("name_prefix too long for parameter names", PyemuWarning) - names = [ - "{0}_{1}".format(name_prefix, fmt.format(i)) - for i in range(pp_df.shape[0]) - ] else: - names = pp_df.name.copy() - too_long = [] - for name in names: - if len(name) > 12: - too_long.append(name) - if len(too_long) > 0: - raise Exception( - "the following parameter names are too long:" + ",".join(too_long) + pp_df.loc[:, "idx"] = np.arange(pp_df.shape[0]) + pp_df.loc[:, "parnme"] = pp_df.apply( + lambda x: "{0}_ppidx:{1}".format(name_prefix, x.idx), + axis=1, ) - tpl_entries = ["~ {0} ~".format(name) for name in names] - pp_df.loc[:, "tpl"] = tpl_entries - pp_df.loc[:, "parnme"] = names - f_tpl = open(tpl_file, "w") - f_tpl.write("ptf ~\n") - f_tpl.write( - pp_df.to_string( - col_space=0, - columns=["name", "x", "y", "zone", "tpl"], - formatters=PP_FMT, - justify="left", - header=False, - index=False, + if "zone" in pp_df.columns: + pp_df.loc[:, "parnme"] = pp_df.apply( + lambda x: x.parnme + "_zone:{0}".format(x.zone), axis=1 ) - + "\n" + pp_df.loc[:, "tpl"] = pp_df.parnme.apply( + lambda x: "~ {0} ~".format(x) + ) + else: + names = pp_df.name.copy() + pp_df.loc[:, "parnme"] = pp_df.name + pp_df.loc[:, "tpl"] = pp_df.parnme.apply( + lambda x: "~ {0} ~".format(x) ) + _write_df_tpl( + tpl_file, + pp_df.loc[:, ["name", "x", "y", "zone", "tpl"]], + sep=" ", + index_label="index", + header=False, + index=False, + quotechar=" ", + quoting=2, + ) return pp_df diff --git a/pyemu/utils/pst_from.py b/pyemu/utils/pst_from.py index 0f8329528..0d32f64b2 100644 --- a/pyemu/utils/pst_from.py +++ b/pyemu/utils/pst_from.py @@ -412,6 +412,18 @@ def _pivot_par_struct_dict(self): struct_dict[gs] = par_dfs return struct_dict + def _rename_par_struct_dict(self, mapdict): + for gs, gps in self.par_struct_dict.items(): + df_dict = {} + for k, li in gps.items(): + tdf = [] + for df in li: + df.parnme.update(mapdict) + df = df.rename(index=mapdict) + tdf.append(df) + df_dict[k] = tdf + self.par_struct_dict[gs] = df_dict + def build_prior( self, fmt="ascii", filename=None, droptol=None, chunk=None, sigma_range=6 ): @@ -621,6 +633,10 @@ def build_pst(self, filename=None, update=False, version=1): uupdate = False pst = pyemu.Pst(filename, load=False) + # TODO should this be under an if:? incase updating and prior info has been set + pst.prior_information = pst.null_prior.merge(pd.DataFrame( + data=[], columns=pst.prior_fieldnames)) + if "pars" in update.keys() or not uupdate: if len(self.par_dfs) > 0: # parameter data from object @@ -642,14 +658,67 @@ def build_pst(self, filename=None, update=False, version=1): par_data = pyemu.pst_utils._populate_dataframe( [], pst.par_fieldnames, pst.par_defaults, pst.par_dtype ) - pst.parameter_data = par_data + # set parameter data + # some pre conditioning to support rentry here is more add_par + # calls are made with update/rebuild pst + shtmx = 0 + gshtmx = 0 + if pst.parameter_data is not None: + # copy existing par data (incase it has been edited) + par_data_orig = pst.parameter_data.copy() + if "longname" in par_data_orig.columns: + # Support existing long names mapping + par_data_orig = par_data_orig.set_index( + "longname") + # starting point for updated mapping + shtmx = par_data_orig.parnme.str.strip('p').astype(int).max() + 1 + gshtmx = par_data_orig.pargp.str.strip('pg').astype(int).max() + 1 + # index of new pars (might need this later) + new_par_data = par_data.index.difference(par_data_orig.index) + else: + new_par_data = slice(None) + # build or update par data + pst.parameter_data = pd.concat( + [pst.parameter_data, + par_data.loc[new_par_data]], axis=0) # pst.template_files = self.tpl_filenames # pst.input_files = self.input_filenames pst.model_input_data = pd.DataFrame( {"pest_file": self.tpl_filenames, "model_file": self.input_filenames}, index=self.tpl_filenames, ) - + # rename pars and obs in case short names are desired + if not self.longnames: + # pull out again for shorthand access + par_data = pst.parameter_data + # new pars will not be mapped start this mapping + npd = par_data.loc[new_par_data] + par_data.loc[npd.index, 'longname'] = npd.parnme + # get short names (using existing names as index starting point) + par_data.loc[npd.index, "shortname"] = [ + 'p' + str(i) for i in range(shtmx, shtmx+len(npd)) + ] + # set to dict + parmap = par_data.loc[npd.index, "shortname"].to_dict() + # rename parnames and propagate to tpls etc. + pst.rename_parameters(parmap, pst_path=self.new_d) + # rename in struct dicts + self._rename_par_struct_dict(parmap) + # save whole shortname-longname mapping (will over write previous) + par_data.set_index("shortname")["longname"].to_csv( + filename.with_name('parlongname.map')) + npd.index = npd.index.map(parmap) + + # build group mapping df + pargpmap = pd.DataFrame(npd.pargp.unique(), + columns=['longname']) + # shortnames from using previous a starting point (if existing) + pargpmap["shortname"] = "pg" + (pargpmap.index+gshtmx).astype(str) + pargpmap_dict = pargpmap.set_index('longname').shortname.to_dict() + par_data.loc[npd.index, "pglong"] = npd.pargp + par_data.loc[npd.index, 'pargp'] = npd.pargp.map(pargpmap_dict) + par_data.groupby('pargp').pglong.first().to_csv( + filename.with_name('pglongname.map')) if "obs" in update.keys() or not uupdate: if len(self.obs_dfs) > 0: obs_data = pd.concat(self.obs_dfs).loc[:, obs_data_cols] @@ -659,18 +728,69 @@ def build_pst(self, filename=None, update=False, version=1): ) obs_data.loc[:, "obsnme"] = [] obs_data.index = [] - obs_data.sort_index(inplace=True) - pst.observation_data = obs_data + # set observation data + # some pre conditioning to support rentry here is more add_obs + # calls are made with update/rebuild pst + shtmx = 0 + gshtmx = 0 + if pst.observation_data is not None: + # copy existing obs data (incase it has been edited) + obs_data_orig = pst.observation_data.copy() + if "longname" in obs_data_orig.columns: + # Support existing long names mapping + obs_data_orig = obs_data_orig.set_index( + "longname") + # starting point for updated mapping + shtmx = obs_data_orig.obsnme.str.strip('ob').astype(int).max() + 1 + gshtmx = obs_data_orig.obgnme.str.strip('obg').astype(int).max() + 1 + # index of new obs (might need this later) + new_obs_data = obs_data.index.difference(obs_data_orig.index) + else: + new_obs_data = slice(None) + # build or update obs data + pst.observation_data = pd.concat( + [pst.observation_data, + obs_data.loc[new_obs_data]], axis=0) # pst.instruction_files = self.ins_filenames # pst.output_files = self.output_filenames pst.model_output_data = pd.DataFrame( {"pest_file": self.ins_filenames, "model_file": self.output_filenames}, index=self.ins_filenames, ) + # rename pars and obs in case short names are desired + if not self.longnames: + # pull out again for shorthand access + obs_data = pst.observation_data + # new obs will not be mapped so start this mapping + nod = obs_data.loc[new_obs_data] + obs_data.loc[nod.index, "longname"] = nod.obsnme + # get short names (using existing names as index starting point) + obs_data.loc[nod.index, "shortname"] = [ + 'ob' + str(i) for i in range(shtmx, shtmx+len(nod)) + ] + obsmap = obs_data.loc[nod.index, "shortname"] + # rename obsnames and propagate to ins files + pst.rename_observations(obsmap.to_dict(), pst_path=self.new_d) + obs_data.set_index("shortname")["longname"].to_csv( + filename.with_name('obslongname.map')) + nod.index = nod.index.map(obsmap) + + # build group mapping df + obgpmap = pd.DataFrame(nod.obgnme.unique(), + columns=['longname']) + # shortnames from using previous a starting point (if existing) + obgpmap["shortname"] = "obg" + (obgpmap.index+gshtmx).astype(str) + obgpmap_dict = obgpmap.set_index('longname').shortname.to_dict() + obs_data.loc[nod.index, "oglong"] = nod.obgnme + obs_data.loc[nod.index, 'obgnme'] = nod.obgnme.map(obgpmap_dict) + obs_data.groupby('obgnme').oglong.first().to_csv( + filename.with_name('oglongname.map')) + + obs_data.sort_index(inplace=True) #TODO + if not uupdate: pst.model_command = self.mod_command - pst.prior_information = pst.null_prior pst.control_data.noptmax = 0 self.pst = pst @@ -1039,7 +1159,6 @@ def _process_array_obs( prefix, ofile_sep, ofile_skip, - longnames, zone_array, ): """private method to setup observations for an array-style file @@ -1053,7 +1172,6 @@ def _process_array_obs( placeholder arg, only whitespace-delimited files are supported ofile_skip (`int`): number of header and/or comment lines to skip at the top of the output file - longnames (`bool`): flag to allow longer observations names zone_array (numpy.ndarray): an integer array used to identify positions to skip in the output array @@ -1072,7 +1190,7 @@ def _process_array_obs( self.logger.lraise( "array obs output file '{0}' not found".format(out_filename) ) - if len(prefix) == 0 and self.longnames: + if len(prefix) == 0: prefix = Path(out_filename).stem f_out = open(self.new_d / out_filename, "r") f_ins = open(self.new_d / ins_filename, "w") @@ -1117,20 +1235,9 @@ def _process_array_obs( f_ins.write(" w ") continue - if longnames: - oname = "oname:{0}_otype:arr_i:{1}_j:{2}".format(prefix, iidx, jr) - if zval is not None: - oname += "_zone:{0}".format(zval) - else: - oname = "{0}_{1}_{2}".format(prefix, iidx, jr) - if zval is not None: - z_str = "_{0}".format(zval) - if len(oname) + len(z_str) < 20: - oname += z_str - if len(oname) > 20: - self.logger.lraise( - "array obs name too long: '{0}'".format(oname) - ) + oname = "oname:{0}_otype:arr_i:{1}_j:{2}".format(prefix, iidx, jr) + if zval is not None: + oname += "_zone:{0}".format(zval) f_ins.write(" !{0}! ".format(oname)) if jr < len(raw) - 1: f_ins.write(" w ") @@ -1255,7 +1362,6 @@ def add_observations( prefix, ofile_sep, ofile_skip, - self.longnames, zone_array, ) @@ -1269,7 +1375,7 @@ def add_observations( new_obs.loc[:, "obgnme"] = obsgp elif prefix is not None and len(prefix) != 0: # if prefix is passed new_obs.loc[:, "obgnme"] = prefix - elif self.longnames: + else: new_obs.loc[:, "obgnme"] = "oname:{0}_otype:arr".format(filenames) # else will default to `obgnme` self.logger.log( @@ -1337,7 +1443,6 @@ def add_observations( typ="obs", index_cols=index_cols, use_cols=use_cols, - longnames=self.longnames, ) df.loc[:, "idx_str"] = df_temp.idx_strs # Select only certain rows if requested @@ -1377,10 +1482,9 @@ def add_observations( obsgp = _check_var_len(obsgp, ncol, fill=fill) nprefix = prefix - if self.longnames: - if len(nprefix) == 0: - nprefix = filenames[0] - nprefix = "oname:{0}_otype:lst".format(nprefix) + if len(nprefix) == 0: + nprefix = filenames[0] + nprefix = "oname:{0}_otype:lst".format(nprefix) df_ins = pyemu.pst_utils.csv_to_ins_file( df.set_index("idx_str"), ins_filename=self.new_d / insfile, @@ -1390,7 +1494,6 @@ def add_observations( includes_header=includes_header, includes_index=False, prefix=nprefix, - longnames=self.longnames, head_lines_len=lenhead, sep=sep, gpname=obsgp, @@ -1875,14 +1978,10 @@ def add_parameters( pargp = pargp.lower() par_name_base = [pnb.lower() for pnb in par_name_base] - #if alt_inst_str is not None and len(alt_inst_str) > 0: - if self.longnames: # allow par names to be long... fine for pestpp - fmt = "_{0}".format(alt_inst_str) + ":{0}" - chk_prefix = "_{0}".format(alt_inst_str) # add `instance` identifier - else: - fmt = "{0}" # may not be so well supported - chk_prefix = "" - + + fmt = "_{0}".format(alt_inst_str) + ":{0}" + chk_prefix = "_{0}".format(alt_inst_str) # add `instance` identifier + # increment name base if already passed for i in range(len(par_name_base)): # multiplier file name will be taken first par group, if passed @@ -1983,7 +2082,6 @@ def add_parameters( use_rows=use_rows, zone_array=zone_array, gpname=pargp, - longnames=self.longnames, ij_in_idx=ij_in_idx, xy_in_idx=xy_in_idx, get_xy=get_xy, @@ -2026,7 +2124,6 @@ def add_parameters( par_type=par_type, zone_array=zone_array, shape=shp, - longnames=self.longnames, get_xy=self.get_xy, fill_value=1.0, gpname=pargp, @@ -2045,6 +2142,7 @@ def add_parameters( "pilot_point", "pilot-point", "pilot-points", + "pp" }: if par_style == "d": self.logger.lraise( @@ -2092,8 +2190,7 @@ def add_parameters( # (stolen from helpers.PstFromFlopyModel()._pp_prep()) # but only settting up one set of pps at a time pnb = par_name_base[0] - if self.longnames: - pnb = "pname:{1}_ptype:pp_pstyle:{0}".format(par_style, pnb) + pnb = "pname:{1}_ptype:pp_pstyle:{0}".format(par_style, pnb) pp_dict = {0: pnb} pp_filename = "{0}pp.dat".format(par_name_store) # pst inputfile (for tpl->in pair) is @@ -2289,7 +2386,6 @@ def add_parameters( pp_dir=self.new_d, tpl_dir=self.tpl_d, shapename=str(self.new_d / "{0}.shp".format(par_name_store)), - longnames=self.longnames, pp_filename_dict=pp_filename_dict, ) else: @@ -2298,7 +2394,6 @@ def add_parameters( pp_locs, tpl_filename, pnb, - longnames=self.longnames, ) df.loc[:, "pargp"] = pargp @@ -2810,7 +2905,6 @@ def write_list_tpl( suffix="", zone_array=None, gpname=None, - longnames=False, get_xy=None, ij_in_idx=None, xy_in_idx=None, @@ -2859,8 +2953,6 @@ def write_list_tpl( `index_cols` provide the indicies for querying `zone_array`. Therefore, array dimension should equal `len(index_cols)`. - longnames (`boolean`): Specify is pars will be specified without the - 12 char restriction - recommended if using Pest++. get_xy (`pyemu.PstFrom` method): Can be specified to get real-world xy from `index_cols` passed (to assist correlation definition) ij_in_idx (`list` or `array`): defining which `index_cols` contain i,j @@ -2894,7 +2986,6 @@ def write_list_tpl( suffix=suffix, gpname=gpname, zone_array=zone_array, - longnames=longnames, get_xy=get_xy, ij_in_idx=ij_in_idx, xy_in_idx=xy_in_idx, @@ -2912,7 +3003,6 @@ def write_list_tpl( suffix=suffix, gpname=gpname, zone_array=zone_array, - longnames=longnames, get_xy=get_xy, ij_in_idx=ij_in_idx, xy_in_idx=xy_in_idx, @@ -3003,14 +3093,6 @@ def write_list_tpl( df_par["x"], df_par["y"] = np.concatenate( df_tpl.apply(lambda r: [[r.x, r.y] for _ in use_cols], axis=1).values ).T - if not longnames: - too_long = df_par.loc[df_par.parnme.apply(lambda x: len(x) > 12), "parnme"] - if too_long.shape[0] > 0: - raise Exception( - "write_list_tpl() error: the following parameter " - "names are too long:{0}" - "".format(",".join(list(too_long))) - ) for use_col in use_cols: df_tpl.loc[:, use_col] = df_tpl.loc[:, use_col].apply( lambda x: "~ {0} ~".format(x) @@ -3041,7 +3123,6 @@ def _write_direct_df_tpl( use_rows=None, suffix="", zone_array=None, - longnames=False, get_xy=None, ij_in_idx=None, xy_in_idx=None, @@ -3071,8 +3152,6 @@ def _write_direct_df_tpl( If not None and `par_type` is `grid` or `zone` it is expected that `index_cols` provide the indicies for querying `zone_array`. Therefore, array dimension should equal `len(index_cols)`. - longnames (`boolean`): Specify is obs/pars will be specified without the - 20/12 char restriction - recommended if using Pest++. get_xy (`pyemu.PstFrom` method): Can be specified to get real-world xy from `index_cols` passed (to include in obs/par name) ij_in_idx (`list` or `array`): defining which `index_cols` contain i,j @@ -3097,7 +3176,7 @@ def _write_direct_df_tpl( sidx.extend(didx) df_ti = pd.DataFrame({"sidx": sidx}, columns=["sidx"]) - inames, fmt = _get_index_strfmt(index_cols, longnames) + inames, fmt = _get_index_strfmt(index_cols) df_ti = _get_index_strings(df_ti, fmt, zero_based) df_ti = _getxy_from_idx(df_ti, get_xy, xy_in_idx, ij_in_idx) @@ -3110,7 +3189,6 @@ def _write_direct_df_tpl( name, gpname, suffix, - longnames, par_style="d", init_df=df, init_fname=in_filename, @@ -3202,26 +3280,25 @@ def _get_use_rows(df, use_rows, zero_based, fnme, logger=None): return use_rows -def _get_index_strfmt(index_cols, longnames): +def _get_index_strfmt(index_cols): # get some index strings for naming - if longnames: - j = "_" - # fmt = "{0}|{1}" - if isinstance(index_cols[0], str): - inames = index_cols - else: - inames = ["idx{0}".format(i) for i in range(len(index_cols))] - # full formatter string - fmt = j.join([f"{iname}|{{{i}}}" for i, iname in enumerate(inames)]) + j = "_" + # fmt = "{0}|{1}" + if isinstance(index_cols[0], str): + inames = index_cols else: - # fmt = "{1:3}" - j = "" - if isinstance(index_cols[0], str): - inames = index_cols - else: - inames = ["{0}".format(i) for i in range(len(index_cols))] - # full formatter string - fmt = j.join([f"{{{i}:3}}" for i, iname in enumerate(inames)]) + inames = ["idx{0}".format(i) for i in range(len(index_cols))] + # full formatter string + fmt = j.join([f"{iname}|{{{i}}}" for i, iname in enumerate(inames)]) + # else: + # # fmt = "{1:3}" + # j = "" + # if isinstance(index_cols[0], str): + # inames = index_cols + # else: + # inames = ["{0}".format(i) for i in range(len(index_cols))] + # # full formatter string + # fmt = j.join([f"{{{i}:3}}" for i, iname in enumerate(inames)]) return inames, fmt @@ -3260,7 +3337,6 @@ def _build_parnames( basename, gpname, suffix, - longnames, par_style, init_df=None, init_fname=None, @@ -3301,45 +3377,43 @@ def _build_parnames( df.loc[:, "parval1_{0}".format(use_col)] = fill_value if typ == "constant": # one par for entire use_col column - if longnames: - fmtr = "pname:{0}_ptype:cn_usecol:{1}" - fmtr += "_pstyle:{0}".format(par_style) - if suffix != "": - fmtr += f"_{suffix}" - else: - fmtr = "{0}{1}" - if suffix != "": - fmtr += suffix + fmtr = "pname:{0}_ptype:cn_usecol:{1}" + fmtr += "_pstyle:{0}".format(par_style) + if suffix != "": + fmtr += f"_{suffix}" + # else: + # fmtr = "{0}{1}" + # if suffix != "": + # fmtr += suffix df.loc[:, use_col] = fmtr.format(nname, use_col) if par_style == "d": _check_diff(init_df.loc[:, use_col].values, init_fname) df.loc[:, "parval1_{0}".format(use_col)] = init_df.loc[:, use_col][0] elif typ == "zone": # one par for each zone - if longnames: - fmtr = "pname:{0}_ptype:zn_usecol:{1}" - if par_style == "d": - # todo - raise NotImplementedError( - "list-style direct zone-type parameters not implemented" - ) - fmtr += "_pstyle:d" - else: - fmtr += "_pstyle:m" - if zone_array is not None: - fmtr += "_zone:{2}" - # df.loc[:, use_col] += df.zval.apply( - # lambda x: "_zone:{0}".format(x) - # ) - if suffix != "": - fmtr += f"_{suffix}" - # df.loc[:, use_col] += "_{0}".format(suffix) + fmtr = "pname:{0}_ptype:zn_usecol:{1}" + if par_style == "d": + # todo + raise NotImplementedError( + "list-style direct zone-type parameters not implemented" + ) + fmtr += "_pstyle:d" else: - fmtr = "{0}{1}" - if zone_array is not None: - fmtr += "z{2}" - if suffix != "": - fmtr += suffix + fmtr += "_pstyle:m" + if zone_array is not None: + fmtr += "_zone:{2}" + # df.loc[:, use_col] += df.zval.apply( + # lambda x: "_zone:{0}".format(x) + # ) + if suffix != "": + fmtr += f"_{suffix}" + # df.loc[:, use_col] += "_{0}".format(suffix) + # else: + # fmtr = "{0}{1}" + # if zone_array is not None: + # fmtr += "z{2}" + # if suffix != "": + # fmtr += suffix if zone_array is not None: df.loc[:, use_col] = df.zval.apply( lambda x: fmtr.format(nname, use_col, x) @@ -3351,23 +3425,14 @@ def _build_parnames( elif typ == "grid": # one par for each index - if longnames: - fmtr = "pname:{0}_ptype:gr_usecol:{1}" - fmtr += "_pstyle:{0}".format(par_style) - if zone_array is not None: - fmtr += "_zone:{2}_{3}" - else: - fmtr += "_{2}" - if suffix != "": - fmtr += f"_{suffix}" + fmtr = "pname:{0}_ptype:gr_usecol:{1}" + fmtr += "_pstyle:{0}".format(par_style) + if zone_array is not None: + fmtr += "_zone:{2}_{3}" else: - fmtr = "{0}{1}" - if zone_array is not None: - fmtr += "z{2}_{3}" - else: - fmtr += "{2}" - if suffix != "": - fmtr += suffix + fmtr += "_{2}" + if suffix != "": + fmtr += f"_{suffix}" if zone_array is not None: df.loc[:, use_col] = df.apply( lambda x: fmtr.format(nname, use_col, x.zval, x.idx_strs), axis=1 @@ -3386,13 +3451,6 @@ def _build_parnames( "or 'grid', not '{0}'".format(typ) ) - if not longnames: - if df.loc[:, use_col].apply(lambda x: len(x)).max() > 12: - too_long = df.loc[:, use_col].apply(lambda x: len(x)) > 12 - print(too_long) - raise ValueError( - "_get_tpl_or_ins_df(): " "couldn't form short par names" - ) if par_style == "d": direct_tpl_df.loc[:, use_col] = ( df.loc[:, use_col].apply(lambda x: "~ {0} ~".format(x)).values @@ -3410,7 +3468,6 @@ def _get_tpl_or_ins_df( use_cols=None, suffix="", zone_array=None, - longnames=False, get_xy=None, ij_in_idx=None, xy_in_idx=None, @@ -3442,8 +3499,6 @@ def _get_tpl_or_ins_df( If not None and `par_type` is `grid` or `zone` it is expected that `index_cols` provide the indicies for querying `zone_array`. Therefore, array dimension should equal `len(index_cols)`. - longnames (`boolean`): Specify is obs/pars will be specified without the - 20/12 char restriction - recommended if using Pest++. get_xy (`pyemu.PstFrom` method): Can be specified to get real-world xy from `index_cols` passed (to include in obs/par name) ij_in_idx (`list` or `array`): defining which `index_cols` contain i,j @@ -3482,7 +3537,7 @@ def _get_tpl_or_ins_df( sidx.extend(aidx) df_ti = pd.DataFrame({"sidx": list(sidx)}, columns=["sidx"]) - inames, fmt = _get_index_strfmt(index_cols, longnames) + inames, fmt = _get_index_strfmt(index_cols) df_ti = _get_index_strings(df_ti, fmt, zero_based) df_ti = _getxy_from_idx(df_ti, get_xy, xy_in_idx, ij_in_idx) @@ -3497,7 +3552,6 @@ def _get_tpl_or_ins_df( name, gpname, suffix, - longnames, par_style, fill_value=par_fill_value, ) @@ -3512,7 +3566,6 @@ def write_array_tpl( zone_array=None, gpname=None, shape=None, - longnames=False, fill_value=1.0, get_xy=None, input_filename=None, @@ -3530,7 +3583,6 @@ def write_array_tpl( not parameterized and are assigned a value of fill_value. Default is None. gpname (`str`): pargp filed in dataframe shape (`tuple`): dimensions of array to write - longnames (`bool`): Use parnames > 12 char fill_value: get_xy: input_filename: @@ -3593,48 +3645,33 @@ def write_array_tpl( ) def constant_namer(i, j): - if longnames: - pname = "pname:{1}_ptype:cn_pstyle:{0}".format(par_style, name) - if suffix != "": - pname += "_{0}".format(suffix) - else: - pname = "{1}{2}".format(par_style[0], name, suffix) - if len(pname) > 12: - raise Exception("constant par name too long:" "{0}".format(pname)) + pname = "pname:{1}_ptype:cn_pstyle:{0}".format(par_style, name) + if suffix != "": + pname += "_{0}".format(suffix) return pname def zone_namer(i, j): zval = 1 if zone_array is not None: zval = zone_array[i, j] - if longnames: - pname = "pname:{1}_ptype:zn_pstyle:{0}_zone:{2}".format( - par_style, name, zval - ) - if suffix != "": - pname += "_{0}".format(suffix) - else: - pname = "{1}_zn{2}".format(par_style[0], name, zval) - if len(pname) > 12: - raise Exception("zone par name too long:{0}".format(pname)) + pname = "pname:{1}_ptype:zn_pstyle:{0}_zone:{2}".format( + par_style, name, zval + ) + if suffix != "": + pname += "_{0}".format(suffix) return pname def grid_namer(i, j): - if longnames: - pname = "pname:{1}_ptype:gr_pstyle:{0}_i:{2}_j:{3}".format( - par_style, name, i, j - ) - if get_xy is not None: - pname += "_x:{0:0.2f}_y:{1:0.2f}".format( - *get_xy([i, j], ij_id=[0, 1])) - if zone_array is not None: - pname += "_zone:{0}".format(zone_array[i, j]) - if suffix != "": - pname += "_{0}".format(suffix) - else: - pname = "{1}{2:03d}{3:03d}".format(par_style[0], name, i, j) - if len(pname) > 12: - raise Exception("grid pname too long:{0}".format(pname)) + pname = "pname:{1}_ptype:gr_pstyle:{0}_i:{2}_j:{3}".format( + par_style, name, i, j + ) + if get_xy is not None: + pname += "_x:{0:0.2f}_y:{1:0.2f}".format( + *get_xy([i, j], ij_id=[0, 1])) + if zone_array is not None: + pname += "_zone:{0}".format(zone_array[i, j]) + if suffix != "": + pname += "_{0}".format(suffix) return pname if par_type == "constant":