diff --git a/src/Bonsai.ML.HiddenMarkovModels/ModelParameters.cs b/src/Bonsai.ML.HiddenMarkovModels/ModelParameters.cs index a94bae28..43bc7078 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/ModelParameters.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/ModelParameters.cs @@ -12,8 +12,11 @@ namespace Bonsai.ML.HiddenMarkovModels { + /// + /// Represents the model parameters of a Hidden Markov Model (HMM). + /// [Combinator] - [Description("")] + [Description("Model parameters of a Hidden Markov Model (HMM).")] [WorkflowElementCategory(ElementCategory.Source)] public class ModelParameters : PythonStringBuilder { @@ -28,7 +31,7 @@ public class ModelParameters : PythonStringBuilder /// [JsonProperty("num_states")] [Description("The number of discrete latent states of the HMM model")] - [Category("InitialParameters")] + [Category("ModelSpecification")] public int NumStates { get => numStates; set { numStates = value; UpdateString(); } } /// @@ -36,7 +39,7 @@ public class ModelParameters : PythonStringBuilder /// [JsonProperty("dimensions")] [Description("The dimensionality of the observations into the HMM model")] - [Category("InitialParameters")] + [Category("ModelSpecification")] public int Dimensions { get => dimensions; set { dimensions = value; UpdateString(); } } /// @@ -45,7 +48,7 @@ public class ModelParameters : PythonStringBuilder [JsonProperty("observation_type")] [JsonConverter(typeof(ObservationsTypeJsonConverter))] [Description("The type of distribution that the HMM will use to model the emission of data observations.")] - [Category("InitialParameters")] + [Category("ModelSpecification")] public ObservationsType ObservationsType { get => observationsType; set { observationsType = value; UpdateString(); } } /// @@ -60,7 +63,10 @@ public StateParameters StateParameters set { stateParameters = value; - ObservationsType = stateParameters.Observations.ObservationsType; + if (value != null) + { + ObservationsType = stateParameters.Observations.ObservationsType; + } UpdateString(); } } @@ -75,6 +81,9 @@ public ModelParameters() ObservationsType = ObservationsType.Gaussian; } + /// + /// Returns an observable sequence of objects. + /// public IObservable Process() { return Observable.Return( @@ -87,6 +96,10 @@ public IObservable Process() }); } + /// + /// Takes an observable seqence and returns an observable sequence of + /// objects that are emitted every time the input sequence emits a new element. + /// public IObservable Process(IObservable source) { return Observable.Select(source, item => @@ -101,17 +114,21 @@ public IObservable Process(IObservable source }); } + /// + /// Transforms an observable sequence of into an observable sequence + /// of objects by accessing internal attributes of the . + /// public IObservable Process(IObservable source) { var sharedSource = source.Publish().RefCount(); var stateParametersObservable = new StateParameters().Process(sharedSource); return sharedSource.Select(pyObject => { - NumStates = pyObject.GetAttr("num_states"); - Dimensions = pyObject.GetAttr("dimensions"); + numStates = pyObject.GetAttr("num_states"); + dimensions = pyObject.GetAttr("dimensions"); var observationsTypeStrPyObj = pyObject.GetAttr("observation_type"); - ObservationsType = GetFromString(observationsTypeStrPyObj); + observationsType = GetFromString(observationsTypeStrPyObj); return new ModelParameters() { @@ -126,12 +143,12 @@ public IObservable Process(IObservable source) }); } + /// protected override string BuildString() { StringBuilder.Clear(); StringBuilder.Append($"num_states={numStates},") .Append($"dimensions={dimensions},"); - if (stateParameters == null) { StringBuilder.Append($"observation_type=\"{GetString(observationsType)}\""); diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/AutoRegressiveObservations.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/AutoRegressiveObservations.cs index cbc39344..55b56f45 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/AutoRegressiveObservations.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/AutoRegressiveObservations.cs @@ -1,9 +1,13 @@ using System.ComponentModel; using System.Collections.Generic; using Newtonsoft.Json; +using System; namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents an autoregressive observations model. + /// [JsonObject(MemberSerialization.OptIn)] public class AutoRegressiveObservations : ObservationsModel { @@ -43,6 +47,7 @@ public class AutoRegressiveObservations : ObservationsModel /// [JsonProperty] + [JsonConverter(typeof(ObservationsTypeJsonConverter))] public override ObservationsType ObservationsType => ObservationsType.AutoRegressive; /// @@ -67,9 +72,12 @@ public override object[] Params ["lags"] = Lags, }; + /// + /// Initializes a new instance of the class. + /// public AutoRegressiveObservations (params object[] args) { - Lags = (int)args[0]; + Lags = Convert.ToInt32(args[0]); UpdateString(); } } diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/AutoRegressiveObservationsModel.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/AutoRegressiveObservationsModel.cs index 4ea95582..06121416 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/AutoRegressiveObservationsModel.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/AutoRegressiveObservationsModel.cs @@ -7,8 +7,12 @@ namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents an operator that is used to create and transform an observable sequence + /// of objects. + /// [Combinator] - [Description("")] + [Description("Creates an observable sequence of AutoRegressiveObservations objects.")] [WorkflowElementCategory(ElementCategory.Source)] [JsonObject(MemberSerialization.OptIn)] public class AutoRegressiveObservationsModel @@ -48,6 +52,9 @@ public class AutoRegressiveObservationsModel [Description("The square root sigmas of the observations for each state.")] public double[,,] SqrtSigmas { get; private set; } = null; + /// + /// Returns an observable sequence of objects. + /// public IObservable Process() { return Observable.Return( @@ -56,6 +63,10 @@ public IObservable Process() }); } + /// + /// Transforms an observable sequence of into an observable sequence + /// of objects by accessing internal attributes of the . + /// public IObservable Process(IObservable source) { return Observable.Select(source, pyObject => diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/BernoulliObservations.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/BernoulliObservations.cs index e2b33035..eacb3b36 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/BernoulliObservations.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/BernoulliObservations.cs @@ -1,9 +1,11 @@ using System.ComponentModel; using Newtonsoft.Json; -using static Bonsai.ML.HiddenMarkovModels.Observations.ObservationsLookup; namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents an bernoulli observations model. + /// [JsonObject(MemberSerialization.OptIn)] public class BernoulliObservations : ObservationsModel { @@ -15,6 +17,7 @@ public class BernoulliObservations : ObservationsModel /// [JsonProperty] + [JsonConverter(typeof(ObservationsTypeJsonConverter))] public override ObservationsType ObservationsType => ObservationsType.Bernoulli; /// diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/BernoulliObservationsModel.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/BernoulliObservationsModel.cs index 529cce89..b79d1919 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/BernoulliObservationsModel.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/BernoulliObservationsModel.cs @@ -7,8 +7,12 @@ namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents an operator that is used to create and transform an observable sequence + /// of objects. + /// [Combinator] - [Description("")] + [Description("Creates an observable sequence of BernoulliObservations objects.")] [WorkflowElementCategory(ElementCategory.Source)] [JsonObject(MemberSerialization.OptIn)] public class BernoulliObservationsModel @@ -20,6 +24,9 @@ public class BernoulliObservationsModel [Description("The logit P of the observations for each state.")] public double[,] LogitPs { get; private set; } = null; + /// + /// Returns an observable sequence of objects. + /// public IObservable Process() { return Observable.Return( @@ -28,6 +35,10 @@ public IObservable Process() }); } + /// + /// Transforms an observable sequence of into an observable sequence + /// of objects by accessing internal attributes of the . + /// public IObservable Process(IObservable source) { return Observable.Select(source, pyObject => diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/ExponentialObservations.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/ExponentialObservations.cs index 536575a2..aedf8675 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/ExponentialObservations.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/ExponentialObservations.cs @@ -1,14 +1,14 @@ using System.ComponentModel; -using System.Text; using Newtonsoft.Json; -using static Bonsai.ML.HiddenMarkovModels.Observations.ObservationsLookup; namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents an exponential observations model. + /// [JsonObject(MemberSerialization.OptIn)] public class ExponentialObservations : ObservationsModel { - /// /// The log lambdas of the observations for each state. /// @@ -17,6 +17,7 @@ public class ExponentialObservations : ObservationsModel /// [JsonProperty] + [JsonConverter(typeof(ObservationsTypeJsonConverter))] public override ObservationsType ObservationsType => ObservationsType.Exponential; /// diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/ExponentialObservationsModel.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/ExponentialObservationsModel.cs index 7cbece9d..8527f2b9 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/ExponentialObservationsModel.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/ExponentialObservationsModel.cs @@ -7,8 +7,12 @@ namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents an operator that is used to create and transform an observable sequence + /// of objects. + /// [Combinator] - [Description("")] + [Description("Creates an observable sequence of ExponentialObservations objects.")] [WorkflowElementCategory(ElementCategory.Source)] [JsonObject(MemberSerialization.OptIn)] public class ExponentialObservationsModel @@ -21,6 +25,9 @@ public class ExponentialObservationsModel [Description("The log lambdas of the observations for each state.")] public double[,] LogLambdas { get; private set; } = null; + /// + /// Returns an observable sequence of objects. + /// public IObservable Process() { return Observable.Return( @@ -29,6 +36,10 @@ public IObservable Process() }); } + /// + /// Transforms an observable sequence of into an observable sequence + /// of objects by accessing internal attributes of the . + /// public IObservable Process(IObservable source) { return Observable.Select(source, pyObject => diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservations.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservations.cs index 2bd81948..c975e3dc 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservations.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservations.cs @@ -1,13 +1,11 @@ -using System; -using Python.Runtime; -using System.Reactive.Linq; using System.ComponentModel; -using System.Xml.Serialization; using Newtonsoft.Json; -using System.Linq; namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents a gaussian observations model. + /// [JsonObject(MemberSerialization.OptIn)] public class GaussianObservations : ObservationsModel { @@ -26,6 +24,7 @@ public class GaussianObservations : ObservationsModel /// [JsonProperty] + [JsonConverter(typeof(ObservationsTypeJsonConverter))] public override ObservationsType ObservationsType => ObservationsType.Gaussian; /// diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservationsModel.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservationsModel.cs index 3aba98af..0d15029f 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservationsModel.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservationsModel.cs @@ -4,12 +4,15 @@ using System.ComponentModel; using System.Xml.Serialization; using Newtonsoft.Json; -using System.Linq; namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents an operator that is used to create and transform an observable sequence + /// of objects. + /// [Combinator] - [Description("")] + [Description("Creates an observable sequence of GaussianObservations objects.")] [WorkflowElementCategory(ElementCategory.Source)] [JsonObject(MemberSerialization.OptIn)] public class GaussianObservationsModel @@ -29,6 +32,9 @@ public class GaussianObservationsModel [Description("The standard deviations of the observations for each state.")] public double[,,] SqrtSigmas { get; private set; } = null; + /// + /// Returns an observable sequence of objects. + /// public IObservable Process() { return Observable.Return( @@ -37,6 +43,10 @@ public IObservable Process() }); } + /// + /// Transforms an observable sequence of into an observable sequence + /// of objects by accessing internal attributes of the . + /// public IObservable Process(IObservable source) { return Observable.Select(source, pyObject => diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservationsStatistics.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservationsStatistics.cs index b5e7c64d..4dbd87b8 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservationsStatistics.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/GaussianObservationsStatistics.cs @@ -1,12 +1,10 @@ -using Bonsai; -using System; using System.ComponentModel; -using System.Reactive.Linq; -using Python.Runtime; -using System.Xml.Serialization; namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents summary statistics and related data of an HMM model with gaussian observations. + /// public class GaussianObservationsStatistics { /// diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/GetGaussianObservationsStatisticsFromHMM.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/GetGaussianObservationsStatisticsFromHMM.cs index f7434171..26bace2e 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/GetGaussianObservationsStatisticsFromHMM.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/GetGaussianObservationsStatisticsFromHMM.cs @@ -1,17 +1,23 @@ -using Bonsai; using System; using System.ComponentModel; using System.Reactive.Linq; using Python.Runtime; -using System.Xml.Serialization; namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents an operator that will transform an observable sequence of + /// into an observable sequence of . + /// [Combinator] [Description("")] [WorkflowElementCategory(ElementCategory.Transform)] public class GetGaussianObservationsStatisticsFromHMM { + /// + /// Transforms an observable sequence of into an observable sequence + /// of objects by accessing internal attributes of the . + /// public IObservable Process(IObservable source) { return Observable.Select(source, pyObject => diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsLookup.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsLookup.cs index a8790e40..5b396965 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsLookup.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsLookup.cs @@ -4,25 +4,39 @@ namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// A lookup class for relating different to + /// and their corresponding Python string representations. + /// public static class ObservationsLookup { - private static readonly Dictionary _lookup; - - static ObservationsLookup() + private static readonly Dictionary _lookup = new Dictionary { - _lookup = new Dictionary - { - { ObservationsType.Gaussian, (typeof(GaussianObservations), "gaussian") }, - { ObservationsType.Exponential, (typeof(ExponentialObservations), "exponential") }, - { ObservationsType.Bernoulli, (typeof(BernoulliObservations), "bernoulli") }, - { ObservationsType.Poisson, (typeof(PoissonObservations), "poisson") }, - { ObservationsType.AutoRegressive, (typeof(AutoRegressiveObservations), "autoregressive") } - }; - } + { ObservationsType.Gaussian, (typeof(GaussianObservations), "gaussian") }, + { ObservationsType.Exponential, (typeof(ExponentialObservations), "exponential") }, + { ObservationsType.Bernoulli, (typeof(BernoulliObservations), "bernoulli") }, + { ObservationsType.Poisson, (typeof(PoissonObservations), "poisson") }, + { ObservationsType.AutoRegressive, (typeof(AutoRegressiveObservations), "autoregressive") } + }; + /// + /// Gets the of the corresponding to the given . + /// public static Type GetObservationsClassType(ObservationsType type) => _lookup[type].Type; + + /// + /// Gets the Python string representation of the given . + /// public static string GetString(ObservationsType type) => _lookup[type].StringValue; + + /// + /// Gets the corresponding to the given Python string representation. + /// public static ObservationsType GetFromString(string value) => _lookup.First(x => x.Value.StringValue == value).Key; + + /// + /// Gets the corresponding to the given of . + /// public static ObservationsType GetFromType(Type type) => _lookup.First(x => x.Value.Type == type).Key; } } diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsModel.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsModel.cs index f145a26c..12728830 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsModel.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsModel.cs @@ -25,6 +25,7 @@ public abstract class ObservationsModel : PythonStringBuilder /// public virtual Dictionary Kwargs => new(); + /// protected override string BuildString() { StringBuilder.Clear(); diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsType.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsType.cs index b78b3f2a..6d9e8581 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsType.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsType.cs @@ -1,11 +1,33 @@ namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents the type of observations in a hidden Markov model. + /// public enum ObservationsType { + /// + /// Gaussian observations. + /// Gaussian, + + /// + /// Exponential observations. + /// Exponential, + + /// + /// Bernoulli observations. + /// Bernoulli, + + /// + /// Poisson observations. + /// Poisson, + + /// + /// Autoregressive observations. + /// AutoRegressive } } \ No newline at end of file diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsTypeJsonConverter.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsTypeJsonConverter.cs index fb3c678a..08abd446 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsTypeJsonConverter.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/ObservationsTypeJsonConverter.cs @@ -4,13 +4,18 @@ namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Provides a type converter to convert between and the corresponding Python string representation. + /// public class ObservationsTypeJsonConverter : JsonConverter { + /// public override void WriteJson(JsonWriter writer, ObservationsType value, JsonSerializer serializer) { writer.WriteValue(GetString(value)); } + /// public override ObservationsType ReadJson(JsonReader reader, Type objectType, ObservationsType existingValue, bool hasExistingValue, JsonSerializer serializer) { string stringValue = reader.Value?.ToString(); diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/PoissonObservations.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/PoissonObservations.cs index e0597ea7..7353668e 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/PoissonObservations.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/PoissonObservations.cs @@ -1,12 +1,11 @@ -using System; -using Python.Runtime; -using System.Reactive.Linq; using System.ComponentModel; -using System.Xml.Serialization; using Newtonsoft.Json; namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents a poisson observations model. + /// [JsonObject(MemberSerialization.OptIn)] public class PoissonObservations : ObservationsModel { @@ -19,6 +18,7 @@ public class PoissonObservations : ObservationsModel /// [JsonProperty] + [JsonConverter(typeof(ObservationsTypeJsonConverter))] public override ObservationsType ObservationsType => ObservationsType.Poisson; /// diff --git a/src/Bonsai.ML.HiddenMarkovModels/Observations/PoissonObservationsModel.cs b/src/Bonsai.ML.HiddenMarkovModels/Observations/PoissonObservationsModel.cs index 0d7ebf6f..06cc1348 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/Observations/PoissonObservationsModel.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/Observations/PoissonObservationsModel.cs @@ -7,8 +7,12 @@ namespace Bonsai.ML.HiddenMarkovModels.Observations { + /// + /// Represents an operator that is used to create and transform an observable sequence + /// of objects. + /// [Combinator] - [Description("")] + [Description("Creates an observable sequence of PoissonObservations objects.")] [WorkflowElementCategory(ElementCategory.Source)] [JsonObject(MemberSerialization.OptIn)] public class PoissonObservationsModel @@ -21,6 +25,9 @@ public class PoissonObservationsModel [Description("The log lambdas of the observations for each state.")] public double[,] LogLambdas { get; private set; } = null; + /// + /// Returns an observable sequence of objects. + /// public IObservable Process() { return Observable.Return( @@ -29,6 +36,10 @@ public IObservable Process() }); } + /// + /// Transforms an observable sequence of into an observable sequence + /// of objects by accessing internal attributes of the . + /// public IObservable Process(IObservable source) { return Observable.Select(source, pyObject => diff --git a/src/Bonsai.ML.HiddenMarkovModels/PythonStringBuilder.cs b/src/Bonsai.ML.HiddenMarkovModels/PythonStringBuilder.cs index c86a8b4c..a480bc51 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/PythonStringBuilder.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/PythonStringBuilder.cs @@ -1,25 +1,38 @@ -using System; using System.Text; namespace Bonsai.ML.HiddenMarkovModels { + /// + /// Provides a base class for building string representations of Python objects. + /// public abstract class PythonStringBuilder { private string _cachedString; private bool _updateString; + + /// + /// The internal string builder used to build the string representation. + /// protected readonly StringBuilder StringBuilder = new StringBuilder(); + /// + /// Sets a flag to update the string cache on the next call to the method. + /// protected void UpdateString() { _updateString = true; } + /// + /// Method used to build a string representation of the object. + /// protected virtual string BuildString() { return StringBuilder.ToString(); } + /// public override string ToString() { if (_updateString) diff --git a/src/Bonsai.ML.HiddenMarkovModels/StateParameters.cs b/src/Bonsai.ML.HiddenMarkovModels/StateParameters.cs index 190c4136..9691f4d7 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/StateParameters.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/StateParameters.cs @@ -11,13 +11,12 @@ namespace Bonsai.ML.HiddenMarkovModels { - /// - /// StateParameters of a Hidden Markov Model (HMM). + /// Represents the state parameters of a Hidden Markov Model (HMM). /// [Combinator] [JsonConverter(typeof(StateParametersJsonConverter))] - [Description("StateParameters of a Hidden Markov Model (HMM).")] + [Description("State parameters of a Hidden Markov Model (HMM).")] [WorkflowElementCategory(ElementCategory.Source)] public class StateParameters : PythonStringBuilder { @@ -74,6 +73,9 @@ public ObservationsModel Observations } } + /// + /// Returns an observable sequence of objects. + /// public IObservable Process() { return Observable.Return( @@ -86,6 +88,10 @@ public IObservable Process() ); } + /// + /// Takes an observable seqence and returns an observable sequence of + /// objects that are emitted every time the input sequence emits a new element. + /// public IObservable Process(IObservable source) { return Observable.Select(source, pyObject => @@ -99,6 +105,10 @@ public IObservable Process(IObservable source }); } + /// + /// Transforms an observable sequence of into an observable sequence + /// of objects by accessing internal attributes of the . + /// public IObservable Process(IObservable source) { return Observable.Select(source, pyObject => @@ -129,6 +139,7 @@ public IObservable Process(IObservable source) }); } + /// protected override string BuildString() { StringBuilder.Clear(); @@ -145,7 +156,10 @@ protected override string BuildString() StringBuilder.Append($"{Observations},"); } - StringBuilder.Remove(StringBuilder.Length - 1, 1); + if (StringBuilder.Length > 0) + { + StringBuilder.Remove(StringBuilder.Length - 1, 1); + } return StringBuilder.ToString(); } diff --git a/src/Bonsai.ML.HiddenMarkovModels/StateParametersJsonConverter.cs b/src/Bonsai.ML.HiddenMarkovModels/StateParametersJsonConverter.cs index c006973e..98fecd38 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/StateParametersJsonConverter.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/StateParametersJsonConverter.cs @@ -7,40 +7,57 @@ namespace Bonsai.ML.HiddenMarkovModels { - public class StateParametersJsonConverter: JsonConverter + /// + /// Provides a type converter to convert between and a JSON string representation. + /// + public class StateParametersJsonConverter : JsonConverter { + /// public override StateParameters ReadJson(JsonReader reader, Type objectType, StateParameters existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject jo = JObject.Load(reader); - StateParameters result = new StateParameters(); result.InitialStateDistribution = jo["InitialStateDistribution"]?.ToObject(); result.LogTransitionProbabilities = jo["LogTransitionProbabilities"]?.ToObject(); - var observationsType = GetFromString(jo["Observations"]["ObservationsType"]?.ToString()); + var observationsObj = (JObject)jo["Observations"]; + var observationsType = GetFromString(observationsObj["ObservationsType"]?.ToString()); - var paramsArray = (JArray)jo["Observations"]["Params"]; - object[] paramsObjArr = new object[paramsArray.Count]; - for (int i = 0; i < paramsArray.Count; i++) + object[] kwargsArray = null; + object[] paramsArray = []; + + if (observationsObj.ContainsKey("Kwargs")) { - paramsObjArr[i] = NumpyHelper.NumpyParser.ParseString(paramsArray[i].ToString(), typeof(double)); + var kwargs = (JObject)observationsObj["Kwargs"]; + kwargsArray = kwargs.Properties() + .Select(p => p.Value.ToObject()) + .ToArray(); + if (kwargsArray.Count() == 0) + { + kwargsArray = null; + } } - var kwargs = (JObject)jo["Observations"]["Kwargs"]; - object[] kwargsArray = kwargs.Properties() - .Select(p => p.Value.ToObject()) - .ToArray(); + var observations = (ObservationsModel)Activator.CreateInstance(GetObservationsClassType(observationsType), kwargsArray); - var observations = kwargsArray.Count() == 0 - ? (ObservationsModel)Activator.CreateInstance(GetObservationsClassType(observationsType)) - : (ObservationsModel)Activator.CreateInstance(GetObservationsClassType(observationsType), kwargsArray); + if (observationsObj.ContainsKey("Params")) + { + var paramsJArray = (JArray)observationsObj["Params"]; + var nParams = paramsJArray.Count; + paramsArray = new object[nParams]; + for (int i = 0; i < nParams; i++) + { + paramsArray[i] = NumpyHelper.NumpyParser.ParseString(paramsJArray[i].ToString(), typeof(double)); + } + } - observations.Params = paramsObjArr; + observations.Params = paramsArray; result.Observations = observations; - + return result; } + /// public override void WriteJson(JsonWriter writer, StateParameters value, JsonSerializer serializer) { writer.WriteStartObject(); diff --git a/src/Bonsai.ML.HiddenMarkovModels/StateProbability.cs b/src/Bonsai.ML.HiddenMarkovModels/StateProbability.cs index fa4f2b3a..f440854a 100644 --- a/src/Bonsai.ML.HiddenMarkovModels/StateProbability.cs +++ b/src/Bonsai.ML.HiddenMarkovModels/StateProbability.cs @@ -8,8 +8,11 @@ namespace Bonsai.ML.HiddenMarkovModels { + /// + /// Represents the probabilities of being in each state of a Hidden Markov Model (HMM) given the observation. + /// [Combinator] - [Description("")] + [Description("The probability of being in each state of a Hidden Markov Model (HMM) given the observation.")] [WorkflowElementCategory(ElementCategory.Transform)] public class StateProbability { @@ -27,6 +30,10 @@ public class StateProbability [Description("The state with the highest probability.")] public int HighestProbableState => Array.IndexOf(Probabilities, Probabilities.Max()); + /// + /// Transforms an observable sequence of into an observable sequence + /// of objects by accessing the `state_probabilities` attribute of the . + /// public IObservable Process(IObservable source) { return Observable.Select(source, pyObject => diff --git a/src/Bonsai.ML.Visualizers/GaussianObservationsClustersVisualizer.cs b/src/Bonsai.ML.Visualizers/GaussianObservationsClustersVisualizer.cs index 4830662e..27c226d6 100644 --- a/src/Bonsai.ML.Visualizers/GaussianObservationsClustersVisualizer.cs +++ b/src/Bonsai.ML.Visualizers/GaussianObservationsClustersVisualizer.cs @@ -15,6 +15,10 @@ namespace Bonsai.ML.Visualizers { + /// + /// Provides a type visualizer of to display how the observations + /// cluster with respect to the mean and covariance of each state of an HMM with gaussian observations model. + /// public class GaussianObservationsClustersVisualizer : DialogTypeVisualizer { private PlotView view; @@ -22,27 +26,50 @@ public class GaussianObservationsClustersVisualizer : DialogTypeVisualizer private List allLineSeries = null; private List allScatterSeries = null; private List colorList = null; - private StatusStrip statusStrip; - public StatusStrip StatusStrip => statusStrip; - private int dimension1SelectedIndex = 0; - public int Dimension1SelectedIndex { get => dimension1SelectedIndex; set => dimension1SelectedIndex = value; } private ToolStripComboBox dimension1ComboBox; private ToolStripLabel dimension1Label; - public ToolStripComboBox Dimension1ComboBox => dimension1ComboBox; - private int dimension2SelectedIndex = 1; - public int Dimension2SelectedIndex { get => dimension2SelectedIndex; set => dimension2SelectedIndex = value; } private ToolStripComboBox dimension2ComboBox; private ToolStripLabel dimension2Label; + private LinearAxis xAxis; + private LinearAxis yAxis; + + /// + /// Gets the status strip. + /// + public StatusStrip StatusStrip => statusStrip; + + /// + /// Gets the selected index of the first dimension. + /// + public int Dimension1SelectedIndex { get => dimension1SelectedIndex; set => dimension1SelectedIndex = value; } + + /// + /// Gets the selected index of the second dimension. + /// + public int Dimension2SelectedIndex { get => dimension2SelectedIndex; set => dimension2SelectedIndex = value; } + + /// + /// Gets the first dimension combo box. + /// + public ToolStripComboBox Dimension1ComboBox => dimension1ComboBox; + + /// + /// Gets the second dimension combo box. + /// public ToolStripComboBox Dimension2ComboBox => dimension2ComboBox; + /// + /// Gets or sets a value indicating whether the data should be buffered. + /// public bool BufferData { get; set; } = true; - public int BufferCount { get; set; } = 250; - private LinearAxis xAxis; - private LinearAxis yAxis; + /// + /// Gets or sets the buffer count. + /// + public int BufferCount { get; set; } = 250; /// public override void Load(IServiceProvider provider) @@ -139,6 +166,7 @@ public override void Show(object value) dimension1ComboBox.SelectedIndex = dimension1SelectedIndex; dimension2ComboBox.SelectedIndexChanged += dimension2ComboBoxSelectedIndexChanged; + dimension2SelectedIndex = Math.Max(dimension2ComboBox.Items.Count - 1, dimension2SelectedIndex); dimension2ComboBox.SelectedIndex = dimension2SelectedIndex; } diff --git a/src/Bonsai.ML.Visualizers/GaussianObservationsStatisticsVisualizer.cs b/src/Bonsai.ML.Visualizers/GaussianObservationsStatisticsVisualizer.cs index 458c09a9..64a5884a 100644 --- a/src/Bonsai.ML.Visualizers/GaussianObservationsStatisticsVisualizer.cs +++ b/src/Bonsai.ML.Visualizers/GaussianObservationsStatisticsVisualizer.cs @@ -12,6 +12,10 @@ namespace Bonsai.ML.Visualizers { + /// + /// Provides a type visualizer of to display the means and standard + /// deviations of each state of an HMM with gaussian observations model. + /// public class GaussianObservationStatisticsVisualizer : DialogTypeVisualizer { diff --git a/src/Bonsai.ML.Visualizers/StateProbabilityVisualizer.cs b/src/Bonsai.ML.Visualizers/StateProbabilityVisualizer.cs index 27e45a4d..13ddf4fd 100644 --- a/src/Bonsai.ML.Visualizers/StateProbabilityVisualizer.cs +++ b/src/Bonsai.ML.Visualizers/StateProbabilityVisualizer.cs @@ -14,9 +14,12 @@ namespace Bonsai.ML.Visualizers { + /// + /// Provides a type visualizer of to display the probabilities + /// of being in each state of an HMM given the observation. + /// public class StateProbabilityVisualizer : DialogTypeVisualizer { - private BarSeriesOxyPlotBase Plot; private List allBarSeries;