Scaling using Python API

Provide easy-to-use, extensible software for modeling, simulating, controlling, and analyzing the neuromusculoskeletal system.
User avatar
Cai Birch
Posts: 31
Joined: Tue Jan 02, 2018 7:40 am

Scaling using Python API

Post by Cai Birch » Tue Jan 08, 2019 8:08 am

I'm trying to scale my model using Python in Spyder but I'm having problems getting the ball rolling. There doesn't seem to be a lot of documentation to assist from my searches and I find the Doxygen page difficult to understand. Could anyone help point me in the right direction with how they may have solved it or links?

Many thanks

Tags:

User avatar
Dimitar Stanev
Posts: 1096
Joined: Fri Jan 31, 2014 5:14 am

Re: Scaling using Python API

Post by Dimitar Stanev » Wed Jan 09, 2019 12:22 am

You should definitely start with the user guide:

https://simtk-confluence.stanford.edu/d ... %27s+Guide

Go through the scripting section and look at the Python, Matlab and C++ examples to familiarize with the OpenSim API. You can also consult the github page by looking at how other use OpenSim:

https://github.com/opensim-org/opensim-core
https://github.com/opensim-org/opensim- ... m/Examples

or other relative open-source repositories.

User avatar
Colin Smith
Posts: 53
Joined: Fri Feb 24, 2012 11:50 am

Re: Scaling using Python API

Post by Colin Smith » Wed Jan 09, 2019 10:25 am

"C:\OpenSim 4.0\resources\Code\GUI\runScaling.py"

Check out that file in the Resources folder that comes with OpenSim 4.0

User avatar
Cai Birch
Posts: 31
Joined: Tue Jan 02, 2018 7:40 am

Re: Scaling using Python API

Post by Cai Birch » Thu Jan 10, 2019 2:42 am

Thanks for the tips. Unfortunately, the user guide doesn't offer too much help and I'm still searching GitHub for any code that might be inuitive to work from. I've tried working from 'runScaling.py' file before but Christopher Dembia mentioned that it was for GUI scripting as I couldn't find the 'getResourcesDir()' object. Nonetheless, I thought that there might be some way around modifying the 'runScaling.py' to work in Spyder.

So far I've been playing around with two bits of code but it's sorta feels like I'm stabbing in the dark with different iterations:

Code: Select all

import opensim as osim
import os.path

myModel = osim.Model('Strong_Model.osim')
myState = myModel.initSystem() 
scaleSetupPath  = os.path.join('C:\OpenSim 4.0\Resources\Scrap code', 'Setup_Scale.xml');
scaleTool = osim.ScaleTool(scaleSetupPath)
scaleTool.run()
with error:

File "C:\Users\pscob\AppData\Local\Continuum\anaconda2\lib\site-packages\opensim-4.0-py2.7.egg\opensim\tools.py", line 4100, in run
return _tools.ScaleTool_run(self)

RuntimeError: std::exception in 'bool OpenSim::ScaleTool::run() const': scale: ERROR- No model specified.

and

Code: Select all

import opensim as osim
import os.path


myModel = osim.Model
myState = myModel.initSystem() ('Strong_Model.osim')
scaleTool = osim.ScaleTool('Setup_Scale4.xml')
myModel = osim.Model('Strong_Model.osim')
myModel.initSystem()
state = myModel.initSystem();
    
scaleTool.setSubjectMass(85)
scaleTool.setSubjectHeight(171);
scaleTool.setSubjectAge(30);
scaleTool.getModelScaler().setApply(True);
scaleTool.getModelScaler().setMarkerFileName('Markerset.xml');
scaleTool.getModelScaler().setPreserveMassDist(True);
scaleTool.getModelScaler().setPrintResultFiles(True);
scaleTool.getModelScaler().setOutputModelFileName('Strong_Model3.osim');
scaleTool.getModelScaler().setOutputScaleFileName('Setup_Scale5.xml')

path2subject = scaleTool.getPathToSubject()

scaleTool.getModelScaler().processModel(state, myModel, path2subject, ());
state = myModel.initSystem();
scaleTool.run();

with error:
File "C:\Users\pscob\AppData\Local\Continuum\anaconda2\lib\site-packages\opensim-4.0-py2.7.egg\opensim\tools.py", line 3222, in processModel
return _tools.ModelScaler_processModel(self, *args)

NotImplementedError: Wrong number or type of arguments for overloaded function 'ModelScaler_processModel'.
Possible C/C++ prototypes are:
OpenSim::ModelScaler::processModel(OpenSim::Model *,std::string const &,double) const
OpenSim::ModelScaler::processModel(OpenSim::Model *,std::string const &) const
OpenSim::ModelScaler::processModel(OpenSim::Model *) const

User avatar
Thomas Uchida
Posts: 1777
Joined: Wed May 16, 2012 11:40 am

Re: Scaling using Python API

Post by Thomas Uchida » Thu Jan 10, 2019 3:37 am

Others have done this in MATLAB; you can find some code on the Forum (e.g., by searching for "ScaleTool"). See, for example, topic 9699: viewtopicPhpbb.php?f=91&t=9699.

User avatar
Colin Smith
Posts: 53
Joined: Fri Feb 24, 2012 11:50 am

Re: Scaling using Python API

Post by Colin Smith » Thu Jan 10, 2019 8:57 am

I have gotten a similar error to the first example you show.

This likely means that the tool cannot find your generic model.

check scaleTool.getPathToSubject(). I think this gets set to the directory where your scale tool setup file is located.

This path gets appended to the generic model file in the scale tool setup file.

If you have absolute paths in your setup file, then override this setting to an empty string with the following before running the tool:

scale.setPathToSubject('')

User avatar
Cai Birch
Posts: 31
Joined: Tue Jan 02, 2018 7:40 am

Re: Scaling using Python API

Post by Cai Birch » Fri Jan 11, 2019 3:42 am

Thanks for the suggestion Colin. All the files (e.g. osim file, setup file, marker file, etc) are located in the same folder on my computer but I gave your suggestion a go with the by adding an empty string inside the parentheses (scaleTool.getPathToSubject('')) but that returns the following error:
TypeError: getPathToSubject() takes exactly 1 argument (2 given)

So I returned it back to the default empty parentheses instead and I'm still getting the same error as before:

File "C:\Users\pscob\AppData\Local\Continuum\anaconda2\lib\site-packages\opensim-4.0-py2.7.egg\opensim\tools.py", line 3222, in processModel
return _tools.ModelScaler_processModel(self, *args)

NotImplementedError: Wrong number or type of arguments for overloaded function 'ModelScaler_processModel'.
Possible C/C++ prototypes are:
OpenSim::ModelScaler::processModel(OpenSim::Model *,std::string const &,double) const
OpenSim::ModelScaler::processModel(OpenSim::Model *,std::string const &) const
OpenSim::ModelScaler::processModel(OpenSim::Model *) const

It seems so close to working as it's just the final few lines that seem to break the program! :?

My latest code:

Code: Select all

import opensim as osim

myModel = osim.Model('Strong_Model.osim')
myModel.initSystem()
myState = myModel.initSystem() 
# Initialize the model and obtain the default state

scaleTool = osim.ScaleTool('Setup_Scale.xml')
scaleTool.getGenericModelMaker().setModelFileName('Strong_Model.osim')

# Import markerdata and retrieve initiala and final time frames
markerData = osim.MarkerData('Static.trc')
initial_time = markerData.getStartFrameTime()
final_time = markerData.getLastFrameTime()

# Create an array double and set as the time range
TimeArray = osim.ArrayDouble()
TimeArray.set(0, initial_time)
TimeArray.set(1,final_time)

scaleTool.getModelScaler().setApply(True)
scaleTool.getModelScaler().setMarkerFileName('Static.trc')
scaleTool.getModelScaler().setOutputScaleFileName("scale_result.xml");
scaleTool.getModelScaler().processModel(myModel)
scaleTool.getMarkerPlacer().setApply(True)
scaleTool.getMarkerPlacer().setTimeRange(TimeArray)
scaleTool.getMarkerPlacer().setStaticPoseFileName("Static.trc");
scaleTool.getMarkerPlacer().setOutputModelFileName("scaledModel.osim");
scaleTool.getMarkerPlacer().setOutputMotionFileName("outputmotion.mot");
scaleTool.setPrintResultFiles(True);
scaleTool.getMarkerPlacer().setMoveModelMarkers(True);

scaleTool.setSubjectMass(85)
scaleTool.setSubjectHeight(171)
scaleTool.setSubjectAge(30)
scaleTool.setName('Glen')
scaleTool.getModelScaler().setMarkerFileName('Markerset.xml')
scaleTool.getModelScaler().setApply(True)
scaleTool.getModelScaler().setPreserveMassDist(True)


path2subject = scaleTool.getPathToSubject()

scaleTool.getModelScaler().processModel(myState,myModel,path2subject, 85);
myState = myModel.initSystem() 
# Run Scale Tool
scaleTool.run();

User avatar
Thomas Uchida
Posts: 1777
Joined: Wed May 16, 2012 11:40 am

Re: Scaling using Python API

Post by Thomas Uchida » Fri Jan 11, 2019 9:28 am

NotImplementedError: Wrong number or type of arguments for overloaded function 'ModelScaler_processModel'.
Possible C/C++ prototypes are:
OpenSim::ModelScaler::processModel(OpenSim::Model *,std::string const &,double) const
OpenSim::ModelScaler::processModel(OpenSim::Model *,std::string const &) const
OpenSim::ModelScaler::processModel(OpenSim::Model *) const
This error indicates that you are passing the wrong arguments to processModel. The first argument in your code

Code: Select all

scaleTool.getModelScaler().processModel(myState,myModel,path2subject, 85);
is a State; none of the three options listed in the error message take a State as the first argument.

User avatar
Cai Birch
Posts: 31
Joined: Tue Jan 02, 2018 7:40 am

Re: Scaling using Python API

Post by Cai Birch » Mon Jan 14, 2019 4:20 am

Thanks for the response. I've removed the 'states' argument from my code and the code is running without any errors. Although it doesn't look like it is scaling the model :s

When I try to scale with Python, the model markers move but the models joints remain in the default pose position rather than the position of my subject with arms and legs slightly abducted. Is there a piece of code I'm missing or is this just how scaling runs via API?

I'm using this code at the end to determine whether the ScaleTool is successful or not and it returns 'False'.

Code: Select all

ScaleSuccess = scaleTool.run()
print (ScaleSucess)
I'm running OpenSim 4.0 and tried running my code with just scaleTool.run() or by processing both ModelScaler and ModelPlacer seperately. When I run scaleTool.run() by itself, nothing changes in the model. When I run ModelScaler and ModelPlacer as seperate processes then the model markers move to experimental marker positions but the bones do not adjust in length...

Many thanks!

User avatar
Hide Kimpara
Posts: 135
Joined: Mon Sep 19, 2016 5:12 am

Re: Scaling using Python API

Post by Hide Kimpara » Tue May 05, 2020 8:01 pm

Hello,

I have similar experience with ScaleTool. Recently, I downloaded the latest OpenSim ver.4.1 and tried to analyze gait motion database with more than 100 subject data. Because of many subject data, I really wanted to run overall process from scaling to estimating muscle activities in automatic. I realized the GUI-based tools are well designed.
I prepared opensim model file based on gate sample models, marker data (*.trc), and setting XML file for scaling tool. I confirmed them working on GUI correctly. Figure attached here shows scaled model (left) and original (right).
opensim_snapshot.png
opensim_snapshot.png (596.78 KiB) Viewed 930 times
However, ScaleTool in script base does not work correctly for me.
Firstly, I tried to apply scale tool in Python, but I failed with feeding the same XML file. Message says the model data absent.
So I checked available methods on ScaleTool in Python and MATLAB, then there is no "setModel()" which is appeared in IKTool or RRATool.
Then, I tried ScaleTool in C++. The script is like this:

Code: Select all

int main()
{
    try {

        ScaleTool ScTool = ScaleTool("AIST0085_L01_Set01_Scale.xml");
        ScTool.print("Out_ScTool.xml");
        ScTool.run();


	}
    catch (const std::exception &ex) {
        
        // In case of an exception, print it out to the screen.
        std::cout << ex.what() << std::endl;

		std::cout << " " << std::endl;
		std::cout << "Press \"Enter\" key." << std::endl;
		//std::cin.get();

        // Return 1 instead of 0 to indicate that something
        // undesirable happened.
        return -1000;
    }

    // If this program executed up to this line, return 0 to
    // indicate that the intended lines of code were executed.
    return 0;
};
However, output messages say this;
Processing subject AIST0085_L01

Step 1: Loading generic model
Updating Model file from 30000 to latest format...
Loaded model gait10dof18musc.osim from file KC_2D_g10dof18m.osim
ControllerSet 'Controllers' was renamed and is being reset to 'controllerset'.
ComponentSet 'MiscComponents' was renamed and is being reset to 'componentset'.
Loading marker set from ''

Exception:
Object: Cannot construct from empty filename. No filename specified.
Thrown at Object.cpp:100 in Object().
line= 0


===ERROR===: Unable to load generic model.
scale: ERROR- No model specified.

Press "Enter" key.
What is the solution for this case? Otherwise, I have to operate scaling works for more than 1000 cases manually on GUI...

Best regards,
Hide

POST REPLY