Esempio n. 1
0
def execute_command():

    source = paths.resource('tracksim.global.sh')

    with open(source, 'r+') as f:
        contents = f.read()

    path = paths.project('bin', 'tracksim')
    contents = contents.replace('###TRACKSIM_PATH###', path)

    path = '/usr/local/bin/tracksim'
    with open(path, 'w+') as f:
        f.write(contents)

    os.chmod(
        path,
        stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
        stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP |
        stat.S_IROTH | stat.S_IXOTH
    )

    register_global_var()

    system.log("""
        [SUCCESS]: The tracksim command has been registered for global use. You
        can now call tracksim globally from a terminal.

        If you have trouble calling tracksim, make sure you have exported
            /usr/local/bin
        in your .bash_profile PATH.
        """)
Esempio n. 2
0
def fetch_command():
    """

    :return:
    """

    cmd = None
    if len(sys.argv) > 1:
        cmd = sys.argv[1].lower()

    if cmd in ['-h', '-help', '--help', '--h']:
        return 'help'

    if cmd is None or cmd.startswith('-'):
        system.log("""
        [ERROR]: tracksim requires a command argument that defines the
        operation to be carried out. The expected structure is:

            $ tracksim [COMMAND] [ARGUMENTS] [--OPTIONS]

        For a list of available commands run:

            $ tracksim help
        """)

        system.end(1)

    return cmd
Esempio n. 3
0
def list_modules():

    for key in dir(ME):
        item = getattr(ME, key)
        if hasattr(item, 'DESCRIPTION'):
            print('')
            system.log('[{}]:\n   {}'.format(
                key.strip('_'),
                cli.reformat(getattr(item, 'DESCRIPTION'))
                    .replace('\n', '\n   ')
            ))
    def test_logging(self):
        """
        """

        system.log('This is a test')

        system.log([
            '1',
            ['2', '3',
             ['4', '5', '6']
             ]
        ])
Esempio n. 5
0
    def error_and_exit(label, key):
        system.log("""
            [ERROR]: No {label} was specified in your tracksim settings.

            Use the configure command to fix this:

                $ tracksim configure {key} "[{LABEL}]"

            or specify the {label} in your deploy command. For details run:

                $ tracksim deploy help
            """.format(label=label, key=key, LABEL=label.upper()))
        sys.exit(1)
Esempio n. 6
0
def show_help():
    """ Prints the basic command help to the console """

    system.log('The following commands are available:')
    list_modules()

    msg = """
        For more information on the various commands, use the help flag on the
        specific command:

            tracksim [COMMAND] --help
        """
    system.log(msg, whitespace_top=1)
Esempio n. 7
0
def echo_key(configs: dict, key: str):
    """

    :param configs:
    :param key:
    :return:
    """

    if key not in configs:
        system.log('[MISSING]: No "{}" key was found'.format(key))
        return

    system.log('[VALUE]: "{}" = {}'.format(key, configs[key]))
Esempio n. 8
0
def find_group_files(path: str) -> typing.List[str]:
    """
    Finds all group configuration JSON files stored in the specified path
    directory

    :param path:
        Path to the directory where the group files search should take place
    """

    paths = []

    # Prioritize group files named "group.json" over other files in the path
    items = ['group.json']
    for item in os.listdir(path):
        if item == 'group.json':
            continue
        items.append(item)

    for item in items:
        item_path = os.path.join(path, item)
        if not os.path.exists(item_path):
            continue

        if not os.path.isfile(item_path) or not item.endswith('.json'):
            continue

        try:
            with open(item_path, 'r+') as f:
                data = json.load(f)
        except json_decoder.JSONDecodeError as err:
            system.log([
                '[ERROR]: Failed to decode json file',
                [
                    'PATH: {}'.format(path),
                    'INFO: {}'.format(err.msg),
                    [
                        'LINE: {}'.format(err.lineno),
                        'CHAR: {}'.format(err.colno)
                    ]
                ]
            ])
            return system.end(1)

        if 'trials' in data:
            paths.append(item_path)

    if not paths:
        system.log('ERROR: No group trial found in path: "{}"'.format(path))
        system.end(2)

    return paths
Esempio n. 9
0
def execute_command():
    """ Runs the deploy command """

    parser = ArgumentParser()

    parser.description = cli.reformat(DESCRIPTION)

    parser.add_argument(
        'deploy',
        type=str,
        help='The deploy command to execute'
    )

    parser.add_argument(
        'root_path',
        type=str,
        help=cli.reformat("""
            The folder in the S3 bucket where your files will be uploaded
            """)
    )

    parser.add_argument(
        '-p', '--profile',
        dest='profile',
        type=str,
        default=None,
        help=cli.reformat("""
            The name of the AWS credentials profile to use for access to the
            AWS S3 bucket resources
            """)
    )

    parser.add_argument(
        '-b', '--bucket',
        dest='bucket',
        type=str,
        default=None,
        help=cli.reformat("""
            The name of the S3 bucket where the files will be uploaded
            """)
    )

    args = vars(parser.parse_args())
    configs = system.load_configs()

    upload_in_folder(
        get_aws_settings(configs, **args),
        paths.results('report')
    )
    system.log('[COMPLETE]: Trials have been deployed')
Esempio n. 10
0
def echo_all(configs: dict):
    """

    :param configs:
    :return:
    """

    keys = list(configs.keys())
    keys.sort()
    out = ['Current Configuration:']
    for k in keys:
        out.append('  * {key}: {value}'.format(key=k, value=configs[k]))

    system.log('\n'.join(out))
Esempio n. 11
0
def execute_command():

    path = '/usr/local/bin/tracksim'
    if not os.path.exists(path):
        system.log(cli.reformat("""
            [INFO]: The tracksim command was not registered. Operation aborted.
            """))
        return

    os.remove(path)

    system.log("""
        [SUCCESS]: The tracksim command is no longer registered for global use.
        """)
Esempio n. 12
0
def print_results(urls: typing.List[str]):
    """

    :param urls:
    :return:
    """

    msg = """
    ------------------------------------------
    Simulation Complete. Results Available At:
    """
    system.log(msg, whitespace=1)

    for r in urls:
        system.log('  * {}'.format(r))
Esempio n. 13
0
def remove_key(configs: dict, key: str):
    """
    Removes the specified key from the tracksim configs if the key exists

    :param configs:
        The tracksim configs object to modify
    :param key:
        The key in the tracksim configs object to remove
    """

    if key in configs:
        del configs[key]
    system.save_configs(configs)
    system.log(
        '[REMOVED]: "{}" from configuration settings'.format(key)
    )
Esempio n. 14
0
def list_trials():
    system.log("===== TRIALS =====", whitespace_bottom=1)

    results_path = paths.results("trials.html")

    for uid, data_path in reader.listings("trial").items():
        url = "file://{}?id={}".format(results_path, uid)

        system.log(
            """
            --- {uid} ---
              {url}
            """.format(
                uid=uid, url=url
            ),
            whitespace_bottom=1,
        )
Esempio n. 15
0
def run(**kwargs):
    """

    :param kwargs:
    :return:
    """

    cli_configs = kwargs.get('settings')
    if cli_configs is None:
        cli_configs = system.load_configs()

    path = get_path(kwargs.get('path'), cli_configs)
    if path is None:
        system.log('ERROR: Invalid or missing path argument')
        sys.exit(1)

    urls = []

    if os.path.isfile(path):
        with open(path, 'r+') as f:
            data = json.load(f)

        urls.append(run_simulation(
            is_group=bool('trials' in data),
            cli_configs=cli_configs,
            settings_path=path,
            **kwargs
        ))

    else:
        group_paths = find_group_files(path)
        if not kwargs.get('run_all_groups'):
            group_paths = group_paths[0:1]

        for p in group_paths:
            urls.append(run_simulation(
                is_group=True,
                cli_configs=cli_configs,
                settings_path=p,
                **kwargs
            ))

    save_recent_path(kwargs.get('path'), cli_configs)
    print_results(urls)
Esempio n. 16
0
def execute_command():
    """

    :return:
    """

    parser = ArgumentParser()

    parser.description = cli.reformat(DESCRIPTION)

    parser.add_argument(
        'generate_command',
        type=str,
        help='The generate command itself'
    )

    parser.add_argument(
        'trial_or_group',
        type=str,
        help='Path to a trial or group file where the data source is specified'
    )

    parser.add_argument(
        'output_filename',
        type=str,
        help='Name of the csv file to be created'
    )

    args = parser.parse_args()
    cli_configs = system.load_configs()

    path = get_path(args.trial_or_group, cli_configs)
    if path is None:
        system.log('ERROR: Invalid or missing trial/group path')
        sys.exit(1)

    settings = configs.load(None, path)
    out_path = os.path.join(settings['directory'], args.output_filename)

    simulate.load_trackway_positions(
        settings,
        save_as=out_path
    )
Esempio n. 17
0
def set_key(configs: dict, key: str, value: typing.List[str]):
    """
    Removes the specified key from the tracksim configs if the key exists

    :param configs:
        The tracksim configs object to modify
    :param key:
        The key in the tracksim configs object to remove
    :param value:
    """

    if key.startswith('path.'):
        for index in range(len(value)):
            value[index] = paths.clean(value[index])

    if len(value) == 1:
        value = value[0]

    configs[key] = value
    system.save_configs(configs)
    system.log('[SET]: "{}" to "{}"'.format(key, value))
Esempio n. 18
0
def run(
        settings: typing.Union[str, dict],
        **kwargs
) -> dict:
    """
    Executes a grouped collection of simulation trials and returns the compiled
    results for the individual trials, as well as results calculated for the
    group of trials

    :param settings:
        Settings for running the group of trials. Each trial configuration
        will inherit values from these settings.
    :param kwargs:
        Optional setting overrides to be included in the group configuration
    """

    settings = configs.load('group', settings, **kwargs)
    trials = []

    system.log('[{}]: STARTING'.format(settings['id']))

    for source in fetch_trial_list(settings):
        if isinstance(source, str):
            original = source
            source = os.path.abspath(os.path.join(settings['path'], source))
            if not os.path.exists(source):
                source = '{}.json'.format(source)
            if not os.path.exists(source):
                system.log(
                    """
                    [ERROR]: Unable to locate simulation trial file "{}"
                    """.format(original)
                )
                raise FileNotFoundError('No such file {}'.format(source))

        trial_settings = configs.load('trial', source, inherits=settings)
        simulate_trial.run(trial_settings)
        trials.append(dict(
            settings=trial_settings,
            index=len(trials) + 1,
            id=trial_settings['id'],
        ))

    system.log('[{}]: ANALYZING'.format(settings['id']))

    url = analyze.create(settings, trials)

    system.log('[{}]: COMPLETE'.format(settings['id']))

    return url
Esempio n. 19
0
def execute_command():
    """

    :return:
    """

    system.log("""
        ==============
        REMOVE RESULTS
        ==============

        This command will remove all analysis, group and trial reports stored
        located in the directory:

        {}
        """.format(paths.results()), whitespace_bottom=1)

    do_it = query.confirm(
        'Are you sure you want to continue',
        default=False
    )

    if not do_it:
        system.log('[ABORTED]: No files were deleted')
        return system.end(0)

    path = paths.results('reports')

    if os.path.exists(path):
        try:
            shutil.rmtree(path)
        except Exception:
            try:
                shutil.rmtree(path)
            except Exception:
                pass

    system.log("""
        [SUCCESS]: All results have been removed
        """, whitespace_top=1)
Esempio n. 20
0
def run(
        path: str,
        source_directory: str,
        directory_name: str,
        force: bool,
        **kwargs
):
    """

    :param path:
    :param source_directory:
    :param directory_name:
    :param force:
    :return:
    """

    target_path = os.path.join(os.path.abspath(path), directory_name)
    if os.path.exists(target_path):

        if not force:
            system.log("""
            [ABORTED EXPORT]
            A file or directory already exists at the specified path:

            {path}

            If you would like to replace the existing data at this path location
            either delete the existing data first, or run this command with the
            force flag.
            """.format(path=target_path))
            system.end(1)

        system.log('[REMOVING]: Existing directory {}'.format(target_path))
        try:
            shutil.rmtree(target_path)
        except OSError:
            try:
                # Give it a second
                shutil.rmtree(target_path)
            except OSError:
                system.log("""
                    [ABORTED EXPORT]
                    The existing directory could not be removed.
                    Unable to continue.
                    """)
                system.end(1)

    omit_html = kwargs.get('omit_html', False)
    omit_data = kwargs.get('omit_data', False)

    def list_ignores(src, names):
        """
        Creates a list of file names that should not be copied to the
        destination during the copytree operation.

        :param src:
            Source directory where the files originate
        :param names:
            A list of file names in the source directory to filter
        :return:
            A list of file names in the source directory that should NOT
            be copied to the destination path
        """

        ignored_names = []
        for name in names:
            if omit_html and not name.endswith('.json'):
                ignored_names.append(name)
            if omit_data and name.endswith('.json'):
                ignored_names.append(name)
        return ignored_names

    shutil.copytree(source_directory, target_path, ignore=list_ignores)

    result = create_index_file(source_directory, target_path)

    system.log("""
        [EXPORT COMPLETE]
        The export process was successful. All existing reports are now
        accessible through the index file:

         * {url}
        """.format(url=result['url']), whitespace=1)
Esempio n. 21
0
def run(
        settings: typing.Union[str, dict],
        trackway_positions: trackway.TrackPosition = None,
        **kwargs
) -> dict:
    """
    Runs and analyzes a simulation of the trackway under the conditions
    specified by the arguments and returns a dictionary of results for the
    trial

    :param settings:
        Either a dictionary containing the configuration values for the trial
        or an absolute path to a json format file that contains the
        configuration values for the trial
    :param trackway_positions:
        A TrackwayDefinition instance populated with phase and position values
    """

    settings = configs.load('trial', settings, **kwargs)

    if 'steps_per_cycle' not in settings:
        settings['steps_per_cycle'] = 20
    if 'moving_ambiguity' not in settings:
        # The coefficient of uncertainty while the foot is moving
        settings['moving_ambiguity'] = 0.1
    if 'duty_cycle' not in settings:
        settings['duty_cycle'] = 0.6

    system.log('[{}]: STARTING'.format(settings['id']))

    activity_phases = load_activity_phases(settings)
    trackway_positions = load_trackway_positions(settings, trackway_positions)

    trackway_definition = trackway.TrackwayDefinition(
        trackway_positions,
        activity_phases
    )
    trackway_definition.reorient_positions()

    foot_positions = limb.Property()

    time_steps = list(generate.time_steps_from_data(
        settings['steps_per_cycle'],
        trackway_definition
    ))

    for key in limb.KEYS:
        out = compute.positions_over_time(
            time_steps=time_steps,
            limb_positions=trackway_definition.limb_positions.get(key),
            activity_phase=trackway_definition.activity_phases.get(key),
            settings=settings
        )
        foot_positions.set(key, out)

    prune.invalid_positions(
        settings,
        time_steps,
        foot_positions
    )

    if len(time_steps) < 1:
        system.log(
            """
            [{}]: INVALID RESULTS
                There are no simulated results to analyze. Either the
                simulation is not valid, or you have set a start and end time
                that is not within the range of valid values. Please check your
                settings file.
            """.format(settings['id']))
        raise ValueError('Invalid Results')

    system.log('[{}]: ANALYZING'.format(settings['id']))

    reorientation_needed = prune.unused_foot_prints(
        trackway_definition.limb_positions,
        foot_positions
    )

    if reorientation_needed:
        # Reorient positions again now that the trackway has been pruned
        trackway_definition.reorient_positions(
            *foot_positions.left_pes,
            *foot_positions.right_pes,
            *foot_positions.left_manus,
            *foot_positions.right_manus
        )

    url = analyze.create(
        track_definition=trackway_definition,
        settings=settings,
        time_steps=time_steps,
        foot_positions=foot_positions
    )

    system.log('[{}]: COMPLETED'.format(settings['id']))

    return url
Esempio n. 22
0
def load_trackway_positions(
        settings: dict,
        existing: limb.Property = None,
        save_as: str = None
) -> limb.Property:
    """
    Loads the trackway positions for the trial from the information provided in
    the settings object, unless an existing trackway positions object has been
    specified

    :param settings:
        Configuration for the simulation trial
    :param existing:
        Optionally the already loaded trackway positions, which will be cloned
        and returned if present
    :param save_as:
        An optional path where the loaded trackway positions shold be saved
    """

    if existing:
        # Ignore if already specified
        return existing.clone()

    data = settings.get('data')

    if isinstance(data, str):
        # Load from a specified file
        if not data.startswith('/'):
            data = os.path.join(settings['path'], data)
        if not os.path.exists(data):
            system.log(
                """
                [ERROR]: No CSV source data exists at the path:

                    {}
                """.format(data)
            )
            raise FileNotFoundError('No CSV source file found')

        return trackway.load_positions_file(data)

    # Generate from configuration settings
    track_offsets = limb.Property().assign(*data['offsets'])
    out = generate.trackway_positions(
        cycle_count=data['count'],
        step_size=data['step_size'],
        track_offsets=track_offsets,
        lateral_displacement=data['lateral_displacement'],
        positional_uncertainty=data.get('uncertainty')
    )

    if not save_as and data.get('save'):
        save_as = data.get('save')

    if save_as:
        trackway.save_positions_file(
            trackway_positions=out,
            path=os.path.join(settings['directory'], save_as)
        )

    return out
Esempio n. 23
0
def load(
        configs_type: typing.Union[str, None],
        source: typing.Union[str, dict],
        inherits: dict = None,
        **kwargs
) -> dict:
    """
    Loads a JSON configuration file from the specified source path if the source
    argument is a string. Otherwise, assumes the source is already a dictionary
    object with the configuration information.

    Then any specified keyword arguments are added to the configurations,
    replacing any keys that were already defined.

    :param configs_type:
        The enumerated type of the configurations to be loaded
    :param source:
        Either a string representing an absolute path to the configs JSON file
        to be loaded, or a dictionary object of configuration values
    :param inherits:
        An optional dictionary of values that should be inherited where they
        do not exist already in the source settings
    :return: The loaded configuration dictionary object augmented by any
        keyword arguments
    """

    c = configs_type[0].lower() if configs_type else None
    if c == 't':
        configs_type = 'trial'
    elif c == 'g':
        configs_type = 'group'
    else:
        configs_type = None

    if isinstance(source, str):
        path = source

        try:
            with open(path, 'r+') as f:
                source = json.load(f)
        except FileNotFoundError:
            system.log([
                '[ERROR]: No such configuration file',
                ['PATH: {}'.format(path)]
            ])
            return system.end(1)
        except json_decoder.JSONDecodeError as err:
            system.log([
                '[ERROR]: Failed to decode configs json file',
                [
                    'PATH: {}'.format(path),
                    'INFO: {}'.format(err.msg),
                    [
                        'LINE: {}'.format(err.lineno),
                        'CHAR: {}'.format(err.colno)
                    ]
                ]
            ])
            return system.end(1)

        source['filename'] = os.path.abspath(path)
        source['path'] = os.path.dirname(source['filename'])
        source['directory'] = os.path.dirname(source['filename'])
    else:
        source = json.loads(json.dumps(source))
        source['path'] = source.get('path', os.path.abspath(os.path.curdir))
        source['directory'] = source.get(
            'directory',
            os.path.abspath(os.path.curdir)
        )

    if configs_type is None:
        configs_type = 'g' if 'trials' in source else 't'

    source['type'] = configs_type

    if inherits:
        for k, v in inherits.items():
            if configs_type == 'trial' and k in ['trials']:
                continue

            if k not in source:
                source[k] = v

    for k, v in kwargs.items():
        source[k] = v

    source['id'] = source['name'].replace(' ', '-')

    return source