Skip to content
  • Search
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse

ZMT zurich med tech

  1. Home
  2. Sim4Life
  3. Anatomical Models
  4. Poser API documentation?

Poser API documentation?

Scheduled Pinned Locked Moved Anatomical Models
3 Posts 2 Posters 558 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    sanand
    wrote on last edited by
    #1

    I'd like to programmatically pose the head in different positions (e.g., yaw by 5 degrees to the right, followed by pitch, etc) using the XPoser API. The workflow I'd like is something like this:

    1. Move head to a position
    2. Run EM FDTD simulation
    3. Run some postprocessing
    4. Repeat 1-3 for entire set of positions (~100 positions)

    I have Sim4Life version 8.0. I see from this forum post that there exists an XPoser API, but it's not not yet in the s4l_v1. Would it be possible to get more information and examples with XPoser (like the apply_postures.py script in that post)? For instance, I see that we can apply a user-defined pose from a .pose file, but I'm wondering if I can just specify the pose programmatically instead. Thank you!

    1 Reply Last reply
    0
    • B Offline
      B Offline
      brown
      ZMT
      wrote on last edited by
      #2

      Unfortunately, you can't currently position the head directly using the API. Additionally, posing of the head is also only currently available for some of the Virtual Population models (including the V4.0 models Yoon-sun and Jeduk, and the prone Ella). We are investigating adding posing to the API for future releases.

      Assuming you are using a model where the head is posable, the only option for the time being would be to generate the .pose files using Python, and then load them as in the post you have referenced.

      I have an example to show how you can generate .pose files using Python scripting. The script does not depend on features of the Sim4Life API. Note that this example will only work for one bone, but it will allow you to specify many rotation angles in its frame of reference.

      import json
      import numpy as np
      from collections import Counter, defaultdict
      from scipy.spatial.transform import Rotation as R
      
      # Configuration 
      project_folder = r'C:\Users\...\\'
      # The default pose is model dependent. Generated by clicking 'Export'
      # after selecting the Poser for a ViP model when no stored postures
      baseline_pose_file = project_folder+'DefaultPose.pose'
      output_pose_file = project_folder+'NewPoses.pose'
      bone_to_pose = 'Humerus_cortical_right'
      # The angles are defined in the reference frame of the bone
      angles = [np.array([0, 10, 0]), np.array([0, 20, 0]), np.array([0, 30, 0])]
      
      
      
      # Get initial pose info from file
      
      # Helper function to modify key names from imported pose json data
      def make_unique(pairs):
          d = {}
          k_counter = Counter(defaultdict(int))
          for k, v in pairs:
              suffix = str(k_counter[k]) if k_counter[k] else ''
              d[k+suffix] = v
              k_counter[k] += 1
          return d
      
      # Process baseline pose file. Every bone is named 'bone', so give unique ID
      with open(baseline_pose_file) as f:
      	old_bones = json.load(f, object_pairs_hook=make_unique)
      with open(baseline_pose_file) as f:
      	original_pose_data = f.readlines()
      new_bones = {}
      for bone in old_bones['all_bones'].keys():
      	bone_id = bone[4:]
      	bone_name = old_bones['all_bones'][bone]['name']
      	new_bones[bone_name] = old_bones['all_bones'][bone]
      	new_bones[bone_name]['idn'] = bone_id
      old_bones['all_bones'] = new_bones
      
      # Get the transformation matrices so we can start applying rotation
      parse_transform_matrix = lambda s : np.fromstring(s.replace('\n',''),sep=" ").reshape(4,4)
      bone_dict = new_bones[bone_to_pose]
      ref_tr        = parse_transform_matrix(bone_dict['ref_tr'])
      parent_ref_tr = parse_transform_matrix(bone_dict['parent_ref_tr'])
      
      # Calculate transform matrices for new .pose file
      posture_strings = []
      for angle in angles:
      	rotation_radians = angle*np.pi/180
      	r1 = R.from_rotvec(rotation_radians).as_matrix().T
      	r2 = np.identity(4)
      	r2[:3,:3] = r1
      
      	# Apply transforms
      	abs_tr = np.matmul(ref_tr, r2)
      	rel_tr = np.matmul(np.linalg.inv(parent_ref_tr), abs_tr)
      
      	# Convert 4x4 transformation array to string writeable to .pose file
      	to_pose_string = lambda s : np.array2string(s).replace('[','').replace(']','').replace('\n  ',' \n')+' \n'
      	abs_tr_str = to_pose_string(abs_tr)
      	rel_tr_str = to_pose_string(rel_tr)
      
      	# Write pose info to file
      	# Defining json structure using dicts
      	posture, postures, bones, bone = {}, {}, {}, {}
      	bone['name'] = bone_to_pose
      	bone['rel_tr'] = rel_tr_str
      	bone['index'] = bone_dict['idn']
      	bone['abs_tr'] = abs_tr_str
      	bone['parent_abs_tr'] = bone_dict['parent_ref_tr']
      	bones['bone'] = bone
      	posture['name'] = str(angle)
      	posture['bones'] = bones
      	postures['posture'] = posture
      
      	json_string = json.dumps(postures, indent=4)
      	json_string = json_string[1:-1]+',' # removing first and last brackets and add , so multiple can be written
      	posture_strings.append(json_string)
      posture_strings[-1] = posture_strings[-1].strip(',')
      
      # Write new .pose file. Posture data gets appended to the original data
      with open(output_pose_file,'w') as f:
      	for line in original_pose_data[:-2]: f.write(line)
      	f.write('\t"postures": {')
      	for line in posture_strings: f.write(line)
      	f.write('}\n}')
      
      1 Reply Last reply
      0
      • S Offline
        S Offline
        sanand
        wrote on last edited by
        #3

        Thank you for the detailed answer!

        1 Reply Last reply
        0
        Reply
        • Reply as topic
        Log in to reply
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes


        • Login

        • Don't have an account? Register

        • Login or register to search.
        • First post
          Last post
        0
        • Search