Repository URL to install this package:
|
Version:
1.1.0 ▾
|
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Fluctio.FluctioSim.EditorUtils.EditorGeneral;
using Fluctio.FluctioSim.EditorUtils.OperatingSystem;
using Fluctio.FluctioSim.Utils.Extensions;
using Fluctio.FluctioSim.Utils.General;
using JetBrains.Annotations;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace Fluctio.FluctioSim.EditorCore.PythonWrappers.TensorboardApi
{
public static class Tensorboard
{
#region Running/stopping
private static readonly SessionProcess SessionProcess = new(typeof(Tensorboard));
[CanBeNull]
private static Process Process
{
get => SessionProcess.Process;
set => SessionProcess.Process = value;
}
[InitializeOnLoadMethod]
private static void StopOnExit()
{
EditorApplication.quitting += async () =>
{
await Stop();
};
Start();
}
private static void Start()
{
if (Process != null)
{
return;
}
var windowTitle = $"{Application.productName} TensorBoard";
Process = PythonVenv.RunInBackground($"tensorboard --logdir {ProcessUtil.InQuotes(MlAgentsLearn.ResultsFolder)} --window_title {ProcessUtil.InQuotes(windowTitle)}", OnOutput);
Process!.Exited += delegate
{
Process = null;
Url = null;
};
}
private static async Task Stop()
{
if (Process == null)
{
return;
}
Debug.Log("Stopping TensorBoard...");
await Process.KillTree();
}
#endregion
#region Opening Url
public static readonly Regex LaunchLineRegex = new(@"^TensorBoard [\d\.]+ at (?<url>http.*?) \(Press CTRL\+C to quit\)$");
private static readonly string UrlStateName = $"{typeof(Tensorboard).FullName}.Url";
[CanBeNull]
private static string Url
{
get
{
var url = SessionState.GetString(UrlStateName, "");
return url != "" ? url: null;
}
set
{
HttpClient.BaseAddress = value != null ? new Uri(value) : null;
SessionState.SetString(UrlStateName, value ?? "");
}
}
private static void OnOutput(string line, ProcessStreamType streamType)
{
if (line.Contains("error"))
{
Debug.LogError(line);
}
var urlGroup = LaunchLineRegex.Match(line).Groups["url"];
if (!urlGroup.Success)
{
return;
}
// delay is needed to set Url and remember it in SessionState from main thread
EditorUpdateEvents.MainThread += () =>
{
Url = urlGroup.Value;
};
}
public static void OpenURL()
{
if (Url == null)
{
Debug.Log("TensorBoard is still initializing, please wait...");
return;
}
Application.OpenURL(Url);
}
#endregion
#region HTTP API
private static readonly HttpClient HttpClient = new()
{
BaseAddress = Url != null ? new Uri(Url) : null
};
//TODO: add caching?
public static async Task<List<ScalarEvent>> GetScalarData(string runId, string behaviorName, string tag)
{
using var profilerScope = new ProfilerScope("Tensorboard.GetScalarData");
var queryParams = new Dictionary<string, string>
{
["run"] = $@"{runId}\{behaviorName}",
["tag"] = tag,
};
var endpoint = new UriBuilder
{
Scheme = "",
Host = "",
Path = "data/plugin/scalars/scalars",
Query = queryParams.ToQueryString(),
};
return await HttpClient.MakeApiCallJson<List<ScalarEvent>>(HttpMethod.Get, endpoint.ToString());
}
public static async Task<List<ScalarEvent>> GetCumulativeReward(string runId, string behaviorName)
{
return await GetScalarData(runId, behaviorName, "Environment/Cumulative Reward");
}
#endregion
}
}