Skip to content

Commit

Permalink
Merge branch 'release'
Browse files Browse the repository at this point in the history
  • Loading branch information
DrRobsAT committed Apr 16, 2024
2 parents 017c2a1 + e89641a commit 78fd5f1
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 86 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

## [1.0.1] - 2024-04-16

### Added

- interpolation of IMP and FRC surface parameter maps (Robert Arnold)

### Changed

- export point impedance and contact force data only if data is available (Robert Arnold)
- test data set (added point force and impedance data) (Robert Arnold)

### Fixed

- load .pyceps with no additional meshes (Robert Arnold)
- load .pyceps with maps without points (Robert Arnold)
- import of point impedance and contact force data (Robert Arnold)

## [1.0.0] - 2024-04-10

### Added
Expand Down Expand Up @@ -79,6 +96,7 @@ _This release was yanked on PyPi due to a missing file._

_Initial release._

[1.0.1]: https://github.com/medunigraz/pyCEPS/releases/tag/1.0.1
[1.0.0]: https://github.com/medunigraz/pyCEPS/releases/tag/1.0.0
[0.1.1]: https://github.com/medunigraz/pyCEPS/releases/tag/0.1.1
[0.1.0]: https://github.com/medunigraz/pyCEPS/releases/tag/0.1.0
Expand Down
38 changes: 30 additions & 8 deletions pyceps/datatypes/study.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ def save(self, filepath=''):
points = ET.SubElement(proc, 'Points',
count=str(len(cmap.points))
)
# export data from EPPoint baseclass only
for key in list(EPPoint('dummy', parent=cmap).__dict__):
if key == 'parent':
# don't save this
Expand Down Expand Up @@ -573,7 +574,8 @@ def interpolate_data(self, which):
Parameters:
which : str
parameter to interpolate, options: ['uni', 'bip', 'act']
parameter to interpolate
options: ['uni', 'bip', 'lat', 'imp', 'frc']
Raises:
KeyError : If parameter to interpolate is unknown
Expand Down Expand Up @@ -609,11 +611,29 @@ def interpolate_data(self, which):
data = np.asarray([p.bipVoltage for p in valid_points])
elif which.lower() == 'uni':
data = np.asarray([p.uniVoltage for p in valid_points])
elif which.lower() == 'imp':
data = np.asarray([p.impedance for p in valid_points])
elif which.lower() == 'frc':
data = np.asarray([p.force for p in valid_points])
else:
raise KeyError()

# check if there is data for interpolation
if np.isnan(data).all():
log.debug('found only NaN in data, cannot interpolate map {}'
.format(which.upper())
)
return

# remove data for redundant points
data = data[unique_ids]
# remove any points with NaN's before interpolation
mask = ~np.isnan(data)
data = data[mask]
unique_points = unique_points[mask]

interpolated = inverse_distance_weighting(unique_points,
data[unique_ids],
data,
mesh_points,
k=7)

Expand Down Expand Up @@ -838,15 +858,17 @@ def export_point_data(self, basename='', which=None, points=None):

if "IMP" in which:
data = [point.impedance for point in points]
dat_file = basename + '.ptdata.IMP.pc.dat'
writer.dump(dat_file, data)
log.info('exported point data to {}'.format(dat_file))
if not np.isnan(data).all():
dat_file = basename + '.ptdata.IMP.pc.dat'
writer.dump(dat_file, data)
log.info('exported point data to {}'.format(dat_file))

if "FRC" in which:
data = [point.force for point in points]
dat_file = basename + '.ptdata.FRC.pc.dat'
writer.dump(dat_file, data)
log.info('exported point data to {}'.format(dat_file))
if not np.isnan(data).all():
dat_file = basename + '.ptdata.FRC.pc.dat'
writer.dump(dat_file, data)
log.info('exported point data to {}'.format(dat_file))

return

Expand Down
87 changes: 49 additions & 38 deletions pyceps/fileio/cartoio.py
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ def load(self, file: str, repo_path: str = ''):

# load additional meshes
mesh_item = root.find('AdditionalMeshes')
if int(mesh_item.get('count')) > 0:
if mesh_item:
_, reg_matrix = xml_load_binary_data(
[x for x in mesh_item.findall('DataArray')
if x.get('name') == 'registrationMatrix'][0]
Expand Down Expand Up @@ -706,24 +706,25 @@ def load(self, file: str, repo_path: str = ''):
points_item = proc.find('Points')
num_points = int(points_item.get('count'))

for arr in points_item.findall('DataArray'):
d_name, data = xml_load_binary_data(arr)
p_data[d_name] = data
for arr in points_item.findall('Traces'):
d_name, data = xml_load_binary_trace(arr)
p_data[d_name] = data

points = []
for i in range(num_points):
new_point = CartoPoint('dummy', parent=new_map)
for key, value in p_data.items():
if hasattr(new_point, key):
setattr(new_point, key, value[i])
else:
log.warning('cannot set attribute "{}" for CartoPoint'
.format(key))
points.append(new_point)
new_map.points = points
if num_points > 0:
for arr in points_item.findall('DataArray'):
d_name, data = xml_load_binary_data(arr)
p_data[d_name] = data
for arr in points_item.findall('Traces'):
d_name, data = xml_load_binary_trace(arr)
p_data[d_name] = data

points = []
for i in range(num_points):
new_point = CartoPoint('dummy', parent=new_map)
for key, value in p_data.items():
if hasattr(new_point, key):
setattr(new_point, key, value[i])
else:
log.warning('cannot set attribute "{}" for CartoPoint'
.format(key))
points.append(new_point)
new_map.points = points

# now we can add the procedure to the study
self.maps[name] = new_map
Expand Down Expand Up @@ -1193,6 +1194,8 @@ def import_map(self, egm_names_from_pos=False):
self.interpolate_data('lat')
self.interpolate_data('bip')
self.interpolate_data('uni')
self.interpolate_data('imp')
self.interpolate_data('frc')
self.bsecg = self.get_map_ecg(method=['median', 'mse', 'ccf'])

def load_mesh(self):
Expand Down Expand Up @@ -1955,8 +1958,10 @@ class CartoPoint(EPPoint):
forceFile : str
name of the points contact force file
<map_name>_<point_name>_Contact_Force.txt
force : PointForce
contact force data for this point
forceData : PointForce
full contact force data for this point
impedanceData : PointImpedance
full impedance data for this point
Methods:
is_valid()
Expand Down Expand Up @@ -1997,10 +2002,11 @@ def __init__(self, name,
self.pointFile = ''
self.barDirection = None
self.tags = tags
self.ecgFile = None
self.ecgFile = ''
self.uniX = np.full(3, np.nan, dtype=np.float32)
self.forceFile = None
self.forceFile = ''
self.forceData = None
self.impedanceData = None

def import_point(self, point_file, egm_names_from_pos=False):
"""
Expand Down Expand Up @@ -2058,8 +2064,12 @@ def import_point(self, point_file, egm_names_from_pos=False):
impedance_time[i] = x.get('Time')
impedance_value[i] = x.get('Value')

self.impedance = PointImpedance(time=impedance_time,
value=impedance_value)
self.impedanceData = PointImpedance(time=impedance_time,
value=impedance_value)
# update base class impedance value with the one closest to LAT
self.impedance = impedance_value[
np.nanargmin(np.abs(impedance_time - self.latAnnotation))
]

self.ecgFile = root.find('ECG').get('FileName')

Expand Down Expand Up @@ -2125,19 +2135,20 @@ def import_point(self, point_file, egm_names_from_pos=False):

# now get the force data for this point
log.debug('reading force file for point {}'.format(self.name))
self.forceFile = (self.pointFile.split('_Point_Export')[0]
+ '_ContactForce.txt'
)

if self.parent.parent.repository.is_file(self.forceFile):
with self.parent.parent.repository.open(self.forceFile) as fid:
self.forceData = read_force_file(
fid, encoding=self.parent.parent.encoding
)
# update base class force value
self.force = self.forceData.force
else:
log.debug('No force file found for point {}'.format(self.name))
try:
self.forceFile = root.find('ContactForce').get('FileName')
force_file = self.parent.parent.repository.join(self.forceFile)
if self.parent.parent.repository.is_file(force_file):
with self.parent.parent.repository.open(force_file) as fid:
self.forceData = read_force_file(
fid, encoding=self.parent.parent.encoding
)
# update base class force value with the one closest to LAT
self.force = self.forceData.force
else:
log.debug('No force file found for point {}'.format(self.name))
except AttributeError:
log.debug('No force data saved for point {}'.format(self.name))

def is_valid(self):
"""
Expand Down
1 change: 0 additions & 1 deletion pyceps/fileio/cartoutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,6 @@ def read_force_file(fid, encoding='cp1252'):
't_lateralAngle': np.empty(0),
'systemTime': np.empty(0)}


# read file version
version = fid.readline().decode(encoding=encoding).rstrip()
if not version.lower().endswith('contactforce.txt_2.0'):
Expand Down
5 changes: 5 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
AUTHOR = 'Robert Arnold'
REQUIRES_PYTHON = '>=3.8'
VERSION = '{{VERSION_PLACEHOLDER}}'
PROJECT_URLS = {
'Github': 'https://github.com/medunigraz/pyCEPS',
'Changelog': 'https://github.com/medunigraz/pyCEPS/blob/main/CHANGELOG.md',
}
CLASSIFIERS = [
# Trove classifiers
# Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
Expand Down Expand Up @@ -95,6 +99,7 @@
author_email=EMAIL,
python_requires=REQUIRES_PYTHON,
url=URL,
project_urls=PROJECT_URLS,
packages=find_packages(exclude=["tests", "*.tests", "*.tests.*", "tests.*"]),
# If your package is a single module, use this instead of 'packages':
# py_modules=['pyceps'],
Expand Down
Binary file modified tests/Export_VT-dummy-02_14_2024-11-23-36.zip
Binary file not shown.
84 changes: 45 additions & 39 deletions tests/VT dummy 02_14_2024 11-23-36.pyceps

Large diffs are not rendered by default.

0 comments on commit 78fd5f1

Please sign in to comment.