sift:tutorials:openbiomechanics_project:impact_shooting_arm_mechanics_free_throw_accuracy

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
sift:tutorials:openbiomechanics_project:impact_shooting_arm_mechanics_free_throw_accuracy [2025/09/15 19:46] wikisysopsift:tutorials:openbiomechanics_project:impact_shooting_arm_mechanics_free_throw_accuracy [2025/09/17 15:02] (current) wikisysop
Line 282: Line 282:
   * Compute_Model_Based_Data   * Compute_Model_Based_Data
   * Compute_Model_Based_Data   * Compute_Model_Based_Data
 +
 +Splitting the pipeline commands into 3 separate files makes the script easier to follow and simplifies future edits and/or debugging.
  
 ====Using Sift for Statistical Analysis and Data Visualization==== ====Using Sift for Statistical Analysis and Data Visualization====
Line 292: Line 294:
 In order to properly identify all data groups for this tutorial a total of 27 queries will be needed, this includes makes, left misses, and right misses in the x, y, and z planes for each shooting arm joint. The completed query file can be downloaded here for convenience: [[https://has-motion.com/download/examples/final freethrow query.q3d|Query Definitions]]. To complete the tutorial manually follow the steps below.  In order to properly identify all data groups for this tutorial a total of 27 queries will be needed, this includes makes, left misses, and right misses in the x, y, and z planes for each shooting arm joint. The completed query file can be downloaded here for convenience: [[https://has-motion.com/download/examples/final freethrow query.q3d|Query Definitions]]. To complete the tutorial manually follow the steps below. 
  
-**1.** Navigate to the Explore tab on the left and select the Query Builder{{:sift_query_builder.png?48x48}}. Click the plus sign beside "Queries" to add a new query definition and name it **"Wrist Angle X Made"**, click save.+**1.** Navigate to the Explore tab on the left and select the Query Builder{{:sift_query_builder.png?48x48}}. Click the plus sign beside "Queries" to add a new query definition and name it **"Wrist Angle X Made"**, click save. \\
 **2.** In the conditions list below your new query add a new condition using the **+**. Name the condition **"Right X"**\\ **2.** In the conditions list below your new query add a new condition using the **+**. Name the condition **"Right X"**\\
  **a.** Under the "Signals" tab select the options shown below. This command will find the right wrist angle on all made shots in the x direction for all cmz files (each trial) and store the data in **"Wrist Angle X Made".**  **a.** Under the "Signals" tab select the options shown below. This command will find the right wrist angle on all made shots in the x direction for all cmz files (each trial) and store the data in **"Wrist Angle X Made".**
Line 342: Line 344:
  
 ===K-Means Clusters=== ===K-Means Clusters===
-Once PCA has been performed on the select groups we can use K-Means testing on the results. K-Means testing creates uses an unsupervised algorithm to create clusters of data with similar characteristics, a more detailed tutorial can be accessed by reading [[https://wiki.has-motion.com/doku.php?id=sift:tutorials:run_k-means|Running K-Means]].+Once PCA has been performed on the select groups we can use K-Means testing on the results. K-Means testing uses an unsupervised algorithm to create clusters of data with similar characteristics, a more detailed tutorial can be accessed by reading [[https://wiki.has-motion.com/doku.php?id=sift:tutorials:run_k-means|Running K-Means]].
  
 To perform **K-Means** on our results navigate to the **Outlier Detection Using PCA** button on the top tool bar. Select **K-Means** from the dropdown menu. This will generate a dialogue box, complete it like so for your wrist, shoulder and elbow joints. To perform **K-Means** on our results navigate to the **Outlier Detection Using PCA** button on the top tool bar. Select **K-Means** from the dropdown menu. This will generate a dialogue box, complete it like so for your wrist, shoulder and elbow joints.
Line 376: Line 378:
 Once the waveforms for makes, left misses, and right misses had been visualized for all 27 queries, subtle differences could be seen between the results for each joint angle based on shot result. The most significant differences could be seen in the flexion/extension patterns for each joint. As such, further analytical testing was conducted on left vs right misses and how they were impacted by shoulder, elbow, and wrist movement in the x direction. The null hypothesis stated that joint movement would be consistent across all shots, this was rejected by our SPM testing which showed small but statistically significant differences in shoulder, elbow, and wrist flexion for left and right misses during the release phase of the shooting motion. These differences were first identified using visual inspection of the signal time plots (below) and confirmed using K-clusters and statistical parametric mapping. Once the waveforms for makes, left misses, and right misses had been visualized for all 27 queries, subtle differences could be seen between the results for each joint angle based on shot result. The most significant differences could be seen in the flexion/extension patterns for each joint. As such, further analytical testing was conducted on left vs right misses and how they were impacted by shoulder, elbow, and wrist movement in the x direction. The null hypothesis stated that joint movement would be consistent across all shots, this was rejected by our SPM testing which showed small but statistically significant differences in shoulder, elbow, and wrist flexion for left and right misses during the release phase of the shooting motion. These differences were first identified using visual inspection of the signal time plots (below) and confirmed using K-clusters and statistical parametric mapping.
  
-**X direction signal-time plots**\\+**X direction signal-time plots (Wrist - Elbow - Shoulder)**\\
 {{:sift:tutorials:openbiomechanics_project:wrist_x.jpg?nolink&500|}}{{:sift:tutorials:openbiomechanics_project:elbow_x.jpg?nolink&500|}}{{:sift:tutorials:openbiomechanics_project:shoulder_x.jpg?nolink&500|}} {{:sift:tutorials:openbiomechanics_project:wrist_x.jpg?nolink&500|}}{{:sift:tutorials:openbiomechanics_project:elbow_x.jpg?nolink&500|}}{{:sift:tutorials:openbiomechanics_project:shoulder_x.jpg?nolink&500|}}
  
Line 407: Line 409:
     
 **Interpreting the signal-signal plot** **Interpreting the signal-signal plot**
-Signal-signal plots in biomechanics are often used to assess the coordination of two joint angles throughout a cycle. We were interested in how the the wrist and elbow flexion angle and joint angular velocity relationship changed amongst the various conditions (made/missed left/missed right). The joint angle signal-signal plot shows the elbow angle remaining fairly consistent throughout the shot, while the deviations from the coordination pattern primarily occur at the wrist. In the angular velocity signal-signal plot, we see deviations in the coordination pattern for both of the missed results category. 
  
-For misses on the right side, the wrist has a faster positive angular velocity upon receiving the ball.+Signal-signal plots in biomechanics are often used to assess the coordination of two joint angles throughout a cycle. We were interested in how the the wrist and elbow flexion angle and joint angular velocity relationship changed amongst the various conditions (made/missed left/missed right). The joint angle signal-signal plot shows the elbow angle remaining fairly consistent throughout the shot, while the deviations from the coordination pattern primarily occur at the wrist. In the angular velocity signal-signal plot, we see deviations in the coordination pattern for both of the missed results category. For misses on the right side, the wrist has a faster positive angular velocity upon receiving the ball.
  
 =====Using the Sift CMD Line for automation===== =====Using the Sift CMD Line for automation=====
Line 425: Line 426:
 {{:kmeans_help.png?nolink&600|}} {{:kmeans_help.png?nolink&600|}}
  
-**To script the SIFT command line process a code editor application and the newest version of Python must be installed.** In this tutorial the code editor **Visual Studio Code** is used.+**To script the SIFT command line process a code editor application and the newest version of Python must be installed.** In this tutorial the code editor **Visual Studio Code** is used. Python is just one method of automating processing through the Sift CLI, any other scripting or programming language can be used.
  
 Below are the steps required to build and execute the SIFT command line script. The final code is rather lengthy, it can be downloaded here if needed[[https://has-motion.com/download/examples/freethrowSiftScript.py |Completed Sift Automation Code]]. Completed Sift Automation Code. The code is designed to automate the all the steps done previously in this tutorial from creating the cmz files in Visual 3D, to running PCA analysis on the signals and conducting SPM tests in Sift. Ultimately all these steps below should be combined and be ran in your code editor of choice. Below are the steps required to build and execute the SIFT command line script. The final code is rather lengthy, it can be downloaded here if needed[[https://has-motion.com/download/examples/freethrowSiftScript.py |Completed Sift Automation Code]]. Completed Sift Automation Code. The code is designed to automate the all the steps done previously in this tutorial from creating the cmz files in Visual 3D, to running PCA analysis on the signals and conducting SPM tests in Sift. Ultimately all these steps below should be combined and be ran in your code editor of choice.
Line 431: Line 432:
 ===Required Libraries=== ===Required Libraries===
 **1.** Import the subprocesses library. This will allow you to run shell commands and manage external processes directly from Python.\\ **1.** Import the subprocesses library. This will allow you to run shell commands and manage external processes directly from Python.\\
-**2.** Import the os library. This will allow you to have access to folders and files within your computer.+**2.** Import the os library. This will allow you to have access to folders and files within your computer.\\
 **3.** Import the tkinter library as well as filedialog from the ktinter import. This is used in prompting the user to select a folder. **3.** Import the tkinter library as well as filedialog from the ktinter import. This is used in prompting the user to select a folder.
  
Line 441: Line 442:
  
 ===Selecting and accessing the work folder=== ===Selecting and accessing the work folder===
-**1.**The code will open a file explorer prompt and ask the user to select the folder with all the data. +**1.**The code will open a file explorer prompt and ask the user to select the folder with all the data. In the example in the image below, the folder that would be selected is the "introproj_testenv" as it contains the data for participant 1,2, and 3.
  
 {{:selectfolderprompt.png?nolink&600|}} {{:selectfolderprompt.png?nolink&600|}}
Line 453: Line 454:
  
 ===Navigating through the work folder=== ===Navigating through the work folder===
-**1.**This part of the code goes through your working folder and checks to see if the folders within it contain any .json or .cmz files. +**1.**This part of the code goes through your working folder and checks to see if the folders within it contain any .json files to be processed. For this specific project the raw data is in json form, if you are using any other file type be sure to change the .json with that file type.
  
-    has_json = any(file.endswith(".json"for file in files) #checks for json files +    for folder,subfolders,files in os.walk(directory): 
-    has_cmz = any(file.endswith(".cmz") for file in files) #Checks for cmz files +        has_json = any(file.endswith(".json") for file in files) #checks for json files
- +
-The logic below checks if a folder has .json files but no .cmz files. This is done as the code will process any folders with .json to create corresponding .cmz files, but if these .cmz files already exist it will skip the folder as to not have to process them again.  +
- +
-**2.** If a folder contains .json files the code then checks folders within the folder to see if .cmz files are stored in there. An example is if this script was already ran, the folder "processed" will already exist in the folder and the code will see that .cmz files are already there which means the main folder does not need to be processed again.It then checks if a folder has .json but no .cmz. If this condition is true, a variable fileName is created based on the folder name which will be used later when saving the Sift project created. Then the code makes a folder called "processed" and checks if it already exists in the current folder, if not it will create it. This folder will be used to store the cmz files as they are created.\\ +
  
 +**2.** If the folder does have a .json file it will first create a variable "fileName" by taking the name of the folder it is working on. This will be used later in the Sift process when naming the project files produced in Sift. 
     if has_json:     if has_json:
-        for sub in subfolders: +        fileName = os.path.basename(folder)    #Creates fileName based on name of folder
-            sub_path = os.path.join(folder,sub) +
-            cmz_files = [f for f in os.listdir(sub_path) if f.endswith(".cmz")] +
-            if cmz_files: +
-                has_cmz = True +
-                break+
  
-\\ +The next step after this is to run the Sift CMD line subprocess. In coding the indentation is very important as it defines the hierarchy of code blocksso before we add the subprocess, ensure that the code formatting looks like this:
-If the folder contains .json files and no .cmz files, the next step is to create a subfolder to hold all the produced .cmz files. It will check if the folder already has a folder labelled "processed" and if not it will create one. The next step after this is to run the Sift CMD line subprocess. Before that is added, the code should look like this:+
  
     import subprocess     import subprocess
Line 481: Line 473:
     directory = askdirectory(title ='Select Folder')     directory = askdirectory(title ='Select Folder')
     os.chdir(directory)     os.chdir(directory)
-   +
     for folder,subfolders,files in os.walk(directory):     for folder,subfolders,files in os.walk(directory):
-        has_json = any(file.endswith(".json") for file in files) #checks for json files +        has_json = any(file.endswith(".json") for file in files) #checks for json files USERS MIGHT HAVE DIFF FILE TYPES 
-        has_cmz = any(file.endswith(".cmz") for file in files) #Checks for cmz files +    
         if has_json:         if has_json:
-            for sub in subfolders: +            fileName = os.path.basename(folder)    #Creates fileName based on name of folder 
-                sub_path = os.path.join(folder,sub) +            #SUBPROCESS STARTS HERE
-                cmz_files = [f for f in os.listdir(sub_path) if f.endswith(".cmz")] +
-                if cmz_files: +
-                    has_cmz = True +
-                    break +
-        #This checks for folders that have unprocessed json files (Checks if it has been processed already by checking for cmz files) +
- +
-        os.chdir(folder) +
-        if has_json and not has_cmz: +
-            fileName = folder[-5:   #Creates fileName based on last 5 letters of folder +
-            folder_name = "processed" +
-            if not os.path.exists(folder_name):     #Creates a folder which all the processed cmz files will be put into +
-                os.mkdir(folder_name) +
-                print(f"Folder '{folder_name}' created."+
-            else: +
-                print(f"Folder '{folder_name}' already exists.")+
                                  
 Ensure that the indentation of your code follows the same format as the code above. Ensure that the indentation of your code follows the same format as the code above.
  
 ====Executing Sift CMD line operations==== ====Executing Sift CMD line operations====
-**1.** The following part of the code is run in the command prompt. This cannot be done if the import subprocess was not done at the beginning of the code. First, Sift will be open in the command prompt which will allow for the specific Sift commands to be used. The first Sift command is going to be "-RunV3DCommand" which runs a single V3D pipeline command. The command that will be ran is to set the variable DEFAULT_DATA to the folder we are currently working on. The following line "-RunV3D" is used to run a full V3D pipeline. For the parameter "script", paste the path to the desired pipeline.+**1.** The following part of the code is run in the command prompt. This cannot be done if the import subprocess was not done at the beginning of the code. First, Sift will be open in the command prompt which will allow for the specific Sift commands to be used. The first Sift command is going to be "-RunV3DCommand" which runs a single V3D pipeline command. The command that will be ran is to set the variable DEFAULT_DATA to the folder we are currently working on.
  
     subprocess.run([     subprocess.run([
Line 518: Line 494:
         "command", "Set_Default_Folders/DEFAULT_DATA="+folder+";",         "command", "Set_Default_Folders/DEFAULT_DATA="+folder+";",
                  
-*An issue you may run into is Sift without GUI not running. This may be caused do to Sift NoGUI already being open on your device. If you want to rerun Sif NoGUI the other instance has to be exited as Sift does not allow for multiple Sift NoGUI to be run simultaneously.+*Note: Only one instance of the Sift command line can be run at once, if you are notified of this error ensure all other command line windows are closed and re-run
                  
 **2.**The following line "-RunV3D" is used to run a full V3D pipeline. For the parameter "script" in the code, paste the path to the desired pipeline. **In order for the pipeline to work for the automation** some changes must be made in the original pipeline that was used. The full pipeline with changes can be [[https://has-motion.com/download/examples/testenvpipeline.v3s|found here]]. **2.**The following line "-RunV3D" is used to run a full V3D pipeline. For the parameter "script" in the code, paste the path to the desired pipeline. **In order for the pipeline to work for the automation** some changes must be made in the original pipeline that was used. The full pipeline with changes can be [[https://has-motion.com/download/examples/testenvpipeline.v3s|found here]].
Line 535: Line 511:
     ;     ;
                
-**b)** In order to make the pipeline save to the newly created "processed" folder, a new folder parameter is made pointing to the "processed" folder. The parameter value for this is the DEFAULT_DATA path then an & followed by the word "processed"This will make it so that it adds "processed" to the end of the path causing the folder to be selected. The File_Save_As command must be changed as well. Set the FOLDER that the .cmz files are being saved to as the new folder created called "FOLDERPROCESSED" +**b)** To simplify the process, the cmz files will be saved to the folder in which the .json are found. In order to make this change make the folder parameter access the folder variable which we previously set as the DEFAULT_DATA_FOLDER
- +
-    Set_Pipeline_Parameter_To_Folder_Path +
-    /PARAMETER_NAME=FOLDERPROCESSED +
-    /PARAMETER_VALUE=&::VISUAL3D_DEFAULT_DATA_FOLDER&processed +
-    ! /FROM_MOTION_FILE_IN_WORKSPACE= +
-    ! /PARAMETER_VALUE_SEARCH_FOR= +
-    ! /PARAMETER_VALUE_REPLACE_WITH= +
-    ! /PARAMETER_VALUE_APPEND= +
-    ! /SET_PROMPT=Select a directory +
-    ! /ALPHABETIZE=TRUE +
-    ;+
  
     File_Save_As     File_Save_As
     /FILE_NAME=TRIAL&::COUNT     /FILE_NAME=TRIAL&::COUNT
-    /FOLDER=::FOLDERPROCESSED+    /FOLDER=::FOLDER
     ! /SET_PROMPT=Save CMZ file as     ! /SET_PROMPT=Save CMZ file as
     ! /SAVE_EMBEDDED_GRAPHICS=FALSE     ! /SAVE_EMBEDDED_GRAPHICS=FALSE
     ! /CREATE_FOLDER_PATH=FALSE     ! /CREATE_FOLDER_PATH=FALSE
 +    ;
 +
 +**c) OPTIONAL** If you are not using .json files for your data you will also have to make changes to the pipeline as it is currently hardcoded to specifically process .json files. In the second command of the pipeline, Set_Pipeline_Parameter_To_List_Of_Files, you can change the FILE_MASK parameter to whichever file type you are using.
 +
 +
 +    Set_Pipeline_Parameter_To_List_Of_Files
 +    /PARAMETER_NAME= FILES
 +    /FOLDER= ::FOLDER
 +    ! /SEARCH_SUBFOLDERS=FALSE
 +    /FILE_MASK=*.json !INSERT YOUR DATA FILE TYPE
 +    ! /ALPHABETIZE=TRUE
 +    ! /RETURN_FOLDER_NAMES=FALSE
 +    ! /RETURN_RELATIVE_FILENAMES=FALSE
     ;     ;
  
Line 559: Line 537:
  
         "-RunV3D",         "-RunV3D",
-        "script","c:/Users/alexh/Downloads/introproj_testenv/testenvpipeline.v3s", #Replace with your pipeline path   +        "script","c:/Users/alexh/Downloads/introproj_testenv/testenvpipelinesimplified.v3s", #Replace with your pipeline path   
  
                  
sift/tutorials/openbiomechanics_project/impact_shooting_arm_mechanics_free_throw_accuracy.1757965595.txt.gz · Last modified: 2025/09/15 19:46 by wikisysop