Beispiel #1
0
def rm_conf(config, force):
    from os import rmdir, remove, scandir
    from os.path import isfile
    from re import fullmatch
    import json
    from lib.utils import points_recast, config_dir, project_folder

    points_old, _ = points_recast([], [], '', True, config, 'tools')
    cleared = clear_data(points_old, config, force)

    if not cleared:
        print('Config not empty.')
        return

    path = config_dir(config)
    for x in scandir(path):
        if fullmatch('.*.cdt', x.name):
            remove(x)

    if isfile(path + '/pstop.pickle'):
        remove(path + '/pstop.pickle')
    rmdir(path)
    print(f"Removed config '{config}' at path:\n  {path}")

    with open(project_folder() + '/output/configs.json', 'r') as config_file:
        configs = json.load(config_file)

    del configs[config]

    with open(project_folder() + '/output/configs.json', 'w') as config_file:
        json.dump(configs, config_file, indent=4)
Beispiel #2
0
def reset_fit(names, delete):
    from os.path import isdir
    from os import chdir, mkdir
    from shutil import rmtree
    from re import fullmatch
    import json
    from lib.utils import (authorization_request, fit_dir, find_fits,
                           project_folder)

    pattern_names = []
    pure_names = []
    all_names = list(find_fits().keys())
    for name in names:
        if name[0] == '§':
            pattern_names += [c for c in all_names
                                if fullmatch(name[1:], c)]
        else:
            pure_names += [name]

    names = list(set(pure_names + pattern_names))
    print(f'Chosen fits are:\n  {names}')

    for name in names:
        fit = fit_dir(name)

        if delete:
            action = 'delete'
            action_p = action + 'd'
        else:
            action = 'reset'
            action_p = action

        what_to_do = 'to ' + action + ' the fit \'' + name + '\''
        authorized = authorization_request(what_to_do)
        if authorized == 'yes':
            rmtree(fit)
            if action == 'reset':
                mkdir(fit)
            elif action == 'delete':
                with open(project_folder() + '/output/fits.json', 'r') as file:
                    fits = json.load(file)
                del fits[name]
                with open(project_folder() + '/output/fits.json', 'w') as file:
                    json.dump(fits, file, indent=4)
            print(f'Fit {name} has been {action_p}.')
        elif authorized == 'quit':
            print('Nothing done on last fit.')
            return
        else:
            print('Nothing done.')
Beispiel #3
0
def local_launch(points, arg_strs):
    from os import system, chdir
    from os.path import abspath
    from subprocess import Popen
    from lib.utils import (point_dir, launch_script_name, make_script_name,
                           project_folder)

    dirs = {Point: abspath(point_dir(Point)) for Point in points}

    for Point in points:
        chdir(dirs[Point])

        arg_str = arg_strs[Point]
        run_num = int(arg_str.split()[1])

        launch_script_n = launch_script_name(Point)
        make_script_n = make_script_name(Point)

        make_script = Popen([
            "python3", make_script_n,
            str(run_num),
            str(Point[0]),
            str(Point[1]),
            project_folder()
        ])
        make_script.wait()
        system('nohup python3 $PWD/' + launch_script_n + arg_str + ' &')
Beispiel #4
0
def show_confs(paths):
    from lib.utils import find_configs, project_folder
    import pprint as pp

    configs = find_configs()

    if paths:
        if not isinstance(configs, dict):
            paths = [project_folder() + '/output/' + c for c in configs]
            configs = dict(zip(configs, paths))

        for name, path in sorted(configs.items(), key=lambda x: x[0].lower()):
            print(name, path, sep=':\n\t')
    else:
        if isinstance(configs, dict):
            configs = list(configs.keys())

        for name in sorted(configs, key=str.lower):
            print(name)
Beispiel #5
0
def new_fit(name, path, caller_path):
    from os.path import isdir, isfile, abspath, basename
    from os import chdir, mkdir, listdir
    from inspect import cleandoc
    import json
    from lib.utils import find_fits, project_folder

    msg_exist = cleandoc("""The requested fit already exists.
                If you want to reset it, please use the specific command.""")

    fits = find_fits()

    chdir(caller_path)

    # actually creates requested folder
    if not path:
        path = caller_path + '/' + name

    if name in fits.keys() or abspath(path) in fits.values():
        print(msg_exist)
        return
    elif basename(path) != name:
        print('At the present time names different from target '
              'directories are not available.')
        return
    else:
        try:
            mkdir(path)
        except (FileExistsError, FileNotFoundError):
            print('Invalid path given.')
            return

    print(f"Created fit '{name}' at path:\n  {abspath(path)}")

    fits = {**fits, name: abspath(path)}
    with open(project_folder() + '/output/fits.json', 'w') as fit_file:
        json.dump(fits, fit_file, indent=4)
Beispiel #6
0
 def make_str(p):
     run_num = int(arg_strs[p].split()[1])
     make_args = str(run_num) + ' ' + str(p[0]) + ' ' + str(p[1]) + \
                 ' ' + project_folder()
     return make_script_name(p) + ' ' + make_args
Beispiel #7
0
def slurm_launch(points, arg_strs, queue, arch, file):
    from os import system, chdir, chmod, makedirs
    from os.path import realpath, basename
    from subprocess import Popen
    from time import time
    from datetime import datetime
    from lib.utils import (point_dir, launch_script_name, make_script_name,
                           project_folder)

    # raise RuntimeError('support for marconi still missing')

    if queue in ['p', 'prod']:
        queue = 'prod'
        qtime = '23:59'
    elif queue in ['d', 'dbg', 'debug']:
        queue = 'dbg'
        qtime = '00:29'
    else:
        raise RuntimeError('slurm_launch: queue not recognized')

    if arch == 'skl':
        account = 'INF19_npqcd_0'
        c_sz = 48  # chunk_size
    elif arch == 'knl':
        account = 'IscrB_TOPPSI'
        c_sz = 68  # chunk_size
    else:
        raise RuntimeError('slurm_launch: arch not recognized')

    dirs = {Point: realpath(point_dir(Point)) for Point in points}

    points_chunks = [
        points[c_sz * i:c_sz * (i + 1)]
        for i in range(len(points) // c_sz + 1)
    ]
    i = 0
    for chunk in points_chunks:
        i += 1

        def make_str(p):
            run_num = int(arg_strs[p].split()[1])
            make_args = str(run_num) + ' ' + str(p[0]) + ' ' + str(p[1]) + \
                        ' ' + project_folder()
            return make_script_name(p) + ' ' + make_args

        def launch_str(p):
            return launch_script_name(p) + arg_strs[p]

        points_makers = [make_str(p) for p in chunk]
        points_launchers = [launch_str(p) for p in chunk]

        points = ['(']
        for j in range(len(chunk)):
            points += [
                '"point_dir=\'' + point_dir(chunk[j]) + '\' ' +
                # 'make=\'' + points_makers[j] + '\' ' +
                'launch=\'' + points_launchers[j] + '\'"'
            ]

            chdir(dirs[chunk[j]])
            make_script = Popen(["python3", *points_makers[j].split()])
            make_script.wait()

        points += [')']
        points = '\n'.join(points)

        file_name = basename(file)
        sbatch_dir = file_name[:-4]

        time_ = datetime.fromtimestamp(time()).strftime('%d-%m-%Y_%H:%M:%S')
        jobname = f'CDT2D_{time_}--{i}'
        scripts_dir = project_folder() + '/lib/scripts'
        with open(scripts_dir + '/sbatch.sh', 'r') as sbatch_template:
            chunk_script = eval('f"""' + sbatch_template.read() + '"""')
            # if queue == 'dbg':
            if file[-3:] != '~~~':
                chunk_script += (f'\n\npython3 {project_folder()}/launcher.py '
                                 f'run --file {file}')
        try:
            makedirs('../' + sbatch_dir)
        except FileExistsError:
            pass
        chdir('../' + sbatch_dir)

        sbatch_file = realpath(jobname + '.sh')
        with open(sbatch_file, 'w') as sbatch_script:
            sbatch_script.write(chunk_script)
        chmod(sbatch_file, 0o777)
        system('sbatch ' + sbatch_file)
Beispiel #8
0
def launch(points_old, points_new, config, linear_history, end_time, end_steps,
           force, time_lengths, adj, max_volume, move22, move24, move_gauge,
           fake_run, debug, queue, arch, file):
    """Output analysis for CDT_2D simulation.
    attempts_str = str(attempts)

    Parameters
    ----------
    points_old : type
        Description of parameter `points_old`.
    points_new : type
        Description of parameter `points_new`.
    config : type
        Description of parameter `config`.
    linear_history : type
        Description of parameter `linear_history`.
    time : type
        Description of parameter `time`.
    steps : type
        Description of parameter `steps`.
    force : type
        Description of parameter `force`.
    time_lengths : type
        Description of parameter `time_lengths`.
    fake_run : type
        Description of parameter `fake_run`.
    debug : type
        Description of parameter `debug`.

    Raises
    ------
    Exception
        descrizione dell'eccezione lanciata
    """

    from os import mkdir, chdir, getcwd, scandir
    from os.path import isfile, isdir
    from shutil import copyfile
    from re import split, sub
    from platform import node
    import json
    from lib.utils import (find_running, point_dir, point_str, moves_weights,
                           authorization_request, end_parser,
                           launch_script_name, make_script_name, config_dir,
                           project_folder)
    from lib.platforms import launch_run

    # set moves' weights
    move22, move24, move_gauge = moves_weights(move22, move24, move_gauge)

    points_run, _ = find_running()
    points_run = [x[0] for x in points_run if x[1] == config]

    points_old_auth = []  # old ones which will get the authorization to rerun
    points_req_run = []  # those requested which are already running
    for Point in points_old:
        if Point not in points_run:
            if not config == 'test' and not force:
                what_to_do = "to rerun simulation"
                authorized = authorization_request(what_to_do, Point)
            else:
                authorized = 'yes'
            if authorized == 'yes':
                points_old_auth += [Point]
            elif authorized == 'quit':
                print('No simulation launched.')
                return
        else:
            points_req_run += [Point]

    points = points_old_auth + points_new

    if len(points_new) > 0:
        print("New simulations will be launched for following (λ, β): ",
              points_new)
    if len(points_old_auth) > 0:
        print("Old simulations will be rerunned for following (λ, β): ",
              points_old_auth)
    if len(points_req_run) > 0:
        print("Simulations for following (λ, β) were already running: ",
              points_req_run)
    if len(points) > 0:
        print()

    arg_strs = {}

    for Point in points:
        chdir(config_dir(config))

        dir_name = point_dir(Point)
        launch_script_n = launch_script_name(Point)
        make_script_n = make_script_name(Point)

        if Point in points_old:
            if not isdir(dir_name + "/history/adjacencies"):
                mkdir(dir_name + "/history/adjacencies")

            with open(dir_name + "/state.json", "r+") as state_file:
                state = json.load(state_file)

            if state['is_thermalized']:
                print('((λ, β) = ' + str(Point) + ') Ha già finito!')
                # @todo da migliorare
                continue

            if state['last_run_succesful']:
                run_num = state['run_done'] + 1
            else:
                print('((λ, β) = ' + str(Point) + ') Problem in the last run')
                continue

            if state['is_thermalized'] and linear_history == '0':
                linear_history = '1M'

            # I'm putting the default because this case is present only for
            # backward compatibility, and before the timelength was stuck to 80
            try:
                time_length = state['timelength']
            except KeyError:
                time_length = time_lengths[Point]

            checkpoints = [
                x.name for x in scandir(dir_name + "/checkpoint")
                if (split('_|\.|run', x.name)[1] == str(run_num - 1)
                    and x.name[-4:] != '.tmp')
            ]
            # nell'ordinamento devo sostituire i '.' con le '~', o in generale
            # un carattere che venga dopo '_', altrimenti 'run1.1_...' viene
            # prima di 'run1_...'
            checkpoints.sort(key=lambda s: s.replace('.', '~'))
            last_check = checkpoints[-1]
        else:
            mkdir(dir_name)
            mkdir(dir_name + "/checkpoint")
            mkdir(dir_name + "/history")
            mkdir(dir_name + "/history/adjacencies")
            mkdir(dir_name + "/bin")

            make_template = project_folder() + '/lib/scripts/make_script.py'
            launch_template = project_folder(
            ) + '/lib/scripts/launch_script.py'
            copyfile(make_template, dir_name + '/' + make_script_n)
            copyfile(launch_template, dir_name + '/' + launch_script_n)

            if fake_run:
                print('Created simulation directory for: (Lambda= ' +
                      str(Point[0]) + ', Beta= ' + str(Point[1]) + ')')

            run_num = 1
            last_check = None
            time_length = time_lengths[Point]

        # devo farlo qui perché prima non sono sicuro che dir_name esista
        # ('mkdir(dir_name)')
        chdir(dir_name)

        if isfile('max_volume_reached'):
            print(f'Point {Point} won\'t be relaunched because it reached '
                  'maximum volume available in the previous run.')
            continue

        if int(run_num) > 1:
            from lib.tools import recovery_history
            recovery_history()

            if linear_history != '0' and not state['linear-history']:
                state['linear-history-cut'] = state['iter_done']
            if state['linear-history']:
                if linear_history == '0':
                    print('\033[38;5;69mWarning:\033[0m')
                    print(f"Point {Point} has been already run with "
                          f"linear_history {state['linear-history']}, so this "
                          f"value will be used.")
                elif linear_history != state['linear-history']:
                    print('\033[38;5;69mWarning:\033[0m')
                    print(f"Point {Point} has been already run with "
                          f"linear_history {state['linear-history']}, so this "
                          f"will be used instead of: {linear_history}.")
                linear_history = state['linear-history']

        # ensure state_file existence or update it
        if int(run_num) == 1:
            state = {
                'Lambda': Point[0],
                'Beta': Point[1],
                'run_done': 0,
                'is_thermalized': False,
                'last_checkpoint': None,
                'iter_done': 0,
                'timelength': time_length
            }

        with open('state.json', 'w') as state_file:
            json.dump(state, state_file, indent=4)

        # END CONDITION MANIPULATION

        # ricongiungo le due variabili perché è ancora facile
        # distinguerle dall'ultimo carattere
        if end_steps != '0':
            end_condition = end_steps
        else:
            end_condition = end_time

        # needed for thermalization loop
        end_partial, end_condition, end_type = end_parser(end_condition)

        if linear_history != '0':  # i.e. `if linear_history:`
            if end_type == 'time':
                end_partial = str(end_condition) + 's'
            else:
                end_partial = end_condition

        # set debug_flag for c++ (in c++ style)
        debug_flag = str(debug).lower()
        # set adj_flag for c++ (in c++ style)
        adj_flag = str(adj).lower()

        # max_volume
        max_volume = int(max_volume[0] if type(max_volume) ==
                         list else max_volume)

        # is necessary to recompile each run because on the grid the launch node
        # could be different from run_node
        exe_name = "CDT_2D-" + point_str(Point)  #+ "_run" + str(run_num)

        arguments = [
            project_folder(), run_num, Point[0], Point[1], time_length,
            end_condition, debug_flag, last_check, linear_history, adj_flag,
            move22, move24, max_volume, end_partial, end_type, exe_name
        ]
        arg_str = ''
        for x in arguments:
            arg_str += ' ' + str(x)
        arg_strs[Point] = arg_str

        if fake_run:
            print()
            print(*(["bin/" + exe_name] + arguments[:8]))

    if not fake_run:
        from lib.platforms import launch_run
        points = list(arg_strs.keys())
        launch_run(points, arg_strs, config, queue, arch, file)
Beispiel #9
0
def define_parser(launcher_path, version):
    """Define the parser for the launcher.

    Parameters
    ----------
    launcher_path : str
        Path to launcher source.
    version: str
        The CDT_2D version number.

    Returns
    -------
    argparse.ArgumentParser
        The argument parser for the launcher.
    dict
        The dictionary of commands to decode file inputs.
    """

    starting_cwd = getcwd()
    chdir(project_folder())

    if exists('output') and isdir('output'):
        if isfile('output/configs.json'):
            import json

            with open('output/configs.json', 'r') as config_file:
                configs_d = json.load(config_file)
            configs = list(configs_d.keys())
        else:
            configs = [x.name for x in scandir('output') if x.is_dir()]

        if isfile('output/fits.json'):
            import json

            with open('output/fits.json', 'r') as fit_file:
                fits_d = json.load(fit_file)
            fits = list(fits_d.keys())
        else:
            fits = []
    else:
        configs = []
        fits = []

    meta_configs = '{...}' if len(configs) > 5 else None
    meta_fits = '{...}' if len(fits) > 5 else None
    # ┏━━━━━━━━━━━━━━━━┓
    # ┗━━━━━━━━━━━━━━━━┛

    msg = cleandoc("""
    ┎────────────────┒
    ┃ CDT2D LAUNCHER ┃
    ┖────────────────┚
    Manage CDT_2D simulations.

    To show the help of subcommand 'sub' run:
        launcher.py sub -h""")

    parser = argparse.ArgumentParser(
        description=msg, formatter_class=argparse.RawDescriptionHelpFormatter)

    parser.add_argument('--version',
                        action='version',
                        version='CDT_2D ' + 'Gauge Fields: ' + version)
    # todo: devo scriverci usage
    #   tipo senza nulla con un numero
    #   oppure il tipo di numeri
    # migliorare la descrizione di ogni comando

    cmds = {'SUBPARSER': '', 'HELP': '', 'VERSION': ''}

    # SUBPARSERS
    subparsers = parser.add_subparsers(dest='command')
    subparsers.required = False

    # run command

    run_cmd = {
        'LAMBDA': '--lamda',
        'BETA': '--beta',
        'RANGE': '--range',
        'CONFIG': '--config',
        'QUEUE': '--queue',
        'ARCH': '--arch',
        'FORCE': '--force',
        'TIMELENGTH': '--timelength',
        'DEBUG': '--debug',
        'FAKE-RUN': '--fake-run',
        'LINEAR-HISTORY': '--linear-history',
        'TIME': '--time',
        'STEPS': '--steps',
        'ADJACENCIES': '--adjacencies',
        'MOVE22': '--move22',
        'MOVE24': '--move24',
        'MOVE_GAUGE': '--move-gauge'
    }
    cmds = update_cmds(cmds, run_cmd)

    run_sub = subparsers.add_parser(
        'run',
        help=msgs.run_h,
        description=msgs.run,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    run_sub.add_argument('-l',
                         '--lamda',
                         nargs='+',
                         type=float,
                         required=True,
                         help=msgs.lamda)
    run_sub.add_argument('-b',
                         '--beta',
                         nargs='+',
                         type=positive_float,
                         required=True,
                         help=msgs.beta)
    run_sub.add_argument('--range',
                         choices=['b', 'l', 'bl', 'lb'],
                         default='',
                         help=msgs.range)
    run_sub.add_argument('-@',
                         dest='is_data',
                         action='store_true',
                         help=msgs.data)
    run_sub.add_argument('-c',
                         '--config',
                         choices=configs,
                         default='test',
                         metavar=meta_configs,
                         help=msgs.config)
    run_sub.add_argument('-q',
                         '--queue',
                         default='debug',
                         choices=['p', 'prod', 'd', 'dbg', 'debug'],
                         help=msgs.queue)
    run_sub.add_argument('--arch',
                         default='skl',
                         choices=['skl', 'knl'],
                         help=msgs.queue)
    run_sub.add_argument('-f', '--force', action='store_true', help=msgs.force)
    run_sub.add_argument('--timelength',
                         nargs='+',
                         type=int,
                         default=80,
                         help=msgs.timelength)
    run_sub.add_argument('-d', '--debug', action='store_true', help='debug')
    run_sub.add_argument('-k',
                         '--fake-run',
                         action='store_true',
                         help=msgs.fake_run)
    run_sub.add_argument('--lin',
                         '--linear-history',
                         dest='linear_history',
                         default='0',
                         type=str,
                         help=msgs.linear_history)
    # run_sub.add_argument('--log-history', dest='linear_history',
    #               action='store_false',
    #               help="if set data points are saved at increasing intervals")
    end_conditions = run_sub.add_mutually_exclusive_group()
    end_conditions.add_argument('--time', default='30m', help=msgs.time)
    end_conditions.add_argument('--steps', default='0', help=msgs.steps)
    run_sub.add_argument('--adj',
                         '--adjacencies',
                         dest='adj_flag',
                         action='store_true',
                         help=msgs.adjacencies)
    run_sub.add_argument('--vol',
                         '--max-volume',
                         dest='max_volume',
                         type=positive_float,
                         nargs=1,
                         default=1e5,
                         help=msgs.maxvol)
    moves_weights = run_sub.add_argument_group("moves' weights",
                                               description=msgs.moves_weights)
    moves_weights.add_argument('--move22',
                               nargs=1,
                               type=non_negative_float,
                               default=0.04,
                               metavar='W_22',
                               help=msgs.move22)
    moves_weights.add_argument('--move24',
                               nargs=1,
                               type=non_negative_float,
                               default=0.06,
                               metavar='W_24',
                               help=msgs.move24)
    moves_weights.add_argument('--move-gauge',
                               nargs=1,
                               type=non_negative_float,
                               default=0.8,
                               metavar='W_g',
                               help=msgs.moveg)
    run_sub.add_argument('--file', help=msgs.file)

    # state command
    class ToggleChoiceAction(argparse.Action):
        def __init__(self, option_strings, dest, ifcall, nargs=None, **kwargs):
            if nargs is not None:
                raise ValueError("nargs not allowed")
            super(ToggleChoiceAction, self).__init__(option_strings,
                                                     dest,
                                                     nargs='?',
                                                     **kwargs)
            self.ifcall = ifcall

        def __call__(self, parser, namespace, values, option_string=None):
            if values is None:
                setattr(namespace, self.dest, self.ifcall)
            else:
                setattr(namespace, self.dest, values)

    state_sub = subparsers.add_parser(
        'state',
        help=msgs.state_h,
        description=msgs.state,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    state_sub.add_argument('-@',
                           dest='is_data',
                           action='store_true',
                           help=msgs.data)
    state_sub.add_argument('-c',
                           '--config',
                           choices=configs,
                           default=configs,
                           metavar=meta_configs,
                           ifcall='test',
                           action=ToggleChoiceAction,
                           help=msgs.config)
    state_sub.add_argument('-f',
                           '--full-show',
                           choices=['1', '2'],
                           default='0',
                           ifcall='1',
                           action=ToggleChoiceAction,
                           help=msgs.full_show)

    # stop command

    stop_sub = subparsers.add_parser(
        'stop',
        help=msgs.stop_h,
        description=msgs.stop,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    points = stop_sub.add_argument_group()
    points.add_argument('-l',
                        '--lamda',
                        nargs='+',
                        type=float,
                        help=msgs.lamda)
    points.add_argument('-b',
                        '--beta',
                        nargs='+',
                        type=positive_float,
                        help=msgs.beta)
    points.add_argument('--range',
                        choices=['b', 'l', 'bl', 'lb'],
                        default='',
                        help=msgs.range)
    points.add_argument('-°',
                        dest='is_all',
                        action='store_true',
                        help=msgs.is_all)
    stop_sub.add_argument('-@',
                          dest='is_data',
                          action='store_true',
                          help=msgs.data)
    stop_sub.add_argument('-c',
                          '--config',
                          choices=configs,
                          default='test',
                          metavar=meta_configs,
                          help=msgs.config)
    stop_sub.add_argument('--pid',
                          nargs='+',
                          type=int,
                          default=None,
                          help=msgs.pid)
    stop_sub.add_argument('-f',
                          '--force',
                          action='store_true',
                          help=msgs.force)

    # plot command

    plot_sub = subparsers.add_parser(
        'plot',
        help=msgs.plot_h,
        description=msgs.plot,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    plot_sub.add_argument('-l',
                          '--lamda',
                          nargs='+',
                          type=float,
                          required=True,
                          help=msgs.lamda)
    plot_sub.add_argument('-b',
                          '--beta',
                          nargs='+',
                          type=positive_float,
                          required=True,
                          help=msgs.beta)
    plot_sub.add_argument('--range',
                          choices=['b', 'l', 'bl', 'lb'],
                          default='',
                          help=msgs.range)
    plot_sub.add_argument('-@',
                          dest='is_data',
                          action='store_true',
                          help=msgs.data)
    plot_sub.add_argument('-c',
                          '--config',
                          choices=configs,
                          default='test',
                          metavar=meta_configs,
                          help=msgs.config)
    plot_sub.add_argument('-g',
                          '--gauge',
                          action='store_true',
                          help=msgs.plot_gauge)

    # show command

    show_sub = subparsers.add_parser(
        'show',
        help=msgs.show_h,
        description=msgs.show,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    show_sub.add_argument('-l',
                          '--lamda',
                          nargs='+',
                          type=float,
                          help=msgs.lamda)
    show_sub.add_argument('-b',
                          '--beta',
                          nargs='+',
                          type=positive_float,
                          help=msgs.beta)
    lambdas = show_sub.add_mutually_exclusive_group()
    lambdas.add_argument('--range',
                         choices=['b', 'l', 'bl', 'lb'],
                         default='',
                         help=msgs.range)
    lambdas.add_argument('-°',
                         dest='is_all',
                         action='store_true',
                         help=msgs.is_all)
    show_sub.add_argument('-@',
                          dest='is_data',
                          action='store_true',
                          help=msgs.data)
    show_sub.add_argument('-c',
                          '--config',
                          choices=configs,
                          default='test',
                          metavar=meta_configs,
                          help=msgs.config)
    show_sub.add_argument('-d',
                          '--disk-usage',
                          default='',
                          const='disk',
                          action='store_const',
                          help=msgs.disk_usage)
    show_sub.add_argument('-n',
                          '--number',
                          dest='disk_usage',
                          const='num',
                          action='store_const',
                          help=msgs.disk_number)

    # utilities subparser

    tools = subparsers.add_parser('tools', help=msgs.tools)
    tools_sub = tools.add_subparsers(dest='tools')

    # recovery command

    recovery_sub = tools_sub.add_parser(
        'recovery',
        help='recovery',
        description=msgs.recovery,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    recovery_sub.add_argument('-l',
                              '--lamda',
                              nargs='+',
                              type=float,
                              help=msgs.lamda)
    recovery_sub.add_argument('-b',
                              '--beta',
                              nargs='+',
                              type=positive_float,
                              help=msgs.beta)
    lambdas = recovery_sub.add_mutually_exclusive_group()
    lambdas.add_argument('--range',
                         choices=['b', 'l', 'bl', 'lb'],
                         default='',
                         help=msgs.range)
    lambdas.add_argument('-°',
                         dest='is_all',
                         action='store_true',
                         help=msgs.is_all)
    recovery_sub.add_argument('-@',
                              dest='is_data',
                              action='store_true',
                              help=msgs.data)
    recovery_sub.add_argument('-c',
                              '--config',
                              choices=configs,
                              default='test',
                              metavar=meta_configs,
                              help=msgs.config)
    recovery_sub.add_argument('-f',
                              '--force',
                              action='store_true',
                              help=msgs.force)
    recovery_sub.add_argument('-F',
                              '--FORCE',
                              action='store_true',
                              help=msgs.very_force)

    # info command

    info_sub = tools_sub.add_parser(
        'info',
        help='info on a sim',
        description=msgs.info,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    info_sub.add_argument('-l',
                          '--lamda',
                          nargs='+',
                          type=float,
                          required=True,
                          help=msgs.lamda)
    info_sub.add_argument('-b',
                          '--beta',
                          nargs='+',
                          type=positive_float,
                          required=True,
                          help=msgs.beta)
    info_sub.add_argument('-@',
                          dest='is_data',
                          action='store_true',
                          help=msgs.data)
    info_sub.add_argument('-c',
                          '--config',
                          choices=configs,
                          default='test',
                          metavar=meta_configs,
                          help=msgs.config)

    # thermalization command

    therm_sub = tools_sub.add_parser(
        'set-therm',
        help='set thermalisation',
        description=msgs.therm,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    therm_sub.add_argument('-l',
                           '--lamda',
                           nargs='+',
                           type=float,
                           required=True,
                           help=msgs.lamda)
    therm_sub.add_argument('-b',
                           '--beta',
                           nargs='+',
                           type=positive_float,
                           required=True,
                           help=msgs.beta)
    therm_sub.add_argument('-@',
                           dest='is_data',
                           action='store_true',
                           help=msgs.data)
    therm_sub.add_argument('-c',
                           '--config',
                           choices=configs,
                           default='test',
                           metavar=meta_configs,
                           help=msgs.config)
    therm_sub.add_argument('-f',
                           '--force',
                           action='store_true',
                           help=msgs.force)
    therm_sub.add_argument('-t',
                           '--is-therm',
                           default='True',
                           choices=['True', 'False'],
                           help=msgs.is_therm)

    # update launcher command

    launch_sub = tools_sub.add_parser(
        'up-launch',
        help='update launch/make_script',
        description=msgs.up_launch,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    points = launch_sub.add_argument_group()
    points.add_argument('-l',
                        '--lamda',
                        nargs='+',
                        type=float,
                        help=msgs.lamda)
    points.add_argument('-b',
                        '--beta',
                        nargs='+',
                        type=positive_float,
                        help=msgs.beta)
    points.add_argument('--range',
                        choices=['b', 'l', 'bl', 'lb'],
                        default='',
                        help=msgs.range)
    points.add_argument('-°',
                        dest='is_all',
                        action='store_true',
                        help=msgs.is_all)
    launch_sub.add_argument('-@',
                            dest='is_data',
                            action='store_true',
                            help=msgs.data)
    launch_sub.add_argument('-c',
                            '--config',
                            choices=configs,
                            default='test',
                            metavar=meta_configs,
                            help=msgs.config)
    launch_sub.add_argument('-f',
                            '--force',
                            action='store_true',
                            help=msgs.force)
    script = launch_sub.add_mutually_exclusive_group()
    script.add_argument('-m', '--make', action='store_true', help=msgs.make)
    script.add_argument('--both', action='store_true', help=msgs.both)

    # autoremove command

    remove_sub = tools_sub.add_parser(
        'autoremove',
        help='autoremove',
        description=msgs.autoremove,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    remove_sub.add_argument('-l',
                            '--lamda',
                            nargs='+',
                            type=float,
                            help=msgs.lamda)
    remove_sub.add_argument('-b',
                            '--beta',
                            nargs='+',
                            type=positive_float,
                            help=msgs.beta)
    lambdas = remove_sub.add_mutually_exclusive_group()
    lambdas.add_argument('--range',
                         choices=['b', 'l', 'bl', 'lb'],
                         default='',
                         help=msgs.range)
    lambdas.add_argument('-°',
                         dest='is_all',
                         action='store_true',
                         help=msgs.is_all)
    remove_sub.add_argument('-@',
                            dest='is_data',
                            action='store_true',
                            help=msgs.data)
    remove_sub.add_argument('-c',
                            '--config',
                            choices=configs,
                            default='test',
                            metavar=meta_configs,
                            help=msgs.config)
    remove_sub.add_argument('-f',
                            '--force',
                            action='store_true',
                            help=msgs.force)
    what = remove_sub.add_mutually_exclusive_group()
    what.add_argument('--bin',
                      ifcall='0',
                      action=ToggleChoiceAction,
                      help=msgs.bin)
    what.add_argument('--check',
                      ifcall='0',
                      action=ToggleChoiceAction,
                      help=msgs.check)

    # upload/download command

    remote_sub = tools_sub.add_parser(
        'remote',
        help='upload/download sim dirs',
        description=msgs.remote,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    remote_sub.add_argument('-l',
                            '--lamda',
                            nargs='+',
                            type=float,
                            help=msgs.lamda)
    remote_sub.add_argument('-b',
                            '--beta',
                            nargs='+',
                            type=positive_float,
                            help=msgs.beta)
    lambdas = remote_sub.add_mutually_exclusive_group()
    lambdas.add_argument('--range',
                         choices=['b', 'l', 'bl', 'lb'],
                         default='',
                         help=msgs.range)
    lambdas.add_argument('-°',
                         dest='is_all',
                         action='store_true',
                         help=msgs.is_all)
    remote_sub.add_argument('-@',
                            dest='is_data',
                            action='store_true',
                            help=msgs.data)
    remote_sub.add_argument('-c',
                            '--config',
                            choices=configs,
                            default='test',
                            metavar=meta_configs,
                            help=msgs.config)
    remote_sub.add_argument('-f',
                            '--force',
                            action='store_true',
                            help=msgs.force)
    load = remote_sub.add_mutually_exclusive_group(required=True)
    load.add_argument('-u', '--upload', action='store_true', help=msgs.upload)
    load.add_argument('-d',
                      '--download',
                      action='store_true',
                      help=msgs.download)
    load.add_argument('-s',
                      '--show',
                      action='store_true',
                      help=msgs.remote_show)

    # config command

    config_sub = tools_sub.add_parser(
        'config',
        help='edit project\'s configuration file',
        description=msgs.config_cmd,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    configs_arg = config_sub.add_mutually_exclusive_group()
    configs_arg.add_argument('-e',
                             '--email',
                             action=ToggleChoiceAction,
                             default=None,
                             ifcall='-',
                             help=msgs.email)
    configs_arg.add_argument('-r',
                             '--remote',
                             action=ToggleChoiceAction,
                             default=None,
                             ifcall='-',
                             help=msgs.rclone_remote)
    configs_arg.add_argument('-p',
                             '--path',
                             action=ToggleChoiceAction,
                             default=None,
                             ifcall='-',
                             help=msgs.rclone_path)
    configs_arg.add_argument('-n',
                             '--node',
                             action=ToggleChoiceAction,
                             default=None,
                             ifcall='-',
                             help=msgs.node)
    config_sub.add_argument('-s',
                            '--show',
                            action='store_true',
                            help=msgs.show_config)

    # new configuration command

    # new_conf_sub = tools_sub.add_parser('new-conf',
    #                 help='show configs directories',
    #                 description=msgs.show_confs,
    #                 formatter_class=argparse.RawDescriptionHelpFormatter)
    # new_conf_sub.add_argument('-p', '--paths', action='store_true',
    #                           help=msgs.show_paths)
    new_conf_sub = tools_sub.add_parser(
        'new-conf',
        help='create new config',
        description=msgs.new_conf,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    new_conf_sub.add_argument('name', nargs=1, type=str)
    new_conf_sub.add_argument('-p',
                              '--path',
                              type=str,
                              default=None,
                              help=msgs.path)

    # show available configurations command

    show_confs_sub = tools_sub.add_parser(
        'show-confs',
        help='show configs directories',
        description=msgs.show_confs,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    show_confs_sub.add_argument('-p',
                                '--paths',
                                action='store_true',
                                help=msgs.show_paths)

    # reset configuration command

    reset_conf_sub = tools_sub.add_parser(
        'reset',
        help='reset or delete config',
        description=msgs.reset,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    reset_conf_sub.add_argument('name', choices=configs)
    # reset_conf_sub.add_argument('-d', '--delete', action='store_true',
    #                             help=msgs.delete)

    # remove configuration command

    rm_conf_sub = tools_sub.add_parser(
        'rm-conf',
        help='remove config',
        description=msgs.rm_conf,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    rm_conf_sub.add_argument('config',
                             choices=configs,
                             metavar=meta_configs,
                             help=msgs.config)
    rm_conf_sub.add_argument('-f',
                             '--force',
                             action='store_true',
                             help=msgs.force)

    # clear command

    clear_sub = tools_sub.add_parser(
        'clear',
        help='clear',
        description=msgs.clear,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    clear_sub.add_argument('-l',
                           '--lamda',
                           nargs='+',
                           type=float,
                           help=msgs.lamda)
    clear_sub.add_argument('-b',
                           '--beta',
                           nargs='+',
                           type=positive_float,
                           help=msgs.beta)
    lambdas = clear_sub.add_mutually_exclusive_group()
    lambdas.add_argument('--range',
                         choices=['b', 'l', 'bl', 'lb'],
                         default='',
                         help=msgs.range)
    lambdas.add_argument('-°',
                         dest='is_all',
                         action='store_true',
                         help=msgs.is_all)
    clear_sub.add_argument('-@',
                           dest='is_data',
                           action='store_true',
                           help=msgs.data)
    clear_sub.add_argument('-c',
                           '--config',
                           choices=configs,
                           default='test',
                           metavar=meta_configs,
                           help=msgs.config)
    clear_sub.add_argument('-f',
                           '--force',
                           action='store_true',
                           help=msgs.force)

    # analysis subparser

    analysis = subparsers.add_parser('analysis', help=msgs.analysis)
    analysis_sub = analysis.add_subparsers(dest='analysis')

    def fit_pattern(fit):
        if not isinstance(fit, str):
            msg = f"{fit} is not a valid str."
            raise argparse.ArgumentTypeError(msg)
        if fit not in fits and fit[0] != '§':
            msg = f"{fit} is not valid fit nor pattern"
            raise argparse.ArgumentTypeError(msg)
        return fit

    # preliminary command

    def config_pattern(config):
        if not isinstance(config, str):
            msg = f"{config} is not a valid str."
            raise argparse.ArgumentTypeError(msg)
        if config not in configs and config[0] != '§':
            msg = f"{config} is not valid config nor pattern"
            raise argparse.ArgumentTypeError(msg)
        return config

    kinds = ['mv', 'mean-volumes', 'd', 'divergent', 'vp', 'volumes-plot']

    pre_sub = analysis_sub.add_parser(
        'pre',
        help='preliminary analyses',
        description=msgs.ana_pre,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    pre_sub.add_argument('-k', '--kind', choices=kinds, help=msgs.pre_kind)
    pre_sub.add_argument('-c',
                         '--config',
                         default=None,
                         metavar=meta_configs,
                         nargs='+',
                         type=config_pattern,
                         help=msgs.config_pattern)
    pre_sub.add_argument('--conf-plot',
                         dest='conf_plot',
                         action='store_true',
                         help=msgs.conf_plot)
    pre_sub.add_argument('-s',
                         '--save_path',
                         type=str,
                         default=None,
                         help=msgs.save_path)
    pre_sub.add_argument('-l',
                         '--load_path',
                         type=str,
                         default=None,
                         help=msgs.load_path)

    # preliminary plots command

    kinds = [
        'v', 'volumes', 'p', 'profiles', 'g', 'action', 'gauge',
        'gauge-action', 'top', 'susc', 'top-susc', 't', 'torelons'
    ]

    pre_plot_sub = analysis_sub.add_parser(
        'pre-plot',
        help='preliminary analyses',
        description=msgs.ana_pre,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    pre_plot_sub.add_argument('fit_name',
                              metavar=meta_fits,
                              nargs='+',
                              type=fit_pattern,
                              help=msgs.fit_names)
    pre_plot_sub.add_argument('-k',
                              '--kind',
                              choices=kinds,
                              help=msgs.pre_kind)

    # new fit command

    new_fit_sub = analysis_sub.add_parser(
        'new-fit',
        help='create new fit',
        description=msgs.new_fit,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    new_fit_sub.add_argument('fit_name', nargs=1, type=str)
    new_fit_sub.add_argument('-p',
                             '--path',
                             type=str,
                             required=True,
                             default=None,
                             help=msgs.fit_path)

    # show available fits command

    show_fits_sub = analysis_sub.add_parser(
        'show-fits',
        help='show fits directories',
        description=msgs.show_fits,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    show_fits_sub.add_argument('-p',
                               '--paths',
                               action='store_true',
                               help=msgs.show_fit_paths)

    # reset fit command

    reset_fit_sub = analysis_sub.add_parser(
        'reset',
        help='reset or delete fit',
        description=msgs.reset,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    reset_fit_sub.add_argument('fit_name',
                               metavar=meta_fits,
                               nargs='+',
                               type=fit_pattern,
                               help=msgs.fit_names)
    reset_fit_sub.add_argument('-d',
                               '--delete',
                               action='store_true',
                               help=msgs.delete_fit)

    # # remove fit command
    #
    # rm_fit_sub = analysis_sub.add_parser('rm-fit', help='remove fit',
    #                     description=msgs.rm_fit,
    #                     formatter_class=argparse.RawDescriptionHelpFormatter)
    # rm_fit_sub.add_argument('fit', metavar=meta_fits, nargs='+',
    #                         type=fit_pattern, help=msgs.fits)
    # rm_fit_sub.add_argument('-f', '--force', action='store_true',
    #                          help=msgs.force)

    # set fit properties

    set_fit_sub = analysis_sub.add_parser(
        'set-fit',
        help='set fit properties',
        description=msgs.set_fit,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    set_fit_sub.add_argument('fit_name',
                             metavar=meta_fits,
                             nargs=1,
                             choices=fits,
                             type=str,
                             help=msgs.fit_names)
    set_fit_sub.add_argument('-l',
                             '--lamda',
                             nargs='+',
                             type=float,
                             help=msgs.lamda)
    set_fit_sub.add_argument('-b',
                             '--beta',
                             nargs='+',
                             type=positive_float,
                             help=msgs.beta)
    set_fit_sub.add_argument('--range',
                             choices=['b', 'l', 'bl', 'lb'],
                             default='',
                             help=msgs.range)
    set_fit_sub.add_argument('-°',
                             dest='is_all',
                             action='store_true',
                             help=msgs.is_all)
    set_fit_sub.add_argument('-c',
                             '--config',
                             choices=configs,
                             default='test',
                             metavar=meta_configs,
                             help=msgs.config)
    set_fit_sub.add_argument('--remove',
                             action='store_true',
                             help=msgs.fit_remove)

    # set fit properties

    kinds = ['s', 'sims', 'o', 'obs']

    info_fit_sub = analysis_sub.add_parser(
        'info-fit',
        help='show fit properties',
        description=msgs.info_fit,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    info_fit_sub.add_argument('fit_name',
                              metavar=meta_fits,
                              nargs=1,
                              choices=fits,
                              type=str,
                              help=msgs.fit_names)
    info_fit_sub.add_argument('-k',
                              '--kind',
                              choices=kinds,
                              help=msgs.pre_kind)

    # sims obs

    sim_obs_sub = analysis_sub.add_parser(
        'sim-obs',
        help='calculate sims observables',
        description=msgs.sim_obs,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    sim_obs_sub.add_argument('-l',
                             '--lamda',
                             nargs='+',
                             type=float,
                             help=msgs.lamda)
    sim_obs_sub.add_argument('-b',
                             '--beta',
                             nargs='+',
                             type=positive_float,
                             help=msgs.beta)
    sim_obs_sub.add_argument('--range',
                             choices=['b', 'l', 'bl', 'lb'],
                             default='',
                             help=msgs.range)
    sim_obs_sub.add_argument('-c',
                             '--config',
                             choices=configs,
                             default='test',
                             metavar=meta_configs,
                             help=msgs.config)
    sim_obs_sub.add_argument('-°',
                             dest='is_all',
                             action='store_true',
                             help=msgs.is_all)
    sim_obs_sub.add_argument('-n',
                             '--fit-name',
                             metavar=meta_fits,
                             type=fit_pattern,
                             nargs='+',
                             help=msgs.fit_names)
    sim_obs_sub.add_argument('-f',
                             '--fit',
                             action='store_true',
                             help=msgs.fit_obs)
    sim_obs_sub.add_argument('-p',
                             '--plot',
                             action='store_true',
                             help=msgs.plot_obs)
    sim_obs_sub.add_argument('--et',
                             '--exclude-torelons',
                             action='store_true',
                             dest='exclude_torelons',
                             help=msgs.excl_tor)
    sim_obs_sub.add_argument('--eb',
                             '--exclude-bootstrap',
                             action='store_true',
                             dest='exclude_bootstrap',
                             help=msgs.excl_tor)
    sim_obs_sub.add_argument('--force', action='store_true', help=msgs.force)

    # refit corr command

    refit_sub = analysis_sub.add_parser(
        'refit-corr',
        help='refit correlation lenghts',
        description=msgs.refit_corr,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    refit_sub.add_argument('-l',
                           '--lamda',
                           nargs='+',
                           type=float,
                           help=msgs.lamda)
    refit_sub.add_argument('-b',
                           '--beta',
                           nargs='+',
                           type=positive_float,
                           help=msgs.beta)
    refit_sub.add_argument('--range',
                           choices=['b', 'l', 'bl', 'lb'],
                           default='',
                           help=msgs.range)
    refit_sub.add_argument('-c',
                           '--config',
                           choices=configs,
                           default='test',
                           metavar=meta_configs,
                           help=msgs.config)
    refit_sub.add_argument('-°',
                           dest='is_all',
                           action='store_true',
                           help=msgs.is_all)
    refit_sub.add_argument('-n',
                           '--fit-name',
                           metavar=meta_fits,
                           type=fit_pattern,
                           nargs='+',
                           help=msgs.fit_names)
    refit_sub.add_argument('-p',
                           '--plot',
                           action='store_true',
                           help=msgs.plot_obs)
    # refit_sub.add_argument('--et', '--exclude-torelons', action='store_true',
    #                          dest='exclude_torelons', help=msgs.excl_tor)
    refit_sub.add_argument('--force', action='store_true', help=msgs.force)

    # export-data command

    data_types = [
        'v', 'volumes', 'p', 'profiles', 'pf', 'profiles-fit', 'pf2',
        'profiles-fit2', 'g', 'gauge-action', 'top', 'susc', 'top-susc', 't',
        'torelons', 'tf', 'torelons-fit', 'tf2', 'torelons-fit2'
    ]

    export_sub = analysis_sub.add_parser(
        'export-data',
        description=msgs.export_data,
        help='export data for fit',
        formatter_class=argparse.RawDescriptionHelpFormatter)
    export_sub.add_argument('fit_name',
                            metavar=meta_fits,
                            type=fit_pattern,
                            nargs='+',
                            help=msgs.fit_names)
    export_sub.add_argument('-u',
                            '--unpack',
                            choices=data_types,
                            help=msgs.unpack)

    # fit command

    kinds = [
        'v', 'volumes', 'p', 'profiles', 't', 'torelons', 'g', 'gauge-action',
        'top', 'susc', 'top-susc'
    ]

    fit_sub = analysis_sub.add_parser(
        'fit',
        help='fit',
        description=msgs.fit,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    fit_sub.add_argument('fit_name',
                         metavar=meta_fits,
                         nargs=1,
                         choices=fits,
                         type=str,
                         help=msgs.fits)
    fit_sub.add_argument('-r',
                         '--reload',
                         action='store_true',
                         help=msgs.reload_data)
    fit_sub.add_argument('-k',
                         '--kind',
                         choices=kinds,
                         default='volumes',
                         help=msgs.fit_kinds)

    chdir(starting_cwd)

    return parser, cmds