o
    7?e|J                     @   s   d Z ddlZddlZddl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 e ZG dd	 d	e	jZd
d Zdd Zdd Zdd Zdd Zdd Zdd ZdS )z;Bridge from event multiplexer storage to generic data APIs.    N)errors)summary_pb2)provider)
tb_logging)tensor_utilc                   @   s   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	d,ddZ
d,ddZd,ddZ	d,ddddZ	d,dddddZ	d,ddddZ	d,dddddZd d! Zd"d# Zd$d% Z	d,ddd&d'Z	d,dddd(d)Zd,d*d+ZdS )-MultiplexerDataProviderc                 C   s   || _ || _dS )a6  Trivial initializer.

        Args:
          multiplexer: A `plugin_event_multiplexer.EventMultiplexer` (note:
            not a boring old `event_multiplexer.EventMultiplexer`).
          logdir: The log directory from which data is being read. Only used
            cosmetically. Should be a `str`.
        N)_multiplexer_logdir)selfZmultiplexerZlogdir r   s/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorboard/backend/event_processing/data_provider.py__init__    s   	
z MultiplexerDataProvider.__init__c                 C   s
   d| j  S )Nz"MultiplexerDataProvider(logdir=%r))r	   r
   r   r   r   __str__,   s   
zMultiplexerDataProvider.__str__c                 C   s    t |jdkrtd|f d S )NZRequestContextz%ctx must be a RequestContext; got: %r)type__name__	TypeError)r
   ctxr   r   r   _validate_context/   s   z)MultiplexerDataProvider._validate_contextc                 C   s$   t |tstdtt||f d S )Nz(experiment_id must be %r, but got %r: %r)
isinstancestrr   r   )r
   experiment_idr   r   r   _validate_experiment_id3   s   
z/MultiplexerDataProvider._validate_experiment_idc                 C   s2   |d u rt dt|trd S t dt||f )Nz#`downsample` required but not givenz+`downsample` must be an int, but got %r: %r)r   r   intr   )r
   
downsampler   r   r   _validate_downsample=   s   

z,MultiplexerDataProvider._validate_downsamplec                 C   s8   |j }|d ur||vrdS |j}|d ur||vrdS dS )NFTrunstags)r
   run_tag_filterruntagr   r   r   r   r   _test_run_tagG   s   z%MultiplexerDataProvider._test_run_tagc              
   C   s6   z| j |W S  ty } zW Y d }~d S d }~ww N)r   ZFirstEventTimestamp
ValueError)r
   run_nameer   r   r   _get_first_event_timestampP   s   z2MultiplexerDataProvider._get_first_event_timestampNc                C   s"   |  | | | tj| jdS )N)Zdata_location)r   r   r   ZExperimentMetadatar	   r
   r   r   r   r   r   experiment_metadataV   s   

z+MultiplexerDataProvider.experiment_metadatac                C   s   |  | | | | j S r#   )r   r   r   ZActivePluginsr(   r   r   r   list_plugins[   s   


z$MultiplexerDataProvider.list_pluginsc                   s,     |  |  fdd j D S )Nc                    s"   g | ]}t j|| |d qS ))Zrun_idr%   
start_time)r   ZRunr'   ).0r    r   r   r   
<listcomp>h   s    z5MultiplexerDataProvider.list_runs.<locals>.<listcomp>)r   r   r   ZRunsr(   r   r   r   	list_runse   s
   


z!MultiplexerDataProvider.list_runs)r   c                C   2   |  | | | | ||tj}| tj|S r#   )r   r   _indexr   DATA_CLASS_SCALAR_listr   ZScalarTimeSeriesr
   r   r   plugin_namer   indexr   r   r   list_scalarsq      

z$MultiplexerDataProvider.list_scalars)r   r   c                C   <   |  | | | | | | ||tj}| t||S r#   )r   r   r   r0   r   r1   _read_convert_scalar_eventr
   r   r   r4   r   r   r5   r   r   r   read_scalars{      
	

z$MultiplexerDataProvider.read_scalarsc                C   r/   r#   )r   r   r0   r   DATA_CLASS_TENSORr2   r   ZTensorTimeSeriesr3   r   r   r   list_tensors   r7   z$MultiplexerDataProvider.list_tensorsc                C   r8   r#   )r   r   r   r0   r   r>   r9   _convert_tensor_eventr;   r   r   r   read_tensors   r=   z$MultiplexerDataProvider.read_tensorsc                 C   s  |du rt jddd}|j}|j}|rCt|dkrC|rCt|dkrC|\}|\}z	| j||}W n ty;   i  Y S w |||ii}	n| j }	i }
|		 D ]6\}}|dur[||vr[qNi }|	 D ]"\}}|durn||vrnqa|j
|krtqa|jj|kr{qa||
|< |||< qaqN|
S )a  List time series and metadata matching the given filters.

        This is like `_list`, but doesn't traverse `Tensors(...)` to
        compute metadata that's not always needed.

        Args:
          plugin_name: A string plugin name filter (required).
          run_tag_filter: An `provider.RunTagFilter`, or `None`.
          data_class_filter: A `summary_pb2.DataClass` filter (required).

        Returns:
          A nested dict `d` such that `d[run][tag]` is a
          `SummaryMetadata` proto.
        Nr      )r   ZRunTagFilterr   r   lenr   SummaryMetadataKeyErrorZAllSummaryMetadataitems
data_classplugin_datar4   )r
   r4   r   Zdata_class_filterr   r   r    r!   metadataZall_metadataresulttag_to_metadataresult_for_runr   r   r   r0      s<    



zMultiplexerDataProvider._indexc              	   C   s   i }|  D ]O\}}i }|||< |  D ]@\}}d}	d}
| j||D ]}|	du s.|	|jk r1|j}	|
du s:|
|jk r=|j}
q#| j||}||	|
|jj|j|j	d||< qq|S )ac  Helper to list scalar or tensor time series.

        Args:
          construct_time_series: `ScalarTimeSeries` or `TensorTimeSeries`.
          index: The result of `self._index(...)`.

        Returns:
          A list of objects of type given by `construct_time_series`,
          suitable to be returned from `list_scalars` or `list_tensors`.
        N)max_stepmax_wall_timeplugin_contentdescriptiondisplay_name)
rF   r   Tensorsstep	wall_timerD   rH   contentsummary_descriptionrQ   )r
   Zconstruct_time_seriesr5   rJ   r    rK   rL   r!   summary_metadatarM   rN   eventr   r   r   r2      s.   zMultiplexerDataProvider._listc                    sf   i }|  D ]*\}}i }|||< |  D ]\}}	| j||}
 fdd|
D }t||||< qq|S )a  Helper to read scalar or tensor data from the multiplexer.

        Args:
          convert_event: Takes `plugin_event_accumulator.TensorEvent` to
            either `provider.ScalarDatum` or `provider.TensorDatum`.
          index: The result of `self._index(...)`.
          downsample: Non-negative `int`; how many samples to return per
            time series.

        Returns:
          A dict of dicts of values returned by `convert_event` calls,
          suitable to be returned from `read_scalars` or `read_tensors`.
        c                    s   g | ]} |qS r   r   r,   r&   convert_eventr   r   r-         z1MultiplexerDataProvider._read.<locals>.<listcomp>)rF   r   rR   _downsample)r
   r[   r5   r   rJ   r    Ztags_for_runrL   r!   rI   eventsdatar   rZ   r   r9      s   zMultiplexerDataProvider._readc             
   C   s   |  | | | | ||tj}i }| D ][\}}i }	|	||< | D ]L\}
}d }d }d }| j||
D ])}|d u sB||jk rE|j}|d u sN||j	k rQ|j	}t
|j}|d u s^||kr`|}q7tj||||jj|j|jd|	|
< q&q|S )N)rM   rN   
max_lengthrO   rP   rQ   )r   r   r0   r   DATA_CLASS_BLOB_SEQUENCErF   r   rR   rS   rT   _tensor_sizetensor_protor   ZBlobSequenceTimeSeriesrH   rU   rV   rQ   )r
   r   r   r4   r   r5   rJ   r    rK   rL   r!   rI   rM   rN   r`   rX   lengthr   r   r   list_blob_sequences  s@   


z+MultiplexerDataProvider.list_blob_sequencesc             	   C   s   |  | | | | | | ||tj}i }| D ]@\}}	i }
|
||< |	D ]3}| j||}i }|D ]}|j	|v r>q6t
|||||||j	< q6dd t| D }t|||
|< q)q|S )Nc                 S   s   g | ]\}}|qS r   r   )r,   rS   Zdatumr   r   r   r-   O  r\   z?MultiplexerDataProvider.read_blob_sequences.<locals>.<listcomp>)r   r   r   r0   r   ra   rF   r   rR   rS   _convert_blob_sequence_eventsortedr]   )r
   r   r   r4   r   r   r5   rJ   r    r   rL   r!   r^   Zdata_by_steprX   r_   r   r   r   read_blob_sequences3  s.   
	



z+MultiplexerDataProvider.read_blob_sequencesc                   s   |  | t|\}}}} }| j||}|jtjkr!t|| j	||}	t
 fdd|	D d }
|
s?td| f t|
j}|| S )Nc                 3   s    | ]
}|j  kr|V  qd S r#   rS   rY   ri   r   r   	<genexpr>c  s    z4MultiplexerDataProvider.read_blob.<locals>.<genexpr>z%s: no such step %r)r   _decode_blob_keyr   rD   rG   r   ra   r   ZNotFoundErrorrR   nextr   make_ndarrayrc   )r
   r   Zblob_keyZunused_experiment_idr4   r    r!   r5   rW   Ztensor_eventsZmatching_stepZtensorr   ri   r   	read_blobS  s$   

z!MultiplexerDataProvider.read_blobr#   )r   
__module____qualname__r   r   r   r   r   r"   r'   r)   r*   r.   r6   r<   r?   rA   r0   r2   r9   re   rh   rn   r   r   r   r   r      sT    

	



1!$ r   c           	      C   s>   t j| |||||fdd}|d}t|}|ddS )a  Generate a blob key: a short, URL-safe string identifying a blob.

    A blob can be located using a set of integer and string fields; here we
    serialize these to allow passing the data through a URL.  Specifically, we
    1) construct a tuple of the arguments in order; 2) represent that as an
    ascii-encoded JSON string (without whitespace); and 3) take the URL-safe
    base64 encoding of that, with no padding.  For example:

        1)  Tuple: ("some_id", "graphs", "train", "graph_def", 2, 0)
        2)   JSON: ["some_id","graphs","train","graph_def",2,0]
        3) base64: WyJzb21lX2lkIiwiZ3JhcGhzIiwidHJhaW4iLCJncmFwaF9kZWYiLDIsMF0K

    Args:
      experiment_id: a string ID identifying an experiment.
      plugin_name: string
      run: string
      tag: string
      step: int
      index: int

    Returns:
      A URL-safe base64-encoded string representing the provided arguments.
    ),:)
separatorsascii=)jsondumpsencodebase64urlsafe_b64encodedecoderstrip)	r   r4   r    r!   rS   r5   stringifiedZ
bytesifiedencodedr   r   r   _encode_blob_keyk  s   

r   c           	      C   s>   t | d }|d}t|\}}}}}}||||||fS )a'  Decode a blob key produced by `_encode_blob_key` into component fields.

    Args:
      key: a blob key, as generated by `_encode_blob_key`.

    Returns:
      A tuple of `(experiment_id, plugin_name, run, tag, step, index)`, with types
      matching the arguments of `_encode_blob_key`.
    z==rt   )ry   urlsafe_b64decoder{   rv   loads)	keydecodedr}   r   r4   r    r!   rS   r5   r   r   r   rk     s   

rk   c                 C   s    t j| j| jt| j dS )zHelper for `read_scalars`.)rS   rT   value)r   ZScalarDatumrS   rT   r   rm   rc   itemrX   r   r   r   r:     s
   r:   c                 C   s   t j| j| jt| jdS )zHelper for `read_tensors`.)rS   rT   numpy)r   ZTensorDatumrS   rT   r   rm   rc   r   r   r   r   r@     s
   
r@   c                    s@   t  j}t fddt|D }tj j j|dS )z!Helper for `read_blob_sequences`.c              
   3   s*    | ]}t t j|V  qd S r#   )r   ZBlobReferencer   rS   )r,   idxrX   r   r4   r    r!   r   r   rj     s    
z/_convert_blob_sequence_event.<locals>.<genexpr>)rT   rS   values)rb   rc   tupleranger   ZBlobSequenceDatumrT   rS   )r   r4   r    r!   rX   Z	num_blobsr   r   r   r   rf     s   
rf   c                 C   s    d}| j jD ]}||j9 }q|S )zCompute the number of elements in a tensor.

    This does not deserialize the full tensor contents.

    Args:
      tensor_proto: A `tensorboard.compat.proto.tensor_pb2.TensorProto`.

    Returns:
      A non-negative `int`.
    rB   )Ztensor_shapedimsize)rc   rJ   r   r   r   r   rb     s   rb   c                    sn   |t  kr
t S |dkrg S tdtt  d |d }|  |t  d g7 } fdd|D S )av  Downsample `xs` to at most `k` elements.

    If `k` is larger than `xs`, then the contents of `xs` itself will be
    returned. If `k` is smaller than `xs`, the last element of `xs` will
    always be included (unless `k` is `0`) and the preceding elements
    will be selected uniformly at random.

    This differs from `random.sample` in that it returns a subsequence
    (i.e., order is preserved) and that it permits `k > len(xs)`.

    The random number generator will always be `random.Random(0)`, so
    this function is deterministic (within a Python process).

    Args:
      xs: A sequence (`collections.abc.Sequence`).
      k: A non-negative integer.

    Returns:
      A new list whose elements are a subsequence of `xs` of length
      `min(k, len(xs))` and that is guaranteed to include the last
      element of `xs`, uniformly selected among such subsequences.
    r   rB   c                    s   g | ]} | qS r   r   )r,   ixsr   r   r-     r\   z_downsample.<locals>.<listcomp>)rC   listrandomRandomsampler   sort)r   kindicesr   r   r   r]     s   "r]   )__doc__ry   rv   r   Ztensorboardr   Ztensorboard.compat.protor   Ztensorboard.datar   Ztensorboard.utilr   r   Z
get_loggerloggerZDataProviderr   r   rk   r:   r@   rf   rb   r]   r   r   r   r   <module>   s(     N)		