Lesson 4: Including a custom scaling law into a musculoskeletal model

Hi

I’ve tried to do that tutorial, but after the first part “Including custom scaling for a single bone” I always get a error message, if I load the StandingModelScalingDisplay.Main.any:

WARNING(OBJ1) :   U:/E..n/M..r/T..s/#..R/Body/A..n/S..g/ScalingCustom.any  :   Thigh.scaling_message_Left_Thigh  :  Custom scaling for 'Left.Thigh' segment is used! Please specify a scaling law should an 'Unresolved object' error occur
ERROR(SCR.PRS9) :   U:/E..n/M..r/T..s/#..R/Body/A..n/L..D/HipNodes.any  :   'Pelvis'  :  Unresolved object

Thanks

Hi,

The problem is that this version of the repository does not match to the tutorial. AMMRV1.5 should work well.

Regards,
Pavel

hi sirs
when we use a custom scaling law for the specific segments, how can we scale other segments? especially, how can we use the custom scaling law into lower extremity model with combining other scaling law?

Dear Chen Zhenxian,

Please follow the tutorial on the anthropometric scaling laws. You can scale your model according to the height and weight of your subject anthropometrically and replace only those segments that you have some information about with the segmental scaling.

Regards,
Pavel

hi Pavel

Many thanks. i want to combine a custom scaling law into low extremity model , so i modify the file "…\Examples\MoCapModel\Model\HumanModel.any " as following :

#ifndef ANYBODY_PATH_BODY_GENERICBODYMODEL
#path ANYBODY_PATH_BODY_GENERICBODYMODEL “<ANYBODY_PATH_BODY>\BodyModels\GenericBodyModel”
#endif

AnyFolder HumanModel={

#include “<ANYBODY_PATH_BODY_GENERICBODYMODEL>\BodyModel.defaults.preprocess.any”
#include “<ANYBODY_PATH_BODY_GENERICBODYMODEL>\BodyModel.defaults.any”
// #include “<ANYBODY_PATH_BODY_GENERICBODYMODEL>\BodyModel.BodyPartsSetup.any”
#include “<ANYBODY_PATH_BODY_GENERICBODYMODEL>\BodyModel.config_info.any”

// // Select the body model:
// // ----------------------
// // This file contains a list of all body parts, select them to create
// // the body model wanted.
#if MotionAndParameterOptimizationModel
AnyFolder &Mannequin=.KinematicStudyForParameterIdentification.Mannequin;
#include “BodyPartsSetupKinematics.any”
#endif

#if InverseDynamicModel
AnyFolder &Mannequin=.InverseDynamicStudy.Mannequin;
#include “BodyPartsSetup.any”
#endif
//
// This file creates the body model from the selected list.
// #include “<ANYBODY_PATH_BODY>\BodyModels\GenericBodyModel\BodyModel.any”

AnyFolder StrengthParameters={
AnyVar SpecificMuscleTensionSpine= 90; //N/cm^2
AnyVar StrengthIndexLeg= 1;
AnyVar SpecificMuscleTensionShoulderArm= 90; //N/cm^2
};
//
// Actual scaling law

#include “CustomScaling.any”

#include “<ANYBODY_PATH_BODY_GENERICBODYMODEL>\BodyModel.NEW.any”
//

// By default there is an option to define a custom scaling law
#include “<ANYBODY_PATH_BODY>\Scaling\ScalingCustom.any”

Scaling = {

// //This is the file which set the segments lenghts
#include “AnyMan.any”

// #include “<ANYBODY_PATH_BODY>\Scaling\AnyFamily\AnyManExternal.any”
//Base scaling laws according to the configuration file

#if BM_SCALING == CONST_SCALING_CUSTOM
// include your custom scaling law, which needs an ‘AnyMan.any’ file
#include “<BM_SCALING_MY_FILE>”
// undefine BM_SCALING_ANTHRO_FILE if an ‘AnyMan.any’ file is not used
#ifdef BM_SCALING_ANTHRO_FILE
Scaling = { //This is the file which set the segments lengths
AnyMessage anthrofile_message = {
Message = “Undefine BM_SCALING_ANTHRO_FILE in case it will not be used by your custom scaling law!”;
TriggerPreProcess = On;
Type = MSG_Message;
};
#include “<BM_SCALING_ANTHRO_FILE>”
};
#endif
#endif

//Base scaling laws according to the configuration file
#if BM_SCALING == CONST_SCALING_STANDARD
#include “<ANYBODY_PATH_BODY>\Scaling\ScalingStandard.any”
#endif

#if BM_SCALING == CONST_SCALING_UNIFORM
#include “<ANYBODY_PATH_BODY>\Scaling\ScalingUniform.any”
Scaling = { //This is the file which set the segments lenghts
#include “<BM_SCALING_ANTHRO_FILE>”
};
#endif

#if BM_SCALING == CONST_SCALING_LENGTHMASS
#include “<ANYBODY_PATH_BODY>\Scaling\ScalingLengthMass.any”
Scaling = { //This is the file which set the segments lenghts
#include “<BM_SCALING_ANTHRO_FILE>”
};
#endif

#if BM_SCALING == CONST_SCALING_LENGTHMASSFAT
#include “<ANYBODY_PATH_BODY>\Scaling\ScalingLengthMassFat.any”
Scaling = { //This is the file which set the segments lenghts
#include “<BM_SCALING_ANTHRO_FILE>”
#include"D:\GAITtest\Application\Examples\GaitLowerExtremity\AnyMan.any"
};
#endif

#if BM_SCALING == CONST_SCALING_UNIFORM_EXTMEASUREMENTS
#include “<ANYBODY_PATH_BODY>\Scaling\ScalingUniformExt.any”
Scaling = { //This is the file which set the segments lenghts
#include “<BM_SCALING_ANTHRO_FILE>”
};
#endif

#if BM_SCALING == CONST_SCALING_LENGTHMASS_EXTMEASUREMENTS
#include “<ANYBODY_PATH_BODY>\Scaling\ScalingLengthMassExt.any”
Scaling = { //This is the file which set the segments lenghts
#include “<BM_SCALING_ANTHRO_FILE>”
};
#endif

#if BM_SCALING == CONST_SCALING_LENGTHMASSFAT_EXTMEASUREMENTS
#include “<ANYBODY_PATH_BODY>\Scaling\ScalingLengthMassFatExt.any”
Scaling = { //This is the file which set the segments lenghts
#include “<BM_SCALING_ANTHRO_FILE>”
};
#endif
};

};

is it right to get the combination? i am not sure how to write the part " scaling { }" and the part " #if MotionAndParameterOptimizationModel …#endif ". many thanks!

No, this is not very good :slight_smile: You can do everything outside of the HumanModel.any. It is not recommended to modify the contents - we will not be able to help you later on.

On the example of MoCap model - this is how you include custom segmental scaling laws:



  AnyFolder Studies ={
  // Usually, there is no need to make changes in the following files. Changes in the Kinematics
  // and InverseDynamics file may lead to model failure and/or unrealistic results:
  
    [b]#include "Model/CustomScaling.any"[/b]
    
    #if  MotionAndParameterOptimizationModel    
    #include "Model/Kinematics.any"  
    #endif    
    
    #if InverseDynamicModel
    #include "Model/InverseDynamics.any"  
    #endif    
    
  };

Typically all segment sizes will be optimized based on the markers, but in your case you define some manually - you need to exclude those from the optimization process. Please check TrialSpecificData for that.

Kind regards,
Pavel

1 Like

ok many thanks for your help , Pavel .:slight_smile:

hi pavel

when i finish the custom segmental scaling  of femur, i find the distal geometry position of femur do not match the analytical  joint, how to fit the anatomical knee geometry to the analytical knee joint?

many thanks

best wishes!

Hi,

Could you please post a screenshot? I do not fully understand what you mean. Could you also write when this is happening - on loading, on initial conditions, etc.?

Pavel

hi pavel

i have attached a picture, on initial conditions. the femur do not match the analytical joint. how could i deal with this problem?

many thanks

best wishes!

hi pavel

could i ask you another question? the strength of all knee flexors and extensors would be reduced after total knee arthoplasty. how can i reduce strength of knee flexors and extensors in MoCap_lowbody model ?

many thanks!

best wishes!

The knee joint axis is supposed to be located somewhat posterior to the femoral condyles and this is what we see on the image. This is the axis which is used to rotate about the tibia about femur - so that the articular surfaces rotate in a sort of spherical way.

The incline is somewhat strange and might, indeed, come from the scaling. You could try to use #define BM_BONY_LANDMARK_DEFINED_JOINTAXIS ON to construct the axis passing through epicondyles.

Alternatively you could try redefine the axis based on some other landmarks that you think represent the knee axis and exclude the original implementation using MechObjectExclude (please search forum for this keyword).

Muscle strength - you can change the strength of an individual muscle by using an AnySetValueOperation (please also try searching the forum) in the PreOperation folder of your InitialConditions.

Regards,
Pavel

hi Pavel

many thanks!   i have deal the  problem of he knee joint axis according to your suggestion.

 but  i have not found any information about 'AnySetValueOperation' , could you give me more clues?

 thank you very much!

Best Wishes!

Sorry, it is called AnyOperationSetValue.

Regards,
Pavel

dear pavel
many thanks for your help!

dear Pavel

i add the 'AnyOperationSetValue' command to set new muscle strength, but i meet a problem when i run the inverse dynamics analysis:

’ ERROR(OBJ1) : D:/Anybody Models/F…t/Body/A…n/Le…M/Mus.any(143) : FlexorDigitorumLongus1.Strength : ‘Set Value’ operation on this value-object is not allowed…’

the code as following :

Main = {

 Main.Studies.InverseDynamicStudy.InitialConditions.PreOperation = {
AnyOperationSetValue TKAMuscleStrength = 
{
  
   AnyFloat  FlexorD = 115.81;
   AnyFloat  FlexorH = 545.55802;
   AnyFloat  ExtensorD = 93.6340;
   AnyFloat  ExtensorH = 106.5021;

  Source = {
    &FlexorD,
    &FlexorD,
    &FlexorD,
    &FlexorH,
    &FlexorH,
    &FlexorH,
    &ExtensorD,
    &ExtensorD,
    &ExtensorD,
    &ExtensorH,
    &ExtensorH,
    &ExtensorH
  };
  Target = {
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorDigitorumLongus1.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorDigitorumLongus2.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorDigitorumLongus3.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorHallucisLongus1.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorHallucisLongus2.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorHallucisLongus3.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorDigitorumLongus1.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorDigitorumLongus2.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorDigitorumLongus3.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorHallucisLongus1.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorHallucisLongus2.Strength,
    &Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorHallucisLongus3.Strength
  };

};
};

AnyOperationMacro InverseDynamicAnalysisSequence =
{
MacroStr =
({
“classoperation Main.Studies.LoadParametersOptimizationResults” + " " + strquote(“Load design”) + " --file=" + strformat("\x22") + “…/Input/” + OutputFileNamePrefix + Main.ModelSetup.C3DFileData.NameOfFile +"-"+“OptimizedParameters.txt” + strformat("\x22"),
“classoperation Main” + strformat("\x22")+ “Update Values” + strformat("\x22"),
“operation Main.Studies.InverseDynamicStudy.InitialConditions”,
“run”,
“operation Main.Studies.HumanModel.Calibration.CalibrationSequence”,
“run”,
“operation Main.Studies.InverseDynamicStudy.InitialConditions.PreOperation.TKAMuscleStrength”,
“run”,
“operation Main.Studies.InverseDynamicStudy.InverseDynamics”,
“run”
#if AutoSaveOption
,
“classoperation Main.Studies.InverseDynamicStudy.Output” + strquote(“Save data”) + " --file="+ “…/Output/” + OutputFileNamePrefix + Main.ModelSetup.C3DFileData.NameOfFile + ".anydata.h5 " + “–type=Deep”
#endif
});
};
};

could you tell me how to deal with this problem?

many thanks!

best wishes!

Hi,

Yes, you need to wrap the original values by DesignVar:

AnyFloat value_to_be_changed = DesignVar(1.0);

It will give a warning that the symbolic link is broken, meaning that you successfully change the muscle strength, but if there is an expression that uses this value - it will not be updated. But it should be reasonably safe to do for a particular muscle.

Regards,
Pavel

Dear pavel
i want to reduce strength of knee flexors and extensors in MoCap_lowbody model. i have modified the file " InverseDynamics.any" according to your suggestions :
Main = {
Main.Studies.InverseDynamicStudy.InitialConditions.PreOperation = {
AnyOperationSetValue TKAMuscleStrength =
{

 AnyFloat FlexorD = DesignVar(115.81);
 AnyFloat FlexorH = DesignVar(545.55802);
 AnyFloat ExtensorD = DesignVar(93.6340);
 AnyFloat ExtensorH = DesignVar(106.5021);

//
Source = {
&FlexorD,
&FlexorD,
&FlexorD,
&FlexorH,
&FlexorH,
&FlexorH,
&ExtensorD,
&ExtensorD,
&ExtensorD,
&ExtensorH,
&ExtensorH,
&ExtensorH
};
Target = {
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorDigitorumLongus1.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorDigitorumLongus2.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorDigitorumLongus3.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorHallucisLongus1.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorHallucisLongus2.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.FlexorHallucisLongus3.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorDigitorumLongus1.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorDigitorumLongus2.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorDigitorumLongus3.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorHallucisLongus1.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorHallucisLongus2.Strength,
&Main.Studies.HumanModel.BodyModel.Left.Leg.Mus.ExtensorHallucisLongus3.Strength
};
};
};

AnyOperationMacro InverseDynamicAnalysisSequence =
{
MacroStr =
({
“classoperation Main.Studies.LoadParametersOptimizationResults” + " " + strquote(“Load design”) + " --file=" + strformat("\x22") + “…/Input/” + OutputFileNamePrefix + Main.ModelSetup.C3DFileData.NameOfFile +"-"+“OptimizedParameters.txt” + strformat("\x22"),
“classoperation Main” + strformat("\x22")+ “Update Values” + strformat("\x22"),
“operation Main.Studies.InverseDynamicStudy.InitialConditions”,
“run”,
“operation Main.Studies.HumanModel.Calibration.CalibrationSequence”,
“run”,
“operation Main.Studies.InverseDynamicStudy.InverseDynamics”,
“run”
#if AutoSaveOption
,
“classoperation Main.Studies.InverseDynamicStudy.Output” + strquote(“Save data”) + " --file="+ “…/Output/” + OutputFileNamePrefix + Main.ModelSetup.C3DFileData.NameOfFile + ".anydata.h5 " + “–type=Deep”
#endif
});
};
};

//** Includes the human body model **// Usually no need to make changes
#include “HumanModel.any”

but I still have not deal with the problem. :mad:
,ERROR(OBJ1) : C:/Pro…es/A…y/A…0/AMMR/Body/A…n/L…M/Mus.any(143) : FlexorDigitorumLongus1.Strength : ‘Set Value’ operation on this value-object is not allowed
ERROR(OBJ1) : C:/Pro…es/A…y/A…0/AMMR/Body/A…n/L…M/Mus.any(159) : FlexorDigitorumLongus2.Strength : ‘Set Value’ operation on this value-object is not allowed…

i have try do it long time, can you help me point out the What does matter really?
in addition, i have attached the file “InverseDynamics.any”
many thanks !!

Hi,

Yes, everything is fine. The problem is that the target values (muscle strengths in the model) have to be DesignVar, which they are not yet.

There are two options to do what you want. One is what you did already, but you would need to access the repository file, which contains the strength definition for those muscles and add DesignVar around needed values.

Then your code should work.

Another option is not to modify the repository and simply exclude those muscles from the analysis and add exactly the same values, but externally from the model, which will have the DesignVar around muscle strengths.

But otherwise everything looks very good.

Regard,
Pavel

1 Like

hi pavel

many thanks!