| import numpy as np |
| import torch |
| from scipy.signal import butter, filtfilt |
| import secrets |
|
|
| def numpy_to_storage(labels, data, storage_file, datatype=None): |
| assert data.shape[1] == len(labels), "# labels doesn't match columns" |
| assert labels[0] == "time" |
|
|
| f = open(storage_file, 'w') |
| |
| if datatype is None: |
| f = open(storage_file, 'w') |
| f.write('name %s\n' % storage_file) |
| f.write('datacolumns %d\n' % data.shape[1]) |
| f.write('datarows %d\n' % data.shape[0]) |
| f.write('range %f %f\n' % (np.min(data[:, 0]), np.max(data[:, 0]))) |
| f.write('endheader \n') |
| |
| else: |
| if datatype == 'IK': |
| f.write('Coordinates\n') |
| elif datatype == 'ID': |
| f.write('Inverse Dynamics Generalized Forces\n') |
| elif datatype == 'GRF': |
| f.write('%s\n' % storage_file) |
| elif datatype == 'muscle_forces': |
| f.write('ModelForces\n') |
| f.write('version=1\n') |
| f.write('nRows=%d\n' % data.shape[0]) |
| f.write('nColumns=%d\n' % data.shape[1]) |
| if datatype == 'IK': |
| f.write('inDegrees=yes\n\n') |
| f.write('Units are S.I. units (second, meters, Newtons, ...)\n') |
| f.write( |
| "If the header above contains a line with 'inDegrees', this indicates whether rotational values are in degrees (yes) or radians (no).\n\n") |
| elif datatype == 'ID': |
| f.write('inDegrees=no\n') |
| elif datatype == 'GRF': |
| f.write('inDegrees=yes\n') |
| elif datatype == 'muscle_forces': |
| f.write('inDegrees=yes\n\n') |
| f.write('This file contains the forces exerted on a model during a simulation.\n\n') |
| f.write("A force is a generalized force, meaning that it can be either a force (N) or a torque (Nm).\n\n") |
| f.write('Units are S.I. units (second, meters, Newtons, ...)\n') |
| f.write('Angles are in degrees.\n\n') |
|
|
| f.write('endheader \n') |
|
|
| for i in range(len(labels)): |
| f.write('%s\t' % labels[i]) |
| f.write('\n') |
|
|
| for i in range(data.shape[0]): |
| for j in range(data.shape[1]): |
| f.write('%20.8f\t' % data[i, j]) |
| f.write('\n') |
|
|
| f.close() |
|
|
|
|
| def lowpass_filter(data, cutoff_cycles=2, num_samples=24, order=4): |
| nyquist = num_samples / 2 |
| normal_cutoff = cutoff_cycles / nyquist |
| b, a = butter(order, normal_cutoff, btype='low', analog=False) |
| return filtfilt(b, a, data, axis=0) |
|
|
| |
| def save_random_stride(model, dataloader, joints, savepath, savepath_recon, device, |
| from_all_batches=False, filter=False): |
| |
| if from_all_batches: |
| batch_data, batch_metadata = [], [] |
| for batch in dataloader: |
| batch_data.append(batch["features"]) |
| batch_metadata.extend(batch["metadata"]) |
| batch_data = torch.cat(batch_data, dim=0) |
|
|
| stride_idx = secrets.randbelow(batch_data.shape[0]) |
| stride_data = batch_data[stride_idx] |
| stride_metadata = batch_metadata[stride_idx] |
| else: |
| ds = dataloader.dataset |
| ds_idx = secrets.randbelow(len(ds)) |
| item = ds[ds_idx] |
|
|
| feats = item["features"] |
| s_idx = secrets.randbelow(feats.shape[0]) |
| stride_data = feats[s_idx] |
|
|
| meta = item["metadata"] |
| try: |
| stride_metadata = meta.iloc[s_idx] |
| except Exception: |
| stride_metadata = meta |
|
|
| print(f"Stride Data Shape: {stride_data.shape}") |
|
|
| |
| model.eval() |
| with torch.no_grad(): |
| reconstructed_data, _, mu, _, _ = model(stride_data.unsqueeze(0).to(device)) |
| reconstructed_data = reconstructed_data.view(-1, 24, 32).cpu().numpy().squeeze() |
| stride_data = stride_data.cpu().numpy().squeeze() |
|
|
| |
| stride_data = stride_data[:, :len(joints)] |
| reconstructed_data = reconstructed_data[:, :len(joints)] |
|
|
| |
| stride_time = stride_data[:, 0] |
| fs = 1.0 / np.mean(np.diff(stride_time)) |
| print(f"Sampling Frequency: {fs} Hz") |
|
|
| |
| if filter: |
| reconstructed_data = lowpass_filter(stride_data, cutoff_cycles=2, num_samples=24) |
|
|
| reconstructed_data[:, 0] = stride_time |
| joints = [j.replace('_ips', '_r').replace('_contra', '_l') for j in joints] |
|
|
| numpy_to_storage(joints, stride_data, savepath, datatype='IK') |
| numpy_to_storage(joints, reconstructed_data, savepath_recon, datatype='IK') |
|
|
| print(f"Stride Metadata: {stride_metadata}") |
| return mu |
|
|
|
|
|
|
|
|
|
|
|
|
|
|