====== Joint Work ======
This page provides three different overviews of how to calculate mechanical work (the time integration of power profiles) at a joint. All three examples assume that a [[visual3d:documentation:pipeline:model_based_data_commands:joint_power|JOINT_POWER]] model-based item already exists.
Calculating mechanical work at a joint requires distinguishing between positive and negative work. The joint power signals will cross zero many times and in some cases will not cross in the "same way" between different groups of participants.
==== Example 1: Use Evaluate_Expression ====
In this method we use [[visual3d:documentation:pipeline:expressions:expressions_overview|Evaluate_Expression]] to create two intermediate signals that allow us to directly integrate joint power to calculate joint work over a stance phase.
! Save a "negative only" signal by setting all frames for all
! three components to DATA NOT FOUND for any frame ABOVE zero
Evaluate_Expression
/EXPRESSION= ( CURRENT_SIGNAL < 0 ) / ( CURRENT_SIGNAL < 0 ) * CURRENT_SIGNAL
/SIGNAL_TYPES=LINK_MODEL_BASED
/SIGNAL_FOLDER=ORIGINAL
/SIGNAL_NAMES=RAnklePower+LAnklePower
! /RESULT_TYPES=DERIVED
/RESULT_FOLDERS=IMPULSE
/RESULT_NAME=_Neg
/APPLY_AS_SUFFIX_TO_SIGNAL_NAME=TRUE
;
! Save a "positive only" signal by setting all frames for all
! three components to DATA NOT FOUND for any frame BELOW zero
Evaluate_Expression
/EXPRESSION=( CURRENT_SIGNAL > 0 ) / ( CURRENT_SIGNAL > 0 ) * CURRENT_SIGNAL
/SIGNAL_TYPES=LINK_MODEL_BASED
/SIGNAL_FOLDER=ORIGINAL
/SIGNAL_NAMES=RAnklePower+LAnklePower
! /RESULT_TYPES=DERIVED
/RESULT_FOLDERS=IMPULSE
/RESULT_NAME=_Pos
/APPLY_AS_SUFFIX_TO_SIGNAL_NAME=TRUE
;
! Integrate over the right stance phase
Metric_Integrate
/RESULT_METRIC_FOLDER=IMPULSE
/RESULT_METRIC_NAME=
/APPLY_AS_SUFFIX_TO_SIGNAL_NAME=TRUE
/SIGNAL_TYPES=DERIVED+DERIVED
/SIGNAL_FOLDER=IMPULSE+IMPULSE
/SIGNAL_NAMES=RAnklePower_Neg+RAnklePower_Pos
/COMPONENT_SEQUENCE=ALL
/EVENT_SEQUENCE=RON+ROFF
/EXCLUDE_EVENTS=
/SEQUENCE_PERCENT_START=
/SEQUENCE_PERCENT_END=
! /GENERATE_MEAN_AND_STDDEV=TRUE
! /APPEND_TO_EXISTING_VALUES=FALSE
;
! Integrate over the left stance phase
Metric_Integrate
/RESULT_METRIC_FOLDER=IMPULSE
/RESULT_METRIC_NAME=
/APPLY_AS_SUFFIX_TO_SIGNAL_NAME=TRUE
/SIGNAL_TYPES=DERIVED+DERIVED
/SIGNAL_FOLDER=IMPULSE+IMPULSE
/SIGNAL_NAMES=LAnklePower_Neg+LAnklePower_Pos
/COMPONENT_SEQUENCE=ALL
/EVENT_SEQUENCE=LON+LOFF
/EXCLUDE_EVENTS=
/SEQUENCE_PERCENT_START=
/SEQUENCE_PERCENT_END=
! /GENERATE_MEAN_AND_STDDEV=TRUE
! /APPEND_TO_EXISTING_VALUES=FALSE
;
==== Example 2: Calculate Positive and Negative Work Separately ====
In this method we determine the phases of positive and negative power by computing [[visual3d:documentation:c3d_signal_types:event_label_data_type|events]] based on threshold crossings of zero. The following is an example that you may have to modify slightly to suit the signals that you have and to match your assumptions about what constitutes noise (e.g. setting the threshold radius parameters).
!**************************************
! Calculate zero crossing events
!**************************************
! Calculate the PowerPos event - when signal crossing ascends
Event_Threshold
/Signal_Types=LINK_MODEL_BASED
/Signal_Names=Right Ankle Power
/Signal_Folder=ORIGINAL
/Event_Name=PowerPos
/Select_X=TRUE
/Select_Y=FALSE
/Select_Z=FALSE
/Threshold=0
/Radius=8
/Frame_Offset=0
/Ascending=TRUE
/Descending=FALSE
/Ensure_Range_Frames_Before_Threshold_Crossing=TRUE
/Ensure_Range_Frames_After_Threshold_Crossing=FALSE
/Start_At_Event=
/End_At_Event=
/Event_Instance=0
;
! Calculate the PowerNeg event - when signal crossing descends
Event_Threshold
/Signal_Types=LINK_MODEL_BASED
/Signal_Names=Right Ankle Power
/Signal_Folder=ORIGINAL
/Event_Name=PowerNeg
/Select_X=TRUE
/Select_Y=FALSE
/Select_Z=FALSE
/Threshold=0
/Radius=8
/Frame_Offset=0
/Ascending=FALSE
/Descending=TRUE
/Ensure_Range_Frames_Before_Threshold_Crossing=TRUE
/Ensure_Range_Frames_After_Threshold_Crossing=FALSE
/Start_At_Event=
/End_At_Event=
/Event_Instance=0
;
!**********************************************************************
! Compute positive and negative work for each range of positive power.
!**********************************************************************
! Calculate right ankle positive work by time integration of right ankle power from
! PowerPos event to PowerNeg event
Metric_Integrate
/Signal_Types=LINK_MODEL_BASED
/Signal_Names=Right Ankle Power
/Signal_Folder=ORIGINAL
/Signal_Components=X
/Event_Sequence=PowerPos+PowerNeg
/Exclude_Events=
/Metric_Name=Right Ankle Positive Work
/Apply_As_Suffix_To_Signal_Name=FALSE
/Generate_Mean_And_STDDEV=FALSE
/Append_To_Existing_Values=FALSE
;
! Calculate right ankle negative work by time integration of right ankle power
! from PowerNeg event to PowerPos event
Metric_Integrate
/Signal_Types=LINK_MODEL_BASED
/Signal_Names=Right Ankle Power
/Signal_Folder=ORIGINAL
/Signal_Components=X
/Event_Sequence=PowerNeg+PowerPos
/Exclude_Events=
/Metric_Name=Right Ankle Negative Work
/Apply_As_Suffix_To_Signal_Name=FALSE
/Generate_Mean_And_STDDEV=FALSE
/Append_To_Existing_Values=FALSE
;
!************************************************************************
! Compute the total positive and total negative work by summing the work.
!************************************************************************
!Compute total positive work for the right ankle
Metric_Sum
/Signal_Types=METRIC
/Signal_Names=Right Ankle Positive Work
/Signal_Folder=PROCESSED
/Signal_Components=X
/Event_Sequence=
/Exclude_Events=
/Metric_Name=Right Ankle Total Positive Work
/Apply_As_Suffix_To_Signal_Name=FALSE
/Generate_Mean_And_STDDEV=FALSE
/Append_To_Existing_Values=FALSE
;
!Compute total negative work for the right ankle
Metric_Sum
/Signal_Types=METRIC
/Signal_Names=Right Ankle Negative Work
/Signal_Folder=PROCESSED
/Signal_Components=X
/Event_Sequence=
/Exclude_Events=
/Metric_Name=Right Ankle Total Negative Work
/Apply_As_Suffix_To_Signal_Name=FALSE
/Generate_Mean_And_STDDEV=FALSE
/Append_To_Existing_Values=FALSE
;
==== Example 3: Calculate Work for Kinetic Event Sequences ====
The previous example breaks down if you want to compute work between kinetic events such as RON and ROFF because 2 occurrences of the event PowerNeg may not be created. This happens because RON is an event in which the Ankle Power is already negative and ROFF is an event in which Ankle Power hasn't become negative yet.
The workaround is to create a PowerNeg event at RON and create a PowerNeg event at ROFF using the following commands before the events section of the script above.
Event_Copy
/EVENT_NAME=RON
/NEW_EVENT_NAME=PowerNeg
/FRAME_OFFSET=-1
/EVENT_INSTANCE=0
! /RANGE_INSTANCE=0
! /EVENT_SEQUENCE=
! /EXCLUDE_EVENTS=
! /START_AT_EVENT=
! /END_AT_EVENT=
;
Event_Copy
/EVENT_NAME=ROFF
/NEW_EVENT_NAME=PowerNeg
/FRAME_OFFSET=0
! /EVENT_INSTANCE=0
! /RANGE_INSTANCE=0
! /EVENT_SEQUENCE=
! /EXCLUDE_EVENTS=
! /START_AT_EVENT=
! /END_AT_EVENT=
;