/// <summary>
 ///   Query one specific song using MinHash algorithm. ConnectionString is set by the caller.
 /// </summary>
 /// <param name = "signatures">Fingerprint signatures from a song</param>
 /// <param name = "dalManager">DAL Manager used to query the underlying database</param>
 /// <param name = "permStorage">Permutation storage</param>
 /// <param name = "seconds">Fingerprints to consider as query points [1.4 sec * N]</param>
 /// <param name = "lHashTables">Number of hash tables from the database</param>
 /// <param name = "lGroupsPerKey">Number of groups per hash table</param>
 /// <param name = "thresholdTables">Threshold percentage [0.07 for 20 LHash Tables, 0.17 for 25 LHashTables]</param>
 /// <param name = "queryTime">Set but the method, representing the query length</param>
 /// <returns>Dictionary with Tracks ID's and the Query Statistics</returns>
 public static Dictionary<Int32, QueryStats> QueryOneSongMinHash(
     IEnumerable<bool[]> signatures,
     DaoGateway dalManager,
     IPermutations permStorage,
     int seconds,
     int lHashTables,
     int lGroupsPerKey,
     int thresholdTables,
     ref long queryTime)
 {
     Stopwatch stopWatch = new Stopwatch();
     stopWatch.Start();
     Dictionary<Int32, QueryStats> stats = new Dictionary<Int32, QueryStats>();
     MinHash minHash = new MinHash(permStorage);
     foreach (bool[] f in signatures)
     {
         if (f == null) continue;
         int[] bin = minHash.ComputeMinHashSignature(f); /*Compute Min Hash on randomly selected fingerprints*/
         Dictionary<int, long> hashes = minHash.GroupMinHashToLSHBuckets(bin, lHashTables, lGroupsPerKey); /*Find all candidates by querying the database*/
         long[] hashbuckets = hashes.Values.ToArray();
         Dictionary<int, List<HashBinMinHash>> candidates = dalManager.ReadFingerprintsByHashBucketLSH(hashbuckets);
         Dictionary<int, List<HashBinMinHash>> potentialCandidates = SelectPotentialMatchesOutOfEntireDataset(candidates, thresholdTables);
         if (potentialCandidates.Count > 0)
         {
             List<Fingerprint> fingerprints = dalManager.ReadFingerprintById(potentialCandidates.Keys);
             Dictionary<Fingerprint, int> fCandidates = new Dictionary<Fingerprint, int>();
             foreach (Fingerprint finger in fingerprints)
                 fCandidates.Add(finger, potentialCandidates[finger.Id].Count);
             ArrangeCandidatesAccordingToFingerprints(f, fCandidates, lHashTables, lGroupsPerKey, stats);
         }
     }
     stopWatch.Stop();
     queryTime = stopWatch.ElapsedMilliseconds; /*Set the query Time parameter*/
     return stats;
 }