Personalize model based on CT data

Hello,

Currently, I’m personalized my model in plug-in-gait-simple model based on the CT. I was wondering is it a good move that I first scaled the model based on the height and mass and then I used the morphing tech in tutorials for the detailed thigh and shank segment?
You said the source femur should be the non-scaled femur, I want to know more about the process of scaling.

Any help would be appreciated!
Thank you!

Best Wishes,
Lee

Hello Lee,

You should define the subjects’ height and weight, and additionally include the code outlined in Tutorial 15: Personalize Your Model (Lesson 2). Yes the source femur STL should be the non-scaled femur (the TLEM 2.0 cadaver bone geometry in the local coordinate system). Then your target femur needs to have the same topology as this bone, this thread may be helpful (https://forum.anyscript.org/t/patient-specific-model-with-mocap-model/2688/10).

Best Regards,
Christine

Hello,

I’m planning to use Plug_in_gait_simple LowerExtremity model to scale the right femur and tibia, the code you mentioned about height and mass are in the Lowerextremity.any, and I include the code in tutorials 15, is it a right move in the picture?

I don’t know if the STL in Plug-in-gait model is non-scaled or not.
Thank you!

Best Wishes,
Lee

Hi Lee,

Bones in mocap models will always be scaled to some extend to match the subject in the recording.

Best regards
Søren

Hello,

I want to scale the femur and tibia bone of right leg in Plug-in_gait_Simple model to simulate the TKA, and I don’t get the workflow of scale.
Should I change the body mass and height first and then custom scale the femur and tibia (How should I get the source bone since it scaled automatically based on the recording data). I’m a little confused about the workflow of scaling bones in the plug-in-gait-simple model, would you mind sharing the idea?

Thank you!
Any help would be appreciated!

Best regards,
Lee

Hi Lee,

In order to get the ‘source_STLs’ for the femur and tibia you need to load the StandingModel.main.any example (AMMR\Application\Examples\StandingModel). Then make sure in the BodyModelConfiguration.any file there is no scaling, you will probably have to change

#define BM_SCALING SCALING_XYZ_ --> #define BM_SCALING SCALING_NONE_

Once that is all set you can double click on the femur and go into the model tree and then right click on the AnyDrawSurf folder in the model tree and click ‘Export Surface’, make sure to do so in the local coordinate system. Then do the same for the tibia.

Could you describe the workflow you are trying to accomplish and which software tools you are using in order to obtain your target_stls (subject-specific stls)? With this information I can then best advise you how to continue in the Plug-in_gait_Simple model with the morphing process.

Kind Regards,
Christine

Hello,

Thank you for your response.
I’m trying to build my own gait model with TKA based on the essay:

Marra, Marco A., et al. “A Subject-Specific Musculoskeletal Modeling Framework to Predict In Vivo Mechanics of Total Knee Arthroplasty.” Journal of Biomechanical Engineering 137.2(2015):020904.

And I’m using the same software mentioned in the essay except for the newer version of Anybody and 6th Grand Challenge Competition Data.

I still want to know more about the rigid-body registration after morphing.

Thank you!
Best Regards,
Lee

Hi,

I couldn’t find the code you mentioned above in StandingModel, and there is no BodyModelConfiguaration.any.

Do you mean StandingModelScalingDisplay or standingModel?

Thank you!
Best Regards,
Lee

Hi Lee,

I will try answer your question,

I think Christine was referring to the StandingModel.

I just checked this model in most recent AMMR and it do have a file called “BodyModelConfiguration.any”

Best regards
Søren

Hello,

Thank you for your response.

I found the “BodyModelConfiguration.any” in the new AMMR 2.2.1, I was wondering if the non-scaled bones are the same in AMMR2.1.1 and AMMR 2.2.1 for I am using the AMMR2.1.1?

Best Regards,
Lee

Hi Lee,

There should be no changes in the shape of the unscaled bones between these versions, but i can not rule out that there could be differences in the re-solution.

Best regards
Søren

Hello,

I used the bones you and Christine mentioned above.
I did it well based on lesson 1 from personalizing your model in tutorials 15.
image

When I used it in the plug-in-gait model follow the code in lesson 2 from tutorials 15, it didn’t work well.
image

I believe I have used the wrong bone. What is the specific bone as generic bone?

Thank you!

Best Regards,
Lee

Hi Lee,
The tutorial was written using the TLEM1 femur. You need to use the TLEM2 one to make it work. We recently changed the default to be TLEM2.

Please right click and export TLEM2 femur surface on an unscaled model.

Kind regards,
Pavel

Hello,

The differences are only the bones( TLEM1 &TLEM2 ) or the code differs too?
Recently I’m trying to use the standingModelSclingDisplay None-scale bones to scale, is it right move?

Thank you!

Best Regards,
Lee

The landmarks should be selected accordingly. But the code stays the same.
Yes, StandingModelScalingDisplay with ScalingNone should be perfect.
P.

Hello,

I believe I did well in lesson1 from tutorials 15.
image

However, It didn’t look right when I use it based on the lesson 2.

I changed the Transform to STLTransform, it showed the same as above.
I changed it to RBFTransform, it showed a little reasonable.

A little confused!

Best Regards,
Lee

Hi Lee,

Can you share what you have in the ‘MyScalingFunctionFemur.any’ file please?

Best Regards,
Christine

/* This file defines a subject-specific morphing law for the Lesson 4 of Scaling tutorial*/

AnyFolder MyScalingFunctionFemur = {

AnyFunTransform3DLin Transform = {
ScaleMat = {{1,0,0},{0,1,0},{0,0,1}};
Offset = {0,0,0};
PreTransforms = {&.STLTransform, &.ReverseTransform};
};

AnyFunTransform3DLin2 AffineTransform =
{
//PreTransforms = {};
Points0 = …TSeg2ScaleFrame(
{
{0.0776166,-0.38519,0.0434183},
{0.0291691,-0.388362,0.0489085},
{0.0702968,-0.375534,-0.0240044},
{0.0171157,-0.195817,0.013274},
{-0.0481888,-0.00649841,0.00942058},
{0.009532983,0.016264,-0.015843}
});
Points1 =
{
{-0.0335496,0.00561388,-0.0159026},
{0.0131622,0.0129517,-0.0401973},
{0.00955101,0.0160026,0.0352691},
{0.0253999,0.200918,-0.0145758},
{0.0797432,0.417332,-0.022623},
{0.0356885,0.431939,0.0166936}
};
Mode = VTK_LANDMARK_AFFINE;
};

AnyFunTransform3DLin2 ReverseTransform = {
Points0 = .AffineTransform.Points1;
Points1 = .AffineTransform.Points0;
Mode = VTK_LANDMARK_RIGIDBODY;
};

AnyFunTransform3DRBF RBFTransform =
{
PreTransforms = {&.AffineTransform};
RBFDef =
{
Type = RBF_ThinPlate;
Param = 1;
};
Points0 = …TSeg2ScaleFrame(
{
{0.0776166,-0.38519,0.0434183},
{0.0874067,-0.392876,0.0191814},
{0.0291691,-0.388362,0.0489085},
{0.0336871,-0.401527,0.0528365},
{0.0702968,-0.375534,-0.0240044},
{0.0840476,-0.405399,-0.0240044},
{0.046656,-0.36353,0.00203508},
{0.0519064,-0.422182,0.045868},
{0.6825022,-0.426252,-0.0176293},
{0.0171157,-0.195817,0.013274},
{-0.0153646,-0.0538598,-0.00275116},
{-0.0111436,-0.0677822,-0.000322446},
{-0.0481888,-0.00649841,0.00942058},
{0.009532983,0.016264,-0.015843},
{-0.0060929,-0.0615546,0.00151425},
{-0.036961,-0.0406715,0.053172},
{-0.038943,-0.0406992,0.0101967},
{0.0005855,-0.0509986,0.0225059},
{0.0885529,-0.388669,0.00365604},
{0.0606754,-0.420174,-0.0318583},
{0.055317,-0.422778,-0.00984486},
{0.0349846,-0.423029,0.0426269},
{0.052857,-0.420594,0.0475201},
{0.080049,-0.370333,0.0108282},
{0.0708826,-0.371049,0.0418323},
{0.0353599,-0.347786,0.0276989},
{0.0536242,-0.343088,0.00172468},
{0.0827935,-0.39489,-0.0240079},
{0.0169421,-0.390191,0.0277442},
{0.0162501,-0.410556,0.0348857},
{0.0284323,-0.386989,0.0139395},
{0.0177057,-0.398845,0.0187154},
{0.0389646,-0.396279,-0.025363},
{0.0888908,-0.401907,-0.00876824},
{0.0548423,-0.397694,0.054172},
{0.077992,-0.421114,0.00714761},
{0.0463893,-0.284064,0.011615},
{0.0632637,-0.3013,0.0116601},
{0.0558027,-0.254465,0.0189366},
{0.0487975,-0.316967,0.00655951},
{0.0640665,-0.335391,0.00255428},
{0.0535251,-0.272982,0.0154517},
{0.0405198,-0.22445,0.0146546},
{0.0213611,-0.169527,0.0158975},
{0.0377727,-0.194215,0.0374407},
{0.0502173,-0.234592,0.0301236},
{0.0506393,-0.239614,0.0207116},
{0.0231513,-0.417397,0.0260686},
{0.0774498,-0.38116,0.0283361},
{0.0749767,-0.375019,0.0308108}
});
Points1 = {
{-0.0335496,0.00561388,-0.0159026},
{-0.0280022,-0.00269058,0.0120236},
{0.0131622,0.0129517,-0.0401973},
{0.012141,-0.000433684,-0.0446263},
{0.00955101,0.0160026,0.0352691},
{0.00075525,-0.0115942,0.0405223},
{0.0119686,0.0280065,0.0120921},
{-0.00935188,-0.0231205,-0.0279828},
{-0.00432023,-0.02776477,0.0308913},
{0.0253999,0.200918,-0.0145758},
{0.0585843,0.361284,0.000857341},
{0.0550661,0.346257,-0.00206488},
{0.0797432,0.417332,-0.022623},
{0.0356885,0.431939,0.0166936},
{0.0503574,0.351978,0.00110147},
{0.06372,0.381583,-0.0571084},
{0.0809548,0.383419,-0.0216873},
{0.0338266,0.35835,-0.0121963},
{-0.024259,0.00394552,0.0217401},
{0.0194315,-0.0242202,0.0356052},
{0.0178418,-0.0246098,0.0145176},
{0.00503235,-0.0230989,-0.0367033},
{-0.0103818,-0.0219988,-0.0288968},
{-0.0198254,0.0267586,0.01261},
{-0.0264373,0.024819,-0.0170189},
{0.0114769,0.0436825,-0.0237335},
{0.00778656,0.0454752,0.00969556},
{0.00118152,0.00134793,0.0426428},
{0.0293845,0.00573355,-0.0302668},
{0.0303841,-0.00849202,-0.0380678},
{0.024226,0.00585466,-0.00989906},
{0.0320057,-0.0066778,-0.0235614},
{0.0327069,-0.00420313,0.0239168},
{-0.0118756,-0.0072693,0.0340803},
{-0.013875,0.00182269,-0.0345471},
{-0.0159371,-0.0209117,0.0101429},
{0.00910361,0.107057,-0.000237901},
{-0.0108107,0.083166,0.00767706},
{-0.00792776,0.133574,-0.00168584},
{0.00402107,0.0750955,0.00614671},
{-0.00431338,0.0517168,0.0142384},
{-0.00429717,0.115213,0.0035777},
{0.00607966,0.182325,-0.00565917},
{0.0207678,0.241608,-0.0108694},
{-0.00150775,0.198673,-0.0232213},
{-0.00827493,0.154543,-0.0107971},
{-0.0024134,0.158461,-0.00343703},
{0.0208062,-0.0232439,-0.0270419},
{-0.0251027,0.00861673,-0.00121048},
{-0.0240169,0.0216748,-0.00427663}
};
BoundingBox =
{
Type = BB_Cartesian;
ScaleXYZ = {2, 2, 2};
DivisionFactorXYZ = 5*{1, 1, 1};
};
BoundingBoxOnOff = On;
};

AnyFunTransform3DSTL STLTransform =
{
PreTransforms = {&.RBFTransform};
RBFDef.Type = RBF_ThinPlate;
AnyFixedRefFrame Input = {
AnySurfSTL SourceSurf = {
FileName = “femur211.stl”;
ScaleXYZ = {1, 1, 1};
};
AnySurfSTL TargetSurf = {
FileName = “TargetFemur.stl”;
ScaleXYZ = {1, 1, 1};
AnyFunTransform3D &pre = …TSeg2ScaleFrame;
};
};

SurfaceObjects0 = {&Input.SourceSurf};
SurfaceObjects1 = {&Input.TargetSurf};
NumPoints = 400;
BoundingBox.ScaleXYZ = {2, 2, 2};
BoundingBox.DivisionFactorXYZ = {1, 1, 1};
BoundingBoxOnOff = On;

};

}; // MyScalingFunctionFemur

Hi Lee,

I have to stress that when constructing a transformation using the vertices of STL surfaces (AnyFunTransform3DSTL), the surfaces have to be topologically equivalent, i.e. the surfaces have the same number of triangles and each neighbour and vertices represent the same features on both surfaces.

So if you do not have this your best bet will be to continue with the AnyFunTransform3DRBF function.

Looking at your code with the RBFDef, it looks fine. You can try using the settings I pasted below and see if there is an improvement. Or also try to select more points to see if that makes a difference.

AnyFunTransform3DRBF RBFTransform = {
  PreTransforms = {&.AffineTransform};
  RBFDef = {
    Type = RBF_Triharmonic;
    Param = 0.2;   

    [..rest of code..] 
 };

You should also bring in your target bone and draw it in another color to see how well the morphing is going. Make a little chunk of code (note: you might have to adjust file names/locations and ScaleXYZ accordingly) like this within the HumanModel.any file:

Main.Studies.HumanModel.BodyModel.Left.Leg.Seg.Thigh = {
  AnyFunTransform3D &CustomMarkerScaling = Main.Studies.HumanModel.SubjectSpecificScaling.Left.Thigh.RegistrationTransform; 

   AnyRefNode SS_STLNode  = {
     AnySurfSTL FemurSTL = {
      FileName = "target\Femur_target_L.stl";
      ScaleXYZ = {1, 1, 1}/1000;
      AnyFunTransform3D &scale = ..CustomMarkerScaling;        
        AnyDrawSurf stldraw = {
          FileName = .FileName;
          ScaleXYZ = {1, 1, 1}/1000;
          AnyFunTransform3D &scale = .scale;
          RGB = {0,1,0};
          Opacity = .....BonesOpacity.Thigh;
        };            
      };
    };
  };

Hello,

Thank you for your help!

I’ll try to select more points to see what will happen?

As you mentioned above about the AnyFunTransform3DSTL, I am wondering how can I do to acquire the topologically equivalent surfaces? Are there some tutorials or software or something else I can reference?

Thank you again!

Best Regards,
Lee