/// <summary>
        /// This creates solid colored blobs with areas proportional to the number of items contained.  When the user
        /// mouses over a blob, the caller can show examples of the items as tooltips
        /// </summary>
        public static void ShowResults2D_Blobs(Border border, SOMResult result, Func<SOMNode, Color> getNodeColor, BlobEvents events = null)
        {
            #region validate
#if DEBUG
            if (!result.Nodes.All(o => o.Position.Length == 2))
            {
                throw new ArgumentException("Node positions need to be 2D");
            }
#endif
            #endregion

            Point[] points = result.Nodes.
                Select(o => new Point(o.Position[0], o.Position[1])).
                ToArray();

            VoronoiResult2D voronoi = Math2D.GetVoronoi(points, true);
            voronoi = Math2D.CapVoronoiCircle(voronoi);

            Color[] colors = result.Nodes.
                Select(o => getNodeColor(o)).
                ToArray();

            //ISOMInput[][] inputsByNode = UtilityCore.ConvertJaggedArray<ISOMInput>(result.InputsByNode);

            Vector size = new Vector(border.ActualWidth - border.Padding.Left - border.Padding.Right, border.ActualHeight - border.Padding.Top - border.Padding.Bottom);
            Canvas canvas = DrawVoronoi_Blobs(voronoi, colors, result.Nodes, result.InputsByNode, size.X.ToInt_Floor(), size.Y.ToInt_Floor(), events);

            border.Child = canvas;
        }
示例#2
0
        public DBRowsDetail(SelfOrganizingMapsDBWindow.QueryResults queryResults, SelfOrganizingMapsDBWindow.ColumnSetStats columns, SOMResult somResult, int nodeIndex)
        {
            InitializeComponent();

            _queryResults = queryResults;
            _columns      = columns;
            _somResult    = somResult;
            _nodeIndex    = nodeIndex;
        }
        public DBRowsDetail(SelfOrganizingMapsDBWindow.QueryResults queryResults, SelfOrganizingMapsDBWindow.ColumnSetStats columns, SOMResult somResult, int nodeIndex)
        {
            InitializeComponent();

            _queryResults = queryResults;
            _columns = columns;
            _somResult = somResult;
            _nodeIndex = nodeIndex;
        }
示例#4
0
        public void Add(VectorND item)
        {
            //TODO: Probably want something that ignores images if this is too soon from a previous call

            SOMItem somItem = GetSOMItem(item, _instructions);

            SOMResult result = _result;

            if (result != null)
            {
                if (_discardDupes)
                {
                    // Run this through the SOM
                    var closest = SelfOrganizingMaps.GetClosest(result.Nodes, somItem);

                    // If it's too similar to another, then just ignore it
                    if (IsTooClose(somItem, result.InputsByNode[closest.Item2], _dupeDistSquared))
                    {
                        return;
                    }
                }
            }

            #region process batch

            // Store this in a need-to-work list
            // When that list gets to a certain size, build a new SOM
            SOMItem[] newItemBatch = null;
            lock (_lock)
            {
                _newItems.Add(somItem);

                if (!_isProcessingBatch && _newItems.Count > _nextBatchSize)
                {
                    _nextBatchSize = StaticRandom.Next(BATCHMIN, BATCHMAX);
                    newItemBatch   = _newItems.ToArray();
                    _newItems.Clear();
                    _isProcessingBatch = true;
                }
            }

            if (newItemBatch != null)
            {
                Task.Run(() => { _result = ProcessNewItemBatch(newItemBatch, _discardDupes, _dupeDistSquared, _result); }).
                ContinueWith(t => { lock (_lock) _isProcessingBatch = false; });
            }

            #endregion
        }
示例#5
0
        private static SOMResult ProcessNewItemBatch(SOMItem[] newItemBatch, bool discardDupes, double dupeDistSquared, SOMResult existing)
        {
            const int TOTALMAX = BATCHMAX * 10;

            // Items only make it here when they aren't too similar to the som nodes, but items within this list may be dupes
            if (discardDupes)
            {
                newItemBatch = DedupeItems(newItemBatch, dupeDistSquared);
            }

            if (newItemBatch.Length > BATCHMAX)
            {
                // There are too many, just take a sample
                newItemBatch = UtilityCore.RandomRange(0, newItemBatch.Length, BATCHMAX).
                               Select(o => newItemBatch[o]).
                               ToArray();
            }

            SOMItem[] existingItems = null;
            if (existing != null)
            {
                existingItems = existing.InputsByNode.
                                SelectMany(o => o).
                                Select(o => ((SOMInput <SOMItem>)o).Source).
                                ToArray();
            }

            SOMItem[] allItems = UtilityCore.ArrayAdd(existingItems, newItemBatch);



            //TODO: This is too simplistic.  See if existingItems + newItemBatch > total.  If so, try to draw down the existing nodes evenly.  Try
            //to preserve previous images better.  Maybe even throw in a timestamp to get a good spread of times
            //
            //or get a SOM of the new, independent of the old.  Then merge the two pulling representatives to keep the most diversity.  Finally,
            //take a SOM of the combined
            if (allItems.Length > TOTALMAX)
            {
                allItems = UtilityCore.RandomRange(0, allItems.Length, TOTALMAX).
                           Select(o => allItems[o]).
                           ToArray();
            }



            SOMInput <SOMItem>[] inputs = allItems.
                                          Select(o => new SOMInput <SOMItem>()
            {
                Source = o, Weights = o.Weights,
            }).
                                          ToArray();

            //TODO: May want rules to persist from run to run
            SOMRules rules = GetSOMRules_Rand();

            return(SelfOrganizingMaps.TrainSOM(inputs, rules, true));
        }
        /// <summary>
        /// This divides the border up into a voronoi, then each node is tiled with examples
        /// </summary>
        public static void ShowResults2D_Tiled(Border border, SOMResult result, int tileWidth, int tileHeight, Action<DrawTileArgs> drawTile, BlobEvents events = null)
        {

            //TODO: Take a func that will render the input onto a writable bitmap, or something dynamic but efficient?
            // or take these in?
            //int tileWidth, int tileHeight



            Point[] points = result.Nodes.
                Select(o => new Point(o.Position[0], o.Position[1])).
                ToArray();

            Vector size = new Vector(border.ActualWidth - border.Padding.Left - border.Padding.Right, border.ActualHeight - border.Padding.Top - border.Padding.Bottom);

            VoronoiResult2D voronoi = Math2D.GetVoronoi(points, true);
            voronoi = Math2D.CapVoronoiCircle(voronoi);
            //voronoi = Math2D.CapVoronoiRectangle(voronoi, aspectRatio: 1d);       //TODO: Implement this

            Canvas canvas = DrawVoronoi_Tiled(voronoi, result.Nodes, result.InputsByNode, size.X.ToInt_Floor(), size.Y.ToInt_Floor(), tileWidth, tileHeight, drawTile, events);

            border.Child = canvas;
        }
 private void Exception_SOM(SOMRequest req, Exception ex)
 {
     _result = new SOMResult(new SOMNode[0], new RowInput[0][], false);
     DoSOM();
 }
示例#8
0
        private static SOMResult ProcessNewItemBatch(SOMItem[] newItemBatch, bool discardDupes, double dupeDistSquared, SOMResult existing)
        {
            const int TOTALMAX = BATCHMAX * 10;

            // Items only make it here when they aren't too similar to the som nodes, but items within this list may be dupes
            if (discardDupes)
            {
                newItemBatch = DedupeItems(newItemBatch, dupeDistSquared);
            }

            if (newItemBatch.Length > BATCHMAX)
            {
                // There are too many, just take a sample
                newItemBatch = UtilityCore.RandomRange(0, newItemBatch.Length, BATCHMAX).
                    Select(o => newItemBatch[o]).
                    ToArray();
            }

            SOMItem[] existingItems = null;
            if (existing != null)
            {
                existingItems = existing.InputsByNode.
                    SelectMany(o => o).
                    Select(o => ((SOMInput<SOMItem>)o).Source).
                    ToArray();
            }

            SOMItem[] allItems = UtilityCore.ArrayAdd(existingItems, newItemBatch);



            //TODO: This is too simplistic.  See if existingItems + newItemBatch > total.  If so, try to draw down the existing nodes evenly.  Try
            //to preserve previous images better.  Maybe even throw in a timestamp to get a good spread of times
            //
            //or get a SOM of the new, independent of the old.  Then merge the two pulling representatives to keep the most diversity.  Finally,
            //take a SOM of the combined
            if (allItems.Length > TOTALMAX)
            {
                allItems = UtilityCore.RandomRange(0, allItems.Length, TOTALMAX).
                    Select(o => allItems[o]).
                    ToArray();
            }






            SOMInput<SOMItem>[] inputs = allItems.
                Select(o => new SOMInput<SOMItem>() { Source = o, Weights = o.Weights, }).
                ToArray();

            //TODO: May want rules to persist from run to run
            SOMRules rules = GetSOMRules_Rand();

            return SelfOrganizingMaps.TrainSOM(inputs, rules, true);
        }
示例#9
0
        private void Timer_Tick(object sender, EventArgs e)
        {
            try
            {
                #region prep

                lblError.Text       = "";
                lblError.Visibility = Visibility.Collapsed;

                if (_recognizer == null)
                {
                    _timer.Stop();
                    ClearVisuals("no recognizer set");
                }

                if (!_recognizer.IsOn)
                {
                    ClearVisuals("Powered Off");
                    return;
                }

                Tuple <int, int> cameraWidthHeight = _recognizer.CameraWidthHeight;
                if (cameraWidthHeight == null)
                {
                    ClearVisuals("recognizer's camera not set");
                    return;
                }

                bool isColor = _recognizer.IsColor;

                #endregion

                #region latest image

                double[] image = _recognizer.LatestImage;
                if (image == null)
                {
                    canvasPixels.Source = null;
                }
                else
                {
                    if (isColor)
                    {
                        canvasPixels.Source = UtilityWPF.GetBitmap_RGB(image, cameraWidthHeight.Item1, cameraWidthHeight.Item2);
                    }
                    else
                    {
                        canvasPixels.Source = UtilityWPF.GetBitmap(image, cameraWidthHeight.Item1, cameraWidthHeight.Item2);
                    }
                }

                #endregion

                #region nn outputs

                Tuple <LifeEventType, double>[] nnOutputs = _recognizer.CurrentOutput;

                panelOutputs.Children.Clear();

                if (nnOutputs != null)
                {
                    DrawNNOutputs(panelOutputs, nnOutputs);
                }

                #endregion

                #region som

                SOMResult som             = _recognizer.SOM;
                bool      shouldRenderSOM = false;

                if (som == null)
                {
                    panelSOM.Visibility = Visibility.Collapsed;
                    panelSOM.Child      = null;
                    _currentSom         = null;
                }
                else if (som != null)
                {
                    shouldRenderSOM = true;

                    if (_currentSom != null && som.Nodes.Length == _currentSom.Nodes.Length && som.Nodes.Length > 0 && som.Nodes[0].Token == _currentSom.Nodes[0].Token)
                    {
                        shouldRenderSOM = false;
                    }
                }

                if (shouldRenderSOM)
                {
                    SelfOrganizingMapsWPF.ShowResults2D_Tiled(panelSOM, som, cameraWidthHeight.Item1, cameraWidthHeight.Item2, DrawSOMTile);
                    _currentSom         = som;
                    panelSOM.Visibility = Visibility.Visible;
                }

                #endregion

                #region training data

                var trainingData = _recognizer.TrainingData;

                if (trainingData == null || trainingData.Item1 == null || trainingData.Item1.ImportantEvents == null || trainingData.Item1.ImportantEvents.Length == 0)
                {
                    _currentTrainingData         = null;
                    panelTrainingData.Child      = null;
                    panelTrainingData.Visibility = Visibility.Collapsed;
                }
                else
                {
                    if (!IsSame(_currentTrainingData, trainingData))
                    {
                        _currentTrainingData = trainingData;
                        DrawTrainingData(panelTrainingData, trainingData);
                        panelTrainingData.Visibility = Visibility.Visible;
                    }
                }

                #endregion
            }
            catch (Exception ex)
            {
                lblError.Text       = ex.Message;
                lblError.Visibility = Visibility.Visible;
            }
        }
        private void ColumnSlider_ValueChanged(object sender, EventArgs e)
        {
            try
            {
                SliderShowValues senderCast = sender as SliderShowValues;
                if (senderCast == null)
                {
                    MessageBox.Show("Couldn't cast sender as a SliderShowValues", TITLE, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                ColumnStats column = senderCast.Tag as ColumnStats;
                if (column == null)
                {
                    MessageBox.Show("Couldn't cast sender.Tag as ColumnStats", TITLE, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                column.Width = senderCast.Value.ToInt_Round();

                _result = null;
                DoSOM();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        private void ColumnTextCheckbox_Checked(object sender, RoutedEventArgs e)
        {
            try
            {
                CheckBox senderCast = sender as CheckBox;
                if (senderCast == null)
                {
                    MessageBox.Show("Couldn't cast sender as a checkbox", TITLE, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                ColumnStats column = senderCast.Tag as ColumnStats;
                if (column == null)
                {
                    MessageBox.Show("Couldn't cast sender.Tag as ColumnStats", TITLE, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                column.ForceText = senderCast.IsChecked.Value;

                _result = null;
                DoSOM();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), TITLE, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        private void ShowResults_Disk(Border border, SOMResult result, Func<SOMNode, Color> getNodeColor)
        {
            Point[] points = result.Nodes.
                Select(o => new Point(o.Position[0], o.Position[1])).
                ToArray();

            VoronoiResult2D voronoi = Math2D.GetVoronoi(points, true);
            voronoi = Math2D.CapVoronoiCircle(voronoi);

            Color[] colors = result.Nodes.
                Select(o => getNodeColor(o)).
                ToArray();

            ImageInput[][] imagesByNode = UtilityCore.ConvertJaggedArray<ImageInput>(result.InputsByNode);

            Vector size = new Vector(border.ActualWidth - border.Padding.Left - border.Padding.Right, border.ActualHeight - border.Padding.Top - border.Padding.Bottom);
            Canvas canvas = DrawVoronoi(voronoi, colors, result.Nodes, imagesByNode, size.X.ToInt_Floor(), size.Y.ToInt_Floor());

            border.Child = canvas;

            // This is for the manual manipulate buttons
            _nodes = result.Nodes;
            _imagesByNode = imagesByNode;
            _wasEllipseTransferred = false;
        }
        private void Timer_Tick(object sender, EventArgs e)
        {
            try
            {
                #region prep

                lblError.Text = "";
                lblError.Visibility = Visibility.Collapsed;

                if (_recognizer == null)
                {
                    _timer.Stop();
                    ClearVisuals("no recognizer set");
                }

                if (!_recognizer.IsOn)
                {
                    ClearVisuals("Powered Off");
                    return;
                }

                Tuple<int, int> cameraWidthHeight = _recognizer.CameraWidthHeight;
                if (cameraWidthHeight == null)
                {
                    ClearVisuals("recognizer's camera not set");
                    return;
                }

                bool isColor = _recognizer.IsColor;

                #endregion

                #region latest image

                double[] image = _recognizer.LatestImage;
                if (image == null)
                {
                    canvasPixels.Source = null;
                }
                else
                {
                    if (isColor)
                    {
                        canvasPixels.Source = UtilityWPF.GetBitmap_RGB(image, cameraWidthHeight.Item1, cameraWidthHeight.Item2);
                    }
                    else
                    {
                        canvasPixels.Source = UtilityWPF.GetBitmap(image, cameraWidthHeight.Item1, cameraWidthHeight.Item2);
                    }
                }

                #endregion

                #region nn outputs

                Tuple<LifeEventType, double>[] nnOutputs = _recognizer.CurrentOutput;

                panelOutputs.Children.Clear();

                if (nnOutputs != null)
                {
                    DrawNNOutputs(panelOutputs, nnOutputs);
                }

                #endregion

                #region som

                SOMResult som = _recognizer.SOM;
                bool shouldRenderSOM = false;

                if (som == null)
                {
                    panelSOM.Visibility = Visibility.Collapsed;
                    panelSOM.Child = null;
                    _currentSom = null;
                }
                else if (som != null)
                {
                    shouldRenderSOM = true;

                    if (_currentSom != null && som.Nodes.Length == _currentSom.Nodes.Length && som.Nodes.Length > 0 && som.Nodes[0].Token == _currentSom.Nodes[0].Token)
                    {
                        shouldRenderSOM = false;
                    }
                }

                if (shouldRenderSOM)
                {
                    SelfOrganizingMapsWPF.ShowResults2D_Tiled(panelSOM, som, cameraWidthHeight.Item1, cameraWidthHeight.Item2, DrawSOMTile);
                    _currentSom = som;
                    panelSOM.Visibility = Visibility.Visible;
                }

                #endregion

                #region training data

                var trainingData = _recognizer.TrainingData;

                if (trainingData == null || trainingData.Item1 == null || trainingData.Item1.ImportantEvents == null || trainingData.Item1.ImportantEvents.Length == 0)
                {
                    _currentTrainingData = null;
                    panelTrainingData.Child = null;
                    panelTrainingData.Visibility = Visibility.Collapsed;
                }
                else
                {
                    if (!IsSame(_currentTrainingData, trainingData))
                    {
                        _currentTrainingData = trainingData;
                        DrawTrainingData(panelTrainingData, trainingData);
                        panelTrainingData.Visibility = Visibility.Visible;
                    }
                }

                #endregion
            }
            catch (Exception ex)
            {
                lblError.Text = ex.Message;
                lblError.Visibility = Visibility.Visible;
            }
        }
示例#14
0
 private static SelfOrganizingMapsDBWindow.RowInput[] GetMatchingRows(SelfOrganizingMapsDBWindow.ColumnStats[] columns, SelfOrganizingMapsDBWindow.QueryResults queryResults, SOMResult som, int nodeIndex)
 {
     return(SelfOrganizingMapsDBWindow.GetSOMInputs(columns, queryResults, false).
            Where(o => SelfOrganizingMaps.GetClosest(som.Nodes, o).Item2 == nodeIndex).
            ToArray());
 }
 private static SelfOrganizingMapsDBWindow.RowInput[] GetMatchingRows(SelfOrganizingMapsDBWindow.ColumnStats[] columns, SelfOrganizingMapsDBWindow.QueryResults queryResults, SOMResult som, int nodeIndex)
 {
     return SelfOrganizingMapsDBWindow.GetSOMInputs(columns, queryResults, false).
         Where(o => SelfOrganizingMaps.GetClosest(som.Nodes, o).Item2 == nodeIndex).
         ToArray();
 }
        /// <summary>
        /// This looks at the current inputs, and starts a new SOM async
        /// </summary>
        private void DoSOM()
        {
            #region Init

            // Parse all the inputs
            QueryRequest queryReq = GetQueryRequest();

            if (queryReq.Columns.Length == 0)
            {
                lblErrorMessage.Text = "No columns specified";
                lblQueryStatus.Text = "";
                pnlColumns.Children.Clear();
                _queryResults = null;
                _columns = null;
                _result = null;
                return;
            }

            #endregion
            #region Query

            // Run query if changed
            if (_queryResults == null || _queryResults.ConnectionString != queryReq.ConnectionString || _queryResults.SQLStatement != queryReq.SQLStatement)
            {
                lblQueryStatus.Text = "Running query...";
                lblErrorMessage.Text = "";
                pnlColumns.Children.Clear();
                _columns = null;
                _result = null;

                _workerQuery.Start(queryReq);
                return;     //_workerQuery.finish will call this method again, and execution will flow past this if statement
            }

            lblQueryStatus.Text = "";

            if (!string.IsNullOrEmpty(_queryResults.Exception))
            {
                lblErrorMessage.Text = _queryResults.Exception;
                _result = null;
                return;
            }

            lblQueryStatus.Text = string.Format("{0} row{1}", _queryResults.Results.Length.ToString("N0"), _queryResults.Results.Length == 1 ? "" : "s");

            #endregion
            #region Columns

            if (_columns != null)
            {
                _columns = _columns.CloneIfSameNames(queryReq.Columns, _queryResults.ColumnNames);      //NOTE: This will still clone if it just holds an exception
            }

            if (_columns == null || !IsSame(queryReq.Columns, _columns.Names))
            {
                lblErrorMessage.Text = "";
                _result = null;
                _workerColumns.Start(new ColumnStatsRequest(queryReq.Columns, _queryResults));
                return;
            }

            if (_columns != null && !string.IsNullOrEmpty(_columns.Exception))
            {
                lblErrorMessage.Text = _columns.Exception;
                _result = null;
                return;
            }

            #endregion
            #region Do SOM

            if (_result == null)
            {
                RowInput[] inputs = GetSOMInputs(_columns.Columns, _queryResults, true);

                //TODO: Get these from the gui.  Add an option to randomize against their settings
                SOMRules rules = GetSOMRules_Rand();

                //TODO: Make an option for display1D.  Then do a SOM for each column and put the results in the column details dump
                _workerSOM.Start(new SOMRequest(inputs, rules));
                return;
            }

            #endregion
            #region Show Results

            var events = new SelfOrganizingMapsWPF.BlobEvents(Polygon_MouseMove, Polygon_MouseLeave, Polygon_Click);

            SelfOrganizingMapsWPF.ShowResults2D_Blobs(panelDisplay, _result, SelfOrganizingMapsWPF.GetNodeColor, events);

            #endregion
        }
 private void Finished_SOM(SOMRequest req, SOMResult result)
 {
     _result = result;
     DoSOM();
 }
        private static void SaveImages(string parentFolder, string childFolder, int width, int height, SOMResult som, bool isColor)
        {
            if (som == null || som.InputsByNode == null || som.InputsByNode.Length == 0)
            {
                return;
            }

            // Pull out the images
            double[][] images = som.InputsByNode.
                SelectMany(o => o).
                Select(o =>
                {
                    var cast = o as SOMInput<SOMList.SOMItem>;
                    if (cast == null) return null;

                    return cast.Source.Original;
                }).
                Where(o => o != null).
                ToArray();

            SaveImages(parentFolder, childFolder, width, height, images, isColor);
        }
示例#19
0
        public void Add(double[] item)
        {
            //TODO: Probably want something that ignores images if this is too soon from a previous call

            SOMItem somItem = GetSOMItem(item, _instructions);

            SOMResult result = _result;
            if (result != null)
            {
                if (_discardDupes)
                {
                    // Run this through the SOM
                    var closest = SelfOrganizingMaps.GetClosest(result.Nodes, somItem);

                    // If it's too similar to another, then just ignore it
                    if (IsTooClose(somItem, result.InputsByNode[closest.Item2], _dupeDistSquared))
                    {
                        return;
                    }
                }
            }

            #region process batch

            // Store this in a need-to-work list
            // When that list gets to a certain size, build a new SOM
            SOMItem[] newItemBatch = null;
            lock (_lock)
            {
                _newItems.Add(somItem);

                if (!_isProcessingBatch && _newItems.Count > _nextBatchSize)
                {
                    _nextBatchSize = StaticRandom.Next(BATCHMIN, BATCHMAX);
                    newItemBatch = _newItems.ToArray();
                    _newItems.Clear();
                    _isProcessingBatch = true;
                }
            }

            if (newItemBatch != null)
            {
                Task.Run(() => { _result = ProcessNewItemBatch(newItemBatch, _discardDupes, _dupeDistSquared, _result); }).
                    ContinueWith(t => { lock (_lock)  _isProcessingBatch = false; });
            }

            #endregion
        }