o
    xiT                     @   s   d Z ddl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 ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ G dd dZdedefddZdS )z^
Functions for reading/writing/manipulating Textgrid classes

This is the 'heart' of praatio.
    N)OptionalTupleSequence)Literal)OrderedDict)TextgridFormatsMIN_INTERVAL_LENGTHCropCollision)textgrid_tier)
point_tier)interval_tier)	constants)errors)my_math)textgrid_io)utilsc                   @   s  e Zd ZdZdPdedefddZdd Zd	d
 Zdd Ze	de
edf fddZe	de
ejdf fddZ		dQdejdee ded ddfddZdd dedd fddZdeded ed! d"edd f
d#d$Zd%ed&ed'edd fd(d)Z	dRd*eded dd fd+d,Zd-edejfd.d/Z	0dSd%ed1ed2ed3 dd fd4d5Z	6dTd7eee  d8edd fd9d:ZdUd;d<Zddedfd=ed>ed? d@edee dee dAeded ddfdBdCZdDedEeddfdFdGZ dHedejfdIdJZ!	dRdHedKejded ddfdLdMZ"	dRded defdNdOZ#dS )VTextgrida  A container that stores and operates over interval and point tiers

    Textgrids are used by the Praat software to group tiers.  Each tier
    contains different annotation information for an audio recording.

    Attributes:
        tierNames(Tuple[str]): the list of tier names in the textgrid
        tiers(Tuple[TextgridTier]): the list of ordered tiers
        minTimestamp(float): the minimum allowable timestamp in the textgrid
        maxTimestamp(float): the maximum allowable timestamp in the textgrid
    NminTimestampmaxTimestampc                 C   s   t  | _|| _|| _dS )zConstructor for Textgrids

        Args:
            minTimestamp: the minimum allowable timestamp in the textgrid
            maxTimestamp: the maximum allowable timestamp in the textgrid
        N)r   	_tierDictr   r   )selfr   r    r   `/home/ubuntu/maya3_transcribe/venv/lib/python3.10/site-packages/praatio/data_classes/textgrid.py__init__+   s   
zTextgrid.__init__c                 C   s
   t | jS N)lenr   r   r   r   r   __len__9   s   
zTextgrid.__len__c                 c   s    | j D ]}|V  qd S r   )tiers)r   entryr   r   r   __iter__<   s   
zTextgrid.__iter__c                 C   sv   t |tsdS d}|t| j|jM }|t| j|jM }|| j|jkM }|r9| jD ]}|| |||kM }q*|S )NFT)
isinstancer   r   iscloser   r   	tierNamesgetTier)r   otherisEqualtierNamer   r   r   __eq__@   s   

zTextgrid.__eq__return.c                 C      t | j S r   )tupler   keysr   r   r   r   r#   O      zTextgrid.tierNamesc                 C   r*   r   )r+   r   valuesr   r   r   r   r   S   r-   zTextgrid.tierswarningtier	tierIndexreportingMode)silencer/   errorc           
      C   s6  t d|tj t |}|j| jv rtd|du r#|| j	|j< n$t
| j}|||j t }|| j	|j< |D ]	}| |||< q:|| _	|j}| jdurb|| jk rb|tjd| j d| d | jdu sl|| jk ro|| _|j}	| jdur|	| jkr|tjd| j d|	 d | jdu s|	| jkr|	| _dS dS )a-  Add a tier to this textgrid.

        Args:
            tier: The tier to add to the textgrid
            tierIndex: Insert the tier into the specified position;
                if None, the tier will appear after all existing tiers
            reportingMode: This flag determines the behavior if there is a size
                difference between the maxTimestamp in the tier and the current
                textgrid.

        Returns:
            None

        Raises:
            TierNameExistsError: The textgrid already contains a tier with the same
                name as the tier being added
            TextgridStateAutoModified: The minimum or maximum timestamp was changed
                when not permitted
            IndexError: TierIndex is too large for the size of the existing tier list
        r2   zTier name already in tierNz,Minimum timestamp in Textgrid changed from (z) to ()z,Maximum timestamp in Textgrid changed from ()r   validateOptionr   ErrorReportingModegetErrorReporternamer#   r   TierNameExistsErrorr   listinsertr   r$   r   TextgridStateAutoModifiedr   )
r   r0   r1   r2   errorReporternewOrderedTierNameListnewTierDicttmpNameminVmaxVr   r   r   addTierW   s@   



zTextgrid.addTiertgonlyMatchingNamesc                 C   sF  | j }| j|j }t||}t| j}|jD ]}||vr!|| qg }|du r+|}n|D ]}|| jv r>||jv r>|| q-|D ]}|| jv rR| |}	||	 qA|D ]K}||jv r||}
|
j||d}
|
	| j}
||jv r||}	||j
}||
j
7 }|	j|||d}	|||	 qU|
}	|	j||d}	||	 qU|S )a1  Append one textgrid to the end of this one

        Args:
            tg: the textgrid to add to this one
            onlyMatchingNames: if False, tiers that don't appear in both
                textgrids will also appear

        Returns:
            the modified version of the current textgrid
        F)r   r   )entriesr   r   )r   r   r   r;   r#   appendr$   rD   neweditTimestampsrG   replaceTier)r   rE   rF   minTimemaxTimeretTGcombinedTierNamesr'   finalTierNamesr0   
appendTier
newEntriesr   r   r   appendTextgrid   sR   















zTextgrid.appendTextgrid	cropStartcropEndmode)strictlax	truncatedrebaseToZeroc                 C   s   t d|t ||krtd| d| d|du r"d}|| }n|}|}t||}| jD ]$}| |}	|	||||}
t	j
j}|t	jjkrKt	j
j}|j|
|d q.|S )a/  Creates a textgrid where all intervals fit within the crop region

        Args:
            cropStart: The start time of the crop interval
            cropEnd: The stop time of the crop interval
            mode: Determines the crop behavior
                - 'strict', only intervals wholly contained by the crop
                    interval will be kept
                - 'lax', partially contained intervals will be kept
                - 'truncated', partially contained intervals will be
                    truncated to fit within the crop region.
            rebaseToZero: if True, the cropped textgrid timestamps will be
                subtracted by the cropStart; if False, timestamps will not
                be changed

        Returns:
            the modified version of the current textgrid
        rV   zCrop error: start time () must occur before end time (r5   Tg        r2   )r   r6   r	   r   ArgumentErrorr   r#   r$   cropr   r7   WARNINGLAXSILENCErD   )r   rT   rU   rV   rZ   minTmaxTnewTGr'   r0   newTierr2   r   r   r   r^      s(   



zTextgrid.cropstartenddoShrinkc           	      C   s   ||krt d| d| d|| }| j}|du r||8 }t| j| j}| jD ]}|||tjj	|}|
| q)||_|S )a  Makes a region in a tier blank (removes all contained entries)

        Intervals that span the region to erase will be truncated.

        Args:
            start:
            end:
            doShrink: if True, all entries appearing after the
                erased interval will be shifted to fill the void (ie
                the duration of the textgrid will be reduced by
                *start* - *end*)

        Returns:
            the modified version of the current textgrid

        Raises:
            ArgumentError
        zEraseRegion error: start time (r[   r5   T)r   r]   r   r   r   r   eraseRegionr   EraseCollisionTRUNCATErD   )	r   rf   rg   rh   diffr   rd   r0   
shrunkTierr   r   r   ri     s    
zTextgrid.eraseRegionoffsetc                 C   sV   t d|tj t| j| j}| jD ]}t|j	dkr!|
||}|j||d q|S )a  Modifies all timestamps by a constant amount

        Args:
            offset: the amount to offset in seconds
            reportingMode: one of "silence", "warning", or "error". This flag
                determines the behavior if there is a size difference between the
                maxTimestamp in the tier and the current textgrid.

        Returns:
            Textgrid: the modified version of the current textgrid
        r2   r   r\   )r   r6   r   r7   r   r   r   r   r   rG   rJ   rD   )r   rn   r2   rE   r0   r   r   r   rJ   9  s   
zTextgrid.editTimestampsr'   c                 C   s
   | j | S )z$Get the tier with the specified name)r   )r   r'   r   r   r   r$   V     
zTextgrid.getTierr4   durationcollisionMode)stretchsplit	no_changer4   c                 C   sZ   t d|tj t| j| j}| j|_| j| |_| jD ]}||||}|	| q|S )a=  Inserts a blank region into a textgrid

        Every item that occurs after *start* will be pushed back by
        *duration* seconds

        Args:
            start:
            duration:
            collisionMode: Determines behavior in the event that an
                interval stradles the starting point.
                One of ['stretch', 'split', 'no change', None]
                - 'stretch' stretches the interval by /duration/ amount
                - 'split' splits the interval into two--everything to the
                    right of 'start' will be advanced by 'duration' seconds
                - 'no change' leaves the interval as is with no change
                - None or any other value throws an AssertionError

        Returns:
            Textgrid: the modified version of the current textgrid
        rq   )
r   r6   r   WhitespaceCollisionr   r   r   r   insertSpacerD   )r   rf   rp   rq   rd   r0   re   r   r   r   rv   Z  s   
zTextgrid.insertSpaceTr#   preserveOtherTiersc           
      C   s&  |du r| j }g }g }|D ]}| |}t|tjr || qt|tjr+|| qd}t|dkrI| |	d}|D ]
}|
| |}q>d}t|dkrf| |	d}|D ]
}|
| |}q[t| j| j}	|r| jD ]}|j|vr~|	| qr|dur|	| |dur|	| |	S )aH  Combine tiers

        Args:
            tierList: A list of tier names to combine. If none, combine
                all tiers.
            preserveOtherTiers: If false, uncombined tiers are not
                included in the output.

        Returns:
            Textgrid: the modified version of the current textgrid
        Nr   )r#   r$   r!   r   IntervalTierrH   r   	PointTierr   popunionr   r   r   r   r9   rD   )
r   r#   rw   intervalTierNamespointTierNamesr'   r0   intervalTier	pointTierrE   r   r   r   
mergeTiers  s@   






zTextgrid.mergeTiersc                 C   s
   t | S )zReturns a copy of this Textgrid)copydeepcopyr   r   r   r   rI     ro   zTextgrid.newfnformat)short_textgridlong_textgridjsontextgrid_jsonincludeBlankSpacesminimumIntervalLengthc                 C   s   t d|t t d|tj | | t| }t||||||}	t	j
|ddd}
|
|	 W d   dS 1 s;w   Y  dS )a;  Save the current textgrid to a file

        Args:
            fn: the fullpath filename of the output
            format: one of ['short_textgrid', 'long_textgrid', 'json', 'textgrid_json']
                'short_textgrid' and 'long_textgrid' are both used by praat
                'json' and 'textgrid_json' are two json variants. 'json' cannot represent
                tiers with different min and max timestamps than the textgrid.
            includeBlankSpaces: if True, blank sections in interval
                tiers will be filled in with an empty interval
                (with a label of ""). If you are unsure, True is recommended
                as Praat needs blanks to render textgrids properly.
            minTimestamp: the minTimestamp of the saved Textgrid;
                if None, use whatever is defined in the Textgrid object.
                If minTimestamp is larger than timestamps in your textgrid,
                an exception will be thrown.
            maxTimestamp: the maxTimestamp of the saved Textgrid;
                if None, use whatever is defined in the Textgrid object.
                If maxTimestamp is smaller than timestamps in your textgrid,
                an exception will be thrown.
            minimumIntervalLength: any labeled intervals smaller
                than this will be removed, useful for removing ultrashort
                or fragmented intervals; if None, don't remove any.
                Removed intervals are merged (without their label) into
                adjacent entries.
            reportingMode: one of "silence", "warning", or "error". This flag
                determines the behavior if there is a size difference between the
                maxTimestamp in the tier and the current textgrid.

        Returns:
            a string representation of the textgrid
        r   r2   wzutf-8)encodingN)r   r6   r   r   r7   validate_tgToDictionaryr   getTextgridAsStrioopenwrite)r   r   r   r   r   r   r   r2   tgAsDicttextgridStrfdr   r   r   save  s"   +
	"zTextgrid.saveoldNamenewNamec                 C   s:   |  |}| j|}| | | |||j| d S r   )r$   r#   index
removeTierrD   rI   rG   )r   r   r   oldTierr1   r   r   r   
renameTier  s   

zTextgrid.renameTierr9   c                 C   s   | j |S r   )r   rz   )r   r9   r   r   r   r     s   zTextgrid.removeTierre   c                 C   s(   | j |}| | | ||| d S r   )r#   r   r   rD   )r   r9   re   r2   r1   r   r   r   rK     s   
zTextgrid.replaceTierc                 C   s   t d|tj t |}d}t| jtt| jkr'd}|tj	d| j  | j
D ]7}| j|jkrCd}|tjd| j d|j d | j|jkrZd}|tjd| j d|j d |o`||}q*|S )	a  Validates this textgrid

        Returns whether the textgrid is valid or not. If reportingMode is "warning"
        or "error" this will also print on error or stop execution, respectively.

        Args:
            reportingMode: one of "silence", "warning", or "error". This flag
                determines the behavior if there is a size difference between the
                maxTimestamp in a tier and the current textgrid.

        Returns:
            True if this Textgrid is valid; False if not

        Raises:
            TierNameExistsError: Two tiers have the same name
            TextgridStateError: A timestamp fall outside of the allowable range
        r2   TFzTier names not unique: z!Textgrid has a min timestamp of (z) but tier has (r5   z!Textgrid has a max timestamp of ()r   r6   r   r7   r8   r   r#   setr   r:   r   r   TextgridStateErrorr   r   )r   r2   r>   isValidr0   r   r   r   r     s<   




zTextgrid.validate)NN)Nr/   )r/   )r4   )NT)r)   r   )$__name__
__module____qualname____doc__floatr   r   r    r(   propertyr   strr#   r
   TextgridTierr   r   intr   rD   boolrS   r^   ri   rJ   r$   rv   r   r   rI   r   r   r   r   rK   r   r   r   r   r   r      s    
@A
8,

)


9		
@
r   rE   r)   c                 C   sD   g }| j D ]}|j|j|j|j|jd}|| q| j| j|dS )N)classr9   xminxmaxrG   )r   r   r   )r   tierTyper9   r   r   rG   rH   )rE   r   r0   
tierAsDictr   r   r   r   I  s   
r   )r   r   r   typingr   r   r   typing_extensionsr   collectionsr   praatio.utilities.constantsr   r   r	   praatio.data_classesr
   r   r   praatio.utilitiesr   r   r   r   r   r   dictr   r   r   r   r   <module>   s*        /