@@ -53,18 +53,21 @@ class IntanRawIO(BaseRawIO):
5353 extension. Additionally it functions with RHS v 1.0 and RHD 1.0, 1.1, 1.2, 1.3, 2.0,
5454 3.0, and 3.1 files.
5555
56+ * The reader can handle three file formats 'header-attached', 'one-file-per-signal' and
57+ 'one-file-per-channel'.
58+
5659 * Intan files contain amplifier channels labeled 'A', 'B' 'C' or 'D'
5760 depending on the port in which they were recorded along with the following
58- additional channels .
61+ additional streams .
5962 0: 'RHD2000' amplifier channel
6063 1: 'RHD2000 auxiliary input channel',
6164 2: 'RHD2000 supply voltage channel',
6265 3: 'USB board ADC input channel',
6366 4: 'USB board digital input channel',
6467 5: 'USB board digital output channel'
6568
66- * Due to the structure of the digital input and output channels these can be accessed
67- as one long vector, which must be post-processed.
69+ * For the "header-attached" and "one-file-per-signal" formats, the structure of the digital input and output channels is
70+ one long vector, which must be post-processed to extract individual digital channel information. See the intantech website for more information on performing this post-processing .
6871
6972 Examples
7073 --------
@@ -511,7 +514,6 @@ def read_rhs(filename, file_format: str):
511514
512515 # 0: RHS2000 amplifier channel.
513516 for chan_info in channels_by_type [0 ]:
514- name = chan_info ["native_channel_name" ]
515517 chan_info ["sampling_rate" ] = sr
516518 chan_info ["units" ] = "uV"
517519 chan_info ["gain" ] = 0.195
@@ -525,6 +527,7 @@ def read_rhs(filename, file_format: str):
525527 chan_info ["dtype" ] = "int16"
526528 ordered_channels .append (chan_info )
527529 if file_format == "header-attached" :
530+ name = chan_info ["native_channel_name" ]
528531 data_dtype += [(name , "uint16" , BLOCK_SIZE )]
529532 else :
530533 data_dtype [0 ] = "int16"
@@ -533,8 +536,8 @@ def read_rhs(filename, file_format: str):
533536 # if we have dc amp we need to grab the correct number of channels
534537 channel_number_dict [10 ] = channel_number_dict [0 ]
535538 for chan_info in channels_by_type [0 ]:
536- name = chan_info ["native_channel_name" ]
537539 chan_info_dc = dict (chan_info )
540+ name = chan_info ["native_channel_name" ]
538541 chan_info_dc ["native_channel_name" ] = name + "_DC"
539542 chan_info_dc ["sampling_rate" ] = sr
540543 chan_info_dc ["units" ] = "mV"
@@ -553,8 +556,8 @@ def read_rhs(filename, file_format: str):
553556 if file_format != "one-file-per-channel" :
554557 channel_number_dict [11 ] = channel_number_dict [0 ] # should be one stim / amplifier channel
555558 for chan_info in channels_by_type [0 ]:
556- name = chan_info ["native_channel_name" ]
557559 chan_info_stim = dict (chan_info )
560+ name = chan_info ["native_channel_name" ]
558561 chan_info_stim ["native_channel_name" ] = name + "_STIM"
559562 chan_info_stim ["sampling_rate" ] = sr
560563 # stim channel are complicated because they are coded
@@ -576,43 +579,51 @@ def read_rhs(filename, file_format: str):
576579
577580 # 3: Analog input channel.
578581 # 4: Analog output channel.
579- for sig_type in [
580- 3 ,
581- 4 ,
582- ]:
582+ for sig_type in [3 , 4 ]:
583583 for chan_info in channels_by_type [sig_type ]:
584- name = chan_info ["native_channel_name" ]
585584 chan_info ["sampling_rate" ] = sr
586585 chan_info ["units" ] = "V"
587586 chan_info ["gain" ] = 0.0003125
588587 chan_info ["offset" ] = - 32768 * 0.0003125
589588 chan_info ["dtype" ] = "uint16"
590589 ordered_channels .append (chan_info )
591590 if file_format == "header-attached" :
591+ name = chan_info ["native_channel_name" ]
592592 data_dtype += [(name , "uint16" , BLOCK_SIZE )]
593593 else :
594594 data_dtype [sig_type ] = "uint16"
595595
596596 # 5: Digital input channel.
597597 # 6: Digital output channel.
598598 for sig_type in [5 , 6 ]:
599- if len (channels_by_type [sig_type ]) > 0 :
600- name = {5 : "DIGITAL-IN" , 6 : "DIGITAL-OUT" }[sig_type ]
601- chan_info = channels_by_type [sig_type ][0 ]
602- # So currently until we have get_digitalsignal_chunk we need to do a tiny hack to
603- # make this memory map work correctly. So since our digital data is not organized
604- # by channel like analog/ADC are we have to overwrite the native name to create
605- # a single permanent name that we can find with channel id
606- chan_info ["native_channel_name" ] = name # overwite to allow memmap to work
607- chan_info ["sampling_rate" ] = sr
608- chan_info ["units" ] = "TTL" # arbitrary units TTL for logic
609- chan_info ["gain" ] = 1.0
610- chan_info ["offset" ] = 0.0
611- chan_info ["dtype" ] = "uint16"
612- ordered_channels .append (chan_info )
613- if file_format == "header-attached" :
614- data_dtype += [(name , "uint16" , BLOCK_SIZE )]
615- else :
599+ if file_format in ["header-attached" , "one-file-per-signal" ]:
600+ if len (channels_by_type [sig_type ]) > 0 :
601+ name = {5 : "DIGITAL-IN" , 6 : "DIGITAL-OUT" }[sig_type ]
602+ chan_info = channels_by_type [sig_type ][0 ]
603+ # So currently until we have get_digitalsignal_chunk we need to do a tiny hack to
604+ # make this memory map work correctly. So since our digital data is not organized
605+ # by channel like analog/ADC are we have to overwrite the native name to create
606+ # a single permanent name that we can find with channel id
607+ chan_info ["native_channel_name" ] = name
608+ chan_info ["sampling_rate" ] = sr
609+ chan_info ["units" ] = "TTL" # arbitrary units TTL for logic
610+ chan_info ["gain" ] = 1.0
611+ chan_info ["offset" ] = 0.0
612+ chan_info ["dtype" ] = "uint16"
613+ ordered_channels .append (chan_info )
614+ if file_format == "header-attached" :
615+ data_dtype += [(name , "uint16" , BLOCK_SIZE )]
616+ else :
617+ data_dtype [sig_type ] = "uint16"
618+ # This case behaves as a binary with 0 and 1 coded as uint16
619+ elif file_format == "one-file-per-channel" :
620+ for chan_info in channels_by_type [sig_type ]:
621+ chan_info ["sampling_rate" ] = sr
622+ chan_info ["units" ] = "TTL"
623+ chan_info ["gain" ] = 1.0
624+ chan_info ["offset" ] = 0.0
625+ chan_info ["dtype" ] = "uint16"
626+ ordered_channels .append (chan_info )
616627 data_dtype [sig_type ] = "uint16"
617628
618629 if global_info ["notch_filter_mode" ] == 2 and global_info ["major_version" ] >= V ("3.0" ):
@@ -788,7 +799,6 @@ def read_rhd(filename, file_format: str):
788799
789800 # 0: RHD2000 amplifier channel
790801 for chan_info in channels_by_type [0 ]:
791- name = chan_info ["native_channel_name" ]
792802 chan_info ["sampling_rate" ] = sr
793803 chan_info ["units" ] = "uV"
794804 chan_info ["gain" ] = 0.195
@@ -801,34 +811,35 @@ def read_rhd(filename, file_format: str):
801811 ordered_channels .append (chan_info )
802812
803813 if file_format == "header-attached" :
814+ name = chan_info ["native_channel_name" ]
804815 data_dtype += [(name , "uint16" , BLOCK_SIZE )]
805816 else :
806817 data_dtype [0 ] = "int16"
807818
808819 # 1: RHD2000 auxiliary input channel
809820 for chan_info in channels_by_type [1 ]:
810- name = chan_info ["native_channel_name" ]
811821 chan_info ["sampling_rate" ] = sr / 4.0
812822 chan_info ["units" ] = "V"
813823 chan_info ["gain" ] = 0.0000374
814824 chan_info ["offset" ] = 0.0
815825 chan_info ["dtype" ] = "uint16"
816826 ordered_channels .append (chan_info )
817827 if file_format == "header-attached" :
828+ name = chan_info ["native_channel_name" ]
818829 data_dtype += [(name , "uint16" , BLOCK_SIZE // 4 )]
819830 else :
820831 data_dtype [1 ] = "uint16"
821832
822833 # 2: RHD2000 supply voltage channel
823834 for chan_info in channels_by_type [2 ]:
824- name = chan_info ["native_channel_name" ]
825835 chan_info ["sampling_rate" ] = sr / BLOCK_SIZE
826836 chan_info ["units" ] = "V"
827837 chan_info ["gain" ] = 0.0000748
828838 chan_info ["offset" ] = 0.0
829839 chan_info ["dtype" ] = "uint16"
830840 ordered_channels .append (chan_info )
831841 if file_format == "header-attached" :
842+ name = chan_info ["native_channel_name" ]
832843 data_dtype += [(name , "uint16" )]
833844 else :
834845 data_dtype [2 ] = "uint16"
@@ -847,7 +858,6 @@ def read_rhd(filename, file_format: str):
847858
848859 # 3: USB board ADC input channel
849860 for chan_info in channels_by_type [3 ]:
850- name = chan_info ["native_channel_name" ]
851861 chan_info ["sampling_rate" ] = sr
852862 chan_info ["units" ] = "V"
853863 if global_info ["eval_board_mode" ] == 0 :
@@ -862,32 +872,41 @@ def read_rhd(filename, file_format: str):
862872 chan_info ["dtype" ] = "uint16"
863873 ordered_channels .append (chan_info )
864874 if file_format == "header-attached" :
875+ name = chan_info ["native_channel_name" ]
865876 data_dtype += [(name , "uint16" , BLOCK_SIZE )]
866877 else :
867878 data_dtype [3 ] = "uint16"
868879
869880 # 4: USB board digital input channel
870881 # 5: USB board digital output channel
871882 for sig_type in [4 , 5 ]:
872- # Now these are included so that user can obtain the
873- # dig signals and process them at the same time
874- if len (channels_by_type [sig_type ]) > 0 :
875- name = {4 : "DIGITAL-IN" , 5 : "DIGITAL-OUT" }[sig_type ]
876- chan_info = channels_by_type [sig_type ][0 ]
877- # So currently until we have get_digitalsignal_chunk we need to do a tiny hack to
878- # make this memory map work correctly. So since our digital data is not organized
879- # by channel like analog/ADC are we have to overwrite the native name to create
880- # a single permanent name that we can find with channel id
881- chan_info ["native_channel_name" ] = name # overwite to allow memmap to work
882- chan_info ["sampling_rate" ] = sr
883- chan_info ["units" ] = "TTL" # arbitrary units TTL for logic
884- chan_info ["gain" ] = 1.0
885- chan_info ["offset" ] = 0.0
886- chan_info ["dtype" ] = "uint16"
887- ordered_channels .append (chan_info )
888- if file_format == "header-attached" :
889- data_dtype += [(name , "uint16" , BLOCK_SIZE )]
890- else :
883+ if file_format in ["header-attached" , "one-file-per-signal" ]:
884+ if len (channels_by_type [sig_type ]) > 0 :
885+ name = {4 : "DIGITAL-IN" , 5 : "DIGITAL-OUT" }[sig_type ]
886+ chan_info = channels_by_type [sig_type ][0 ]
887+ # So currently until we have get_digitalsignal_chunk we need to do a tiny hack to
888+ # make this memory map work correctly. So since our digital data is not organized
889+ # by channel like analog/ADC are we have to overwrite the native name to create
890+ # a single permanent name that we can find with channel id
891+ chan_info ["native_channel_name" ] = name
892+ chan_info ["sampling_rate" ] = sr
893+ chan_info ["units" ] = "TTL" # arbitrary units TTL for logic
894+ chan_info ["gain" ] = 1.0
895+ chan_info ["offset" ] = 0.0
896+ chan_info ["dtype" ] = "uint16"
897+ ordered_channels .append (chan_info )
898+ if file_format == "header-attached" :
899+ data_dtype += [(name , "uint16" , BLOCK_SIZE )]
900+ else :
901+ data_dtype [sig_type ] = "uint16"
902+ elif file_format == "one-file-per-channel" :
903+ for chan_info in channels_by_type [sig_type ]:
904+ chan_info ["sampling_rate" ] = sr
905+ chan_info ["units" ] = "TTL"
906+ chan_info ["gain" ] = 1.0
907+ chan_info ["offset" ] = 0.0
908+ chan_info ["dtype" ] = "uint16"
909+ ordered_channels .append (chan_info )
891910 data_dtype [sig_type ] = "uint16"
892911
893912 if global_info ["notch_filter_mode" ] == 2 and version >= V ("3.0" ):
0 commit comments