# Copyright 2019 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Unit tests for `tensorboard.backend.event_processing.data_provider`."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os

import six
from six.moves import xrange  # pylint: disable=redefined-builtin
import numpy as np

from tensorboard import context
from tensorboard.backend.event_processing import data_provider
from tensorboard.backend.event_processing import (
    plugin_event_multiplexer as event_multiplexer,
)
from tensorboard.compat.proto import summary_pb2
from tensorboard.data import provider as base_provider
from tensorboard.plugins.graph import metadata as graph_metadata
from tensorboard.plugins.histogram import metadata as histogram_metadata
from tensorboard.plugins.histogram import summary_v2 as histogram_summary
from tensorboard.plugins.scalar import metadata as scalar_metadata
from tensorboard.plugins.scalar import summary_v2 as scalar_summary
from tensorboard.plugins.image import metadata as image_metadata
from tensorboard.plugins.image import summary_v2 as image_summary
from tensorboard.util import tensor_util
import tensorflow.compat.v1 as tf1
import tensorflow.compat.v2 as tf


tf1.enable_eager_execution()


class MultiplexerDataProviderTest(tf.test.TestCase):
    def setUp(self):
        super(MultiplexerDataProviderTest, self).setUp()
        self.logdir = self.get_temp_dir()
        self.ctx = context.RequestContext()

        logdir = os.path.join(self.logdir, "polynomials")
        with tf.summary.create_file_writer(logdir).as_default():
            for i in xrange(10):
                scalar_summary.scalar(
                    "square", i ** 2, step=2 * i, description="boxen"
                )
                scalar_summary.scalar("cube", i ** 3, step=3 * i)

        logdir = os.path.join(self.logdir, "waves")
        with tf.summary.create_file_writer(logdir).as_default():
            for i in xrange(10):
                scalar_summary.scalar("sine", tf.sin(float(i)), step=i)
                scalar_summary.scalar(
                    "square", tf.sign(tf.sin(float(i))), step=i
                )
                # Summary with rank-0 data but not owned by the scalars plugin.
                metadata = summary_pb2.SummaryMetadata()
                metadata.plugin_data.plugin_name = "marigraphs"
                metadata.data_class = summary_pb2.DATA_CLASS_SCALAR
                tf.summary.write(
                    "high_tide", tensor=i, step=i, metadata=metadata
                )
                # Summary with rank-1 data of scalar data class (bad!).
                metadata = summary_pb2.SummaryMetadata()
                metadata.plugin_data.plugin_name = "greetings"
                metadata.data_class = summary_pb2.DATA_CLASS_SCALAR
                tf.summary.write(
                    "bad", tensor=[i, i], step=i, metadata=metadata
                )

        logdir = os.path.join(self.logdir, "lebesgue")
        with tf.summary.create_file_writer(logdir).as_default():
            data = [
                ("very smooth", (0.0, 0.25, 0.5, 0.75, 1.0), "uniform"),
                ("very smoothn't", (0.0, 0.01, 0.99, 1.0), "bimodal"),
            ]
            for (description, distribution, name) in data:
                tensor = tf.constant([distribution], dtype=tf.float64)
                for i in xrange(1, 11):
                    histogram_summary.histogram(
                        name, tensor * i, step=i, description=description
                    )

        logdir = os.path.join(self.logdir, "mondrian")
        with tf.summary.create_file_writer(logdir).as_default():
            data = [
                ("red", (221, 28, 38), "top-right"),
                ("blue", (1, 91, 158), "bottom-left"),
                ("yellow", (239, 220, 111), "bottom-right"),
            ]
            for (name, color, description) in data:
                image_1x1 = tf.constant([[[color]]], dtype=tf.uint8)
                for i in xrange(1, 11):
                    # Use a non-monotonic sequence of sample sizes to
                    # test `max_length` calculation.
                    k = 6 - abs(6 - i)  # 1, .., 6, .., 2
                    # a `k`-sample image summary of `i`-by-`i` images
                    image = tf.tile(image_1x1, [k, i, i, 1])
                    image_summary.image(
                        name,
                        image,
                        step=i,
                        description=description,
                        max_outputs=99,
                    )

    def create_multiplexer(self):
        multiplexer = event_multiplexer.EventMultiplexer()
        multiplexer.AddRunsFromDirectory(self.logdir)
        multiplexer.Reload()
        return multiplexer

    def create_provider(self):
        multiplexer = self.create_multiplexer()
        return data_provider.MultiplexerDataProvider(multiplexer, self.logdir)

    def test_data_location(self):
        provider = self.create_provider()
        result = provider.data_location(self.ctx, experiment_id="unused")
        self.assertEqual(result, self.logdir)

    def test_list_plugins_with_no_graph(self):
        provider = self.create_provider()
        result = provider.list_plugins(self.ctx, experiment_id="unused")
        self.assertItemsEqual(
            result,
            [
                "greetings",
                "marigraphs",
                histogram_metadata.PLUGIN_NAME,
                image_metadata.PLUGIN_NAME,
                scalar_metadata.PLUGIN_NAME,
            ],
        )

    def test_list_plugins_with_graph(self):
        with tf.compat.v1.Graph().as_default() as graph:
            writer = tf.compat.v1.summary.FileWriter(self.logdir)
            writer.add_graph(graph)
            writer.flush()

        provider = self.create_provider()
        result = provider.list_plugins(self.ctx, experiment_id="unused")
        self.assertItemsEqual(
            result,
            [
                "greetings",
                "marigraphs",
                graph_metadata.PLUGIN_NAME,
                histogram_metadata.PLUGIN_NAME,
                image_metadata.PLUGIN_NAME,
                scalar_metadata.PLUGIN_NAME,
            ],
        )

    def test_list_runs(self):
        # We can't control the timestamps of events written to disk (without
        # manually reading the tfrecords, modifying the data, and writing
        # them back out), so we provide a fake multiplexer instead.
        start_times = {
            "second_2": 2.0,
            "first": 1.5,
            "no_time": None,
            "second_1": 2.0,
        }

        class FakeMultiplexer(object):
            def Runs(multiplexer):
                result = ["second_2", "first", "no_time", "second_1"]
                self.assertItemsEqual(result, start_times)
                return result

            def FirstEventTimestamp(multiplexer, run):
                self.assertIn(run, start_times)
                result = start_times[run]
                if result is None:
                    raise ValueError("No event timestep could be found")
                else:
                    return result

        multiplexer = FakeMultiplexer()
        provider = data_provider.MultiplexerDataProvider(
            multiplexer, "fake_logdir"
        )
        result = provider.list_runs(self.ctx, experiment_id="unused")
        self.assertItemsEqual(
            result,
            [
                base_provider.Run(
                    run_id=run, run_name=run, start_time=start_time
                )
                for (run, start_time) in six.iteritems(start_times)
            ],
        )

    def test_list_scalars_all(self):
        provider = self.create_provider()
        result = provider.list_scalars(
            self.ctx,
            experiment_id="unused",
            plugin_name=scalar_metadata.PLUGIN_NAME,
            run_tag_filter=None,
        )
        self.assertItemsEqual(result.keys(), ["polynomials", "waves"])
        self.assertItemsEqual(result["polynomials"].keys(), ["square", "cube"])
        self.assertItemsEqual(result["waves"].keys(), ["square", "sine"])
        sample = result["polynomials"]["square"]
        self.assertIsInstance(sample, base_provider.ScalarTimeSeries)
        self.assertEqual(sample.max_step, 18)
        # nothing to test for wall time, as it can't be mocked out
        self.assertEqual(sample.plugin_content, b"")
        self.assertEqual(
            sample.display_name, ""
        )  # not written by V2 summary ops
        self.assertEqual(sample.description, "boxen")

    def test_list_scalars_filters(self):
        provider = self.create_provider()

        result = provider.list_scalars(
            self.ctx,
            experiment_id="unused",
            plugin_name=scalar_metadata.PLUGIN_NAME,
            run_tag_filter=base_provider.RunTagFilter(["waves"], ["square"]),
        )
        self.assertItemsEqual(result.keys(), ["waves"])
        self.assertItemsEqual(result["waves"].keys(), ["square"])

        result = provider.list_scalars(
            self.ctx,
            experiment_id="unused",
            plugin_name=scalar_metadata.PLUGIN_NAME,
            run_tag_filter=base_provider.RunTagFilter(
                tags=["square", "quartic"]
            ),
        )
        self.assertItemsEqual(result.keys(), ["polynomials", "waves"])
        self.assertItemsEqual(result["polynomials"].keys(), ["square"])
        self.assertItemsEqual(result["waves"].keys(), ["square"])

        result = provider.list_scalars(
            self.ctx,
            experiment_id="unused",
            plugin_name=scalar_metadata.PLUGIN_NAME,
            run_tag_filter=base_provider.RunTagFilter(runs=["waves", "hugs"]),
        )
        self.assertItemsEqual(result.keys(), ["waves"])
        self.assertItemsEqual(result["waves"].keys(), ["sine", "square"])

        result = provider.list_scalars(
            self.ctx,
            experiment_id="unused",
            plugin_name=scalar_metadata.PLUGIN_NAME,
            run_tag_filter=base_provider.RunTagFilter(["un"], ["likely"]),
        )
        self.assertEqual(result, {})

    def test_read_scalars(self):
        multiplexer = self.create_multiplexer()
        provider = data_provider.MultiplexerDataProvider(
            multiplexer, self.logdir
        )

        run_tag_filter = base_provider.RunTagFilter(
            runs=["waves", "polynomials", "unicorns"],
            tags=["sine", "square", "cube", "iridescence"],
        )
        result = provider.read_scalars(
            self.ctx,
            experiment_id="unused",
            plugin_name=scalar_metadata.PLUGIN_NAME,
            run_tag_filter=run_tag_filter,
            downsample=100,
        )

        self.assertItemsEqual(result.keys(), ["polynomials", "waves"])
        self.assertItemsEqual(result["polynomials"].keys(), ["square", "cube"])
        self.assertItemsEqual(result["waves"].keys(), ["square", "sine"])
        for run in result:
            for tag in result[run]:
                tensor_events = multiplexer.Tensors(run, tag)
                self.assertLen(result[run][tag], len(tensor_events))
                for (datum, event) in zip(result[run][tag], tensor_events):
                    self.assertEqual(datum.step, event.step)
                    self.assertEqual(datum.wall_time, event.wall_time)
                    self.assertEqual(
                        datum.value,
                        tensor_util.make_ndarray(event.tensor_proto).item(),
                    )

    def test_read_scalars_downsamples(self):
        # TODO(@wchargin): Verify that this always includes the most
        # recent datum, as specified by the interface.
        multiplexer = self.create_multiplexer()
        provider = data_provider.MultiplexerDataProvider(
            multiplexer, self.logdir
        )
        result = provider.read_scalars(
            self.ctx,
            experiment_id="unused",
            plugin_name=scalar_metadata.PLUGIN_NAME,
            downsample=3,
        )
        self.assertLen(result["waves"]["sine"], 3)

    def test_read_scalars_but_not_rank_0(self):
        provider = self.create_provider()
        run_tag_filter = base_provider.RunTagFilter(["waves"], ["bad"])
        # No explicit checks yet.
        with six.assertRaisesRegex(
            self,
            ValueError,
            "can only convert an array of size 1 to a Python scalar",
        ):
            provider.read_scalars(
                self.ctx,
                experiment_id="unused",
                plugin_name="greetings",
                run_tag_filter=run_tag_filter,
                downsample=100,
            )

    def test_list_tensors_all(self):
        provider = self.create_provider()
        result = provider.list_tensors(
            self.ctx,
            experiment_id="unused",
            plugin_name=histogram_metadata.PLUGIN_NAME,
            run_tag_filter=None,
        )
        self.assertItemsEqual(result.keys(), ["lebesgue"])
        self.assertItemsEqual(result["lebesgue"].keys(), ["uniform", "bimodal"])
        sample = result["lebesgue"]["uniform"]
        self.assertIsInstance(sample, base_provider.TensorTimeSeries)
        self.assertEqual(sample.max_step, 10)
        # nothing to test for wall time, as it can't be mocked out
        self.assertEqual(sample.plugin_content, b"")
        self.assertEqual(
            sample.display_name, ""
        )  # not written by V2 summary ops
        self.assertEqual(sample.description, "very smooth")

    def test_list_tensors_filters(self):
        provider = self.create_provider()

        # Quick check only, as scalars and tensors use the same underlying
        # filtering implementation.
        result = provider.list_tensors(
            self.ctx,
            experiment_id="unused",
            plugin_name=histogram_metadata.PLUGIN_NAME,
            run_tag_filter=base_provider.RunTagFilter(
                ["lebesgue"], ["uniform"]
            ),
        )
        self.assertItemsEqual(result.keys(), ["lebesgue"])
        self.assertItemsEqual(result["lebesgue"].keys(), ["uniform"])

    def test_read_tensors(self):
        multiplexer = self.create_multiplexer()
        provider = data_provider.MultiplexerDataProvider(
            multiplexer, self.logdir
        )

        run_tag_filter = base_provider.RunTagFilter(
            runs=["lebesgue"],
            tags=["uniform", "bimodal"],
        )
        result = provider.read_tensors(
            self.ctx,
            experiment_id="unused",
            plugin_name=histogram_metadata.PLUGIN_NAME,
            run_tag_filter=run_tag_filter,
            downsample=100,
        )

        self.assertItemsEqual(result.keys(), ["lebesgue"])
        self.assertItemsEqual(result["lebesgue"].keys(), ["uniform", "bimodal"])
        for run in result:
            for tag in result[run]:
                tensor_events = multiplexer.Tensors(run, tag)
                self.assertLen(result[run][tag], len(tensor_events))
                for (datum, event) in zip(result[run][tag], tensor_events):
                    self.assertEqual(datum.step, event.step)
                    self.assertEqual(datum.wall_time, event.wall_time)
                    np.testing.assert_equal(
                        datum.numpy,
                        tensor_util.make_ndarray(event.tensor_proto),
                    )

    def test_read_tensors_downsamples(self):
        multiplexer = self.create_multiplexer()
        provider = data_provider.MultiplexerDataProvider(
            multiplexer, self.logdir
        )
        result = provider.read_tensors(
            self.ctx,
            experiment_id="unused",
            plugin_name=histogram_metadata.PLUGIN_NAME,
            downsample=3,
        )
        self.assertLen(result["lebesgue"]["uniform"], 3)

    def test_list_blob_sequences(self):
        provider = self.create_provider()

        with self.subTest("finds all time series for a plugin"):
            result = provider.list_blob_sequences(
                self.ctx,
                experiment_id="unused",
                plugin_name=image_metadata.PLUGIN_NAME,
            )
            self.assertItemsEqual(result.keys(), ["mondrian"])
            self.assertItemsEqual(
                result["mondrian"].keys(), ["red", "blue", "yellow"]
            )
            sample = result["mondrian"]["blue"]
            self.assertIsInstance(sample, base_provider.BlobSequenceTimeSeries)
            self.assertEqual(sample.max_step, 10)
            # nothing to test for wall time, as it can't be mocked out
            self.assertEqual(sample.plugin_content, b"")
            self.assertEqual(sample.max_length, 6 + 2)
            self.assertEqual(sample.description, "bottom-left")
            self.assertEqual(sample.display_name, "")

        with self.subTest("filters by run/tag"):
            result = provider.list_blob_sequences(
                self.ctx,
                experiment_id="unused",
                plugin_name=image_metadata.PLUGIN_NAME,
                run_tag_filter=base_provider.RunTagFilter(
                    runs=["mondrian", "picasso"], tags=["yellow", "green't"]
                ),
            )
            self.assertItemsEqual(result.keys(), ["mondrian"])
            self.assertItemsEqual(result["mondrian"].keys(), ["yellow"])
            self.assertIsInstance(
                result["mondrian"]["yellow"],
                base_provider.BlobSequenceTimeSeries,
            )

    def test_read_blob_sequences_and_read_blob(self):
        provider = self.create_provider()

        with self.subTest("reads all time series for a plugin"):
            result = provider.read_blob_sequences(
                self.ctx,
                experiment_id="unused",
                plugin_name=image_metadata.PLUGIN_NAME,
                downsample=4,
            )
            self.assertItemsEqual(result.keys(), ["mondrian"])
            self.assertItemsEqual(
                result["mondrian"].keys(), ["red", "blue", "yellow"]
            )
            sample = result["mondrian"]["blue"]
            self.assertLen(sample, 4)  # downsampled from 10
            last = sample[-1]
            self.assertIsInstance(last, base_provider.BlobSequenceDatum)
            self.assertEqual(last.step, 10)
            self.assertLen(last.values, 2 + 2)
            blobs = [
                provider.read_blob(self.ctx, blob_key=v.blob_key)
                for v in last.values
            ]
            self.assertEqual(blobs[0], b"10")
            self.assertEqual(blobs[1], b"10")
            self.assertStartsWith(blobs[2], b"\x89PNG")
            self.assertStartsWith(blobs[3], b"\x89PNG")

            blue1 = blobs[2]
            blue2 = blobs[3]
            red1 = provider.read_blob(
                self.ctx,
                blob_key=result["mondrian"]["red"][-1].values[2].blob_key,
            )
            self.assertEqual(blue1, blue2)
            self.assertNotEqual(blue1, red1)

        with self.subTest("filters by run/tag"):
            result = provider.read_blob_sequences(
                self.ctx,
                experiment_id="unused",
                plugin_name=image_metadata.PLUGIN_NAME,
                run_tag_filter=base_provider.RunTagFilter(
                    runs=["mondrian", "picasso"], tags=["yellow", "green't"]
                ),
                downsample=1,
            )
            self.assertItemsEqual(result.keys(), ["mondrian"])
            self.assertItemsEqual(result["mondrian"].keys(), ["yellow"])
            self.assertIsInstance(
                result["mondrian"]["yellow"][0],
                base_provider.BlobSequenceDatum,
            )


class DownsampleTest(tf.test.TestCase):
    """Tests for the `_downsample` private helper function."""

    def test_deterministic(self):
        xs = "abcdefg"
        expected = data_provider._downsample(xs, k=4)
        for _ in range(100):
            actual = data_provider._downsample(xs, k=4)
            self.assertEqual(actual, expected)

    def test_underlong_ok(self):
        xs = list("abcdefg")
        actual = data_provider._downsample(xs, k=10)
        expected = list("abcdefg")
        self.assertIsNot(actual, xs)
        self.assertEqual(actual, expected)

    def test_inorder(self):
        xs = list(range(10000))
        actual = data_provider._downsample(xs, k=100)
        self.assertEqual(actual, sorted(actual))

    def test_zero(self):
        xs = "abcdefg"
        actual = data_provider._downsample(xs, k=0)
        self.assertEqual(actual, [])


if __name__ == "__main__":
    tf.test.main()

[((46, 0, 46, 28), 'tensorflow.compat.v1.enable_eager_execution', 'tf1.enable_eager_execution', ({}, {}), '()', True, 'import tensorflow.compat.v1 as tf1\n'), ((541, 4, 541, 18), 'tensorflow.compat.v2.test.main', 'tf.test.main', ({}, {}), '()', True, 'import tensorflow.compat.v2 as tf\n'), ((53, 19, 53, 43), 'tensorboard.context.RequestContext', 'context.RequestContext', ({}, {}), '()', False, 'from tensorboard import context\n'), ((55, 17, 55, 57), 'os.path.join', 'os.path.join', ({(55, 30, 55, 41): 'self.logdir', (55, 43, 55, 56): '"""polynomials"""'}, {}), "(self.logdir, 'polynomials')", False, 'import os\n'), ((63, 17, 63, 51), 'os.path.join', 'os.path.join', ({(63, 30, 63, 41): 'self.logdir', (63, 43, 63, 50): '"""waves"""'}, {}), "(self.logdir, 'waves')", False, 'import os\n'), ((85, 17, 85, 54), 'os.path.join', 'os.path.join', ({(85, 30, 85, 41): 'self.logdir', (85, 43, 85, 53): '"""lebesgue"""'}, {}), "(self.logdir, 'lebesgue')", False, 'import os\n'), ((98, 17, 98, 54), 'os.path.join', 'os.path.join', ({(98, 30, 98, 41): 'self.logdir', (98, 43, 98, 53): '"""mondrian"""'}, {}), "(self.logdir, 'mondrian')", False, 'import os\n'), ((122, 22, 122, 58), 'tensorboard.backend.event_processing.plugin_event_multiplexer.EventMultiplexer', 'event_multiplexer.EventMultiplexer', ({}, {}), '()', True, 'from tensorboard.backend.event_processing import plugin_event_multiplexer as event_multiplexer\n'), ((129, 15, 129, 78), 'tensorboard.backend.event_processing.data_provider.MultiplexerDataProvider', 'data_provider.MultiplexerDataProvider', ({(129, 53, 129, 64): 'multiplexer', (129, 66, 129, 77): 'self.logdir'}, {}), '(multiplexer, self.logdir)', False, 'from tensorboard.backend.event_processing import data_provider\n'), ((196, 19, 198, 9), 'tensorboard.backend.event_processing.data_provider.MultiplexerDataProvider', 'data_provider.MultiplexerDataProvider', ({(197, 12, 197, 23): 'multiplexer', (197, 25, 197, 38): '"""fake_logdir"""'}, {}), "(multiplexer, 'fake_logdir')", False, 'from tensorboard.backend.event_processing import data_provider\n'), ((274, 19, 276, 9), 'tensorboard.backend.event_processing.data_provider.MultiplexerDataProvider', 'data_provider.MultiplexerDataProvider', ({(275, 12, 275, 23): 'multiplexer', (275, 25, 275, 36): 'self.logdir'}, {}), '(multiplexer, self.logdir)', False, 'from tensorboard.backend.event_processing import data_provider\n'), ((278, 25, 281, 9), 'tensorboard.data.provider.RunTagFilter', 'base_provider.RunTagFilter', (), '', True, 'from tensorboard.data import provider as base_provider\n'), ((309, 19, 311, 9), 'tensorboard.backend.event_processing.data_provider.MultiplexerDataProvider', 'data_provider.MultiplexerDataProvider', ({(310, 12, 310, 23): 'multiplexer', (310, 25, 310, 36): 'self.logdir'}, {}), '(multiplexer, self.logdir)', False, 'from tensorboard.backend.event_processing import data_provider\n'), ((322, 25, 322, 71), 'tensorboard.data.provider.RunTagFilter', 'base_provider.RunTagFilter', ({(322, 52, 322, 61): "['waves']", (322, 63, 322, 70): "['bad']"}, {}), "(['waves'], ['bad'])", True, 'from tensorboard.data import provider as base_provider\n'), ((375, 19, 377, 9), 'tensorboard.backend.event_processing.data_provider.MultiplexerDataProvider', 'data_provider.MultiplexerDataProvider', ({(376, 12, 376, 23): 'multiplexer', (376, 25, 376, 36): 'self.logdir'}, {}), '(multiplexer, self.logdir)', False, 'from tensorboard.backend.event_processing import data_provider\n'), ((379, 25, 382, 9), 'tensorboard.data.provider.RunTagFilter', 'base_provider.RunTagFilter', (), '', True, 'from tensorboard.data import provider as base_provider\n'), ((407, 19, 409, 9), 'tensorboard.backend.event_processing.data_provider.MultiplexerDataProvider', 'data_provider.MultiplexerDataProvider', ({(408, 12, 408, 23): 'multiplexer', (408, 25, 408, 36): 'self.logdir'}, {}), '(multiplexer, self.logdir)', False, 'from tensorboard.backend.event_processing import data_provider\n'), ((517, 19, 517, 53), 'tensorboard.backend.event_processing.data_provider._downsample', 'data_provider._downsample', (), '', False, 'from tensorboard.backend.event_processing import data_provider\n'), ((524, 17, 524, 52), 'tensorboard.backend.event_processing.data_provider._downsample', 'data_provider._downsample', (), '', False, 'from tensorboard.backend.event_processing import data_provider\n'), ((531, 17, 531, 53), 'tensorboard.backend.event_processing.data_provider._downsample', 'data_provider._downsample', (), '', False, 'from tensorboard.backend.event_processing import data_provider\n'), ((536, 17, 536, 51), 'tensorboard.backend.event_processing.data_provider._downsample', 'data_provider._downsample', (), '', False, 'from tensorboard.backend.event_processing import data_provider\n'), ((57, 21, 57, 31), 'six.moves.xrange', 'xrange', ({(57, 28, 57, 30): '(10)'}, {}), '(10)', False, 'from six.moves import xrange\n'), ((65, 21, 65, 31), 'six.moves.xrange', 'xrange', ({(65, 28, 65, 30): '(10)'}, {}), '(10)', False, 'from six.moves import xrange\n'), ((152, 21, 152, 65), 'tensorflow.compat.v2.compat.v1.summary.FileWriter', 'tf.compat.v1.summary.FileWriter', ({(152, 53, 152, 64): 'self.logdir'}, {}), '(self.logdir)', True, 'import tensorflow.compat.v2 as tf\n'), ((324, 13, 328, 9), 'six.assertRaisesRegex', 'six.assertRaisesRegex', ({(325, 12, 325, 16): 'self', (326, 12, 326, 22): 'ValueError', (327, 12, 327, 68): '"""can only convert an array of size 1 to a Python scalar"""'}, {}), "(self, ValueError,\n    'can only convert an array of size 1 to a Python scalar')", False, 'import six\n'), ((519, 21, 519, 55), 'tensorboard.backend.event_processing.data_provider._downsample', 'data_provider._downsample', (), '', False, 'from tensorboard.backend.event_processing import data_provider\n'), ((58, 16, 60, 17), 'tensorboard.plugins.scalar.summary_v2.scalar', 'scalar_summary.scalar', (), '', True, 'from tensorboard.plugins.scalar import summary_v2 as scalar_summary\n'), ((61, 16, 61, 65), 'tensorboard.plugins.scalar.summary_v2.scalar', 'scalar_summary.scalar', (), '', True, 'from tensorboard.plugins.scalar import summary_v2 as scalar_summary\n'), ((71, 27, 71, 56), 'tensorboard.compat.proto.summary_pb2.SummaryMetadata', 'summary_pb2.SummaryMetadata', ({}, {}), '()', False, 'from tensorboard.compat.proto import summary_pb2\n'), ((74, 16, 76, 17), 'tensorflow.compat.v2.summary.write', 'tf.summary.write', (), '', True, 'import tensorflow.compat.v2 as tf\n'), ((78, 27, 78, 56), 'tensorboard.compat.proto.summary_pb2.SummaryMetadata', 'summary_pb2.SummaryMetadata', ({}, {}), '()', False, 'from tensorboard.compat.proto import summary_pb2\n'), ((81, 16, 83, 17), 'tensorflow.compat.v2.summary.write', 'tf.summary.write', (), '', True, 'import tensorflow.compat.v2 as tf\n'), ((92, 25, 92, 70), 'tensorflow.compat.v2.constant', 'tf.constant', (), '', True, 'import tensorflow.compat.v2 as tf\n'), ((93, 25, 93, 38), 'six.moves.xrange', 'xrange', ({(93, 32, 93, 33): '(1)', (93, 35, 93, 37): '(11)'}, {}), '(1, 11)', False, 'from six.moves import xrange\n'), ((106, 28, 106, 68), 'tensorflow.compat.v2.constant', 'tf.constant', (), '', True, 'import tensorflow.compat.v2 as tf\n'), ((107, 25, 107, 38), 'six.moves.xrange', 'xrange', ({(107, 32, 107, 33): '(1)', (107, 35, 107, 37): '(11)'}, {}), '(1, 11)', False, 'from six.moves import xrange\n'), ((203, 16, 205, 17), 'tensorboard.data.provider.Run', 'base_provider.Run', (), '', True, 'from tensorboard.data import provider as base_provider\n'), ((238, 27, 238, 76), 'tensorboard.data.provider.RunTagFilter', 'base_provider.RunTagFilter', ({(238, 54, 238, 63): "['waves']", (238, 65, 238, 75): "['square']"}, {}), "(['waves'], ['square'])", True, 'from tensorboard.data import provider as base_provider\n'), ((247, 27, 249, 13), 'tensorboard.data.provider.RunTagFilter', 'base_provider.RunTagFilter', (), '', True, 'from tensorboard.data import provider as base_provider\n'), ((259, 27, 259, 77), 'tensorboard.data.provider.RunTagFilter', 'base_provider.RunTagFilter', (), '', True, 'from tensorboard.data import provider as base_provider\n'), ((268, 27, 268, 73), 'tensorboard.data.provider.RunTagFilter', 'base_provider.RunTagFilter', ({(268, 54, 268, 60): "['un']", (268, 62, 268, 72): "['likely']"}, {}), "(['un'], ['likely'])", True, 'from tensorboard.data import provider as base_provider\n'), ((366, 27, 368, 13), 'tensorboard.data.provider.RunTagFilter', 'base_provider.RunTagFilter', ({(367, 16, 367, 28): "['lebesgue']", (367, 30, 367, 41): "['uniform']"}, {}), "(['lebesgue'], ['uniform'])", True, 'from tensorboard.data import provider as base_provider\n'), ((56, 13, 56, 50), 'tensorflow.compat.v2.summary.create_file_writer', 'tf.summary.create_file_writer', ({(56, 43, 56, 49): 'logdir'}, {}), '(logdir)', True, 'import tensorflow.compat.v2 as tf\n'), ((64, 13, 64, 50), 'tensorflow.compat.v2.summary.create_file_writer', 'tf.summary.create_file_writer', ({(64, 43, 64, 49): 'logdir'}, {}), '(logdir)', True, 'import tensorflow.compat.v2 as tf\n'), ((86, 13, 86, 50), 'tensorflow.compat.v2.summary.create_file_writer', 'tf.summary.create_file_writer', ({(86, 43, 86, 49): 'logdir'}, {}), '(logdir)', True, 'import tensorflow.compat.v2 as tf\n'), ((94, 20, 96, 21), 'tensorboard.plugins.histogram.summary_v2.histogram', 'histogram_summary.histogram', (), '', True, 'from tensorboard.plugins.histogram import summary_v2 as histogram_summary\n'), ((99, 13, 99, 50), 'tensorflow.compat.v2.summary.create_file_writer', 'tf.summary.create_file_writer', ({(99, 43, 99, 49): 'logdir'}, {}), '(logdir)', True, 'import tensorflow.compat.v2 as tf\n'), ((112, 28, 112, 60), 'tensorflow.compat.v2.tile', 'tf.tile', ({(112, 36, 112, 45): 'image_1x1', (112, 47, 112, 59): '[k, i, i, 1]'}, {}), '(image_1x1, [k, i, i, 1])', True, 'import tensorflow.compat.v2 as tf\n'), ((113, 20, 119, 21), 'tensorboard.plugins.image.summary_v2.image', 'image_summary.image', (), '', True, 'from tensorboard.plugins.image import summary_v2 as image_summary\n'), ((151, 13, 151, 33), 'tensorflow.compat.v2.compat.v1.Graph', 'tf.compat.v1.Graph', ({}, {}), '()', True, 'import tensorflow.compat.v2 as tf\n'), ((206, 41, 206, 67), 'six.iteritems', 'six.iteritems', ({(206, 55, 206, 66): 'start_times'}, {}), '(start_times)', False, 'import six\n'), ((445, 31, 447, 17), 'tensorboard.data.provider.RunTagFilter', 'base_provider.RunTagFilter', (), '', True, 'from tensorboard.data import provider as base_provider\n'), ((499, 31, 501, 17), 'tensorboard.data.provider.RunTagFilter', 'base_provider.RunTagFilter', (), '', True, 'from tensorboard.data import provider as base_provider\n'), ((402, 24, 402, 68), 'tensorboard.util.tensor_util.make_ndarray', 'tensor_util.make_ndarray', ({(402, 49, 402, 67): 'event.tensor_proto'}, {}), '(event.tensor_proto)', False, 'from tensorboard.util import tensor_util\n'), ((302, 24, 302, 68), 'tensorboard.util.tensor_util.make_ndarray', 'tensor_util.make_ndarray', ({(302, 49, 302, 67): 'event.tensor_proto'}, {}), '(event.tensor_proto)', False, 'from tensorboard.util import tensor_util\n')]