public SubstrateDescription(String filename)
        {
            useLeo      = false;
            HiddenCount = 0;
            InputCount  = 0;
            OutputCount = 0;

            hiddenNeurons = new List <PointF>();
            inputNeurons  = new List <PointF>();
            outputNeurons = new List <PointF>();

            neuronGroups = new List <NeuronGroup>();

            XmlDocument document = new XmlDocument();

            document.Load(filename);
            XmlElement xmlSubstrate = (XmlElement)document.SelectSingleNode("substrate");

            if (xmlSubstrate == null)
            {
                throw new Exception("The genome XML is missing the root 'substrate' element.");
            }
            this.useLeo = bool.Parse(XmlUtilities.GetAttribute(xmlSubstrate, "leo").Value);
            //--- Read neuron genes into a list.
            //NeuronGeneList neuronGeneList = new NeuronGeneList();

            XmlElement  xmlGroups        = (XmlElement)xmlSubstrate.SelectSingleNode("neuronGroups");
            XmlNodeList listNeuronGroups = xmlGroups.SelectNodes("group");

            foreach (XmlElement xmlNeuronGroup in listNeuronGroups)
            {
                int    id  = int.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "id").Value);
                String tmp = XmlUtilities.GetAttribute(xmlNeuronGroup, "type").Value;

                int neuronGroupType = -1;

                float       startX = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "startx").Value);
                float       startY = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "starty").Value);
                float       endX   = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "endx").Value);
                float       endY   = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "endy").Value);
                uint        dx     = uint.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "dx").Value);
                uint        dy     = uint.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "dy").Value);
                NeuronGroup ng     = null;

                if (tmp.Equals("Hidden"))
                {
                    neuronGroupType = 2;
                    ng           = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, HiddenCount);
                    HiddenCount += dx * dy;
                }
                else if (tmp.Equals("Output"))
                {
                    neuronGroupType = 1;
                    ng           = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, OutputCount);
                    OutputCount += dx * dy;
                }
                else if (tmp.Equals("Input"))
                {
                    neuronGroupType = 0;
                    ng          = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, InputCount);
                    InputCount += dx * dy;
                }

                // Debug
                //Console.WriteLine(id + " " + neuronGroupType + " " + startX + " " + startY + " " + endX + " " + endY + " " + dx + " " + dy);
                //Console.WriteLine("InputCount = " + InputCount);

                neuronGroups.Add(ng);
            }
            //Load Connections
            XmlElement  xmlConnections  = (XmlElement)xmlSubstrate.SelectSingleNode("connections");
            XmlNodeList listConnections = xmlConnections.SelectNodes("connection");

            foreach (XmlElement xmlConnection in listConnections)
            {
                int srcID = int.Parse(XmlUtilities.GetAttribute(xmlConnection, "src-id").Value);
                int tgID  = int.Parse(XmlUtilities.GetAttribute(xmlConnection, "tg-id").Value);
                foreach (NeuronGroup n in neuronGroups)
                {
                    if (n.GroupID == srcID)
                    {
                        n.ConnectedTo.Add(tgID);
                    }
                }
            }
        }
        public SubstrateDescription(String filename)
        {
            useLeo = false;
            HiddenCount = 0;
            InputCount = 0;
            OutputCount = 0;
            TransCount = 0;
            ReceiveCount = 0;

            hiddenNeurons = new List<PointF>();
            inputNeurons = new List<PointF>();
            outputNeurons = new List<PointF>();
            transNeurons = new List<PointF>();
            receiveNeurons = new List<PointF>();

            neuronGroups = new List<NeuronGroup>();

            XmlDocument document = new XmlDocument();
            document.Load(filename);
            XmlElement xmlSubstrate = (XmlElement)document.SelectSingleNode("substrate");

            if (xmlSubstrate == null)
                throw new Exception("The genome XML is missing the root 'substrate' element.");
            this.useLeo = bool.Parse(XmlUtilities.GetAttribute(xmlSubstrate, "leo").Value);
            //--- Read neuron genes into a list.
            //NeuronGeneList neuronGeneList = new NeuronGeneList();

            XmlElement xmlGroups = (XmlElement)xmlSubstrate.SelectSingleNode("neuronGroups");
            XmlNodeList listNeuronGroups = xmlGroups.SelectNodes("group");
            foreach (XmlElement xmlNeuronGroup in listNeuronGroups)
            {
                int id = int.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "id").Value);
                String tmp = XmlUtilities.GetAttribute(xmlNeuronGroup, "type").Value;

                int neuronGroupType = -1;

                float startX = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "startx").Value);
                float startY = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "starty").Value);
                float endX = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "endx").Value);
                float endY = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "endy").Value);
                uint dx = uint.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "dx").Value);
                uint dy = uint.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "dy").Value);
                NeuronGroup ng = null;

                if (tmp.Equals("Transmit"))
                {
                    neuronGroupType = 4;
                    ng = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, TransCount);
                    TransCount += dx * dy;
                }
                else if (tmp.Equals("Receive"))
                {
                    neuronGroupType = 3;
                    ng = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, ReceiveCount);
                    ReceiveCount += dx * dy;
                }
                else if (tmp.Equals("Hidden"))
                {
                    neuronGroupType = 2;
                    ng = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, HiddenCount);
                    HiddenCount += dx * dy;
                }
                else if (tmp.Equals("Output"))
                {
                    neuronGroupType = 1;
                    ng = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, OutputCount);
                    OutputCount += dx * dy;
                }
                else if (tmp.Equals("Input"))
                {
                    neuronGroupType = 0;
                    ng = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, InputCount);
                    InputCount += dx * dy;
                }

                //  Console.WriteLine(id + " " + neuronGroupType + " " + startX + " " + startY + " " + endX + " " + endY + " " + dx + " " + dy);

                neuronGroups.Add(ng);
            }
            //Load Connections
            XmlElement xmlConnections = (XmlElement)xmlSubstrate.SelectSingleNode("connections");
            XmlNodeList listConnections = xmlConnections.SelectNodes("connection");
            foreach (XmlElement xmlConnection in listConnections)
            {
                int srcID = int.Parse(XmlUtilities.GetAttribute(xmlConnection, "src-id").Value);
                int tgID = int.Parse(XmlUtilities.GetAttribute(xmlConnection, "tg-id").Value);
                foreach (NeuronGroup n in neuronGroups)
                {
                    if (n.GroupID == srcID)
                    {
                        n.ConnectedTo.Add(tgID);
                    }
                }
            }
        }
        public SubstrateDescription(String filename)
        {
            useLeo = false;
            useMultiPlaneSubstrate = false;
            HiddenCount = 0;
            InputCount = 0;
            OutputCount = 0;

            hiddenNeurons = new List<PointF>();
            inputNeurons = new List<PointF>();
            outputNeurons = new List<PointF>();

            planesConnected = new List<Point>();
            planes = new List<int>();

            neuronGroups = new List<NeuronGroup>();

            XmlDocument document = new XmlDocument();
            document.Load(filename);
            XmlElement xmlSubstrate = (XmlElement)document.SelectSingleNode("substrate");

            if (xmlSubstrate == null)
                throw new Exception("The genome XML is missing the root 'substrate' element.");

            this.useLeo = bool.Parse(XmlUtilities.GetAttribute(xmlSubstrate, "leo").Value);

            // Use multi-plane substrate? If attribute not present, it should default to "false"
            String strUseMultiPlaneSubstrate = XmlUtilities.GetAttributeValue(xmlSubstrate, "multiplane", false);
            if (strUseMultiPlaneSubstrate != "")
            {
                this.useMultiPlaneSubstrate = bool.Parse(strUseMultiPlaneSubstrate);
            }
            if (useMultiPlaneSubstrate)
            {
                Console.WriteLine("Using multi-plane substrate.");
            }

            //--- Read neuron genes into a list.
            //NeuronGeneList neuronGeneList = new NeuronGeneList();

            XmlElement xmlGroups = (XmlElement)xmlSubstrate.SelectSingleNode("neuronGroups");
            XmlNodeList listNeuronGroups = xmlGroups.SelectNodes("group");
            foreach (XmlElement xmlNeuronGroup in listNeuronGroups)
            {
                int id = int.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "id").Value);
                String tmp = XmlUtilities.GetAttribute(xmlNeuronGroup, "type").Value;

                int neuronGroupType = -1;

                float startX = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "startx").Value);
                float startY = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "starty").Value);
                float endX = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "endx").Value);
                float endY = float.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "endy").Value);
                uint dx = uint.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "dx").Value);
                uint dy = uint.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "dy").Value);
                int plane = 0;
                NeuronGroup ng = null;

                if (useMultiPlaneSubstrate)
                {
                    plane = int.Parse(XmlUtilities.GetAttribute(xmlNeuronGroup, "plane").Value);
                }

                if (tmp.Equals("Hidden"))
                {
                    neuronGroupType = 2;
                    ng = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, HiddenCount, plane);
                    HiddenCount += dx * dy;
                }
                else if (tmp.Equals("Output"))
                {
                    neuronGroupType = 1;
                    ng = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, OutputCount, plane);
                    OutputCount += dx * dy;
                }
                else if (tmp.Equals("Input"))
                {
                    neuronGroupType = 0;
                    ng = new NeuronGroup(startX, startY, endX, endY, dx, dy, id, neuronGroupType, InputCount, plane);
                    InputCount += dx * dy;
                }

                if (!planes.Contains(plane))
                { // If this is the first time encountering a plane id, store it
                    planes.Add(plane);
                }

                //  Console.WriteLine(id + " " + neuronGroupType + " " + startX + " " + startY + " " + endX + " " + endY + " " + dx + " " + dy);

                neuronGroups.Add(ng);
            }
            //Load Connections
            XmlElement xmlConnections = (XmlElement)xmlSubstrate.SelectSingleNode("connections");
            XmlNodeList listConnections = xmlConnections.SelectNodes("connection");
            foreach (XmlElement xmlConnection in listConnections)
            {
                int srcID = int.Parse(XmlUtilities.GetAttribute(xmlConnection, "src-id").Value);
                int tgID = int.Parse(XmlUtilities.GetAttribute(xmlConnection, "tg-id").Value);
                bool hive = string.Equals("hivebrain", XmlUtilities.GetAttribute(xmlConnection, "type").Value);

                // Find the source and target neuron groups
                NeuronGroup src = null;
                NeuronGroup tg = null;
                foreach (NeuronGroup n in neuronGroups)
                {
                    if (n.GroupID == srcID)
                    {
                        src = n;
                    }
                    if (n.GroupID == tgID)
                    {
                        tg = n;
                    }
                }

                // Connect them
                if (hive)
                    src.HiveConnectedTo.Add(tgID);
                else
                    src.ConnectedTo.Add(tgID);

                // Check/set plane connectivity
                if (!areThesePlanesConnected(src.Plane, tg.Plane))
                {
                    connectThesePlanes(src.Plane, tg.Plane);
                }

            }

            // DEBUG INFO - PRINT ALL PLANE CONNECTIONS
            Console.WriteLine("Plane connections:");
            foreach (Point p in planesConnected)
            {
                Console.WriteLine("   {0} <---> {1}", p.X, p.Y);
            }

            xmlConnections = (XmlElement)xmlSubstrate.SelectSingleNode("visualize");
            if (xmlConnections == null) return;

            listConnections = xmlConnections.SelectNodes("node");
            uint vis_id = 0;
            visualizeNodes = new List<vis_node>();
            foreach (XmlElement xmlConnection in listConnections)
            {
                int groupID = int.Parse(XmlUtilities.GetAttribute(xmlConnection, "group-id").Value);

                int number = int.Parse(XmlUtilities.GetAttribute(xmlConnection, "number").Value);
                int ypos = int.Parse(XmlUtilities.GetAttribute(xmlConnection, "ypos").Value);
                int xpos = int.Parse(XmlUtilities.GetAttribute(xmlConnection, "xpos").Value);

                float zfilter = float.Parse(XmlUtilities.GetAttribute(xmlConnection, "z").Value);

                //  int c = 0; //index in group
                foreach (NeuronGroup n in neuronGroups)
                {
                    if (n.GroupID == groupID)
                    {
                        //n.gr
                        visualizeNodes.Add(new vis_node(vis_id, n.NeuronPositions[number].X, n.NeuronPositions[number].Y, xpos, ypos, zfilter, groupID, number));
                        vis_id++;
                        //n.NeuronPositions[number].x;
                        //n.NeuronPositions[number].y;

                        // foreach (PointF source in ng.NeuronPositions)

                    }
                    //   c++;
                }

            }
        }