/// <inheritdoc/> public override object GetNormalisedValuePrecise(object originalValue, int identifier) { DimensionData.Metadata meta = this[identifier].MetaData; // Determine which textualDimensionsList to use Dictionary <string, Dictionary <string, int> > textualDimensionsListReverse; if (nodeDimensionData.Select(x => x.Identifier).FirstOrDefault() != null) { textualDimensionsListReverse = nodeTextualDimensionsListReverse; } else { textualDimensionsListReverse = edgeTextualDimensionsListReverse; } if (meta.Type == IATKDataType.String) { int stringIdx = textualDimensionsListReverse[this[identifier].Identifier][originalValue.ToString()]; return(UtilMath.NormaliseValue(stringIdx, meta.Min, meta.Max, 0f, 1f)); } else { return(UtilMath.NormaliseValue((float)originalValue, meta.Min, meta.Max, 0f, 1f)); } }
/// <summary> /// Initialises the metadata for the data, including its string identifier and type. This function assumes that the header is the first element. /// </summary> /// <param name="lines">A string array representing lines from a data file.</param> /// <returns><c>true</c> if the headers and types were successfully loaded, otherwise <c>false</c>.</returns> private bool LoadMetaData(string[] lines, ref List <DimensionData> dimensionData) { if (lines.Length > 0) { string[] identifiers = lines[0].Split(split); // Create metadata DimensionData.Metadata[] metadata = new DimensionData.Metadata[identifiers.Length]; // Clean string identifiers for each dimension for (int i = 0; i < identifiers.Length; i++) { string id = CleanDataString(identifiers[i]); identifiers[i] = id; } // Check the types for each dimension if (lines.Length > 1) { string[] typesToRead = lines[1].Split(split); for (int i = 0; i < typesToRead.Length; i++) { metadata[i].Type = DataTypeExtension.inferFromString(CleanDataString(typesToRead[i])); } } // Populate the dimension data list for (int i = 0; i < identifiers.Length; ++i) { dimensionData.Add(new DimensionData(identifiers[i], i, metadata[i])); } return(true); } return(false); }
/// <inheritdoc/> public override object GetValuePrecise(float normalisedValue, string identifier) { DimensionData.Metadata meta = this[identifier].MetaData; // Determine which textualDimensionsList to use Dictionary <string, Dictionary <int, string> > textualDimensionsList; if (nodeDimensionData.FirstOrDefault(x => x.Identifier == identifier) != null) { textualDimensionsList = nodeTextualDimensionsList; } else { textualDimensionsList = edgeTextualDimensionsList; } float normValue = UtilMath.NormaliseValue(normalisedValue, 0f, 1f, meta.Min, meta.Max); // Dimensions of type String should return a string from the textual dimensions list if (meta.Type == IATKDataType.String) { return(textualDimensionsList[identifier][(int)normValue]); } // Otherwise re can return the de-normalised value else { return(normValue); } }
/// <inheritdoc/> public override object GetValueApproximate(float normalisedValue, string identifier) { DimensionData.Metadata meta = this[identifier].MetaData; // Determine which textualDimensionsList to use Dictionary <string, Dictionary <int, string> > textualDimensionsList; if (nodeDimensionData.FirstOrDefault(x => x.Identifier == identifier) != null) { textualDimensionsList = nodeTextualDimensionsList; } else { textualDimensionsList = edgeTextualDimensionsList; } // Dimensions of type String should return a string from the textual dimensions list if (meta.Type == IATKDataType.String) { // Since this function allows for approximate input values, we need to find the value closest to the given one float normValue = UtilMath.NormaliseValue(ValueClosestTo(this[identifier].Data, normalisedValue), 0f, 1f, meta.Min, meta.Max); return(textualDimensionsList[identifier][(int)normValue]); } // Otherwise we can return a de-normalised value else { return(UtilMath.NormaliseValue(normalisedValue, 0f, 1f, meta.Min, meta.Max)); } }
/// <inheritdoc/> public override object GetNormalisedValuePrecise(object originalValue, int identifier) { DimensionData.Metadata meta = this[identifier].MetaData; if (meta.Type == IATKDataType.String) { int stringIdx = textualDimensionsListReverse[this[identifier].Identifier][originalValue.ToString()]; return(UtilMath.NormaliseValue(stringIdx, meta.Min, meta.Max, 0f, 1f)); } else { return(UtilMath.NormaliseValue((float)originalValue, meta.Min, meta.Max, 0f, 1f)); } }
/// <inheritdoc/> public override object GetValuePrecise(float normalisedValue, string identifier) { DimensionData.Metadata meta = this[identifier].MetaData; float normValue = UtilMath.NormaliseValue(normalisedValue, 0f, 1f, meta.Min, meta.Max); // Dimensions of type String should return a string from the textual dimensions list if (meta.Type == IATKDataType.String) { return(textualDimensionsList[this[identifier].Identifier][(int)normValue]); } // Otherwise re can return the de-normalised value else { return(normValue); } }
/// <inheritdoc/> public override object GetValueApproximate(float normalisedValue, string identifier) { DimensionData.Metadata meta = this[identifier].MetaData; // Dimensions of type String should return a string from the textual dimensions list if (meta.Type == IATKDataType.String) { // Since this function allows for approximate input values, we need to find the value closest to the given one float normValue = UtilMath.NormaliseValue(ValueClosestTo(this[identifier].Data, normalisedValue), 0f, 1f, meta.Min, meta.Max); return(textualDimensionsList[identifier][(int)normValue]); } // Otherwise we can return a de-normalised value else { return(UtilMath.NormaliseValue(normalisedValue, 0f, 1f, meta.Min, meta.Max)); } }
/// <summary> /// Normalises a given column from a 2D array of float values within the range 0..1. This function also sets some metadata values. /// </summary> /// <param name="dataArray">A 2D float array of data.</param> /// <param name="col">An integer index of the column to normalise.</param> /// <returns>A normalised float array in the range 0..1.</returns> private float[] NormaliseColumn(float[,] dataArray, int col, ref List <DimensionData> dimensionData) { float[] result = GetColumn(dataArray, col); float minValue = result.Min(); float maxValue = result.Max(); if (minValue == maxValue) { // where there are no distinct values, need the dimension to be distinct // otherwise lots of maths breaks with division by zero, etc. // this is the most elegant hack I could think of, but should be fixed properly in future minValue -= 1.0f; maxValue += 1.0f; } // Populate metadata values DimensionData.Metadata metadata = dimensionData[col].MetaData; metadata.Min = minValue; metadata.Max = maxValue; metadata.Categories = result.Distinct().Select(x => UtilMath.NormaliseValue(x, minValue, maxValue, 0.0f, 1.0f)).ToArray(); metadata.CategoryCount = metadata.Categories.Count(); metadata.BinCount = (int)(maxValue - minValue + 1); dimensionData[col].SetMetadata(metadata); for (int j = 0; j < result.Length; j++) { if (minValue < maxValue) { result[j] = UtilMath.NormaliseValue(result[j], minValue, maxValue, 0f, 1f); } else { // Avoid NaNs or nonsensical normalization result[j] = 0; } } return(result); }