diff --git a/quickstats/clis/core.py b/quickstats/clis/core.py
index af0e799dc469c47aa2830b9583b1c172d1f1b004..5ff53e5e8361dfcd012e4cccebbde9f72ea0a960 100644
--- a/quickstats/clis/core.py
+++ b/quickstats/clis/core.py
@@ -275,6 +275,8 @@ def compile_macros(macros):
               help='Path to the directory containing the source file for the macro.')
 @click.option('-n', '--name',
               help='Name of the macro. By default, the name of the input directory is used.')
+@click.option('-f', '--force', is_flag=True,
+              help='Force overwrite existing files.')
 @click.option('--copy-files/--do-not-copy-files', 'copy_files', default=True,
               help='Whether to copy files from the input directory (required if not already copied).')
 @click.option('--add-to-workspace-extension/--do-not-add-to-workspace-extension', 'workspace_extension',
@@ -290,6 +292,8 @@ def add_macro(**kwargs):
 @click.command(name='remove_macro')
 @click.option('-n', '--name', required=True,
               help='Name of the macro.')
+@click.option('-f', '--force', is_flag=True,
+              help='Force remove files without notification.')
 @click.option('--remove-files/--do-not-remove-files', 'remove_files',
               default=False, show_default=True,
               help='Whether to remove the macro from the workspace extension list only or also remove the files.')
diff --git a/quickstats/components/likelihood.py b/quickstats/components/likelihood.py
index dbc29a81585dcfdd88fd162e7ea62e4ad1136405..47e78f80b6abd568dc40c48ebbec8126fe73f31a 100644
--- a/quickstats/components/likelihood.py
+++ b/quickstats/components/likelihood.py
@@ -162,7 +162,7 @@ class Likelihood(AnalysisObject):
         fit_result = {}
         self.stdout.info("INFO: NLL evaluation completed with")
         if mode in [FitMode.HYBRID, FitMode.UNCOND, FitMode.NOFIT]:
-            best_fit_str = ", ".join([f"{name}={value:.5f}" for name, value in muhat.items()])
+            best_fit_str = ", ".join([f"{name} = {value:.5f}" for name, value in muhat.items()])
             self.stdout.info("best fit : ".rjust(15) + f"{best_fit_str}")
             self.stdout.info("uncond NLL = ".rjust(15) + f"{nll_uncond:.5f}")
             fit_result['uncond_fit'] = {
diff --git a/quickstats/core/methods.py b/quickstats/core/methods.py
index 6b30e678499b41fd21f2e109dff3aaab5c66bd5d..d1c1114c4fb412a109c5ffe1bb50a0615de7e365 100644
--- a/quickstats/core/methods.py
+++ b/quickstats/core/methods.py
@@ -75,7 +75,8 @@ def get_workspace_extension_config():
         extension_config = json.load(file)
     return extension_config
 
-def add_macro(path:str, name:Optional[str]=None, copy_files:bool=True, workspace_extension:bool=True):
+def add_macro(path:str, name:Optional[str]=None, copy_files:bool=True,
+              workspace_extension:bool=True, force:bool=False):
     if not os.path.isdir(path):
         raise ValueError("macro path must be a directory")
     if name is None:
@@ -87,8 +88,7 @@ def add_macro(path:str, name:Optional[str]=None, copy_files:bool=True, workspace
     if copy_files:
         dest_path = os.path.join(macro_path, name)
         if os.path.exists(dest_path):
-            answer = input(f'WARNING: The macro already exists in {dest_path}, overwrite? [Y/N]')
-            if answer == "Y":
+            if force or input(f'WARNING: The macro already exists in {dest_path}, overwrite? [Y/N]') == "Y":
                 shutil.rmtree(dest_path)
                 shutil.copytree(path, dest_path)
                 quickstats._PRINT_.info(f'INFO: Overwritten contents for the macro "{name}" from {path} to {dest_path}.')
@@ -107,26 +107,25 @@ def add_macro(path:str, name:Optional[str]=None, copy_files:bool=True, workspace
                 json.dump(extension_config, file, indent=2)
         quickstats._PRINT_.info(f'INFO: The macro "{name}" has been added to the workspace extension list.')
         
-def remove_macro(name:str, remove_files:bool=True):
+def remove_macro(name:str, remove_files:bool=True, force:bool=False):
     resource_path = quickstats.resource_path
     extension_config_file = os.path.join(resource_path, "workspace_extensions.json")
     extension_config = get_workspace_extension_config()
     if (name not in extension_config):
-        quickstats.__PRINT__.info(f'WARNING: Extension "{name}" not found in the workspace extension list. Skipped.')
+        quickstats._PRINT_.info(f'WARNING: Extension "{name}" not found in the workspace extension list. Skipped.')
     else:
         extension_config.remove(name)
         with open(extension_config_file, "w") as file:
             json.dump(extension_config, file, indent=2)
-        quickstats.__PRINT__.info(f'INFO: The extension "{name}" has been removed from the workspace extension list.')
+        quickstats._PRINT_.info(f'INFO: The extension "{name}" has been removed from the workspace extension list.')
     if remove_files:
         macro_path = quickstats.macro_path
         extension_path = os.path.abspath(os.path.join(macro_path, name))
-        answer = input(f'WARNING: Attempting to remove files from {extension_path}, confirm? [Y/N]')
-        if answer == "Y":
-            quickstats._PRINT_.info(f'INFO: Removal confirmed.')
+        if force or input(f'WARNING: Attempting to remove files from {extension_path}, confirm? [Y/N]') == "Y":
+            quickstats._PRINT_.info(f'INFO: Files for the macro "{name}" has been removed from {extension_path}.')
             shutil.rmtree(extension_path)
         else:
-            quickstats._PRINT_.info(f'INFO: Removal cancelled.')
+            quickstats._PRINT_.info(f'INFO: Macro files removal cancelled.')
 
 def load_corelib():
     if not quickstats.corelib_loaded:
diff --git a/quickstats/utils/roofit_utils.py b/quickstats/utils/roofit_utils.py
index d70878012f4c1778d7726516d3efce40ade6a3f4..e86d4f5a3a15223aa72929492ef7c0a54bd3b742 100644
--- a/quickstats/utils/roofit_utils.py
+++ b/quickstats/utils/roofit_utils.py
@@ -321,5 +321,21 @@ def translate_formula(name:str, formula:str):
     expr = formula
     for i, variable in enumerate(variables):
         expr = re.sub(r"\b" + variable + r"\b", f"@{i}", expr)
-    translated_formula = f"expr::{name}('{expr}', {','.join(variables)})"
-    return translated_formula, variables
\ No newline at end of file
+    translated_formula = f"expr::{name}('{expr}', {', '.join(variables)})"
+    return translated_formula, variables
+
+def recover_formula(formula:str):
+    expr_regex = re.compile(r"'(.*?)'")
+    expressions = expr_regex.findall(formula)
+    if len(expressions) != 1:
+        raise RuntimeError("invalid RooFit factory expression")
+    expression = expressions[0]
+    variables_regex = re.compile(r"\('.*?',(.*)\)")
+    variables = variables_regex.findall(formula)
+    if len(variables) != 1:
+        raise RuntimeError("invalid RooFit factory expression")
+    variables = [i.strip() for i in variables[0].split(",") if i.strip()]
+    recovered_formula = expression
+    for i, variable in enumerate(variables):
+        recovered_formula = re.sub(f"@{i}(?![0-9])", variable, recovered_formula)
+    return recovered_formula
\ No newline at end of file
diff --git a/setup.sh b/setup.sh
index 1469d468d934cdcdce6123cfabcd8c1e4537aff6..e6afb916006458922a82f930ed0430bff344ecd8 100644
--- a/setup.sh
+++ b/setup.sh
@@ -37,4 +37,23 @@ elif [[ "$EnvironmentName" = "conda" ]];
 then
 	echo Entering default conda environment
 	export PATH=/afs/cern.ch/work/c/chlcheng/local/miniconda/envs/root-latest/bin:$PATH
-fi
\ No newline at end of file
+elif [[ "$EnvironmentName" = "nightly" ]];
+then
+setupATLAS
+source /cvmfs/sft.cern.ch/lcg/views/dev3/latest/x86_64-centos7-gcc11-opt/setup.sh
+	export PATH=${DIR}/bin:${PATH}
+	export PYTHONPATH=${DIR}:${PYTHONPATH}	
+elif [[ "$EnvironmentName" = "102b" ]];
+then
+setupATLAS
+source /cvmfs/sft.cern.ch/lcg/views/LCG_102b/x86_64-centos7-gcc11-opt/setup.sh
+	export PATH=${DIR}/bin:${PATH}
+	export PYTHONPATH=${DIR}:${PYTHONPATH}	
+elif [[ "$EnvironmentName" = "102a" ]];
+then
+setupATLAS
+source /cvmfs/sft.cern.ch/lcg/views/LCG_102a/x86_64-centos7-gcc11-opt/setup.sh
+	export PATH=${DIR}/bin:${PATH}
+	export PYTHONPATH=${DIR}:${PYTHONPATH}	
+fi
+