U
    f»{j¿L  ã                	   @   sÔ   d Z ddlmZ ddlZddlmZmZmZ ddl	m
Z
 ddlmZ dd	lmZmZmZmZ dd
lmZ ddlmZ ddlmZ ddlmZmZmZmZmZ ddd„Zeddd„ƒZdd„ ZeG dd„ deƒƒZ dS )z*Conversion tool from Neuroscan CNT to FIF.é    )ÚpathNé   )ÚwarnÚfill_docÚ_check_option)Ú_topo_to_sphereé   )ÚFIFF)Ú_mult_cal_oneÚ_find_channelsÚ_create_chsÚread_str)Ú_empty_info)ÚBaseRaw)ÚAnnotationsé   )Ú
_read_teegÚ_get_event_parserÚ_session_date_2_meas_dateÚ$_compute_robust_event_table_positionÚCNTEventType3Úint16c              	   C   sh  d}d}|fdd„}t | dƒ�R}| |¡ tj| d¡dd�\}| |¡ tj| d¡dd�\}t||d	�}W 5 Q R X t | dƒ�}t||d
�}	W 5 Q R X t|	jd�}
t | dƒ� }| |d ¡ | |	j	¡}W 5 Q R X t
|
|ƒƒ}|søtt
ƒ t
ƒ t
ƒ dƒS |tjdd„ |D ƒtd�|t|d ƒ|d�}tjdd„ |D ƒtd�}t dd„ |D ƒ¡}t|| ||dd�S dS )aU  CNT Annotation File Reader.

    This method opens the .cnt files, searches all the metadata to construct
    the annotations and parses the event table. Notice that CNT files, can
    point to a different file containing the events. This case when the
    event table is separated from the main .cnt is not supported.

    Parameters
    ----------
    fname: str
        path to cnt file containing the annotations.
    data_format : 'int16' | 'int32'
        Defines the data format the data is read in.

    Returns
    -------
    annot : instance of Annotations
        The annotations.
    ér  éx  c                 S   sH   |dkrdnd}|t kr$| || 9 } | d d|  }|||  }|d S )Nr   r   é   é„  éK   r   )r   )ÚoffsetÚ
n_channelsÚ
event_typeÚdata_formatÚn_bytesZ
event_time© r"   úM/var/www/html/bwave/python/venv/lib/python3.8/site-packages/mne/io/cnt/cnt.pyÚ_translating_function0   s    z4_read_annotations_cnt.<locals>._translating_functionÚrbr   ú<u2)Údtype©Úfidr    )Zteeg_offset)r   é	   Nc                 S   s   g | ]
}|j ‘qS r"   )ZOffset©Ú.0Úer"   r"   r#   Ú
<listcomp>Q   s     z)_read_annotations_cnt.<locals>.<listcomp>r   )r   r   r    c                 S   s   g | ]}t |d dƒ‘qS )ZLatencyg        )Úgetattrr+   r"   r"   r#   r.   V   s     c                 S   s   g | ]}t |jƒ‘qS r"   )ÚstrZStimTyper+   r"   r"   r#   r.   Y   s     )ÚonsetÚdurationÚdescriptionZ	orig_time)ÚopenÚseekÚnpZ
frombufferÚreadr   r   r   r   Útotal_lengthÚlistr   ÚarrayÚfloatÚtype)Úfnamer    ZSETUP_NCHANNELS_OFFSETZSETUP_RATE_OFFSETr$   r)   r   ÚsfreqZevent_table_posZteegZevent_parserÚbufferZ	my_eventsr1   r2   r3   r"   r"   r#   Ú_read_annotations_cnt   sL    ÿ
	

 ÿÿ
üÿýr@   r"   Úautoúmm/dd/yyFc	           	      C   s   t | ||||||||d�	S )a-
  Read CNT data as raw object.

    .. Note::
        2d spatial coordinates (x, y) for EEG channels are read from the file
        header and fit to a sphere to compute corresponding z-coordinates.
        If channels assigned as EEG channels have locations
        far away from the head (i.e. x and y coordinates don't fit to a
        sphere), all the channel locations will be distorted
        (all channels that are not assigned with keywords ``eog``, ``ecg``,
        ``emg`` and ``misc`` are assigned as EEG channels). If you are not
        sure that the channel locations in the header are correct, it is
        probably safer to replace them with :meth:`mne.io.Raw.set_montage`.
        Montages can be created/imported with:

        - Standard montages with :func:`mne.channels.make_standard_montage`
        - Montages for `Compumedics systems <https://compumedicsneuroscan.com/
          scan-acquire-configuration-files/>`_ with
          :func:`mne.channels.read_dig_dat`
        - Other reader functions are listed under *See Also* at
          :class:`mne.channels.DigMontage`

    Parameters
    ----------
    input_fname : str
        Path to the data file.
    eog : list | tuple | 'auto' | 'header'
        Names of channels or list of indices that should be designated
        EOG channels. If 'header', VEOG and HEOG channels assigned in the file
        header are used. If 'auto', channel names containing 'EOG' are used.
        Defaults to empty tuple.
    misc : list | tuple
        Names of channels or list of indices that should be designated
        MISC channels. Defaults to empty tuple.
    ecg : list | tuple | 'auto'
        Names of channels or list of indices that should be designated
        ECG channels. If 'auto', the channel names containing 'ECG' are used.
        Defaults to empty tuple.
    emg : list | tuple
        Names of channels or list of indices that should be designated
        EMG channels. If 'auto', the channel names containing 'EMG' are used.
        Defaults to empty tuple.
    data_format : 'auto' | 'int16' | 'int32'
        Defines the data format the data is read in. If 'auto', it is
        determined from the file header using ``numsamples`` field.
        Defaults to 'auto'.
    date_format : 'mm/dd/yy' | 'dd/mm/yy'
        Format of date in the header. Defaults to 'mm/dd/yy'.
    %(preload)s
    %(verbose)s

    Returns
    -------
    raw : instance of RawCNT.
        The raw data.

    See Also
    --------
    mne.io.Raw : Documentation of attribute and methods.

    Notes
    -----
    .. versionadded:: 0.12
    )ÚeogÚmiscÚecgÚemgr    Údate_formatÚpreloadÚverbose)ÚRawCNT)	Úinput_fnamerC   rD   rE   rF   r    rG   rH   rI   r"   r"   r#   Úread_raw_cnt`   s    C
   þrL   c           /   	   C   s  d}t ƒ }t| ddd���Ž}	|	 d¡ t|	dƒ}
|
 ¡ r@t|
ƒnd}
|	 d¡ t|	dƒ ¡ }t|ƒdkrp|d nd}t|ƒdkrˆ|d	 nd}|	 d
d¡ t|	dƒ}|dkr²tj	}n|dkrÂtj
}ntj}t|	dƒ}|dkrâtj}n|dkròtj}nd}|	 d¡ t|	dƒ}dt|	dƒt|	dƒf }t||ƒ}|	 d¡ tj|	ddd�d }|	 d¡ tj|	ddd�d }|dk�r–|	 d¡ dd„ tj|	dd
d�D ƒ}|	 d¡ tj|	ddd �d }tj|	ddd �d }|	 d!¡ tj|	d"dd�d }|	 d#¡ tj|	d$dd�d }|	 d
d¡ tj|	d$dd�d }t|	|d%�}|	 d&¡ tj|	d'dd�d |d(< ||k �rf|| }n||d)|   }td*|d+d,d-gƒ |d+k�rÖ|dk�s®|||  d.k�rÈtd/ƒ d
}|||  }n|||  }n|d,k�räd
nd0}|||  }tj|	d"dd�d |d1< |d1 dk�r,|d1  |  < nd|d1< tƒ tƒ tƒ tƒ tƒ f\}}}} }!tƒ }"t|ƒD �]<}#|	 |d)|#  ¡ t|	dƒ}$| |$¡ |	 |d)|#  d0 ¡ tj|	d2dd�d �rÆ|" |$¡ |	 |d)|#  d3 ¡ tj|	d$d
d�}%|%d  d	9  < |! |%¡ |	 |d)|#  d4 ¡ | tj|	ddd�d ¡ |	 |d)|#  d5 ¡ tj|	d$dd�d }&|	 |d)|#  d6 ¡ tj|	d$dd�d }'| |'|& d7 d8 ¡ �qdW 5 Q R X t|ƒ}(|dk�rÈ||(d9< |dk�rÚ||(d:< ||
|||d;œ})|d+k�rþt|d<ƒ}|d+k�rt|d=ƒ}|d+k�r&t|d>ƒ}t||tjtj||||ƒ} d?d„ t| ƒD ƒ}*t|!|*ƒ}+t t| ƒdftj¡},|+|,dd…dd@…f< t | |,ƒD ]\}-}.|-j!|.dA� �q�|j!t "|¡||dB� t#|ƒdk�rÐdnt#|ƒ}|(j!|||"|)| dC� dD|(_$|( %¡  |(|fS )EzRead the cnt header.r   r%   r   ©Ú	bufferingé   é   éy   Ú éÿÿÿÿr   r   ÚMÚFÚRÚLNéÍ   z%s %sé
   é   r   r&   ©r'   Úcountr   Úheaderi’  c                 S   s   g | ]}|d kr|‘qS )r   r"   )r,   Úidxr"   r"   r#   r.   Ñ   s    ÿz!_get_cnt_info.<locals>.<listcomp>Úi2i¶  Úi1)r\   i`  ú<i4ie  Zf4r(   iz  z<f4Zcontinuous_secondsr   r    rA   r   Úint32)r   r   zDCould not define the number of bytes automatically. Defaulting to 2.r   Úchannel_offsetÚu1é   é/   é;   éG   g�íµ ÷Æ°>gš™™™™™i@ZlowpassZhighpass)ÚhandÚidÚsexÚ
first_nameÚ	last_nameZEOGZECGZEMGc                 S   s"   g | ]\}}|d  t jkr|‘qS )Z	coil_type)r	   ÚFIFFV_COIL_EEG)r,   r^   Úchr"   r"   r#   r.   +  s    ÿr   )Úloc)Ú	baselinesÚ	n_samplesr!   )Ú	meas_dater3   ÚbadsÚsubject_infoÚchsF)&Údictr4   r5   r   ÚisdigitÚintÚsplitÚlenr	   ZFIFFV_SUBJ_SEX_MALEZFIFFV_SUBJ_SEX_FEMALEZFIFFV_SUBJ_SEX_UNKNOWNZFIFFV_SUBJ_HAND_RIGHTZFIFFV_SUBJ_HAND_LEFTr   r6   Úfromfiler   r   r   r9   ÚrangeÚappendr   r   r   rn   ZFIFFV_EEG_CHÚ	enumerater   ÚfullÚnanÚzipÚupdater:   r0   Z	_unlockedZ_update_redundant)/rK   rC   rE   rF   rD   r    rG   Zdata_offsetÚcnt_infor)   Z
patient_idZpatient_namerm   rl   rk   ri   Zsession_labelZsession_daters   r   r>   Zlowpass_toggleZhighpass_togglerr   Z	lowcutoffZ
highcutoffZevent_offsetÚ	data_sizer!   Zch_namesÚcalsrq   rv   Úposrt   Zch_idxZch_nameZxyZsensitivityÚcalÚinforu   ZeegsZcoordsZlocsro   rp   r"   r"   r#   Ú_get_cnt_info¨   s   














 ÿ
ÿÿ



ÿ    ÿ



$

 ÿ






    ÿ
ÿ  þrŠ   c                       s*   e Zd ZdZd‡ fdd„	Zd	d
„ Z‡  ZS )rJ   a©	  Raw object from Neuroscan CNT file.

    .. Note::
        The channel positions are read from the file header. Channels that are
        not assigned with keywords ``eog``, ``ecg``, ``emg`` and ``misc`` are
        assigned as eeg channels. All the eeg channel locations are fit to a
        sphere when computing the z-coordinates for the channels. If channels
        assigned as eeg channels have locations far away from the head (i.e.
        x and y coordinates don't fit to a sphere), all the channel locations
        will be distorted. If you are not sure that the channel locations in
        the header are correct, it is probably safer to use a (standard)
        montage. See :func:`mne.channels.make_standard_montage`

    Parameters
    ----------
    input_fname : str
        Path to the CNT file.
    eog : list | tuple
        Names of channels or list of indices that should be designated
        EOG channels. If 'auto', the channel names beginning with
        ``EOG`` are used. Defaults to empty tuple.
    misc : list | tuple
        Names of channels or list of indices that should be designated
        MISC channels. Defaults to empty tuple.
    ecg : list | tuple
        Names of channels or list of indices that should be designated
        ECG channels. If 'auto', the channel names beginning with
        ``ECG`` are used. Defaults to empty tuple.
    emg : list | tuple
        Names of channels or list of indices that should be designated
        EMG channels. If 'auto', the channel names beginning with
        ``EMG`` are used. Defaults to empty tuple.
    data_format : 'auto' | 'int16' | 'int32'
        Defines the data format the data is read in. If 'auto', it is
        determined from the file header using ``numsamples`` field.
        Defaults to 'auto'.
    date_format : 'mm/dd/yy' | 'dd/mm/yy'
        Format of date in the header. Defaults to 'mm/dd/yy'.
    %(preload)s
    stim_channel : bool | None
        Add a stim channel from the events. Defaults to None to trigger a
        future warning.

        .. warning:: This defaults to True in 0.18 but will change to False in
                     0.19 (when no stim channel synthesis will be allowed)
                     and be removed in 0.20; migrate code to use
                     :func:`mne.events_from_annotations` instead.

        .. versionadded:: 0.18
    %(verbose)s

    See Also
    --------
    mne.io.Raw : Documentation of attribute and methods.
    r"   rA   rB   FNc
              	      sž   t d|ddgƒ |dkrd}
nd}
t |¡}t|||||||
ƒ\}}|d d g}tt| ƒj|||g|g|d|	d	� |d
 dkr„dnd}|  t||d�¡ d S )NrG   rB   zdd/mm/yyz%d/%m/%y %H:%M:%Sz%m/%d/%y %H:%M:%Srr   r   ry   )Ú	filenamesZ
raw_extrasÚ
last_sampsZorig_formatrI   r!   r   rb   r   )r    )	r   r   ÚabspathrŠ   ÚsuperrJ   Ú__init__Zset_annotationsr@   )ÚselfrK   rC   rD   rE   rF   r    rG   rH   rI   Z_date_formatr‰   r„   rŒ   ©Ú	__class__r"   r#   r�   y  s.    
 ÿ
     þ
ÿzRawCNT.__init__c           "   	   C   s†  | j | d }d| j | kr4|d }	| j | d }
n|}	d}
| j | d }| j | d }| j | d }|dkrrd	nd
}||	 }|| |	 }tdƒ| | | }t||ƒ}|| }t| j| ddd���¶}| d|	d|| |    ¡ t d||¡|	 D �]|}|t||	 ||	 | fƒ }|| }t ||f¡}|dk�sH|| dk�rL|nd}||d k�rf||7 }|| | | }|| }tj	|||d�}|j
||	|fdd�}t ||| f¡}t|ƒD ]0\}}t|| |d | ƒ}||d|	…|f< �q¼d| j | k�r|| } || }!|
| |!… |d< ||||| …f ||< ||  || dd…df 8  < t|dd…||…f ||||ƒ qøW 5 Q R X dS )z>Take a chunk of raw data, multiply by mult or cals, and store.Z
orig_nchanZstim_channelr   Nrc   rq   r!   r   ra   z<i2g    „×—Ar%   r   rM   r   r   r   r[   ÚC)ÚorderrS   )Z_raw_extrasry   Úminr4   Z
_filenamesr5   r6   ZarangeZzerosr|   Zreshaper   Úslicer
   )"r�   Údatar^   ÚfiÚstartÚstopr†   Zmultr   Z
f_channelsZstim_chrc   rq   r!   r'   Ú
chunk_sizeZ	data_leftÚ
block_sizeZs_offsetr)   Zsample_startZsample_stopZn_sampsÚoneZextra_sampsr\   Zn_chunksZsampsÚblockZset_idxÚrowZblock_sliceZ_data_startZ
_data_stopr"   r"   r#   Ú_read_segment_file�  sx    
ÿÿ

ÿÿÿÿ
ÿÿ
ÿ  ÿzRawCNT._read_segment_file)r"   r"   r"   r"   rA   rB   FN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r�   r    Ú__classcell__r"   r"   r‘   r#   rJ   ?  s   8           þrJ   )r   )r"   r"   r"   r"   rA   rB   FN)!r¤   Úosr   Únumpyr6   Úutilsr   r   r   Zchannels.layoutr   Ú	constantsr	   r
   r   r   r   Z	meas_infor   Úbaser   Úannotationsr   Z_utilsr   r   r   r   r   r@   rL   rŠ   rJ   r"   r"   r"   r#   Ú<module>   s.   
H         þG 