o
    e}                     @   s   d Z ddlmZ ddlZddlZddlmZmZmZmZm	Z	m
Z
mZmZmZmZ ddlZddlZddlmZmZmZ ddlmZmZ eeZG dd	 d	ZG d
d dZG dd deZdejde	ee e	e! f  fddZ"dS )a   Read SPE files.

This plugin supports reading files saved in the Princeton Instruments
SPE file format.

Parameters
----------
check_filesize : bool
    The number of frames in the file is stored in the file header. However,
    this number may be wrong for certain software. If this is `True`
    (default), derive the number of frames also from the file size and
    raise a warning if the two values do not match.
char_encoding : str
    Deprecated. Exists for backwards compatibility; use ``char_encoding`` of
    ``metadata`` instead.
sdt_meta : bool
    Deprecated. Exists for backwards compatibility; use ``sdt_control`` of
    ``metadata`` instead.

Methods
-------
.. note::
    Check the respective function for a list of supported kwargs and detailed
    documentation.

.. autosummary::
    :toctree:

    SpePlugin.read
    SpePlugin.iter
    SpePlugin.properties
    SpePlugin.metadata

    )datetimeN)
AnyCallableDictIteratorListMappingOptionalSequenceTupleUnion   )RequestIOModeInitializationError)PluginV3ImagePropertiesc                   @   sx  e Zd ZdZdddddddZi d	d
ddeg ddfdddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,i d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUddVdWdXdYddZZd[Zeej	eej
eejeejeejd\Zg d]Zg d^Zd_gZd`S )aSpecaW  SPE file specification data

    Tuples of (offset, datatype, count), where offset is the offset in the SPE
    file and datatype is the datatype as used in `numpy.fromfile`()

    `data_start` is the offset of actual image data.

    `dtypes` translates SPE datatypes (0...4) to numpy ones, e. g. dtypes[0]
    is dtype("<f") (which is np.float32).

    `controllers` maps the `type` metadata to a human readable name

    `readout_modes` maps the `readoutMode` metadata to something human readable
    although this may not be accurate since there is next to no documentation
    to be found.
    )l   <h)*   <H)i  r   )i  z<Q)i  z<i)i  <f)datatypexdimydimxml_footer_offset	NumFramesfile_header_verNumROI)i  r   ROIsi  ))startxr   )endxr   )groupxr   )startyr   )endyr   )groupyr   
   xDimDet)   r   yDimDet)   r   	VChipXdim)   r   	VChipYdim)   r   Zcontroller_version)r   r   Zlogic_output)r   r   Zamp_high_cap_low_noise)   r   mode)   r   exposure_sec)r'   r   date)   z<10SZdetector_temp)$   r   Zdetector_type)(   r   Zst_diode),   r   Z
delay_time).   r   Zshutter_control)2   r   absorb_live)4   r   Zabsorb_mode)6   r   can_do_virtual_chip)8   r   threshold_min_live):   r   Zthreshold_min_val)<   r   threshold_max_live)@   r   Zthreshold_max_val)B   r   
time_local)   <7Stime_utc)   rH   Z
adc_offset)   r   Zadc_rate)   r   Zadc_type)   r   Zadc_resolution)   r   Zadc_bit_adjust)   r   Zgain)   r   comments)   z<80S   	geometric)iX  r   )i  z<16S)i  z<436S)b   r   )d   r   )f   r   )h   r   )i  r   )i  r   )i  r   )i  r   )i  r   )Z
sw_versionspare_4
XPrePixelsXPostPixels
YPrePixelsYPostPixelsZreadout_timer   typeZclockspeed_usreadout_modeZwindow_sizer   i  )r      r      r2   )znew120 (Type II)zold120 (Type I)ZST130ZST121ZST138zDC131 (PentaMax)zST133 (MicroMax/Roper)zST135 (GPIB)ZVTCCDzST116 (GPIB)zOMA3 (GPIB)ZOMA4)z
full framezframe transferkineticsrY   N)__name__
__module____qualname____doc__basicnpdtypemetadata
data_startZfloat32Zint32Zint16Zuint16Zuint32dtypescontrollersreadout_modes	no_decode rp   rp   CD:\Projects\ConvertPro\env\Lib\site-packages\imageio/plugins/spe.pyr   A   s    	
 #$%&'()*+,-./012345D





r   c                       s0  e Zd ZdZi ddddddddd	dd
dddddddddddddddddddddddZdd d!d"d#ZG d$d% d%Zi d&eded'd(ed)eded(d*ed+eded,de	d-eded.d/e
d0d1ededd2e	d3eded4d5ed6edd2d7d8 d9edd:d;d8 d<eded=d:ed>edd?d@d8 dAededBd=e
dCdDededd fdEd8dFeded5dBe
d0dGeded,dedHededdIe
dJdKededdedLededId=e
d0ededdeeded=dMe
d0ededdeeded/dNe
d0ededMdOe
d0ededOdPe
d0ededPd.e
d0dQdRededSdTdUd8 idVZedWee	 dXeeef fdYdZZedWee	 d[eeef dXee	ef f fd\d]Zed^e	d_e	dXeed`f f fdadbZedhddedee	f fdfdgZ  ZS )iSDTControlSpeca&  Extract metadata written by the SDT-control software

    Some of it is encoded in the comment strings
    (see :py:meth:`parse_comments`). Also, date and time are encoded in a
    peculiar way (see :py:meth:`get_datetime`). Use :py:meth:`extract_metadata`
    to update the metadata dict.
    u   Jänr`   JanFebr   u   Märra   MarAprr0   ZMairS   MayJunr)   Jul   Augr2   Sep	   ZOktr'   OctNov   ZDez   DecstandardZTOCCSLrb   	arbitrary)ZSEQUZSETOZKINEZSEARc                
   @   sz   e Zd ZU dZeed< 	 eed< 	 eege	f ed< 	 e
def ed< 	 edfdededeege	f dee fddZdS )	zSDTControlSpec.CommentDescz>Describe how to extract a metadata entry from a comment stringnslicecvtNscalec                 C   s   || _ || _|| _|| _d S N)r   r   r   r   )selfr   r   r   r   rp   rp   rq   __init__   s   
z#SDTControlSpec.CommentDesc.__init__)rc   rd   re   rf   int__annotations__r   r   strr   r   floatr	   r   rp   rp   rp   rq   CommentDesc   s*   
 r   Zsdt_major_versionrE   D   Zsdt_minor_versionF   Zsdt_controller_namer   Zexposure_timerD   I   gư>Z
color_coder-   Zdetection_channels   r/   Zbackground_subtractionc                 C      | dkS )NBrp   xrp   rp   rq   <lambda>      zSDTControlSpec.<lambda>Z	em_active    c                 C   r   )NErp   r   rp   rp   rq   r   	  r   Zem_gain   Zmodulation_active!   c                 C   r   )NArp   r   rp   rp   rq   r     r   Z
pixel_size   g?Zsequence_typec                    s
    j |  S r   )sequence_typesr   	__class__rp   rq   r        
 gridZn_macroZdelay_macro   gMbP?Zn_miniZ
delay_mini%   O   r9   7   )Zn_microZdelay_microZ	n_subpicsZdelay_shutterZdelay_prebleachZbleach_timeZrecovery_timeZbleach_piezo_active"   #   c                 C   r   )Nzrp   r   rp   rp   rq   r     r   ))rS   r   )rS   r`   rQ   returnc                 C   sX   | d dd dkrdS zt | d dd t | d dd fW S  ty+   Y dS w )a-  Get the version of SDT-control metadata encoded in the comments

        Parameters
        ----------
        comments
            List of SPE file comments, typically ``metadata["comments"]``.

        Returns
        -------
        Major and minor version. ``-1, -1`` if detection failed.
        r0   r   L   ZCOMVER)r   N   P   )r   
ValueError)rQ   rp   rp   rq   get_comment_version"  s   *z"SDTControlSpec.get_comment_versionversionc                    s6  i }t |d d D ]\}z j|d |f }W n	 ty    Y q
w | D ]@\}}z|| |j |j }|jdur?||j9 }|||< W q% tye } zt	
d| d|  d||< W Y d}~q%d}~ww q
| jvrdtdd  j}	t	
d	|d  d
|d dd|	 d | d | d  }
|
 |d< |S )aC  Extract SDT-control metadata from comments

        Parameters
        ----------
        comments
            List of SPE file comments, typically ``metadata["comments"]``.
        version
            Major and minor version of SDT-control metadata format

        Returns
        -------
        Dict of metadata
        r`   r   Nz-Failed to decode SDT-control metadata field `z`: z, c                 S   s   | d  d| d dS )Nr   .r`   02rp   r   rp   rp   rq   r   ^      z/SDTControlSpec.parse_comments.<locals>.<lambda>z)Unsupported SDT-control metadata version r   r   z. Only versions z@ are supported. Some or all SDT-control metadata may be missing.r   comment)rangecomment_fieldsKeyErroritemsr   r   r   r   	Exceptionwarningswarnjoinmapstrip)rQ   r   Zsdt_mdminorZcmtnamespecveZsupported_verr   r   rp   rq   parse_comments6  sB   


zSDTControlSpec.parse_commentsr4   timeNc              
      s   z1 j | dd  }tt| dd |t| dd t|dd t|dd t|dd W S  tyM } ztd| d W Y d	}~d	S d	}~ww )
ai  Turn date and time saved by SDT-control into proper datetime object

        Parameters
        ----------
        date
            SPE file date, typically ``metadata["date"]``.
        time
            SPE file date, typically ``metadata["time_local"]``.

        Returns
        -------
        File's datetime if parsing was succsessful, else None.
        r   rS   r}   r   r0   r)   z1Failed to decode date from SDT-control metadata: r   N)monthsr   r   r   loggerinfo)r4   r   monthr   r   rp   rq   get_datetimei  s    zSDTControlSpec.get_datetimelatin1metachar_encodingc                    s     | d }tdd |D rtd dS  | d |}| d | |  | d | d }|rC|| d< | d | d | d	 }z||| d
< | d	 W n t	yc   t
d Y nw | d | d dS )ar  Extract SDT-control metadata from SPE metadata

        SDT-control stores some metadata in comments and other fields.
        Extract them and remove unused entries.

        Parameters
        ----------
        meta
            SPE file metadata. Modified in place.
        char_encoding
            Character encoding used to decode strings in the metadata.
        rQ   c                 s   s    | ]}|d k V  qdS )r   Nrp   .0crp   rp   rq   	<genexpr>  s    z2SDTControlSpec.extract_metadata.<locals>.<genexpr>zSDT-control comments not found.Nr4   rF   r   rY   Zmodulation_scriptzHFailed to decode SDT-control laser modulation script. Bad char_encoding?rI   r3   )r   anyr   debugr   popupdater   decodeUnicodeDecodeErrorr   r   )r   r   Zcomversdt_metadtZsp4r   rp   rq   extract_metadata  s.   





zSDTControlSpec.extract_metadata)r   )rc   rd   re   rf   r   r   r   r   r   r   r   r   staticmethodr
   r   r   r   r   r   r   r   r   r   r   __classcell__rp   rp   r   rq   rr      s    	
	
" 

2$"rr   c                       s  e Zd Z			ddededee dee ddf
 fdd	Zd
ddede	j
fddZdee	j
 fddZ	
			d dededededeeef f
ddZdededeeef fddZdeeef fddZd!dedefddZdeeef dedeeef fddZ  ZS )"	SpePluginTNrequestcheck_filesizer   r   r   c              	      sl  t  | |jjtjkrtd|durtdt	 || _
|dur(tdt	 || _| j | _zy| tjd}|d | _tj|d  | _|d |d	 f| _|d
 | _|r|d dkra|d }n| jdtj | j }|tj }|| jd | jd  | jj  }|| jkrtd| jj d| j d| d t|| j| _| jtj W dS  ty   tdw )a  Instantiate a new SPE file plugin object

        Parameters
        ----------
        request : Request
            A request object representing the resource to be operated on.
        check_filesize : bool
            If True, compute the number of frames from the filesize, compare it
            to the frame count in the file header, and raise a warning if the
            counts don't match. (Certain software may create files with
        char_encoding : str
            Deprecated. Exists for backwards compatibility; use ``char_encoding`` of
            ``metadata`` instead.
        sdt_meta : bool
            Deprecated. Exists for backwards compatibility; use ``sdt_control`` of
            ``metadata`` instead.

        zcannot write SPE filesNz{Passing `char_encoding` to the constructor is deprecated. Use `char_encoding` parameter of the `metadata()` method instead.ztPassing `sdt_meta` to the constructor is deprecated. Use `sdt_control` parameter of the `metadata()` method instead.r   r   r   r   r   r   ra   r   r   r`   zThe file header of z claims there are z  frames, but there are actually z frames.z)SPE plugin cannot read the provided file.) superr   r1   Zio_moder   writer   r   r   DeprecationWarning_char_encoding	_sdt_metar   Zget_file_file_parse_headerr   rg   _file_header_verrl   _dtype_shape_lenseekosSEEK_ENDtellrk   itemsizefilenameminr   )r   r   r   r   r   r   Zdata_endliner   rp   rq   r     sT   




 
zSpePlugin.__init__.indexr   c                C   s   |t u rtj}| jd | jd  | j }| jg| jR }n=|dk r)td| d|| jkr:td| d| j dtj|| jd  | jd  | jj  }| jd | jd  }| j}| j	| t
j| j| j|d}||S )a<  Read a frame or all frames from the file

        Parameters
        ----------
        index : int
            Select the index-th frame from the file. If index is `...`,
            select all frames and stack them along a new axis.

        Returns
        -------
        A Numpy array of pixel values.

        r   r`   zIndex `z` is smaller than 0.z5` exceeds the number of frames stored in this file (`z`).ri   count)Ellipsisr   rk   r   r   
IndexErrorr   r   r   r   rh   fromfileZreshape)r   r   read_offsetr   Z	out_shapedatarp   rp   rq   read  s&   

zSpePlugin.readc                    s    fddt  jD S )zrIterate over the frames in the file

        Yields
        ------
        A Numpy array of pixel values.
        c                 3   s    | ]	} j |d V  qdS )r   N)r   )r   ir   rp   rq   r   1  s    z!SpePlugin.iter.<locals>.<genexpr>)r   r   r  rp   r  rq   iter)  s   zSpePlugin.iterr   exclude_appliedsdt_controlc                 C   s>   | j dk r| jdur| j}| jdur| j}| ||S |  S )ua  SPE specific metadata.

        Parameters
        ----------
        index : int
            Ignored as SPE files only store global metadata.
        exclude_applied : bool
            Ignored. Exists for API compatibility.
        char_encoding : str
            The encoding to use when parsing strings.
        sdt_control : bool
            If `True`, decode special metadata written by the
            SDT-control software if present.

        Returns
        -------
        metadata : dict
            Key-value pairs of metadata.

        Notes
        -----
        SPE v3 stores metadata as XML, whereas SPE v2 uses a binary format.

        .. rubric:: Supported SPE v2 Metadata fields

        ROIs : list of dict
            Regions of interest used for recording images. Each dict has the
            "top_left" key containing x and y coordinates of the top left corner,
            the "bottom_right" key with x and y coordinates of the bottom right
            corner, and the "bin" key with number of binned pixels in x and y
            directions.
        comments : list of str
            The SPE format allows for 5 comment strings of 80 characters each.
        controller_version : int
            Hardware version
        logic_output : int
            Definition of output BNC
        amp_hi_cap_low_noise : int
            Amp switching mode
        mode : int
            Timing mode
        exp_sec : float
            Alternative exposure in seconds
        date : str
            Date string
        detector_temp : float
            Detector temperature
        detector_type : int
            CCD / diode array type
        st_diode : int
            Trigger diode
        delay_time : float
            Used with async mode
        shutter_control : int
            Normal, disabled open, or disabled closed
        absorb_live : bool
            on / off
        absorb_mode : int
            Reference strip or file
        can_do_virtual_chip : bool
            True or False whether chip can do virtual chip
        threshold_min_live : bool
            on / off
        threshold_min_val : float
            Threshold minimum value
        threshold_max_live : bool
            on / off
        threshold_max_val : float
            Threshold maximum value
        time_local : str
            Experiment local time
        time_utc : str
            Experiment UTC time
        adc_offset : int
            ADC offset
        adc_rate : int
            ADC rate
        adc_type : int
            ADC type
        adc_resolution : int
            ADC resolution
        adc_bit_adjust : int
            ADC bit adjust
        gain : int
            gain
        sw_version : str
            Version of software which created this file
        spare_4 : bytes
            Reserved space
        readout_time : float
            Experiment readout time
        type : str
            Controller type
        clockspeed_us : float
            Vertical clock speed in microseconds
        readout_mode : ["full frame", "frame transfer", "kinetics", ""]
            Readout mode. Empty string means that this was not set by the
            Software.
        window_size : int
            Window size for Kinetics mode
        file_header_ver : float
            File header version
        chip_size : [int, int]
            x and y dimensions of the camera chip
        virt_chip_size : [int, int]
            Virtual chip x and y dimensions
        pre_pixels : [int, int]
            Pre pixels in x and y dimensions
        post_pixels : [int, int],
            Post pixels in x and y dimensions
        geometric : list of {"rotate", "reverse", "flip"}
            Geometric operations
        sdt_major_version : int
            (only for files created by SDT-control)
            Major version of SDT-control software
        sdt_minor_version : int
            (only for files created by SDT-control)
            Minor version of SDT-control software
        sdt_controller_name : str
            (only for files created by SDT-control)
            Controller name
        exposure_time : float
            (only for files created by SDT-control)
            Exposure time in seconds
        color_code : str
            (only for files created by SDT-control)
            Color channels used
        detection_channels : int
            (only for files created by SDT-control)
            Number of channels
        background_subtraction : bool
            (only for files created by SDT-control)
            Whether background subtraction war turned on
        em_active : bool
            (only for files created by SDT-control)
            Whether EM was turned on
        em_gain : int
            (only for files created by SDT-control)
            EM gain
        modulation_active : bool
            (only for files created by SDT-control)
            Whether laser modulation (“attenuate”) was turned on
        pixel_size : float
            (only for files created by SDT-control)
            Camera pixel size
        sequence_type : str
            (only for files created by SDT-control)
            Type of sequnce (standard, TOCCSL, arbitrary, …)
        grid : float
            (only for files created by SDT-control)
            Sequence time unit (“grid size”) in seconds
        n_macro : int
            (only for files created by SDT-control)
            Number of macro loops
        delay_macro : float
            (only for files created by SDT-control)
            Time between macro loops in seconds
        n_mini : int
            (only for files created by SDT-control)
            Number of mini loops
        delay_mini : float
            (only for files created by SDT-control)
            Time between mini loops in seconds
        n_micro : int (only for files created by SDT-control)
            Number of micro loops
        delay_micro : float (only for files created by SDT-control)
            Time between micro loops in seconds
        n_subpics : int
            (only for files created by SDT-control)
            Number of sub-pictures
        delay_shutter : float
            (only for files created by SDT-control)
            Camera shutter delay in seconds
        delay_prebleach : float
            (only for files created by SDT-control)
            Pre-bleach delay in seconds
        bleach_time : float
            (only for files created by SDT-control)
            Bleaching time in seconds
        recovery_time : float
            (only for files created by SDT-control)
            Recovery time in seconds
        comment : str
            (only for files created by SDT-control)
            User-entered comment. This replaces the "comments" field.
        datetime : datetime.datetime
            (only for files created by SDT-control)
            Combines the "date" and "time_local" keys. The latter two plus
            "time_utc" are removed.
        modulation_script : str
            (only for files created by SDT-control)
            Laser modulation script. Replaces the "spare_4" key.
        bleach_piezo_active : bool
            (only for files created by SDT-control)
            Whether piezo for bleaching was enabled
        ra   N)r   r   r   _metadata_pre_v3_metadata_post_v3)r   r   r  r   r  rp   rp   rq   rj   3  s    
M

zSpePlugin.metadatac           	         s  |  tj|  dd}|dk rdn|}t d d|  d<  fdddD  d<  fd	dd
D  d<  fdddD  d<  fdddD  d< dd  d D  d< g } dd}|d@ ri|d |d@ rr|d |d@ r{|d | d<  d }d|  krttjkrn n
tj|d   d< nd d<  d }d|  krttjkrn n
tj|d   d< nd d< dD ]
}t	 |  |< q|rt
 |  S )aZ  Extract metadata from SPE v2 files

        Parameters
        ----------
        char_encoding
            String character encoding
        sdt_control
            If `True`, try to decode special metadata written by the
            SDT-control software.

        Returns
        -------
        dict mapping metadata names to values.

        r   Nr`   r    c                       g | ]}  |d qS r   r   r   kmrp   rq   
<listcomp>  r   z.SpePlugin._metadata_pre_v3.<locals>.<listcomp>)r(   r*   Z	chip_sizec                    r  r   r	  r
  r  rp   rq   r     r   )r,   r.   Zvirt_chip_sizec                    r  r   r	  r
  r  rp   rq   r  !  r   )rZ   r\   Z
pre_pixelsc                    r  r   r	  r
  r  rp   rq   r  "  r   )r[   r]   Zpost_pixelsc                 S   s   g | ]}t |qS rp   )r   r   rp   rp   rq   r  %  s    rQ   rT   r   rotater   reverser0   flipr^   r_   )r;   r>   r@   rC   )r   r   rj   r   roi_array_to_dictappendlenrm   rn   boolrr   r   )	r   r   r  nrgftrr  rp   r  rq   r    s>   


zSpePlugin._metadata_pre_v3c                 C   s0   |  tjd}| j|d  | j }d|iS )zExtract XML metadata from SPE v3 files

        Returns
        -------
        dict with key `"__xml"`, whose value is the XML metadata
        r   r   Z__xml)r   r   rg   r   r   r   )r   r   xmlrp   rp   rq   r  M  s   
zSpePlugin._metadata_post_v3c                 C   s:   |t u rt| jg| jR | j| jddS t| j| jddS )a  Standardized ndimage metadata.

        Parameters
        ----------
        index : int
            If the index is an integer, select the index-th frame and return
            its properties. If index is an Ellipsis (...), return the
            properties of all frames in the file stacked along a new batch
            dimension.

        Returns
        -------
        properties : ImageProperties
            A dataclass filled with standardized image metadata.
        T)shaperi   Zn_imagesis_batchF)r  ri   r  )r   r   r   r   r   )r   r   rp   rp   rq   
propertiesZ  s   zSpePlugin.propertiesr   c           	   	      s   i }t  fdd}| D ]`\}}| j|d  t|dk r#dn|d }t j| j|d |d}|jjdkrV|t	j
vrVz||}W n tyU   td	| d
 Y nw z| }W n tyj   t |}Y nw |||< q|S )a  Get information from SPE file header

        Parameters
        ----------
        spec
            Maps header entry name to its location, data type description and
            optionally number of entries. See :py:attr:`Spec.basic` and
            :py:attr:`Spec.metadata`.
        char_encoding
            String character encoding

        Returns
        -------
        Dict mapping header entry name to its value
        c                    s
   |   S r   )r   r   r   rp   rq   r     r   z)SpePlugin._parse_header.<locals>.<lambda>r   ra   r`   r   r   SzFailed to decode "z3" metadata string. Check `char_encoding` parameter.)rh   Z	vectorizer   r   r   r  r   ri   kindr   ro   r   r   r   itemr   Zsqueeze)	r   r   r   retr   r   spZcntr   rp   r  rq   r   t  s*   

zSpePlugin._parse_header)TNN).Tr   T).)rc   rd   re   r   r  r	   r   r   r   rh   ndarrayr   r   r  r   r   rj   r  r  r   r  r   r   r   r   rp   rp   r   rq   r     sV    P%

 UF

r   ar   c           	      C   sd   g }| g d } | D ]%\}}}}}}t |t |gt |t |gt |t |gd}|| q
|S )a\  Convert the `ROIs` structured arrays to :py:class:`dict`

    Parameters
    ----------
    a
        Structured array containing ROI data

    Returns
    -------
    One dict per ROI. Keys are "top_left", "bottom_right", and "bin",
    values are tuples whose first element is the x axis value and the
    second element is the y axis value.
    )r!   r$   r"   r%   r#   r&   )top_leftbottom_rightbin)r   r  )	r&  Z	dict_listsxZsyexZeyZgxgyZroi_dictrp   rp   rq   r    s   r  )#rf   r   loggingr   typingr   r   r   r   r   r   r	   r
   r   r   r   numpyrh   Zcore.requestr   r   r   Zcore.v3_plugin_apir   r   	getLoggerrc   r   r   rr   r   r%  r   r   r  rp   rp   rp   rq   <module>   s&   #0
  r   (s