o
    ĎiM                     @   s   d Z ddl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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)selfmultiplexerlogdir r   n/home/jeff/fluffinator/venv/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 )NRequestContextz%ctx must be a RequestContext; got: %r)type__name__	TypeError)r
   ctxr   r   r   _validate_context0   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_id4   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_tagH   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   FirstEventTimestamp
ValueError)r
   run_nameer   r   r   _get_first_event_timestampQ   s   z2MultiplexerDataProvider._get_first_event_timestampNc                C   s"   |  | | | tj| jdS )N)data_location)r   r   r   ExperimentMetadatar	   r
   r   r   r   r   r   experiment_metadataW   s   

z+MultiplexerDataProvider.experiment_metadatac                C   s   |  | | | | j S r&   )r   r   r   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 ))run_idr)   
start_time)r   Runr+   ).0r#   r   r   r   
<listcomp>i   s    z5MultiplexerDataProvider.list_runs.<locals>.<listcomp>)r   r   r   Runsr.   r   r   r   	list_runsf   s
   


z!MultiplexerDataProvider.list_runs)r"   c                C   2   |  | | | | ||tj}| tj|S r&   )r   r   _indexr   DATA_CLASS_SCALAR_listr   ScalarTimeSeriesr
   r   r   plugin_namer"   indexr   r   r   list_scalarsr      

z$MultiplexerDataProvider.list_scalars)r   r"   c                C   <   |  | | | | | | ||tj}| t||S r&   )r   r   r   r:   r   r;   _read_convert_scalar_eventr
   r   r   r?   r   r"   r@   r   r   r   read_scalars|      
	

z$MultiplexerDataProvider.read_scalarsc                C   s|   |  | | | | ||tj}tt}| D ] \}}| D ]\}	}
| j	
||	}|r:t|d || |	< q#q|S )N)r   r   r:   r   r;   collectionsdefaultdictdictitemsr   TensorsrE   )r
   r   r   r?   r"   r@   run_tag_to_last_scalar_datumr#   tags_for_runr$   metadataeventsr   r   r   read_last_scalars   s   




z)MultiplexerDataProvider.read_last_scalarsc                C   r9   r&   )r   r   r:   r   DATA_CLASS_TENSORr<   r   TensorTimeSeriesr>   r   r   r   list_tensors   rB   z$MultiplexerDataProvider.list_tensorsc                C   rC   r&   )r   r   r   r:   r   rT   rD   _convert_tensor_eventrF   r   r   r   read_tensors   rH   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   RunTagFilterr    r!   lenr   SummaryMetadataKeyErrorAllSummaryMetadatarM   
data_classplugin_datar?   )r
   r?   r"   data_class_filterr    r!   r#   r$   rQ   all_metadataresulttag_to_metadataresult_for_runr   r   r   r:      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)
rM   r   rN   step	wall_timer\   r`   contentsummary_descriptionrj   )r
   construct_time_seriesr@   rc   r#   rd   re   r$   summary_metadatarf   rg   eventr   r   r   r<      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   r5   r*   convert_eventr   r   r6   &      z1MultiplexerDataProvider._read.<locals>.<listcomp>)rM   r   rN   _downsample)r
   rt   r@   r   rc   r#   rP   re   r$   rQ   rR   datar   rs   r   rD     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)rf   rg   
max_lengthrh   ri   rj   )r   r   r:   r   DATA_CLASS_BLOB_SEQUENCErM   r   rN   rk   rl   _tensor_sizetensor_protor   BlobSequenceTimeSeriesr`   rm   rn   rj   )r
   r   r   r?   r"   r@   rc   r#   rd   re   r$   rQ   rf   rg   rx   rq   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   )r5   rk   datumr   r   r   r6   h  ru   z?MultiplexerDataProvider.read_blob_sequences.<locals>.<listcomp>)r   r   r   r:   r   ry   rM   r   rN   rk   _convert_blob_sequence_eventsortedrv   )r
   r   r   r?   r   r"   r@   rc   r#   r!   re   r$   rR   data_by_steprq   rw   r   r   r   read_blob_sequencesL  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&   rk   rr   r   r   r   	<genexpr>|  s    z4MultiplexerDataProvider.read_blob.<locals>.<genexpr>z%s: no such step %r)r   _decode_blob_keyr   r\   r_   r   ry   r   NotFoundErrorrN   nextr   make_ndarrayr{   )r
   r   blob_keyunused_experiment_idr?   r#   r$   r@   rp   tensor_eventsmatching_steptensorr   r   r   	read_blobl  s$   

z!MultiplexerDataProvider.read_blobr&   )r   
__module____qualname__r   r   r   r   r   r%   r+   r/   r1   r8   rA   rG   rS   rV   rX   r:   r<   rD   r~   r   r   r   r   r   r   r       s\    

	



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   r?   r#   r$   rk   r@   stringified
bytesifiedencodedr   r   r   _encode_blob_key  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==r   )r   urlsafe_b64decoder   r   loads)	keydecodedr   r   r?   r#   r$   rk   r@   r   r   r   r     s   

r   c                 C   s    t j| j| jt| j dS )zHelper for `read_scalars`.)rk   rl   value)r   ScalarDatumrk   rl   r   r   r{   itemrq   r   r   r   rE     s
   rE   c                 C   s   t j| j| jt| jdS )zHelper for `read_tensors`.)rk   rl   numpy)r   TensorDatumrk   rl   r   r   r{   r   r   r   r   rW     s
   
rW   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   BlobReferencer   rk   )r5   idxrq   r   r?   r#   r$   r   r   r     s    
z/_convert_blob_sequence_event.<locals>.<genexpr>)rl   rk   values)rz   r{   tupleranger   BlobSequenceDatumrl   rk   )r   r?   r#   r$   rq   	num_blobsr   r   r   r   r     s   
r   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`.
    rY   )tensor_shapedimsize)r{   rc   r   r   r   r   rz     s   rz   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   rY   c                    s   g | ]} | qS r   r   )r5   ixsr   r   r6     ru   z_downsample.<locals>.<listcomp>)r[   listrandomRandomsampler   sort)r   kindicesr   r   r   rv     s   "rv   )__doc__r   rJ   r   r   tensorboardr   tensorboard.compat.protor   tensorboard.datar   tensorboard.utilr   r   
get_loggerloggerDataProviderr   r   r   rE   rW   r   rz   rv   r   r   r   r   <module>   s*     f)		