replicates the pest parrep util. replaces the parval1 field in the
            parameter data section dataframe

        Parameters
        ----------
        parfile : str
            parameter file to use.  If None, try to use
            a parameter file that corresponds to the case name.
            Default is None
        enforce_hounds : bool
            flag to enforce parameter bounds after parameter values are updated.
            This is useful because PEST and PEST++ round the parameter values in the
            par file, which may cause slight bound violations

def parrep(self, parfile=None,enforce_bounds=True):
        """replicates the pest parrep util. replaces the parval1 field in the
            parameter data section dataframe

        Parameters
        ----------
        parfile : str
            parameter file to use.  If None, try to use
            a parameter file that corresponds to the case name.
            Default is None
        enforce_hounds : bool
            flag to enforce parameter bounds after parameter values are updated.
            This is useful because PEST and PEST++ round the parameter values in the
            par file, which may cause slight bound violations

        """
        if parfile is None:
            parfile = self.filename.replace(".pst", ".par")
        par_df = pst_utils.read_parfile(parfile)
        self.parameter_data.index = self.parameter_data.parnme
        par_df.index = par_df.parnme
        self.parameter_data.parval1 = par_df.parval1
        self.parameter_data.scale = par_df.scale
        self.parameter_data.offset = par_df.offset

        if enforce_bounds:
            par = self.parameter_data
            idx = par.loc[par.parval1 > par.parubnd,"parnme"]
            par.loc[idx,"parval1"] = par.loc[idx,"parubnd"]
            idx = par.loc[par.parval1 < par.parlbnd,"parnme"]
            par.loc[idx, "parval1"] = par.loc[idx, "parlbnd"]