@@ -10,11 +10,11 @@ class XDFImport():
1010 Read an XDF file and enable to export stream in a convenient format (e.g., an EEG stream into an mne.Raw instance).
1111
1212 Arguments:
13- file_path: Path to LSL data (i.e., XDF file ). Can be absolute or relative.
13+ file_path: Path to XDF file ( LSL data recorded with LabRecorder ). Can be absolute or relative.
1414 stream_type: Define which type of stream the user is looking to convert.
1515 stream_matches: List of the stream index(es) in the XDF the user wishes to convert (can be `str` which the class will try to match to the name of an existing stream or an `int` which will be interpreted as such). Do not set to convert all of the request type
16+ mne_type_map: Dict to map stream types to mne channel types
1617 scale: Scaling factor or 'auto' for automatic scaling, None for no scaling.
17- save_FIF_path: Boolean indicating whether to save the converted data to FIF format.
1818 """
1919
2020 file_path : str
@@ -25,18 +25,16 @@ class XDFImport():
2525
2626 def __init__ (self ,
2727 file_path : str ,
28- stream_type : str = 'EEG' ,
29- stream_matches : list = None ,
28+ select_type : str = None ,
29+ select_matches : list = None ,
3030 mne_type_map : dict = None ,
3131 scale : float | str = None ,
32- save_FIF_path : bool = None ,
3332 verbose : bool = False ,
3433 convert_to_mne : bool = True ,
3534 ):
3635
3736 self .file_path = file_path
3837 self .scale = scale
39- self .save_FIF_path = save_FIF_path
4038
4139 self .selected_stream_indices = []
4240 self .map_id_to_idx = {}
@@ -48,44 +46,74 @@ def __init__(self,
4846
4947 self .available_streams = [XDFStream (stream , mne_type_map = mne_type_map ) for stream in streams ]
5048
51-
52- if verbose :
53- self .print_available_streams ()
54-
5549 self .map_streams ()
5650
5751 # Prepare the "selected_streams" list
58- if stream_matches is None :
59- self .select_streams_by_type ( stream_type )
52+ if select_matches is not None :
53+ self .select_streams_by_matches ( select_matches )
6054 else :
61- self .select_streams_by_matches (stream_matches )
55+ self .select_streams_by_type (select_type )
56+
57+ if verbose :
58+ print (self )
6259
6360 # Create MNE objects
6461 if convert_to_mne :
6562 self .convert_streams_to_mne ()
6663
64+ @property
65+ def raws_dict (self ):
66+ ret = dict ()
67+ for stream in self .selected_data_streams :
68+ ret [stream .name ] = stream .raw
69+ return ret
70+
71+ @property
72+ def raws (self ):
73+ return [stream .raw for stream in self .selected_data_streams ]
74+
75+ @property
76+ def annotations_dict (self ):
77+ ret = dict ()
78+ for stream in self .selected_markers_streams :
79+ ret [stream .name ] = stream .annotations
80+ return ret
81+
82+ @property
83+ def annotations (self ):
84+ return [stream .annotations for stream in self .selected_markers_streams ]
85+
86+ @property
87+ def annotations_flat (self ):
88+ ret = []
89+ for x in self .annotations :
90+ ret += x
91+ return ret
92+
6793 @property
6894 def selected_streams (self ):
6995 return [self .available_streams [idx ] for idx in self .selected_stream_indices ]
7096
97+ @property
98+ def selected_data_streams (self ):
99+ return [self .available_streams [idx ] for idx in self .selected_stream_indices if self .available_streams [idx ].is_mne_raw_compatible ]
100+
101+ @property
102+ def selected_markers_streams (self ):
103+ return [self .available_streams [idx ] for idx in self .selected_stream_indices if self .available_streams [idx ].is_mne_annotations_compatible ]
104+
71105 @property
72106 def selected_stream_names (self ):
73107 return [stream .name for stream in self .selected_streams ]
74108
75109 @property
76- def raw_all (self ):
77- ret = dict ()
78- for stream in self .selected_streams :
79- ret [stream .name ] = stream .raw
80- return ret
110+ def selected_data_stream_names (self ):
111+ return [stream .name for stream in self .selected_data_streams ]
112+
113+ @property
114+ def selected_markers_stream_names (self ):
115+ return [stream .name for stream in self .selected_markers_streams ]
81116
82- def print_available_streams (self ):
83- print (f"List of available streams in XDF file { self .file_path } :" )
84- for stream in self .available_streams :
85- print (f" Stream id { stream .id } of type '{ stream .type } ' with name '{ stream .name } '" )
86- print (f" Channel names: { ',' .join (stream .ch_names )} " )
87- print (f" Channel types: { ',' .join (stream .ch_types )} " )
88-
89117 def get_streams_for_type (self , stream_type : str ):
90118 return [stream for stream in self .available_streams if stream .type == stream_type ]
91119
@@ -113,8 +141,13 @@ def select_streams_by_type(self, stream_type: str) -> list:
113141
114142 if self .verbose :
115143 print (f"Looking for streams of type '{ stream_type } '" )
116-
117- self .selected_stream_indices = self .get_stream_indices_for_type (stream_type )
144+
145+ if stream_type is not None :
146+ self .selected_stream_indices = self .get_stream_indices_for_type (stream_type )
147+ else :
148+ # Use all the mne raw compatible
149+ # TODO this if is complicated
150+ self .selected_stream_indices = [idx for idx , stream in enumerate (self .available_streams ) if stream .is_mne_compatible ]
118151
119152 # Assert that we have found at least one real stream of selected type
120153 if len (self .selected_stream_indices ) == 0 :
@@ -156,7 +189,7 @@ def convert_streams_to_mne(self):
156189 """
157190
158191 # Find if all the stream have unique names (true if any stream name is duplicated)
159- names = [ stream . name for stream in self .selected_streams ]
192+ names = self .selected_stream_names
160193
161194 for stream in self .selected_streams :
162195 if self .verbose :
@@ -168,18 +201,14 @@ def convert_streams_to_mne(self):
168201
169202 stream .convert_to_mne (self .scale , append_stream_id = has_duplicate_names )
170203
171- # Save file is asked too
172- if self .save_FIF_path is not None :
173- stream .save_fif_file (self .save_FIF_path )
174-
175204 if self .verbose :
176205 print ("Convertion done." )
177206
178- def save_fif_files (self , dir_path ):
179- return [stream .save_fif_file (dir_path ) for stream in self .selected_streams ]
207+ def save_to_fif_files (self , dir_path ):
208+ return [stream .save_to_fif_file (dir_path ) for stream in self .selected_data_streams ]
180209
181210 def rename_channels (self , new_names ):
182- return [stream .rename_channels (new_names ) for stream in self .selected_streams ]
211+ return [stream .rename_channels (new_names ) for stream in self .selected_data_streams ]
183212
184213 def set_montage (self , montage ):
185214 """
@@ -190,12 +219,22 @@ def set_montage(self, montage):
190219 montage: A path to a local Dig montage or a mne standard montage.
191220 """
192221 if self .verbose or True :
193- print (f"Setting '{ montage } ' as the montage for streams: { ',' .join (self .selected_stream_names )} " )
222+ print (f"Setting '{ montage } ' as the montage for streams: { ',' .join (self .selected_data_stream_names )} " )
194223
195224
196- for stream in self .selected_streams :
225+ for stream in self .selected_data_streams :
197226 try :
198227 stream .set_montage (montage )
199228 except ValueError as e :
200229 warnings .warn (f"Invalid montage given to mne.set_montage(): { montage } " )
201230 raise e
231+
232+ def __str__ (self ):
233+ available_streams_str = "\n " .join ([str (stream ) for stream in self .available_streams ])
234+ selected_streams_str = "," .join ([stream .name for stream in self .selected_streams ])
235+ return f"""XDFImport with { len (self .available_streams )} available streams and { len (self .selected_streams )} selected streams (loaded from { self .file_path } )
236+ Available streams:
237+ { available_streams_str }
238+ Selected streams: [{ selected_streams_str } ]
239+ """
240+
0 commit comments