We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Facing issue while converting tensorboard logs to Aim
## 🐛 Bug

<!-- A clear and concise description of what the bug is. -->
Trying to convert tensorboard event log file to Aim Run, but getting below error,

One more question, do we have a way to sync tensorboard logs real-time, like while training is in-progress parallelly can we sync tensorboard logs? Currently it's cli command to sync once we have tensorboard logs in place.

Many thanks!

```
The lock file /mnt/c/sharath_mk/ubuntu/aim/.aim/.repo_lock is on a filesystem of type `drvfs` (device id: 14). Using soft file locks to avoid potential data corruption.
2022-07-25 15:21:57.067693: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory
2022-07-25 15:21:57.067771: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
Converting TensorBoard logs:   0%|                                                                                                                         | 0/1 [00:00<?, ?it/sWARNING:tensorflow:From /home/miniconda3/lib/python3.8/site-packages/tensorflow/python/summary/summary_iterator.py:27: tf_record_iterator (from tensorflow.python.lib.io.tf_record) is deprecated and will be removed in a future version.
Instructions for updating:
Use eager execution and: 
`tf.data.TFRecordDataset(path)`
Parsing logs in /mnt/c/sharath_mk/ubuntu/aim/tensorboard/run_tb_sync/test_tb:   0%|                                                              | 0/2 [00:00<?, ?it/s]
Converting TensorBoard logs:   0%|                                                                                                                         | 0/1 [00:00<?, ?it/s]
Traceback (most recent call last):
  File "/home/miniconda3/bin/aim", line 8, in <module>
    sys.exit(cli_entry_point())
  File "/home/miniconda3/lib/python3.8/site-packages/click/core.py", line 1128, in __call__
    return self.main(*args, **kwargs)
  File "/home/miniconda3/lib/python3.8/site-packages/click/core.py", line 1053, in main
    rv = self.invoke(ctx)
  File "/home/miniconda3/lib/python3.8/site-packages/click/core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/miniconda3/lib/python3.8/site-packages/click/core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/miniconda3/lib/python3.8/site-packages/click/core.py", line 1395, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/miniconda3/lib/python3.8/site-packages/click/core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "/home/miniconda3/lib/python3.8/site-packages/click/decorators.py", line 26, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/home/miniconda3/lib/python3.8/site-packages/aim/cli/convert/commands.py", line 39, in convert_tensorboard
    parse_tb_logs(logdir, repo_inst, flat, no_cache)
  File "/home/miniconda3/lib/python3.8/site-packages/aim/cli/convert/processors/tensorboard.py", line 220, in parse_tb_logs
    track_val = value.tensor.float_val[0]
IndexError: list index (0) out of range
```
### To reproduce

<!-- Reproduction steps. -->
Log tensorbord event log file

### Expected behavior

<!-- Fill in expected behavior.  -->

### Environment

- Aim Version (e.g., 3.0.1)
- Python version
- pip version
- OS (e.g., Linux)
- Any other relevant information

### Additional context

<!-- Add any other context about the problem here. -->


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `aim/cli/convert/processors/tensorboard.py`
Content:
```
1 import json
2 import os
3 
4 import click
5 from tqdm import tqdm
6 
7 from aim import Audio, Image, Run
8 
9 
10 def parse_tb_logs(tb_logs, repo_inst, flat=False, no_cache=False):
11     """
12     This function scans and collects records from TB log files.
13 
14     Creates and uses cache file "tb_logs_cache" in the repo dir
15     to track previously processed files and values
16 
17     For more info please refer to our integration guides.
18     """
19 
20     try:
21         # This import statement takes long to complete
22         import tensorflow as tf
23         from tensorflow.python.summary.summary_iterator import summary_iterator
24     except ImportError:
25         click.echo(
26             'Could not process TensorBoard logs - failed to import tensorflow module.', err=True
27         )
28         return
29 
30     supported_plugins = ('images', 'scalars')
31     unsupported_plugin_noticed = False
32     tb_logs_cache_path = os.path.join(repo_inst.path, 'tb_logs_cache')
33 
34     if no_cache and os.path.exists(tb_logs_cache_path):
35         os.remove(tb_logs_cache_path)
36     try:
37         with open(tb_logs_cache_path) as FS:
38             tb_logs_cache = json.load(FS)
39     except Exception:
40         tb_logs_cache = {}
41 
42     def get_parent(current_path, level=0):
43         # level 0 is the direct parent directory
44         if level <= 0:
45             return os.path.dirname(current_path)
46         elif current_path in ('', '.', '/'):
47             return current_path
48         return get_parent(os.path.dirname(current_path), level - 1)
49 
50     tb_logs = os.path.abspath(tb_logs)
51     run_dir_candidates = set()
52     for root, dirs, files in os.walk(tb_logs):
53         for file in files:
54             if not file.startswith('events.out.tfevents'):
55                 continue
56 
57             file_path = os.path.abspath(os.path.join(root, file))
58             run_dir = get_parent(file_path)
59 
60             if not run_dir.startswith(tb_logs):
61                 # it's outside tb_logs
62                 continue
63 
64             run_dir_candidates.add(run_dir)
65 
66     def get_level(current_path):
67         level = -1
68         while current_path.startswith(tb_logs):
69             current_path, _ = os.path.split(current_path)
70             level += 1
71         return level
72 
73     run_dir_candidates = sorted(run_dir_candidates, key=get_level, reverse=True)
74     run_dir_candidates_filtered = set()
75     run_dir_ignored = set()
76     groups = set()
77 
78     for run_dir in run_dir_candidates:
79         if run_dir in run_dir_candidates_filtered:
80             # already tagged as a run dir
81             continue
82 
83         if run_dir in groups:
84             # run dir which has other run dirs inside, so we skip it
85             run_dir_ignored.add(run_dir)
86             continue
87 
88         depth = get_level(run_dir)
89         if depth >= 2:
90             if flat:
91                 run_group_dir = get_parent(run_dir, 0)
92                 new_run_dir = run_dir
93             else:
94                 run_group_dir = get_parent(run_dir, 1)
95                 new_run_dir = get_parent(run_dir, 0)
96                 if new_run_dir in groups:
97                     new_run_dir = run_dir
98             groups.add(run_group_dir)
99         elif depth == 1:
100             new_run_dir = run_dir
101         else:
102             continue
103         run_dir_candidates_filtered.add(new_run_dir)
104 
105     if run_dir_ignored:
106         click.echo('WARN: Found directory entries with unorganized even files!\n'
107                    'Please read the preparation instructions to properly process these files.\n'
108                    'Event files in the following directories will be ignored:', err=True)
109         for c, r in enumerate(run_dir_ignored, start=1):
110             click.echo(f'{c}: {r}', err=True)
111 
112     for path in tqdm(run_dir_candidates_filtered,
113                      desc='Converting TensorBoard logs',
114                      total=len(run_dir_candidates_filtered)):
115 
116         events = {}
117         for root, dirs, files in os.walk(path):
118             for file in files:
119                 if 'events.out.tfevents' not in file:
120                     continue
121                 file_path = os.path.join(root, file)
122                 if file_path == os.path.join(path, file):
123                     entry = None
124                 else:
125                     entry = os.path.basename(os.path.dirname(file_path))
126                 events[file_path] = {
127                     'context': {
128                         'entry': entry
129                     }
130                 }
131 
132         if path not in tb_logs_cache:
133             tb_logs_cache[path] = {}
134 
135         run_cache = tb_logs_cache[path]
136         if run_cache:
137             run = Run(
138                 run_hash=run_cache['run_hash'],
139                 repo=repo_inst,
140                 system_tracking_interval=None,
141                 log_system_params=False,
142                 capture_terminal_logs=False,
143             )
144         else:
145             run = Run(
146                 repo=repo_inst,
147                 system_tracking_interval=None,
148                 log_system_params=False,
149                 capture_terminal_logs=False,
150             )
151             run['tensorboard_logdir'] = path
152             run_cache.update({
153                 'run_hash': run.hash,
154                 'events': {},
155             })
156         run_tb_events = run_cache['events']
157 
158         events_to_process = []
159         for event in events:
160             last_modified_at = os.path.getmtime(event)
161             try:
162                 assert last_modified_at == run_tb_events[event]['last_modified_at']
163             except (KeyError, AssertionError, RuntimeError):
164                 # Something has changed or hasn't been processed before
165                 events_to_process.append(event)
166                 try:
167                     run_tb_events[event]['last_modified_at'] = last_modified_at
168                 except KeyError:
169                     # Completely new event
170                     run_tb_events[event] = {
171                         'last_modified_at': last_modified_at,
172                         'values': {},
173                     }
174 
175         if not events_to_process:
176             continue
177 
178         for event_file in tqdm(events_to_process, desc=f'Parsing logs in {path}', total=len(events_to_process)):
179             run_tb_log = run_tb_events[event_file]
180             event_context = events[event_file]['context']
181             try:
182                 for event in summary_iterator(event_file):
183                     timestamp = event.wall_time
184                     step = event.step
185                     fail_count = 0
186                     _err_info = None
187 
188                     for value in event.summary.value:
189                         tag = value.tag
190 
191                         plugin_name = value.metadata.plugin_data.plugin_name
192                         value_id = f'{tag}_{plugin_name}'
193                         if value_id in run_tb_log['values']:
194                             if run_tb_log['values'][value_id]['timestamp'] >= timestamp:
195                                 # prevent previously tracked data from re-tracking upon file update
196                                 continue
197 
198                         if len(plugin_name) > 0 and plugin_name not in supported_plugins:
199                             if not unsupported_plugin_noticed:
200                                 click.echo(
201                                     'Found unsupported plugin type in the log file. '
202                                     'Data for these wont be processed. '
203                                     'Supported plugin types are: {}'.format(', '.join(supported_plugins)),
204                                     err=True
205                                 )
206                                 unsupported_plugin_noticed = True
207                             continue
208                         track_val = None
209                         try:
210                             if value.HasField('tensor'):
211                                 # TODO: [MV] check the case when audios are passed via tensor
212                                 if plugin_name == 'images':
213                                     tensor = value.tensor.string_val[2:]
214                                     track_val = [
215                                         Image(tf.image.decode_image(t).numpy()) for t in tensor
216                                     ]
217                                     if len(track_val) == 1:
218                                         track_val = track_val[0]
219                                 else:
220                                     track_val = value.tensor.float_val[0]
221                             elif value.HasField('simple_value'):
222                                 track_val = value.simple_value
223                             elif value.HasField('image'):
224                                 track_val = Image(tf.image.decode_image(value.image.encoded_image_string).numpy())
225                             elif value.HasField('audio'):
226                                 tf_audio, sample_rate = tf.audio.decode_wav(value.audio.encoded_audio_string)
227                                 track_val = Audio(tf_audio.numpy(), rate=sample_rate)
228 
229                         except RuntimeError as exc:
230                             # catch all the nasty failures
231                             fail_count += 1
232                             if not _err_info:
233                                 _err_info = str(exc)
234                             continue
235 
236                         run_tb_log['values'][value_id] = {
237                             'step': step,
238                             'timestamp': timestamp
239                         }
240                         if track_val is not None:
241                             run._tracker._track(track_val, timestamp, tag, step, context=event_context)
242                     if fail_count:
243                         click.echo(f'Failed to process {fail_count} entries. First exception: {_err_info}', err=True)
244 
245             except RuntimeError as exc:
246                 click.echo(f'Failed to read log file {event_file} - {exc}', err=True)
247 
248     # refresh cache
249     with open(tb_logs_cache_path, 'w') as FS:
250         json.dump(tb_logs_cache, FS)
251 
252     click.echo('TensorBoard logs conversion complete!')
253
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/aim/cli/convert/processors/tensorboard.py b/aim/cli/convert/processors/tensorboard.py
--- a/aim/cli/convert/processors/tensorboard.py
+++ b/aim/cli/convert/processors/tensorboard.py
@@ -21,6 +21,7 @@
         # This import statement takes long to complete
         import tensorflow as tf
         from tensorflow.python.summary.summary_iterator import summary_iterator
+        from tensorboard.util import tensor_util
     except ImportError:
         click.echo(
             'Could not process TensorBoard logs - failed to import tensorflow module.', err=True
@@ -70,6 +71,13 @@
             level += 1
         return level
 
+    def create_ndarray(tensor):
+        res = tensor_util.make_ndarray(tensor)
+        if res.dtype == "object":
+            return None
+        else:
+            return res
+
     run_dir_candidates = sorted(run_dir_candidates, key=get_level, reverse=True)
     run_dir_candidates_filtered = set()
     run_dir_ignored = set()
@@ -216,6 +224,8 @@
                                     ]
                                     if len(track_val) == 1:
                                         track_val = track_val[0]
+                                elif plugin_name == "scalars" or plugin_name == "":
+                                    track_val = create_ndarray(value.tensor)
                                 else:
                                     track_val = value.tensor.float_val[0]
                             elif value.HasField('simple_value'):

{"golden_diff": "diff --git a/aim/cli/convert/processors/tensorboard.py b/aim/cli/convert/processors/tensorboard.py\n--- a/aim/cli/convert/processors/tensorboard.py\n+++ b/aim/cli/convert/processors/tensorboard.py\n@@ -21,6 +21,7 @@\n         # This import statement takes long to complete\n         import tensorflow as tf\n         from tensorflow.python.summary.summary_iterator import summary_iterator\n+        from tensorboard.util import tensor_util\n     except ImportError:\n         click.echo(\n             'Could not process TensorBoard logs - failed to import tensorflow module.', err=True\n@@ -70,6 +71,13 @@\n             level += 1\n         return level\n \n+    def create_ndarray(tensor):\n+        res = tensor_util.make_ndarray(tensor)\n+        if res.dtype == \"object\":\n+            return None\n+        else:\n+            return res\n+\n     run_dir_candidates = sorted(run_dir_candidates, key=get_level, reverse=True)\n     run_dir_candidates_filtered = set()\n     run_dir_ignored = set()\n@@ -216,6 +224,8 @@\n                                     ]\n                                     if len(track_val) == 1:\n                                         track_val = track_val[0]\n+                                elif plugin_name == \"scalars\" or plugin_name == \"\":\n+                                    track_val = create_ndarray(value.tensor)\n                                 else:\n                                     track_val = value.tensor.float_val[0]\n                             elif value.HasField('simple_value'):\n", "issue": "Facing issue while converting tensorboard logs to Aim\n## \ud83d\udc1b Bug\r\n\r\n<!-- A clear and concise description of what the bug is. -->\r\nTrying to convert tensorboard event log file to Aim Run, but getting below error,\r\n\r\nOne more question, do we have a way to sync tensorboard logs real-time, like while training is in-progress parallelly can we sync tensorboard logs? Currently it's cli command to sync once we have tensorboard logs in place.\r\n\r\nMany thanks!\r\n\r\n```\r\nThe lock file /mnt/c/sharath_mk/ubuntu/aim/.aim/.repo_lock is on a filesystem of type `drvfs` (device id: 14). Using soft file locks to avoid potential data corruption.\r\n2022-07-25 15:21:57.067693: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory\r\n2022-07-25 15:21:57.067771: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\r\nConverting TensorBoard logs:   0%|                                                                                                                         | 0/1 [00:00<?, ?it/sWARNING:tensorflow:From /home/miniconda3/lib/python3.8/site-packages/tensorflow/python/summary/summary_iterator.py:27: tf_record_iterator (from tensorflow.python.lib.io.tf_record) is deprecated and will be removed in a future version.\r\nInstructions for updating:\r\nUse eager execution and: \r\n`tf.data.TFRecordDataset(path)`\r\nParsing logs in /mnt/c/sharath_mk/ubuntu/aim/tensorboard/run_tb_sync/test_tb:   0%|                                                              | 0/2 [00:00<?, ?it/s]\r\nConverting TensorBoard logs:   0%|                                                                                                                         | 0/1 [00:00<?, ?it/s]\r\nTraceback (most recent call last):\r\n  File \"/home/miniconda3/bin/aim\", line 8, in <module>\r\n    sys.exit(cli_entry_point())\r\n  File \"/home/miniconda3/lib/python3.8/site-packages/click/core.py\", line 1128, in __call__\r\n    return self.main(*args, **kwargs)\r\n  File \"/home/miniconda3/lib/python3.8/site-packages/click/core.py\", line 1053, in main\r\n    rv = self.invoke(ctx)\r\n  File \"/home/miniconda3/lib/python3.8/site-packages/click/core.py\", line 1659, in invoke\r\n    return _process_result(sub_ctx.command.invoke(sub_ctx))\r\n  File \"/home/miniconda3/lib/python3.8/site-packages/click/core.py\", line 1659, in invoke\r\n    return _process_result(sub_ctx.command.invoke(sub_ctx))\r\n  File \"/home/miniconda3/lib/python3.8/site-packages/click/core.py\", line 1395, in invoke\r\n    return ctx.invoke(self.callback, **ctx.params)\r\n  File \"/home/miniconda3/lib/python3.8/site-packages/click/core.py\", line 754, in invoke\r\n    return __callback(*args, **kwargs)\r\n  File \"/home/miniconda3/lib/python3.8/site-packages/click/decorators.py\", line 26, in new_func\r\n    return f(get_current_context(), *args, **kwargs)\r\n  File \"/home/miniconda3/lib/python3.8/site-packages/aim/cli/convert/commands.py\", line 39, in convert_tensorboard\r\n    parse_tb_logs(logdir, repo_inst, flat, no_cache)\r\n  File \"/home/miniconda3/lib/python3.8/site-packages/aim/cli/convert/processors/tensorboard.py\", line 220, in parse_tb_logs\r\n    track_val = value.tensor.float_val[0]\r\nIndexError: list index (0) out of range\r\n```\r\n### To reproduce\r\n\r\n<!-- Reproduction steps. -->\r\nLog tensorbord event log file\r\n\r\n### Expected behavior\r\n\r\n<!-- Fill in expected behavior.  -->\r\n\r\n### Environment\r\n\r\n- Aim Version (e.g., 3.0.1)\r\n- Python version\r\n- pip version\r\n- OS (e.g., Linux)\r\n- Any other relevant information\r\n\r\n### Additional context\r\n\r\n<!-- Add any other context about the problem here. -->\r\n\n", "before_files": [{"content": "import json\nimport os\n\nimport click\nfrom tqdm import tqdm\n\nfrom aim import Audio, Image, Run\n\n\ndef parse_tb_logs(tb_logs, repo_inst, flat=False, no_cache=False):\n    \"\"\"\n    This function scans and collects records from TB log files.\n\n    Creates and uses cache file \"tb_logs_cache\" in the repo dir\n    to track previously processed files and values\n\n    For more info please refer to our integration guides.\n    \"\"\"\n\n    try:\n        # This import statement takes long to complete\n        import tensorflow as tf\n        from tensorflow.python.summary.summary_iterator import summary_iterator\n    except ImportError:\n        click.echo(\n            'Could not process TensorBoard logs - failed to import tensorflow module.', err=True\n        )\n        return\n\n    supported_plugins = ('images', 'scalars')\n    unsupported_plugin_noticed = False\n    tb_logs_cache_path = os.path.join(repo_inst.path, 'tb_logs_cache')\n\n    if no_cache and os.path.exists(tb_logs_cache_path):\n        os.remove(tb_logs_cache_path)\n    try:\n        with open(tb_logs_cache_path) as FS:\n            tb_logs_cache = json.load(FS)\n    except Exception:\n        tb_logs_cache = {}\n\n    def get_parent(current_path, level=0):\n        # level 0 is the direct parent directory\n        if level <= 0:\n            return os.path.dirname(current_path)\n        elif current_path in ('', '.', '/'):\n            return current_path\n        return get_parent(os.path.dirname(current_path), level - 1)\n\n    tb_logs = os.path.abspath(tb_logs)\n    run_dir_candidates = set()\n    for root, dirs, files in os.walk(tb_logs):\n        for file in files:\n            if not file.startswith('events.out.tfevents'):\n                continue\n\n            file_path = os.path.abspath(os.path.join(root, file))\n            run_dir = get_parent(file_path)\n\n            if not run_dir.startswith(tb_logs):\n                # it's outside tb_logs\n                continue\n\n            run_dir_candidates.add(run_dir)\n\n    def get_level(current_path):\n        level = -1\n        while current_path.startswith(tb_logs):\n            current_path, _ = os.path.split(current_path)\n            level += 1\n        return level\n\n    run_dir_candidates = sorted(run_dir_candidates, key=get_level, reverse=True)\n    run_dir_candidates_filtered = set()\n    run_dir_ignored = set()\n    groups = set()\n\n    for run_dir in run_dir_candidates:\n        if run_dir in run_dir_candidates_filtered:\n            # already tagged as a run dir\n            continue\n\n        if run_dir in groups:\n            # run dir which has other run dirs inside, so we skip it\n            run_dir_ignored.add(run_dir)\n            continue\n\n        depth = get_level(run_dir)\n        if depth >= 2:\n            if flat:\n                run_group_dir = get_parent(run_dir, 0)\n                new_run_dir = run_dir\n            else:\n                run_group_dir = get_parent(run_dir, 1)\n                new_run_dir = get_parent(run_dir, 0)\n                if new_run_dir in groups:\n                    new_run_dir = run_dir\n            groups.add(run_group_dir)\n        elif depth == 1:\n            new_run_dir = run_dir\n        else:\n            continue\n        run_dir_candidates_filtered.add(new_run_dir)\n\n    if run_dir_ignored:\n        click.echo('WARN: Found directory entries with unorganized even files!\\n'\n                   'Please read the preparation instructions to properly process these files.\\n'\n                   'Event files in the following directories will be ignored:', err=True)\n        for c, r in enumerate(run_dir_ignored, start=1):\n            click.echo(f'{c}: {r}', err=True)\n\n    for path in tqdm(run_dir_candidates_filtered,\n                     desc='Converting TensorBoard logs',\n                     total=len(run_dir_candidates_filtered)):\n\n        events = {}\n        for root, dirs, files in os.walk(path):\n            for file in files:\n                if 'events.out.tfevents' not in file:\n                    continue\n                file_path = os.path.join(root, file)\n                if file_path == os.path.join(path, file):\n                    entry = None\n                else:\n                    entry = os.path.basename(os.path.dirname(file_path))\n                events[file_path] = {\n                    'context': {\n                        'entry': entry\n                    }\n                }\n\n        if path not in tb_logs_cache:\n            tb_logs_cache[path] = {}\n\n        run_cache = tb_logs_cache[path]\n        if run_cache:\n            run = Run(\n                run_hash=run_cache['run_hash'],\n                repo=repo_inst,\n                system_tracking_interval=None,\n                log_system_params=False,\n                capture_terminal_logs=False,\n            )\n        else:\n            run = Run(\n                repo=repo_inst,\n                system_tracking_interval=None,\n                log_system_params=False,\n                capture_terminal_logs=False,\n            )\n            run['tensorboard_logdir'] = path\n            run_cache.update({\n                'run_hash': run.hash,\n                'events': {},\n            })\n        run_tb_events = run_cache['events']\n\n        events_to_process = []\n        for event in events:\n            last_modified_at = os.path.getmtime(event)\n            try:\n                assert last_modified_at == run_tb_events[event]['last_modified_at']\n            except (KeyError, AssertionError, RuntimeError):\n                # Something has changed or hasn't been processed before\n                events_to_process.append(event)\n                try:\n                    run_tb_events[event]['last_modified_at'] = last_modified_at\n                except KeyError:\n                    # Completely new event\n                    run_tb_events[event] = {\n                        'last_modified_at': last_modified_at,\n                        'values': {},\n                    }\n\n        if not events_to_process:\n            continue\n\n        for event_file in tqdm(events_to_process, desc=f'Parsing logs in {path}', total=len(events_to_process)):\n            run_tb_log = run_tb_events[event_file]\n            event_context = events[event_file]['context']\n            try:\n                for event in summary_iterator(event_file):\n                    timestamp = event.wall_time\n                    step = event.step\n                    fail_count = 0\n                    _err_info = None\n\n                    for value in event.summary.value:\n                        tag = value.tag\n\n                        plugin_name = value.metadata.plugin_data.plugin_name\n                        value_id = f'{tag}_{plugin_name}'\n                        if value_id in run_tb_log['values']:\n                            if run_tb_log['values'][value_id]['timestamp'] >= timestamp:\n                                # prevent previously tracked data from re-tracking upon file update\n                                continue\n\n                        if len(plugin_name) > 0 and plugin_name not in supported_plugins:\n                            if not unsupported_plugin_noticed:\n                                click.echo(\n                                    'Found unsupported plugin type in the log file. '\n                                    'Data for these wont be processed. '\n                                    'Supported plugin types are: {}'.format(', '.join(supported_plugins)),\n                                    err=True\n                                )\n                                unsupported_plugin_noticed = True\n                            continue\n                        track_val = None\n                        try:\n                            if value.HasField('tensor'):\n                                # TODO: [MV] check the case when audios are passed via tensor\n                                if plugin_name == 'images':\n                                    tensor = value.tensor.string_val[2:]\n                                    track_val = [\n                                        Image(tf.image.decode_image(t).numpy()) for t in tensor\n                                    ]\n                                    if len(track_val) == 1:\n                                        track_val = track_val[0]\n                                else:\n                                    track_val = value.tensor.float_val[0]\n                            elif value.HasField('simple_value'):\n                                track_val = value.simple_value\n                            elif value.HasField('image'):\n                                track_val = Image(tf.image.decode_image(value.image.encoded_image_string).numpy())\n                            elif value.HasField('audio'):\n                                tf_audio, sample_rate = tf.audio.decode_wav(value.audio.encoded_audio_string)\n                                track_val = Audio(tf_audio.numpy(), rate=sample_rate)\n\n                        except RuntimeError as exc:\n                            # catch all the nasty failures\n                            fail_count += 1\n                            if not _err_info:\n                                _err_info = str(exc)\n                            continue\n\n                        run_tb_log['values'][value_id] = {\n                            'step': step,\n                            'timestamp': timestamp\n                        }\n                        if track_val is not None:\n                            run._tracker._track(track_val, timestamp, tag, step, context=event_context)\n                    if fail_count:\n                        click.echo(f'Failed to process {fail_count} entries. First exception: {_err_info}', err=True)\n\n            except RuntimeError as exc:\n                click.echo(f'Failed to read log file {event_file} - {exc}', err=True)\n\n    # refresh cache\n    with open(tb_logs_cache_path, 'w') as FS:\n        json.dump(tb_logs_cache, FS)\n\n    click.echo('TensorBoard logs conversion complete!')\n", "path": "aim/cli/convert/processors/tensorboard.py"}], "after_files": [{"content": "import json\nimport os\n\nimport click\nfrom tqdm import tqdm\n\nfrom aim import Audio, Image, Run\n\n\ndef parse_tb_logs(tb_logs, repo_inst, flat=False, no_cache=False):\n    \"\"\"\n    This function scans and collects records from TB log files.\n\n    Creates and uses cache file \"tb_logs_cache\" in the repo dir\n    to track previously processed files and values\n\n    For more info please refer to our integration guides.\n    \"\"\"\n\n    try:\n        # This import statement takes long to complete\n        import tensorflow as tf\n        from tensorflow.python.summary.summary_iterator import summary_iterator\n        from tensorboard.util import tensor_util\n    except ImportError:\n        click.echo(\n            'Could not process TensorBoard logs - failed to import tensorflow module.', err=True\n        )\n        return\n\n    supported_plugins = ('images', 'scalars')\n    unsupported_plugin_noticed = False\n    tb_logs_cache_path = os.path.join(repo_inst.path, 'tb_logs_cache')\n\n    if no_cache and os.path.exists(tb_logs_cache_path):\n        os.remove(tb_logs_cache_path)\n    try:\n        with open(tb_logs_cache_path) as FS:\n            tb_logs_cache = json.load(FS)\n    except Exception:\n        tb_logs_cache = {}\n\n    def get_parent(current_path, level=0):\n        # level 0 is the direct parent directory\n        if level <= 0:\n            return os.path.dirname(current_path)\n        elif current_path in ('', '.', '/'):\n            return current_path\n        return get_parent(os.path.dirname(current_path), level - 1)\n\n    tb_logs = os.path.abspath(tb_logs)\n    run_dir_candidates = set()\n    for root, dirs, files in os.walk(tb_logs):\n        for file in files:\n            if not file.startswith('events.out.tfevents'):\n                continue\n\n            file_path = os.path.abspath(os.path.join(root, file))\n            run_dir = get_parent(file_path)\n\n            if not run_dir.startswith(tb_logs):\n                # it's outside tb_logs\n                continue\n\n            run_dir_candidates.add(run_dir)\n\n    def get_level(current_path):\n        level = -1\n        while current_path.startswith(tb_logs):\n            current_path, _ = os.path.split(current_path)\n            level += 1\n        return level\n\n    def create_ndarray(tensor):\n        res = tensor_util.make_ndarray(tensor)\n        if res.dtype == \"object\":\n            return None\n        else:\n            return res\n\n    run_dir_candidates = sorted(run_dir_candidates, key=get_level, reverse=True)\n    run_dir_candidates_filtered = set()\n    run_dir_ignored = set()\n    groups = set()\n\n    for run_dir in run_dir_candidates:\n        if run_dir in run_dir_candidates_filtered:\n            # already tagged as a run dir\n            continue\n\n        if run_dir in groups:\n            # run dir which has other run dirs inside, so we skip it\n            run_dir_ignored.add(run_dir)\n            continue\n\n        depth = get_level(run_dir)\n        if depth >= 2:\n            if flat:\n                run_group_dir = get_parent(run_dir, 0)\n                new_run_dir = run_dir\n            else:\n                run_group_dir = get_parent(run_dir, 1)\n                new_run_dir = get_parent(run_dir, 0)\n                if new_run_dir in groups:\n                    new_run_dir = run_dir\n            groups.add(run_group_dir)\n        elif depth == 1:\n            new_run_dir = run_dir\n        else:\n            continue\n        run_dir_candidates_filtered.add(new_run_dir)\n\n    if run_dir_ignored:\n        click.echo('WARN: Found directory entries with unorganized even files!\\n'\n                   'Please read the preparation instructions to properly process these files.\\n'\n                   'Event files in the following directories will be ignored:', err=True)\n        for c, r in enumerate(run_dir_ignored, start=1):\n            click.echo(f'{c}: {r}', err=True)\n\n    for path in tqdm(run_dir_candidates_filtered,\n                     desc='Converting TensorBoard logs',\n                     total=len(run_dir_candidates_filtered)):\n\n        events = {}\n        for root, dirs, files in os.walk(path):\n            for file in files:\n                if 'events.out.tfevents' not in file:\n                    continue\n                file_path = os.path.join(root, file)\n                if file_path == os.path.join(path, file):\n                    entry = None\n                else:\n                    entry = os.path.basename(os.path.dirname(file_path))\n                events[file_path] = {\n                    'context': {\n                        'entry': entry\n                    }\n                }\n\n        if path not in tb_logs_cache:\n            tb_logs_cache[path] = {}\n\n        run_cache = tb_logs_cache[path]\n        if run_cache:\n            run = Run(\n                run_hash=run_cache['run_hash'],\n                repo=repo_inst,\n                system_tracking_interval=None,\n                log_system_params=False,\n                capture_terminal_logs=False,\n            )\n        else:\n            run = Run(\n                repo=repo_inst,\n                system_tracking_interval=None,\n                log_system_params=False,\n                capture_terminal_logs=False,\n            )\n            run['tensorboard_logdir'] = path\n            run_cache.update({\n                'run_hash': run.hash,\n                'events': {},\n            })\n        run_tb_events = run_cache['events']\n\n        events_to_process = []\n        for event in events:\n            last_modified_at = os.path.getmtime(event)\n            try:\n                assert last_modified_at == run_tb_events[event]['last_modified_at']\n            except (KeyError, AssertionError, RuntimeError):\n                # Something has changed or hasn't been processed before\n                events_to_process.append(event)\n                try:\n                    run_tb_events[event]['last_modified_at'] = last_modified_at\n                except KeyError:\n                    # Completely new event\n                    run_tb_events[event] = {\n                        'last_modified_at': last_modified_at,\n                        'values': {},\n                    }\n\n        if not events_to_process:\n            continue\n\n        for event_file in tqdm(events_to_process, desc=f'Parsing logs in {path}', total=len(events_to_process)):\n            run_tb_log = run_tb_events[event_file]\n            event_context = events[event_file]['context']\n            try:\n                for event in summary_iterator(event_file):\n                    timestamp = event.wall_time\n                    step = event.step\n                    fail_count = 0\n                    _err_info = None\n\n                    for value in event.summary.value:\n                        tag = value.tag\n\n                        plugin_name = value.metadata.plugin_data.plugin_name\n                        value_id = f'{tag}_{plugin_name}'\n                        if value_id in run_tb_log['values']:\n                            if run_tb_log['values'][value_id]['timestamp'] >= timestamp:\n                                # prevent previously tracked data from re-tracking upon file update\n                                continue\n\n                        if len(plugin_name) > 0 and plugin_name not in supported_plugins:\n                            if not unsupported_plugin_noticed:\n                                click.echo(\n                                    'Found unsupported plugin type in the log file. '\n                                    'Data for these wont be processed. '\n                                    'Supported plugin types are: {}'.format(', '.join(supported_plugins)),\n                                    err=True\n                                )\n                                unsupported_plugin_noticed = True\n                            continue\n                        track_val = None\n                        try:\n                            if value.HasField('tensor'):\n                                # TODO: [MV] check the case when audios are passed via tensor\n                                if plugin_name == 'images':\n                                    tensor = value.tensor.string_val[2:]\n                                    track_val = [\n                                        Image(tf.image.decode_image(t).numpy()) for t in tensor\n                                    ]\n                                    if len(track_val) == 1:\n                                        track_val = track_val[0]\n                                elif plugin_name == \"scalars\" or plugin_name == \"\":\n                                    track_val = create_ndarray(value.tensor)\n                                else:\n                                    track_val = value.tensor.float_val[0]\n                            elif value.HasField('simple_value'):\n                                track_val = value.simple_value\n                            elif value.HasField('image'):\n                                track_val = Image(tf.image.decode_image(value.image.encoded_image_string).numpy())\n                            elif value.HasField('audio'):\n                                tf_audio, sample_rate = tf.audio.decode_wav(value.audio.encoded_audio_string)\n                                track_val = Audio(tf_audio.numpy(), rate=sample_rate)\n\n                        except RuntimeError as exc:\n                            # catch all the nasty failures\n                            fail_count += 1\n                            if not _err_info:\n                                _err_info = str(exc)\n                            continue\n\n                        run_tb_log['values'][value_id] = {\n                            'step': step,\n                            'timestamp': timestamp\n                        }\n                        if track_val is not None:\n                            run._tracker._track(track_val, timestamp, tag, step, context=event_context)\n                    if fail_count:\n                        click.echo(f'Failed to process {fail_count} entries. First exception: {_err_info}', err=True)\n\n            except RuntimeError as exc:\n                click.echo(f'Failed to read log file {event_file} - {exc}', err=True)\n\n    # refresh cache\n    with open(tb_logs_cache_path, 'w') as FS:\n        json.dump(tb_logs_cache, FS)\n\n    click.echo('TensorBoard logs conversion complete!')\n", "path": "aim/cli/convert/processors/tensorboard.py"}]}