public NetworkHelper(IList<Minutia> features, SOMParams somParams)
        {
            var trainingFeaturesCount = features.Count;
            var inputs = new double[trainingFeaturesCount][];
            var featureCharacteristicsCount = somParams.CharacteristicsCount;

            for (var i = 0; i < trainingFeaturesCount; i++)
            {
                var feature = features[i];

                inputs[i] = new double[featureCharacteristicsCount];
                inputs[i][0] = feature.Angle * somParams.AngleMultiplier;
                inputs[i][1] = (double)feature.MinutiaType * somParams.TypeMultiplier;
                inputs[i][2] = feature.X * somParams.CoordsMultiplier;
                inputs[i][3] = feature.Y * somParams.CoordsMultiplier;
                inputs[i][4] = feature.GetHashCode()*somParams.HashCodeMultiplier;
            }

            _networkSize = CreateRectangleFromFeatures(trainingFeaturesCount);

            _som = new DistanceNetwork(featureCharacteristicsCount, trainingFeaturesCount);
            _teacher = new SOMLearning(_som, _networkSize[0], _networkSize[1]);
            _inputs = inputs;
            _learningRadius = somParams.LearningRadius;
            _fixedLearningRate = somParams.LearningRate / 10;
            _driftingLearningRate = _fixedLearningRate * 9;
        }
        public NetworkHelper(double[][] features, SOMParams somParams)
        {
            var trainingFeaturesCount = features.GetLength(0);
            var featureCharacteristicsCount = somParams.CharacteristicsCount;

            _networkSize = CreateRectangleFromFeatures(trainingFeaturesCount);

            _som = new DistanceNetwork(featureCharacteristicsCount, trainingFeaturesCount);
            _teacher = new SOMLearning(_som, _networkSize[0], _networkSize[1]);
            _inputs = features;
            _learningRadius = somParams.LearningRadius;
            _fixedLearningRate = somParams.LearningRate / 10;
            _driftingLearningRate = _fixedLearningRate * 9;
        }
        public static double[][] GetQueryFeaturesSet(Bitmap image, SOMParams somParams)
        {
            var featExtractor = new Ratha1995MinutiaeExtractor();
            var features = featExtractor.ExtractFeatures(image);

            var queryFeaturesSet = new double[features.Count][];

            for (var i = 0; i < features.Count; i++)
            {
                // create new sample
                var feature = features[i];

                queryFeaturesSet[i] = new double[somParams.CharacteristicsCount];
                queryFeaturesSet[i][0] = feature.Angle * somParams.AngleMultiplier;
                queryFeaturesSet[i][1] = (double)feature.MinutiaType * somParams.TypeMultiplier;
                queryFeaturesSet[i][2] = feature.X * somParams.CoordsMultiplier;
                queryFeaturesSet[i][3] = feature.Y * somParams.CoordsMultiplier;
                queryFeaturesSet[i][4] = feature.GetHashCode() * somParams.HashCodeMultiplier;
            }

            return queryFeaturesSet;
        }
		// On "Start" button click
		private void startButton_Click(object sender, EventArgs e)
		{
			// get iterations count
			try
			{
				iterations = Math.Max(5, Math.Min(1000000, int.Parse( iterationsBox.Text )));
			}
			catch
			{
				iterations = 500;
			}
			// get learning rate
			try
			{
                learningRate = Math.Max(0.00001, Math.Min(1.0, double.Parse( rateBox.Text )));
			}
			catch
			{
				learningRate = 0.3;
			}
			// get radius
			try
			{
				learningRadius = Math.Max(1, Math.Min(30, int.Parse( radiusBox.Text )));
			}
			catch
			{
				learningRadius = 3;
			}

            try
            {
                angleMultiplier = Math.Max(0.00001, Math.Min(100, double.Parse(textBoxAngleMultiplier.Text)));
            }
            catch
            {
                angleMultiplier = 1;
            }

            try
            {
                typeMultiplier = Math.Max(0.00001, Math.Min(100, double.Parse(textBoxTypeMultiplier.Text)));
            }
            catch
            {
                typeMultiplier = 1;
            }

            try
            {
                coordsMultiplier = Math.Max(0.00001, Math.Min(100, double.Parse(textBoxCoordsMultiplier.Text)));
            }
            catch
            {
                coordsMultiplier = 1;
            }

            try
            {
                hashCodeMultiplier = Math.Max(0, Math.Min(100, double.Parse(textBoxHashCodeMultiplier.Text)));
            }
            catch
            {
                hashCodeMultiplier = 1;
            }
			// update settings controls
			UpdateSettings( );

            _SOMParams = new SOMParams(learningRadius, learningRate, angleMultiplier, typeMultiplier, coordsMultiplier, hashCodeMultiplier, iterations, 5);

            // generate training set
            queryFeaturesSet = NetworkHelper.GetQueryFeaturesSet(inputImage, _SOMParams);

			// disable all settings controls except "Stop" button
			EnableControls( false );

			// run worker thread
			needToStop = false;
			workerThread = new Thread( SearchSolution );
			workerThread.Start( );
		}
        public double[][] LoadTaughtPeople(SOMParams somParams)
        {
            double[][] features;
            var fileName = GetTaughtFeaturesFilenameByParams(somParams);

            People = new List<Person>();
            using (var sr = new StreamReader(fileName))
            {
                var lineCount = File.ReadAllLines(fileName).Count();
                features = new double[lineCount - 1][];
                var count = 0;
                var line = sr.ReadLine();
                var splitStringArray = new string[1] {";"};

                line = sr.ReadLine();
                var members = line.Split(splitStringArray, StringSplitOptions.None);
                var person = new Person(members[0]);
                var finger = new Fingerprint(int.Parse(members[1]));
                var scan = new Scan(int.Parse(members[2]));
                var feature = new Minutia((short)double.Parse(members[3]), (short)double.Parse(members[4]), double.Parse(members[5]))
                {
                    MinutiaType = (MinutiaType)double.Parse(members[6])
                };
                scan.Features.Add(feature);

                features[count] = new double[5];
                features[count][2] = double.Parse(members[3]);
                features[count][3] = double.Parse(members[4]);
                features[count][0] = double.Parse(members[5]);
                features[count][1] = double.Parse(members[6]);
                features[count][4] = double.Parse(members[7]);
                count++;

                // Read lines from the file until the end of the file is reached.
                while ((line = sr.ReadLine()) != null)
                {
                    members = line.Split(splitStringArray, StringSplitOptions.None);

                    features[count] = new double[5];
                    features[count][2] = double.Parse(members[3]);
                    features[count][3] = double.Parse(members[4]);
                    features[count][0] = double.Parse(members[5]);
                    features[count][1] = double.Parse(members[6]);
                    features[count][4] = double.Parse(members[7]);
                    count++;

                    feature = new Minutia((short)double.Parse(members[3]), (short)double.Parse(members[4]), double.Parse(members[5]))
                    {
                        MinutiaType = (MinutiaType)double.Parse(members[6])
                    };
                    scan.Features.Add(feature);

                    var scanId = int.Parse(members[2]);
                    if (scan.Id != scanId)
                    {
                        finger.Scans.Add(scan);
                        scan = new Scan(scanId);
                    }

                    var fingerId = int.Parse(members[1]);
                    if (finger.Id != fingerId)
                    {
                        person.Fingerprints.Add(finger);
                        finger = new Fingerprint(fingerId);
                    }

                    if (person.Id != members[0])
                    {
                        People.Add(person);
                        person = new Person(members[0]);
                    }
                }

                finger.Scans.Add(scan);
                person.Fingerprints.Add(finger);
                People.Add(person);

                sr.Close();
            }

            return features;
        }
        public void SaveTaughtPeople(double[][] features, SOMParams somParams)
        {
            var fileName = GetTaughtFeaturesFilenameByParams(somParams);
            var fs = new StreamWriter(fileName, false);
            fs.WriteLine("Person;Finger;Scan;FeatureX;FeatureY;FeatureAngle;FeatureType");
            var count = 0;

            foreach (var person in People)
            {
                foreach (var fingerprint in person.Fingerprints)
                {
                    foreach (var scan in fingerprint.Scans)
                    {
                        var scanFeaturesCount = scan.Features.Count;
                        var scanFeaturesIter = 0;
                        while (scanFeaturesCount > scanFeaturesIter)
                        {
                            fs.WriteLine("{0};{1};{2};{3:f4};{4:f4};{5:f4};{6:f4};{7:f4}", person.Id, fingerprint.Id,
                                scan.Id, features[count][2], features[count][3], features[count][0], features[count][1],
                                features[count][4]);
                            count++;
                            scanFeaturesIter++;
                        }
                    }
                }
            }
            fs.Close();
        }
 public static bool IsAlreadyTaughtAndSaved(SOMParams somParams)
 {
     return File.Exists(GetTaughtFeaturesFilenameByParams(somParams));
 }
 private static string GetTaughtFeaturesFilenameByParams(SOMParams somParams)
 {
     return string.Format(@"{0}{1}_{2}_{3}_{4}_{5}_{6}_{7}_{8}{9}", Folder, TaughtFeaturesDatabasePrefix,
         somParams.LearningRadius, somParams.LearningRate * 100000, somParams.Iterations, somParams.AngleMultiplier * 100000,
         somParams.TypeMultiplier * 100000, somParams.CoordsMultiplier * 100000, somParams.HashCodeMultiplier * 100000,
         TaughtFeaturesDatabaseSuffix);
 }
 private void InitializeParams()
 {
     _somParamses = new List<SOMParams>();
     foreach (var iteration in _iterations)
     {
         foreach (var learningRate in _learningRates)
         {
             foreach (var learningRadius in _learningRadiuses)
             {
                 foreach (var angleMultiplier in _angleMultipliers)
                 {
                     foreach (var typeMultiplier in _typeMultipliers)
                     {
                         foreach (var coordsMultiplier in _coordsMultipliers)
                         {
                             foreach (var hashCodeMultiplier in _hashCodeMultipliers)
                             {
                                 var somParams = new SOMParams(learningRadius, learningRate, angleMultiplier, typeMultiplier, coordsMultiplier, hashCodeMultiplier, iteration, 5);
                                 _somParamses.Add(somParams);
                             }
                         }
                     }
                 }
             }
         }
     }
 }