/// <summary> /// Loads macros from rewindable reader instance. /// </summary> /// <param name="rewinder">The instance to read data from.</param> private void Load(RewindableTextReader rewinder) { Helper.ThrowIfNull(rewinder); string line = null; while ((line = rewinder.ReadLine()) != null) { MacroName macro = MacroName.Create(line); switch (macro.Symbol) { case "o": LoadGlobalOptions(rewinder); break; case "v": VarFloor var = new VarFloor() { Macro = macro, Variance = ReadTagArray(rewinder, "<VARIANCE>"), }; VarFloors.Add(var.Macro.Name, var); break; case "t": Transition trans = new Transition() { Macro = macro, Matrix = ReadTransition(rewinder), }; Transitions.Add(trans.Macro.Name, trans); break; case "s": HmmStream stream = ReadStream(rewinder); stream.Name = macro.Name; Streams.Add(macro.Name, stream); break; case "h": HmmModel model = ReadModel(rewinder, Streams, Transitions); model.Macro = macro; Models.Add(macro.Name, model); break; default: throw new InvalidDataException(Helper.NeutralFormat( "Macro name [{0}] is not supported in line [{1}].", macro.Name, macro.Name)); } } }
/// <summary> /// Loads global options information from text reader instance. /// </summary> /// <param name="rewinder">The rewindable text reader to load data from.</param> private void LoadGlobalOptions(RewindableTextReader rewinder) { Helper.ThrowIfNull(rewinder); foreach (string line in rewinder.ReadLines(new string[] { MacroName.Indicator }, false)) { string[] items = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (items.Length <= 1) { throw new InvalidDataException(Helper.NeutralFormat( "The information in global options should be with (<tag> <value>+), but it is [{0}]", line)); } switch (items[0]) { case "<STREAMINFO>": StreamInfo = ParseSizedArray(ParseIntArray(items.Skip(1))); break; case "<MSDINFO>": MsdInfo = ParseSizedArray(ParseIntArray(items.Skip(1))); break; case "<VECSIZE>": LoadVecSize(items.Skip(1)); break; default: throw new InvalidDataException(Helper.NeutralFormat( "The line [{0}] of global options is not supported.", line)); } } }
/// <summary> /// Reads one transition instance from text reader instance. /// </summary> /// <param name="rewinder">The text reader to read double matrix from.</param> /// <returns>Transition instance loaded.</returns> private static double[,] ReadTransition(RewindableTextReader rewinder) { Helper.ThrowIfNull(rewinder); int size = ParseTagValue(rewinder.ReadLine(), "<TRANSP>"); double[,] values = ParseDoubleMatrix( rewinder.ReadLines(new string[] { "<", MacroName.Indicator }, false).ToArray(), size); return values; }
/// <summary> /// Reads double matrix from the text reader with the expected tag. /// </summary> /// <param name="rewinder">Text reader to read array from.</param> /// <param name="tag">Expected tag to start in the stream.</param> /// <returns>Double matrix from the text reader.</returns> private static double[] ReadTagArray(RewindableTextReader rewinder, string tag) { Helper.ThrowIfNull(rewinder); Helper.ThrowIfNull(tag); string line = rewinder.ReadLine(); int size = ParseTagValue(line, tag); double[] values = new double[0]; if (size > 0) { values = ParseDoubleArray(rewinder.ReadLine()); if (values.Length != size) { throw new InvalidDataException(Helper.NeutralFormat("Mismatched value is found, " + "declared as [{0}], but as [{1}].", size, values.Length)); } } return values; }
/// <summary> /// Reads one HMM gaussian instance from text reader instance. /// </summary> /// <param name="rewinder">The text reader to read gaussian from.</param> /// <returns>HMM gaussian instance loaded.</returns> private static Gaussian ReadGaussian(RewindableTextReader rewinder) { Helper.ThrowIfNull(rewinder); Gaussian gaussian = new Gaussian(); gaussian.Mean = ReadTagArray(rewinder, "<MEAN>"); gaussian.Variance = ReadTagArray(rewinder, "<VARIANCE>"); if (gaussian.Mean.Length != gaussian.Variance.Length) { throw new InvalidDataException(Helper.NeutralFormat( "The dimension of mean [{0}] should equal with that of variance [{1}].", gaussian.Mean.Length, gaussian.Variance.Length)); } gaussian.Length = gaussian.Mean.Length; string line = rewinder.PeekLine(); if (line != null && line.StartsWith("<GCONST>")) { string[] items = ParseTagValues(rewinder.ReadLine(), "<GCONST>"); if (items.Length != 1) { throw new InvalidDataException(Helper.NeutralFormat( "Single value is expected for <GCONST>, but it is with line [{0}].", line)); } gaussian.GlobalConstant = float.Parse(items[0], CultureInfo.InvariantCulture); } return gaussian; }
/// <summary> /// Reads one HMM stream instance from text reader instance. /// </summary> /// <param name="rewinder">The text reader to read stream from.</param> /// <returns>HMM stream instance loaded.</returns> private static HmmStream ReadStream(RewindableTextReader rewinder) { Helper.ThrowIfNull(rewinder); HmmStream stream = new HmmStream(); string line = rewinder.PeekLine(); int streamIndex = 0; if (line.StartsWith("<STREAM>")) { streamIndex = ParseTagValue(rewinder.ReadLine(), "<STREAM>"); } int mixtureNumber = 1; line = rewinder.PeekLine(); if (line.StartsWith("<NUMMIXES>")) { mixtureNumber = ParseTagValue(rewinder.ReadLine(), "<NUMMIXES>"); } List<Gaussian> gaussians = new List<Gaussian>(); for (int i = 0; i < mixtureNumber; i++) { int mixtureIndex = 0; float weight = 0.0f; line = rewinder.PeekLine(); if (line.StartsWith("<MIXTURE>")) { string[] values = ParseTagValues(rewinder.ReadLine(), "<MIXTURE>"); mixtureIndex = int.Parse(values[0], CultureInfo.InvariantCulture); weight = float.Parse(values[1], CultureInfo.InvariantCulture); if (mixtureIndex != i + 1) { throw new InvalidDataException( Helper.NeutralFormat("The mixture index is mis-matched between {0} and {1} in line [{2}]", i, mixtureIndex, line)); } } Gaussian gaussian = ReadGaussian(rewinder); gaussian.Weight = weight; gaussians.Add(gaussian); } stream.Gaussians = gaussians.ToArray(); return stream; }
/// <summary> /// Reads one HMM state instance from text reader instance. /// </summary> /// <param name="rewinder">Rewindable text reader instance to read HMM model from.</param> /// <param name="streams">Global HMM streams if any reference.</param> /// <returns>HMM state instance loaded.</returns> private static HmmState ReadState(RewindableTextReader rewinder, Dictionary<string, HmmStream> streams) { Helper.ThrowIfNull(rewinder); Helper.ThrowIfNull(streams); HmmState state = new HmmState(); int stateIndex = ParseTagValue(rewinder.ReadLine(), "<STATE>"); string line = rewinder.PeekLine(); if (line.StartsWith("<SWEIGHTS>")) { rewinder.ReadLine(); line = rewinder.ReadLine(); line = rewinder.PeekLine(); } if (line.StartsWith(MacroName.Indicator)) { MacroName macro = MacroName.Create(rewinder.ReadLine()); if (macro.Symbol != "s") { throw new InvalidDataException( Helper.NeutralFormat("Stream symbol 's' is expected for line [{0}].", line)); } if (!streams.ContainsKey(macro.Name)) { throw new InvalidDataException(Helper.NeutralFormat( "Referenced macro [{0}] does not exist, used by line [{1}].", macro.Name, line)); } state.Streams.Add(streams[macro.Name]); } else { while (line.StartsWith("<STREAM>")) { HmmStream stream = ReadStream(rewinder); state.Streams.Add(stream); line = rewinder.PeekLine(); } } return state; }
/// <summary> /// Reads one HMM model instance from text reader instance. /// </summary> /// <param name="rewinder">Rewindable text reader instance to read HMM model from.</param> /// <param name="streams">Global HMM streams if any reference.</param> /// <param name="transition">Global transitions if any reference.</param> /// <returns>HMM model instance loaded.</returns> private static HmmModel ReadModel(RewindableTextReader rewinder, Dictionary<string, HmmStream> streams, Dictionary<string, Transition> transition) { Helper.ThrowIfNull(rewinder); Helper.ThrowIfNull(streams); Helper.ThrowIfNull(transition); HmmModel model = new HmmModel(); Ensure(rewinder.ReadLine(), "<BEGINHMM>"); int stateCount = ParseTagValue(rewinder.ReadLine(), "<NUMSTATES>"); // Excludes the entrance and existing states for (int i = 1; i < stateCount - 1; i++) { HmmState state = ReadState(rewinder, streams); model.States.Add(state); } if (rewinder.PeekLine().StartsWith("~t")) { MacroName macro = MacroName.Create(rewinder.ReadLine()); if (!transition.ContainsKey(macro.Name)) { throw new InvalidDataException(Helper.NeutralFormat("Transition [{0}] is not found.", macro.Name)); } model.Transition = transition[macro.Name]; } else if (rewinder.PeekLine().StartsWith("<TRANSP>")) { model.Transition = new Transition() { Matrix = ReadTransition(rewinder), }; } Ensure(rewinder.ReadLine(), "<ENDHMM>"); return model; }
/// <summary> /// Loads the macros in Master Macro File from text reader instance. /// </summary> /// <param name="reader">Text reader instance to read macros from.</param> /// <returns>MasterMacroFile.</returns> public MasterMacroFile Load(TextReader reader) { Helper.ThrowIfNull(reader); Reset(); using (RewindableTextReader rewinder = new RewindableTextReader(reader)) { Load(rewinder); } return this; }