KINECAL 1.0.2

File: <base>/view_files.py (8,907 bytes)
# -*- coding: utf-8 -*-
"""
Created on Wed March 2 13:44:00 2022

@author: seanmb

This file will show you some of the basic uses of KINECAL
It uses the sway_utils library to calculate the metrics.
"""

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from matplotlib import cm

import numpy as np
import seaborn as sns
import pandas as pd

import matplotlib.pyplot as plt

import os
import sys

sys.path.append(os.path.abspath('..')) #if this is not working, update this path with the locatiojn of your sway_utils folder
from sway_utils.recordings import KinectRecording
import sway_utils.metrics as sm

start_frame = 200
end_frame = 500

HAs = [25, 504, 505] #Healthy Adults
CaRs = [201, 309, 311] #Clinically at Risk

#%%
"""
view depth files

The depth files are stored as ushort values in binary format.

Below, is a code sippit to allow you to open individual files.

"""

file_path = os.path.abspath('../505/505_Quiet-Standing-Eyes-Open/depth/DepthUshort63638319336726.bin')
depth_image = np.fromfile(file_path, dtype='ushort')
depth_image = depth_image.reshape([424, 512])


"""
It is can be useful to use different colour maps to view the depth informaiton
"""
plt.imshow(depth_image, cmap='binary')
plt.show()
plt.imshow(depth_image, cmap='jet')
plt.show()
plt.imshow(depth_image, cmap='prism')
plt.show()
plt.imshow(depth_image, cmap='bone')
plt.show()


#%%
"""
Save in depth files as images

If you are saving the depth images scaling the images to 0-255 and converting to unit8 is a advisable

Note it this is a destrucive process and you should work with the raw depth data in your models
"""

import imageio
depth_image_for_saving = (depth_image-np.min(depth_image))/(np.max(depth_image)-np.min(depth_image))*255
depth_image_for_saving = depth_image_for_saving.astype('uint8')
imageio.imwrite('depth_image_for_saving.jpeg', depth_image_for_saving)

# %%
def centre(data):
    """
    This method is uesed to centre the CoM pathes by subtrcting the 
    mean value from each value in the CoM path
    """
    data_mean = np.mean(data)
    centred_data = np.subtract(data, data_mean)
    return centred_data


#%%
"""
This section uses the sway_utils library to produce a stabilogram for each of the participant records.
Three healthy adults and three Clinically-at-risk participants are used to provide a comparison.

The records are processed using the recording object from the sway_utils library.

NOTE: The first time the files are processed, cache files for joint positions 
will be created (.csv and .npy).  Subsequent runs will use the cache, making analysis much quicker.
In addition, the csv file is a convenient format for 3rd party analysis.

The data are filtered using a butterworth filter and is saved into a [3, 26, 599] (axis, joint, frame) array called stacked_filtered_XYZ_values
The raw values are also cached and stored in an array called stacked_raw_XYZ_values.

CoM positions are estimated using the Euclidean mean of the HIP_LEFT HIP_RIGHT SPINE_MID.
the mean position of HIP_LEFTx HIP_RIGHTx SPINE_MIDx represents the ML-axis
the mean position of HIP_LEFTz HIP_RIGHTz, SPINE_MIDz represents the AP-axis

The CoM values can be converted to stabilograms, using the confidence_ellips method of the sway_utils library,
and displayed using Matplotlib

NOTE: the data are centred, and a standardised x and y scale is used to make the comparison easier.

Quiet standing, eyes open, is used in this comparison.

"""



start_frame = 200
end_frame = start_frame + (30*10)

for part_id in HAs+CaRs:
    str_part_id = str(part_id)
        
    fig = plt.figure(figsize=(6,6))
    ax = fig.add_subplot(111)
    ax.set_xlim([-5, 5])
    ax.set_ylim([-5, 5])
    
    skel_root_path = os.path.abspath('../' + str_part_id + '/' + str_part_id + '_Quiet-Standing-Eyes-Open/skel')
    recording = KinectRecording(skel_root_path, "", 'Quiet-Standing-Eyes-Open', str_part_id)
    #recording.calculate_walked_skel_angles()
    #ML_path = recording.stacked_filtered_XYZ_values[0, 25][start_frame:end_frame]*100
    #AP_path = recording.stacked_filtered_XYZ_values[2, 25][start_frame:end_frame]*100
    ML_path = centre(recording.stacked_filtered_XYZ_values[0, 25][start_frame:end_frame]*100) # the midle 10 seconds are retreived and converted to cm
    AP_path = centre(recording.stacked_filtered_XYZ_values[2, 25][start_frame:end_frame]*100)
    
    #ML_path = centre(recording.stacked_raw_XYZ_values[0, 25][start_frame:end_frame])*100 # the midle 10 seconds are retreived and converted to cm
    #AP_path = centre(recording.stacked_raw_XYZ_values[2, 25][start_frame:end_frame])*100
    
    elp, width, height, AREA_CE, angle = sm.confidence_ellipse(ML_path, 
                                                               AP_path, 
                                                               ax, 
                                                               n_std=1.96,
                                                               edgecolor='red')
    AREA_CE = round(AREA_CE, 2)
    
    ax.scatter(ML_path, AP_path, s=1)
    #AREA_CE =  round((elp.height/2) * (elp.width/2) * np.pi, 2)
    ax.set_title('Quiet-Standing-Eyes-Open ' + str_part_id + '\n CoM 95% CE' + 
                 '\n' + str(round(width, 2)) + 'cm' + 
                 ' x ' + 
                 str(round(height, 2)) + 'cm' + 
                 ' Area:' + str(AREA_CE) + '$cm^2$')
    
    ax.set_aspect('equal')
    plt.xlabel('ML (cm)')
    plt.ylabel('AP (cm)')
    plt.show()

#%%
"""
Read in Skeleton files using the recording object

Note if this is the first time you are reading the files cache files for joint positions 
will be created (.csv and .npy).  Subsiquent runns with use the cashe.

These values are filterd using a butterworth filter and is saved into a [3, 26, 599] (axis, joint, frame) array called stacked_filtered_XYZ_values

The CoM value is used here to create a stabilogram.  
Note the value are centred to make comparison eaiser.

"""
plt.figure(figsize=(6, 6), dpi=72)
plt.xlim([-5, 5])
plt.ylim([-5, 5])

line_style = ['-', '--', '-.', ':']


line_index = 0
for part_id in HAs:
    str_part_id = str(part_id)
    #skel_root_path = os.path.abspath('../504/504_Quiet-Standing-Eyes-Open/skel')
    skel_root_path = os.path.abspath('../' + str_part_id + '/' + str_part_id + '_Quiet-Standing-Eyes-Open/skel')
    recording = KinectRecording(skel_root_path, "", 'Quiet-Standing-Eyes-Open', str_part_id)
    plt.plot(centre(recording.stacked_filtered_XYZ_values[0, 25][start_frame:end_frame])*100,
            centre(recording.stacked_filtered_XYZ_values[2, 25][start_frame:end_frame])*100, 
            color='black', linestyle=line_style[line_index])
    line_index += 1

line_index = 0
for part_id in CaRs:
    str_part_id = str(part_id)
    #skel_root_path = os.path.abspath('../504/504_Quiet-Standing-Eyes-Open/skel')
    skel_root_path = os.path.abspath('../' + str_part_id + '/' + str_part_id + '_Quiet-Standing-Eyes-Open/skel')
    recording = KinectRecording(skel_root_path, "", 'Quiet-Standing-Eyes-Open', part_id)
    plt.plot(centre(recording.stacked_filtered_XYZ_values[0, 25][start_frame:end_frame])*100,
            centre(recording.stacked_filtered_XYZ_values[2, 25][start_frame:end_frame])*100, 
            color='red', linestyle=line_style[line_index])
    line_index += 1

plt.legend(HAs + CaRs, loc=1)
plt.title('Stacked Stabilogram')
plt.xlabel('ML (cm)')
plt.ylabel('AP (cm)')
plt.show()

#%%

"""
JOint angles, in Sagital (SP), Frontal (FR) and Transvers (TR) planies can 
also be caclulated using the sway_utils library

As before, once processed the calulated values are cached.

"""
plt.figure(figsize=(8, 6), dpi=72)

skel_root_path = os.path.abspath('../' + str(HAs[0]) +'/' + str(HAs[0]) +'_STS-5/skel')
recording = KinectRecording(skel_root_path, "", 'STS-5', HAs[0])
recording.calculate_walked_skel_angles()
KNEE_left = recording.walked_skel_angles['KNEELEFT_a_SP']
KNEE_right = recording.walked_skel_angles['KNEERIGHT_a_SP']
plt.plot(KNEE_left, color='black')
plt.plot(KNEE_right, color='black')

    
skel_root_path = os.path.abspath('../' + str(CaRs[0]) +'/' + str(CaRs[0]) +'_STS-5/skel')
recording = KinectRecording(skel_root_path, "", 'STS-5', CaRs[0])
recording.calculate_walked_skel_angles()
KNEE_left = recording.walked_skel_angles['KNEELEFT_a_SP']
KNEE_right = recording.walked_skel_angles['KNEERIGHT_a_SP']
plt.plot(KNEE_left, color='red')
plt.plot(KNEE_right, color='red')

plt.legend([str(HAs[0])+ '_KNEE_left', str(HAs[0]) + '_KNEE_right',
            str(CaRs[0])+ '_KNEE_left', str(CaRs[0]) + '_KNEE_right'], loc=1)
plt.xlabel('frame #')
plt.ylabel('relitive angle (deg)')
plt.show()