Skip to content

Commit f339aeb

Browse files
committed
Quick pass on duration
1 parent 47b06a6 commit f339aeb

File tree

4 files changed

+37
-15
lines changed

4 files changed

+37
-15
lines changed

hed/models/model_constants.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
11
""" Defined constants for definitions, def labels, and expanded labels. """
2-
COLUMN_TO_HED_TAGS = "column_to_hed_tags"
3-
ROW_HED_STRING = "HED"
4-
COLUMN_ISSUES = "column_issues"
5-
ROW_ISSUES = "row_issues"
6-
7-
82
class DefTagNames:
93
""" Source names for definitions, def labels, and expanded labels. """
104

@@ -19,9 +13,11 @@ class DefTagNames:
1913
ONSET_ORG_KEY = "Onset"
2014
OFFSET_ORG_KEY = "Offset"
2115
INSET_ORG_KEY = "Inset"
16+
DURATION_ORG_KEY = "Duration"
2217

2318
ONSET_KEY = ONSET_ORG_KEY.lower()
2419
OFFSET_KEY = OFFSET_ORG_KEY.lower()
2520
INSET_KEY = INSET_ORG_KEY.lower()
21+
DURATION_KEY = DURATION_ORG_KEY.lower()
2622

2723
TEMPORAL_KEYS = {ONSET_KEY, OFFSET_KEY, INSET_KEY}

hed/tools/analysis/event_manager.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
""" Manager of events of temporal extent. """
22
import pandas as pd
3+
import bisect
34

45
from hed.errors import HedFileError
56
from hed.models import HedString
@@ -28,7 +29,6 @@ def __init__(self, input_data, hed_schema, extra_defs=None):
2829
are separated from the rest of the annotations, which are contained in self.hed_strings.
2930
3031
"""
31-
3232
self.event_list = [[] for _ in range(len(input_data.dataframe))]
3333
self.hed_schema = hed_schema
3434
self.input_data = input_data
@@ -56,11 +56,26 @@ def _create_event_list(self, input_data):
5656
onset_dict = {} # Temporary dictionary keeping track of temporal events that haven't ended yet.
5757
for event_index, hed in enumerate(hed_strings):
5858
self._extract_temporal_events(hed, event_index, onset_dict)
59+
self._extract_duration_events(hed, event_index)
5960
# Now handle the events that extend to end of list
6061
for item in onset_dict.values():
6162
item.set_end(len(self.onsets), None)
6263
self.hed_strings = hed_strings
6364

65+
def _extract_duration_events(self, hed, event_index):
66+
groups = hed.find_top_level_tags(anchor_tags={DefTagNames.DURATION_KEY})
67+
to_remove = []
68+
for duration_tag, group in groups:
69+
start_time = self.onsets[event_index]
70+
new_event = TemporalEvent(group, event_index, start_time)
71+
end_time = new_event.end_time
72+
# Todo: This may need updating. end_index==len(self.onsets) in the edge case
73+
end_index = bisect.bisect_right(self.onsets, end_time)
74+
new_event.set_end(end_index, end_time)
75+
self.event_list[event_index].append(new_event)
76+
to_remove.append(group)
77+
hed.remove(to_remove)
78+
6479
def _extract_temporal_events(self, hed, event_index, onset_dict):
6580
""" Extract the temporal events and remove them from the other HED strings.
6681
@@ -77,18 +92,19 @@ def _extract_temporal_events(self, hed, event_index, onset_dict):
7792
return
7893
group_tuples = hed.find_top_level_tags(anchor_tags={DefTagNames.ONSET_KEY, DefTagNames.OFFSET_KEY},
7994
include_groups=2)
95+
8096
to_remove = []
81-
for tup in group_tuples:
82-
anchor_tag = tup[1].find_def_tags(recursive=False, include_groups=0)[0]
97+
for def_tag, group in group_tuples:
98+
anchor_tag = group.find_def_tags(recursive=False, include_groups=0)[0]
8399
anchor = anchor_tag.extension.lower()
84-
if anchor in onset_dict or tup[0].short_base_tag.lower() == DefTagNames.OFFSET_KEY:
100+
if anchor in onset_dict or group.short_base_tag.lower() == DefTagNames.OFFSET_KEY:
85101
temporal_event = onset_dict.pop(anchor)
86102
temporal_event.set_end(event_index, self.onsets[event_index])
87-
if tup[0] == DefTagNames.ONSET_KEY:
88-
new_event = TemporalEvent(tup[1], event_index, self.onsets[event_index])
103+
if def_tag == DefTagNames.ONSET_KEY:
104+
new_event = TemporalEvent(group, event_index, self.onsets[event_index])
89105
self.event_list[event_index].append(new_event)
90106
onset_dict[anchor] = new_event
91-
to_remove.append(tup[1])
107+
to_remove.append(group)
92108
hed.remove(to_remove)
93109

94110
def unfold_context(self, remove_types=[]):

hed/tools/analysis/temporal_event.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ def _split_group(self, contents):
4040
to_remove.append(item)
4141
elif item.short_base_tag.lower() == "duration":
4242
to_remove.append(item)
43-
self.end_time = self.start_time + float(item.extension.lower()) # Will need to be fixed for units
43+
self.end_time = self.start_time + item.value_as_default_unit()
44+
# We don't want the empty group
45+
contents = contents.get_first_group()
4446
elif item.short_base_tag.lower() == "def":
4547
self.anchor = item.short_tag
4648
contents.remove(to_remove)

tests/tools/analysis/test_event_manager.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,19 @@ def test_onset_ordering_bad(self):
107107

108108
def test_duration_context(self):
109109
df = pd.DataFrame({'onset': [1, 2, 3, 4, 5],
110-
'HED': ['(Duration/4.0 s, Black)', '(Duration/2 s, Red)', 'Blue', 'n/a', 'Label/1']})
110+
'HED': ['(Duration/4.0 s, (Black))', '(Duration/2 s, (Red))', 'Blue', 'n/a', 'Label/1']})
111111
manager = EventManager(TabularInput(df), self.schema)
112112
hed, base, context = manager.unfold_context()
113113
pass
114114

115+
def test_duration_context2(self):
116+
df = pd.DataFrame({'onset': [1, 2, 3, 4, 5],
117+
'HED': ['(Duration/5.0 s, (Black))', '(Duration/2 s, (Red))', 'Blue', 'n/a', 'Label/1']})
118+
manager = EventManager(TabularInput(df), self.schema)
119+
hed, base, context = manager.unfold_context()
120+
pass
121+
122+
115123

116124
if __name__ == '__main__':
117125
unittest.main()

0 commit comments

Comments
 (0)