--- a +++ b/app/AnyPy.py @@ -0,0 +1,194 @@ +import datetime +import glob +import os +import re +import shutil +import subprocess + +from anypytools import AnyMacro +from anypytools import AnyPyProcess +from anypytools.macro_commands import (MacroCommand, Load, Dump, + SaveData, OperationRun) + +from AnyWriter import AnyWriter +from AnybodyResults import AnybodyResults +from config.Configuration import env + + +class AnyPy: + LOAD = 'load' + INITIAL_CONDITIONS = 'initial_conditions' + KINEMATICS = 'kinematics' + INVERSE_DYNAMICS = 'inverse_dynamics' + # SET_ORDER = 'set_order' + SAVE_H5 = 'save_h5' + LOAD_H5 = 'load_h5' + DUMP_JOINT_ANGLES = 'dump_angles' + DUMP_STEPS = 'dump_steps' + DUMP_LEAP_VECTORS = 'dump_leap_vectors' + REPLAY = 'replay' + LOG_FILE = 'AnyPy{}.log'.format(datetime.datetime.today().strftime('%Y%m%d_%H%M%S')) + + INTERPOL_DIR = '/Model/InterpolVec' + + def __init__(self, main_filepath, template_directory): + self.any_path, self.any_model = os.path.split(main_filepath) + self.main_filepath = main_filepath + self.template_directory = template_directory + self.operations = [] + self.macrolist = [] + self.output = None + + if env.args('any_interpol_files'): + print('Using interpolation files from "{}"'.format(os.path.normpath(self.any_path + AnyPy.INTERPOL_DIR))) + + if env.args('any_bvh_file'): + print("Convert bvh file to anybody interpolation files") + from resources.pymo.pymo.parsers import BVHParser as Pymo_BVHParser + any_writer = AnyWriter(template_directory='config/anybody_templates/', + output_directory=os.path.normpath(self.any_path + AnyPy.INTERPOL_DIR) + '/') + any_writer.write(Pymo_BVHParser().parse(env.config.any_bvh_file)) + + if env.args('any_files_dir'): + self.copy_files() + + # remove frames from start and end (cut) + if env.config.start_frame or env.config.end_frame: + start_frame = int(env.config.start_frame) - 1 if env.config.start_frame else 0 + end_frame = int(env.config.end_frame) - 1 if 'end' not in env.config.end_frame.lower() else None + any_writer = AnyWriter(output_directory=os.path.normpath(self.any_path + AnyPy.INTERPOL_DIR) + '/') + any_writer.extract_frames(start_frame, end_frame) + any_writer.extract_frame_timeseries(start_frame, end_frame) + + self.output_path = '' + if env.args('output_file_path'): + self.output_path = os.path.normpath( + os.path.join(os.path.split(env.config.output_file_path)[0], + os.path.split(env.config.output_file_path)[1].replace(".anydata.h5", "") + '.anydata.h5')) + + self.initialize_operations() + + def initialize_operations(self): + """build the macrolist executed by AnyPyTools""" + operation_cmd = {AnyPy.LOAD: Load(self.main_filepath), + AnyPy.INITIAL_CONDITIONS: OperationRun('Main.Study.InitialConditions'), + AnyPy.KINEMATICS: OperationRun('Main.Study.Kinematics'), + AnyPy.INVERSE_DYNAMICS: OperationRun('Main.Study.InverseDynamics'), + # AnyPy.SET_ORDER: SetValue('Main.HumanModel.Mannequin.InterpolationFunctions.intorder', + # env.config.order), + AnyPy.SAVE_H5: SaveData('Main.Study', self.output_path), + AnyPy.DUMP_JOINT_ANGLES: Dump('Main.Study.Output.JointAngleOutputs'), + AnyPy.DUMP_STEPS: Dump('Main.Study.nStep'), + AnyPy.DUMP_LEAP_VECTORS: Dump('Main.HumanModel.Mannequin.Posture.Right')} + + if env.config.load: + self.add_operation(AnyPy.LOAD) + if env.config.initial_conditions: + self.add_operation(AnyPy.INITIAL_CONDITIONS) + if env.config.kinematic: + self.add_operation(AnyPy.KINEMATICS) + if env.config.inverse_dynamics: + self.add_operation(AnyPy.INVERSE_DYNAMICS) + if env.config.nstep: + self.set_step() + # if env.config.order: + # self.add_operation(AnyPy.SET_ORDER) + if env.config.plot: + # requirement for plot is run of kinematic analysis + self.add_operation(AnyPy.LOAD) + self.add_operation(AnyPy.KINEMATICS) + # dump interpolated joint angles + self.add_operation(AnyPy.DUMP_JOINT_ANGLES) + # dump nStep + self.add_operation(AnyPy.DUMP_STEPS) + # dump Mannequin vectors including the joint angles from the bvh file + self.add_operation(AnyPy.DUMP_LEAP_VECTORS) + + if self.output_path: + # save study output to hdf5, to view and replay analysis later + self.add_operation(AnyPy.SAVE_H5) + + for operation in self.operations: + self.macrolist.append(operation_cmd[operation]) + + def post_operations(self): + macro_output_path = 'classoperation Main.Study.Output "Load data" --file="{}"'.format(self.output_path) + + """build the macrolist executed by AnyPyTools""" + operation_cmd = {AnyPy.LOAD: Load(self.main_filepath), + AnyPy.LOAD_H5: MacroCommand(macro_output_path), + AnyPy.REPLAY: OperationRun("Main.Study.ReplayKinematics")} + + self.macrolist = [] + for operation in operation_cmd: + self.macrolist.append(str(operation_cmd[operation])) + + print('Starting Anybody with the macros:\n{}'.format(self.macrolist)) + print('Executing "{}" in "{}"'.format(self.any_path, self.any_model)) + + # save current working directory and change to Anybody project folder + cwd = os.getcwd() + os.chdir(self.any_path) + + # write macro file to be opened by AnyBody GUI + macro_replay_path = os.path.join(self.any_path, 'replay.anymcr') + with open(macro_replay_path, 'wb') as macro_file: + macro_file.write("\n".join(self.macrolist).encode("UTF-8")) + macro_file.flush() + anybodycmd = [os.path.realpath('C:/Program Files/AnyBody Technology/AnyBody.7.1/AnyBody.exe'), + "-m", macro_file.name] + + # execute AnyBody GUI with the command from anybodycmd + subprocess.Popen(anybodycmd) + + # change back to original folder + os.chdir(cwd) + + def add_operation(self, operation): + """add operation to a list if not already in the list (unique)""" + if operation not in self.operations: + self.operations.append(operation) + + def copy_files(self): + """"copy interpolation files""" + for file in glob.glob(self.template_directory + r'/*.any'): + print('copying "{}" to "{}"'.format(file, + os.path.normpath(self.any_path + + AnyPy.INTERPOL_DIR + "/" + os.path.split(file)[-1]))) + shutil.copy(file, self.any_path + AnyPy.INTERPOL_DIR) + + def run(self): + if not self.macrolist: + print("No operation for AnyBody was selected -> will terminate now") + return False + + # print('Starting Anybody with the operations: {}'.format(self.operations)) + print('Starting Anybody with the macros:\n{}'.format(AnyMacro(self.macrolist))) + print('Executing "{}" in "{}"'.format(self.any_path, self.any_model)) + + # save current working directory and change to Anybody project folder + cwd = os.getcwd() + os.chdir(self.any_path) + app = AnyPyProcess() + + self.output = app.start_macro(macrolist=self.macrolist) + + # change back to original folder + os.chdir(cwd) + return True + + def plot(self): + """open the plot for the joint angles""" + print('Loading the plot ...') + AnybodyResults(self.output).plot() + + def set_step(self): + """replace the nstep value with the new selected value""" + regex_step = re.compile(r'nStep\s*=.*\d+.*;') + step_setting = 'nStep = {};'.format(env.config.nstep) + with open(self.main_filepath) as file: + old_file = file.read() + new_file = re.sub(regex_step, step_setting, old_file) + with open(self.main_filepath, 'w') as file: + file.write(new_file) + print('"{}" written to "{}"'.format(step_setting, self.main_filepath))