o
    i eoW                     @   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 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ddddZdZeejejgZeejgZdd Zdd Zdd Zdd Z dd Z!dd Z"dd Z#dd  Z$G d!d" d"ej%Z&dS )#zThe TensorBoard metrics plugin.    N)wrappers)errors)plugin_util)	http_util)provider)base_plugin)metadataz	image/bmpz	image/gifz
image/jpegz	image/pngzimage/svg+xml)bmpgifjpegpngsvgzapplication/octet-streamc                 C   sj   t t}t t}|  D ]"\}}| D ]\}}|j}t|r/|| | || | qq||fS )a  Gets maps from tags to descriptions, and descriptions to runs.

    Args:
        mapping: a nested map `d` such that `d[run][tag]` is a time series
          produced by DataProvider's `list_*` methods.

    Returns:
        A tuple containing
            tag_to_descriptions: A map from tag strings to a set of description
                strings.
            description_to_runs: A map from description strings to a set of run
                strings.
    )collectionsdefaultdictsetitemsdescriptionlenadd)mappingtag_to_descriptionsdescription_to_runsruntag_to_contenttag	metadatumr    r   Y/var/www/myenv/lib/python3.10/site-packages/tensorboard/plugins/metrics/metrics_plugin.py_get_tag_description_info4   s   

r   c           	      C   sl   g }| D ](}t || }t|dkrdnd}d| d d| }|d | }|| qd}|d| S )	a  Creates a single description from a set of descriptions.

    Descriptions may be composites when a single tag has different descriptions
    across multiple runs.

    Args:
        descriptions: A list of description strings.
        description_to_runs: A map from description strings to a set of run
            strings.

    Returns:
        The combined description string.
       runsr   z## For z: z, 
z# Multiple descriptions
)sortedr   joinappend)	descriptionsr   prefixed_descriptionsr   r    run_or_runs
run_headerdescription_htmlheaderr   r   r   _build_combined_descriptionN   s   r+   c                 C   sX   t | \}}i }|D ]}t|| }t|dkr|d }nt||}t|||< q
|S )a  Returns a map of tags to descriptions.

    Args:
        mapping: a nested map `d` such that `d[run][tag]` is a time series
          produced by DataProvider's `list_*` methods.

    Returns:
        A map from tag strings to description HTML strings. E.g.
        {
            "loss": "<h1>Multiple descriptions</h1><h2>For runs: test, train
            </h2><p>...</p>",
            "loss2": "<p>The lossy details</p>",
        }
    r   r   )r   r"   r   r+   r   markdown_to_safe_html)r   r   r   resultr   r%   r   r   r   r   _get_tag_to_descriptionh   s   
r.   c                    s    fdd D S )aM  Returns a map of run names to a list of tag names.

    Args:
        mapping: a nested map `d` such that `d[run][tag]` is a time series
          produced by DataProvider's `list_*` methods.

    Returns:
        A map from run strings to a list of tag strings. E.g.
            {"loss001a": ["actor/loss", "critic/loss"], ...}
    c                    s   i | ]	}|t  | qS r   )r"   .0r   r   r   r   
<dictcomp>   s    z%_get_run_tag_info.<locals>.<dictcomp>r   r1   r   r1   r   _get_run_tag_info   s   r3   c                 C      t | t| dS )a  Prepares a scalar or histogram mapping for client consumption.

    Args:
        mapping: a nested map `d` such that `d[run][tag]` is a time series
          produced by DataProvider's `list_*` methods.

    Returns:
        A dict with the following fields:
            runTagInfo: the return type of `_get_run_tag_info`
            tagDescriptions: the return type of `_get_tag_to_description`
    )
runTagInfotagDescriptions)r3   r.   r1   r   r   r   _format_basic_mapping   s   r7   c                 C   sH   |d }g }| D ]}t |j|krq||j|j|j| jd q|S )a  Formats image metadata from a list of BlobSequenceDatum's for clients.

    This expects that frontend clients need to access images based on the
    run+tag+sample.

    Args:
        sorted_datum_list: a list of DataProvider's `BlobSequenceDatum`, sorted by
            step. This can be produced via DataProvider's `read_blob_sequences`.
        sample: zero-indexed integer for the requested sample.

    Returns:
        A list of `ImageStepDatum` (see http_api.md).
       )stepwallTimeimageId)r   valuesr$   r9   	wall_timeblob_key)sorted_datum_listsampleindex	step_datadatumr   r   r   !_format_image_blob_sequence_datum   s   
rD   c                 C   sL   t t}|  D ]\}}| D ]\}}d|jd i|| |< qq	t|S )a
  Returns a map of tag names to run information.

    Args:
        mapping: the result of DataProvider's `list_blob_sequences`.

    Returns:
        A nested map from run strings to tag string to image info, where image
        info is an object of form {"maxSamplesPerStep": num}. For example,
        {
            "reshaped": {
                "test": {"maxSamplesPerStep": 1},
                "train": {"maxSamplesPerStep": 1}
            },
            "convolved": {"test": {"maxSamplesPerStep": 50}},
        }
    maxSamplesPerStepr8   )r   r   dictr   
max_length)r   tag_run_image_infor   r   r   r   r   r   r   _get_tag_run_image_info   s   

rI   c                 C   r4   )aV  Prepares an image mapping for client consumption.

    Args:
        mapping: the result of DataProvider's `list_blob_sequences`.

    Returns:
        A dict with the following fields:
            tagRunSampledInfo: the return type of `_get_tag_run_image_info`
            tagDescriptions: the return type of `_get_tag_description_info`
    )r6   tagRunSampledInfo)r.   rI   r1   r   r   r   _format_image_mapping   s   rK   c                   @   s   e Zd ZdZejZdd Zdd Zdd Z	dd	 Z
d
d Zejjdd Zd)ddZdd Zejjd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$ Zejjd%d& Zd'd( ZdS )*MetricsPluginzMetrics Plugin for TensorBoard.c                 C   sr   |j | _|jpi }|tjd|tjd|tjdd| _t	j
ddd| _t	j
ddd| _t	j
d	dd| _d
S )zInstantiates MetricsPlugin.

        Args:
            context: A base_plugin.TBContext instance. MetricsLoader checks that
                it contains a valid `data_provider`.
        i  3   
   )scalars
histogramsimageszscalar time seriesr   )	data_kindlatest_known_versionzhistogram time serieszimage time seriesN)data_provider_data_providersampling_hintsgetscalar_metadataPLUGIN_NAMEhistogram_metadataimage_metadata_plugin_downsamplingr   _MetadataVersionChecker_scalar_version_checker_histogram_version_checker_image_version_checker)selfcontextrV   r   r   r   __init__   s(   
zMetricsPlugin.__init__c                 C   s   t jdddS )NTzTime Series)is_ng_componenttab_name)r   FrontendMetadatara   r   r   r   frontend_metadata  s   zMetricsPlugin.frontend_metadatac                 C   s   | j | j| jdS )N)z/tagsz/timeSeriesz
/imageData)_serve_tags_serve_time_series_serve_image_datarg   r   r   r   get_plugin_apps  s   zMetricsPlugin.get_plugin_appsc                 C   s   t jtjtjfS N)rX   rY   rZ   r[   rg   r   r   r   data_plugin_names&  s   zMetricsPlugin.data_plugin_namesc                 C   s   dS )NFr   rg   r   r   r   	is_active-  s   zMetricsPlugin.is_activec                 C   s4   t |j}t |j}| j||d}t||dS )N)
experimentapplication/json)r   rb   environexperiment_id
_tags_implr   Respond)ra   requestctxrp   rA   r   r   r   ri   0  s   zMetricsPlugin._serve_tagsNc                 C   s   | j j||tjd}| |tj| j}| j j||tjd}|du r#i }| |tj| j	}| j j
||tjd}|du r<i }| |tj| j}i }t||d< t||d< t||d< |S )a  Returns tag metadata for a given experiment's logged metrics.

        Args:
            ctx: A `tensorboard.context.RequestContext` value.
            experiment: optional string ID of the request's experiment.

        Returns:
            A nested dict 'd' with keys in ("scalars", "histograms", "images")
                and values being the return type of _format_*mapping.
        )rs   plugin_nameNrO   rP   rQ   )rU   list_scalarsrX   rY   _filter_by_versionparse_plugin_metadatar^   list_tensorsrZ   r_   list_blob_sequencesr[   r`   r7   rK   )ra   rw   rp   scalar_mappinghistogram_mappingimage_mappingr-   r   r   r   rt   7  sN   zMetricsPlugin._tags_implc           
      C   s^   dd |D }|  D ]!\}}|  D ]\}}||j}	||	j||s%q||| |< qq|S )z@Filter `DataProvider.list_*` output by summary metadata version.c                 S   s   i | ]}|i qS r   r   r/   r   r   r   r2   o  s    z4MetricsPlugin._filter_by_version.<locals>.<dictcomp>)r   plugin_contentokversion)
ra   r   parse_metadataversion_checkerr-   r   r   r   r   mdr   r   r   rz   m  s   
z MetricsPlugin._filter_by_versionc                 C   s   t |j}t |j}|jdkr|jd}n|jd}|s%t	dzt
|}W n ty8   t	dw | |||}t||dS )NPOSTrequestszMissing 'requests' fieldz"Unable to parse 'requests' as JSONrq   )r   rb   rr   rs   methodformrW   argsr   InvalidArgumentErrorjsonloads
ValueError_time_series_implr   ru   )ra   rv   rw   rp   series_requests_stringseries_requestsresponser   r   r   rj   x  s    

z MetricsPlugin._serve_time_seriesc                    s    fdd|D }|S )a~  Constructs a list of responses from a list of series requests.

        Args:
            ctx: A `tensorboard.context.RequestContext` value.
            experiment: string ID of the request's experiment.
            series_requests: a list of `TimeSeriesRequest` dicts (see http_api.md).

        Returns:
            A list of `TimeSeriesResponse` dicts (see http_api.md).
        c                    s   g | ]	}  |qS r   )_get_time_series)r0   rv   rw   rp   ra   r   r   
<listcomp>  s    z3MetricsPlugin._time_series_impl.<locals>.<listcomp>r   )ra   rw   rp   r   	responsesr   r   r   r     s   zMetricsPlugin._time_series_implc                 C   sZ   | d}| d}| d}| d}||d}t|tr"||d< t|tr+||d< |S )Nr   r   pluginr@   )r   r   )rW   
isinstancestrint)ra   series_requestr   r   r   r@   r   r   r   r   _create_base_response  s   






z#MetricsPlugin._create_base_responsec                 C   s   | d}| d}| d}| d}t|tsdS |tjkr,|tjkr,|tjkr,dS |tv r7t|ts7dS |tv rBt|t	sBdS d S )	Nr   r   r   r@   zMissing tagzInvalid pluginzMissing runzMissing sample)
rW   r   r   rX   rY   rZ   r[   _SINGLE_RUN_PLUGINS_SAMPLED_PLUGINSr   )ra   r   r   r   r   r@   r   r   r   _get_invalid_request_error  s   







z(MetricsPlugin._get_invalid_request_errorc                 C   s   | d}| d}| d}| d}| |}| |}	|	r&|	|d< |S |r+|gnd}
d}|tjkr<| ||||
}|tjkrI| ||||
}|tjkrW| 	|||||
}||d< |S )aY  Returns time series data for a given tag, plugin.

        Args:
            ctx: A `tensorboard.context.RequestContext` value.
            experiment: string ID of the request's experiment.
            series_request: a `TimeSeriesRequest` (see http_api.md).

        Returns:
            A `TimeSeriesResponse` dict (see http_api.md).
        r   r   r   r@   errorNrunToSeries)
rW   r   r   rX   rY   _get_run_to_scalar_seriesrZ   _get_run_to_histogram_seriesr[   _get_run_to_image_series)ra   rw   rp   r   r   r   r   r@   r   request_errorr    run_to_seriesr   r   r   r     s2   









zMetricsPlugin._get_time_seriesc           
   	   C   sh   | j j||tj| jd tj||gdd}i }| D ]\}}||vr$qdd || D }	|	||< q|S )a  Builds a run-to-scalar-series dict for client consumption.

        Args:
            ctx: A `tensorboard.context.RequestContext` value.
            experiment: a string experiment id.
            tag: string of the requested tag.
            runs: optional list of run names as strings.

        Returns:
            A map from string run names to `ScalarStepDatum` (see http_api.md).
        rO   r    tagsrs   rx   
downsamplerun_tag_filterc                 S   s   g | ]}|j |j|jd qS ))r:   r9   value)r=   r9   r   r0   rC   r   r   r   r     s    z;MetricsPlugin._get_run_to_scalar_series.<locals>.<listcomp>)rU   read_scalarsrX   rY   r\   r   RunTagFilterr   
ra   rw   rp   r   r    r   r   
result_runtag_datar<   r   r   r   r     s    
z'MetricsPlugin._get_run_to_scalar_seriesc                 C   s   |j  }dd |D }|S )zFormats a histogram datum's bins for client consumption.

        Args:
            datum: a DataProvider's TensorDatum.

        Returns:
            A list of `HistogramBin`s (see http_api.md).
        c                 S   s$   g | ]}|d  |d |d dqS )r   r   r8   )minmaxcountr   )r0   xr   r   r   r     s   $ z>MetricsPlugin._format_histogram_datum_bins.<locals>.<listcomp>)numpytolist)ra   rC   
numpy_listbinsr   r   r   _format_histogram_datum_bins  s   
	z*MetricsPlugin._format_histogram_datum_binsc           
   	      sl    j j||tj jd tj||gdd}i }| D ]\}}||vr$q fdd|| D }	|	||< q|S )a  Builds a run-to-histogram-series dict for client consumption.

        Args:
            ctx: A `tensorboard.context.RequestContext` value.
            experiment: a string experiment id.
            tag: string of the requested tag.
            runs: optional list of run names as strings.

        Returns:
            A map from string run names to `HistogramStepDatum` (see http_api.md).
        rP   r   r   c                    s"   g | ]}|j |j |d qS ))r:   r9   r   )r=   r9   r   r   rg   r   r   r   4  s    z>MetricsPlugin._get_run_to_histogram_series.<locals>.<listcomp>)rU   read_tensorsrZ   rY   r\   r   r   r   r   r   rg   r   r     s    

z*MetricsPlugin._get_run_to_histogram_seriesc              	   C   sl   | j j||tj| jd tj||gdd}i }| D ]\}}	||	vr$q|	| }
t|
|}|r3|||< q|S )a  Builds a run-to-image-series dict for client consumption.

        Args:
            ctx: A `tensorboard.context.RequestContext` value.
            experiment: a string experiment id.
            tag: string of the requested tag.
            sample: zero-indexed integer for the requested sample.
            runs: optional list of run names as strings.

        Returns:
            A `RunToSeries` dict (see http_api.md).
        rQ   )r   r   )	rU   read_blob_sequencesr[   rY   r\   r   r   r   rD   )ra   rw   rp   r   r@   r    r   r   r   r   blob_sequence_datum_listseriesr   r   r   r   @  s&   z&MetricsPlugin._get_run_to_image_seriesc                 C   sB   t |j}|jd }|std| ||\}}t|||S )zServes an individual image.r;   zMissing 'imageId' field)	r   rb   rr   r   r   r   _image_data_implr   ru   )ra   rv   rw   r>   datacontent_typer   r   r   rk   b  s   

zMetricsPlugin._serve_image_datac                 C   s0   | j j||d}td|}t|t}||fS )ao  Gets the image data for a blob key.

        Args:
            ctx: A `tensorboard.context.RequestContext` value.
            blob_key: a string identifier for a DataProvider blob.

        Returns:
            A tuple containing:
              data: a raw bytestring of the requested image's contents.
              content_type: a string HTTP content type.
        )r>   N)rU   	read_blobimghdrwhat_IMGHDR_TO_MIMETYPErW   _DEFAULT_IMAGE_MIMETYPE)ra   rw   r>   r   
image_typer   r   r   r   r   m  s   zMetricsPlugin._image_data_implrm   )__name__
__module____qualname____doc__r   rY   rx   rc   rh   rl   rn   ro   r   Requestapplicationri   rt   rz   rj   r   r   r   r   r   r   r   r   rk   r   r   r   r   r   rL      s2    !

6
)$$"

rL   )'r   r   r   r   werkzeugr   tensorboardr   r   tensorboard.backendr   tensorboard.datar   tensorboard.pluginsr   tensorboard.plugins.histogramr   rZ   tensorboard.plugins.imager[   tensorboard.plugins.metricstensorboard.plugins.scalarrX   r   r   	frozensetrY   r   r   r   r+   r.   r3   r7   rD   rI   rK   TBPluginrL   r   r   r   r   <module>   sD   
! 