88import numba as nb
99import numpy as np
1010
11- import explorepy .tools
1211from explorepy ._exceptions import FletcherError
1312
1413
@@ -44,6 +43,7 @@ class PACKET_ID(IntEnum):
4443 PUSHMARKER = 194
4544 CALIBINFO = 195
4645 CALIBINFO_USBC = 197
46+ CALIBINFO_PRO = 196
4747 TRIGGER_OUT = 177 # Trigger-out of Explore device
4848 TRIGGER_IN = 178 # Trigger-in to Explore device
4949 VERSION_INFO = 199
@@ -226,15 +226,19 @@ def int32_to_status(data):
226226 }
227227 return status
228228
229- def calculate_impedance (self , imp_calib_info ):
229+ def calculate_impedance (self , imp_calib_info , index = None ):
230230 """calculate impedance with the help of impedance calibration info
231231
232232 Args:
233233 imp_calib_info (dict): dictionary of impedance calibration info including slope, offset and noise level
234234
235235 """
236- scale = imp_calib_info ["slope" ]
237- offset = imp_calib_info ["offset" ]
236+ if index is None :
237+ scale = imp_calib_info ["slope" ]
238+ offset = imp_calib_info ["offset" ]
239+ else :
240+ scale = imp_calib_info ["slope" ][index ]
241+ offset = imp_calib_info ["offset" ][index ]
238242 self .imp_data = np .round (
239243 (self .get_ptp ()
240244 - imp_calib_info ["noise_level" ]) * scale / 1.0e6 - offset ,
@@ -576,13 +580,6 @@ def __init__(self, timestamp, payload, time_offset=0):
576580 super ().__init__ (timestamp , payload , time_offset )
577581
578582 def _convert (self , bin_data ):
579- precise_ts = np .ndarray .item (
580- np .frombuffer (bin_data ,
581- dtype = np .dtype (np .uint32 ).newbyteorder ("<" ),
582- count = 1 ,
583- offset = 0 ))
584- scale = 100000 if explorepy .tools .is_explore_pro_device () else 10000
585- self .timestamp = precise_ts / scale + self ._time_offset
586583 code = np .ndarray .item (
587584 np .frombuffer (bin_data ,
588585 dtype = np .dtype (np .uint16 ).newbyteorder ("<" ),
@@ -710,35 +707,61 @@ def __str__(self):
710707
711708
712709class CalibrationInfoBase (Packet ):
713- @abc .abstractmethod
714- def _convert (self , bin_data , offset_multiplier = 0.001 ):
715- slope = np .frombuffer (bin_data ,
716- dtype = np .dtype (np .uint16 ).newbyteorder ("<" ),
717- count = 1 ,
718- offset = 0 ).item ()
719- self .slope = slope * 10.0
720- offset = np .frombuffer (bin_data ,
721- dtype = np .dtype (np .uint16 ).newbyteorder ("<" ),
722- count = 1 ,
723- offset = 2 ).item ()
724- self .offset = offset * offset_multiplier
710+ """Base class for calibration packets"""
711+
712+ channels = 4
713+ offset_multiplier = 0.001
714+
715+ def __init__ (self , timestamp , payload , time_offset = 0 ):
716+ # Must exist before Packet.__init__ calls _convert()
717+ self .slope = []
718+ self .offset = []
719+ super ().__init__ (timestamp , payload , time_offset )
720+
721+ def _convert (self , bin_data ):
722+ dtype_u16 = np .dtype ("<u2" )
723+ calib_pair_count = len (bin_data ) // 4
724+ for i in range (self .channels ):
725+ if calib_pair_count <= i :
726+ # Copy first value
727+ self .slope .append (self .slope [0 ])
728+ self .offset .append (self .offset [0 ])
729+ continue
730+ base = i * 4
731+
732+ slope = np .frombuffer (
733+ bin_data ,
734+ dtype = dtype_u16 ,
735+ count = 1 ,
736+ offset = base
737+ ).item ()
738+ self .slope .append (slope * 10.0 )
739+
740+ offset = np .frombuffer (
741+ bin_data ,
742+ dtype = dtype_u16 ,
743+ count = 1 ,
744+ offset = base + 2
745+ ).item ()
746+ self .offset .append (offset * self .offset_multiplier )
725747
726748 def get_info (self ):
727- """Get calibration info"""
728749 return {"slope" : self .slope , "offset" : self .offset }
729750
730751 def __str__ (self ):
731- return "calibration info: slope = " + str ( self .slope ) + " \t offset = " + str ( self .offset )
752+ return f "calibration info: slope = { self .slope } \t offset = { self .offset } "
732753
733754
734755class CalibrationInfo (CalibrationInfoBase ):
735- def _convert (self , bin_data ):
736- super ()._convert (bin_data , offset_multiplier = 0.001 )
756+ offset_multiplier = 0.001
737757
738758
739759class CalibrationInfo_USBC (CalibrationInfoBase ):
740- def _convert (self , bin_data ):
741- super ()._convert (bin_data , offset_multiplier = 0.01 )
760+ offset_multiplier = 0.01
761+
762+
763+ class CalibrationInfoPro (CalibrationInfoBase ):
764+ offset_multiplier = 0.01
742765
743766
744767class BleImpedancePacket (EEG98_USBC ):
@@ -759,6 +782,19 @@ def populate_packet_with_data(self, ble_packet_list):
759782 data_array = np .concatenate ((data_array , data ), axis = 1 )
760783 self .data = data_array
761784
785+ def resize_packet (self , full_data , index ):
786+ self .data = full_data [index * 8 : index * 8 + 8 , :]
787+
788+ def populate_data_1d (self , ble_packet_list ):
789+ data_array = None
790+ for i in range (len (ble_packet_list )):
791+ _ , data = ble_packet_list [i ].get_data ()
792+ if data_array is None :
793+ data_array = data
794+ else :
795+ data_array = np .concatenate ((data_array , data ), axis = 0 )
796+ self .data = data_array
797+
762798
763799class VersionInfoPacket (Packet ):
764800 def __init__ (self , timestamp , payload , time_offset = 0 ):
@@ -800,6 +836,7 @@ def __str__(self):
800836 PACKET_ID .CMDSTAT : CommandStatus ,
801837 PACKET_ID .CALIBINFO : CalibrationInfo ,
802838 PACKET_ID .CALIBINFO_USBC : CalibrationInfo_USBC ,
839+ PACKET_ID .CALIBINFO_PRO : CalibrationInfoPro ,
803840 PACKET_ID .PUSHMARKER : PushButtonMarker ,
804841 PACKET_ID .TRIGGER_IN : TriggerIn ,
805842 PACKET_ID .TRIGGER_OUT : TriggerOut ,
0 commit comments