Finds hash matches that align in time with other matches and finds
            consensus about which hashes are "true" signal from the audio.
            Returns a dictionary with match information.
337231
def align_matches(self, matches: list)->Optional[dict]:
        
        # align by diffs
        diff_counter: dict = {}
        largest = 0
        largest_count = 0
        song_id = -1
        for sid, diff in matches:

            if diff not in diff_counter:
                diff_counter[diff] = {}
            if sid not in diff_counter[diff]:
                diff_counter[diff][sid] = 0
            diff_counter[diff][sid] += 1

            if diff_counter[diff][sid] > largest_count:
                largest = diff
                largest_count = diff_counter[diff][sid]
                song_id = sid

        # extract idenfication
        song = database.get_song_by_id(song_id)
        if song:
            songname = song.song_name
        else:
            return None

        # return match info
        nseconds = round(
            float(largest) / fingerprint.DEFAULT_FS *
            fingerprint.DEFAULT_WINDOW_SIZE * fingerprint.DEFAULT_OVERLAP_RATIO,
            5
        )
        song = {
            'song_id': song_id,
            'song_name': songname,
            MetaMusic.CONFIDENCE: largest_count,
            MetaMusic.OFFSET: int(largest),
            'offset_seconds': nseconds,
            'file_sha1': binascii.hexlify(song.file_sha1).decode('utf-8'),
        }
        return song
834694
def _compare_match(dict1, dict2):
    '''
    
    '''
    for karg, warg in six.iteritems(dict1):
        if karg in dict2 and dict2[karg] != warg:
            return False
    return True
176290
def _parse_info(self, s):
        
        # Sample rate.
        match = re.search(r'(\d+) hz', s)
        if match:
            self.samplerate = int(match.group(1))
        else:
            self.samplerate = 0

        # Channel count.
        match = re.search(r'hz, ([^,]+),', s)
        if match:
            mode = match.group(1)
            if mode == 'stereo':
                self.channels = 2
            else:
                cmatch = re.match(r'(\d+)\.?(\d)?', mode)
                if cmatch:
                    self.channels = sum(map(int, cmatch.group().split('.')))
                else:
                    self.channels = 1
        else:
            self.channels = 0

        # Duration.
        match = re.search(
            r'duration: (\d+):(\d+):(\d+).(\d)', s
        )
        if match:
            durparts = list(map(int, match.groups()))
            duration = (
                durparts[0] * 60 * 60 +
                durparts[1] * 60 +
                durparts[2] +
                float(durparts[3]) / 10
            )
            self.duration = duration
        else:
            # No duration found.
            self.duration = 0
836930
def has_multiple_timesteps(data):
    """"""
    if "timestep" in data.keys():
        if len(np.unique(data["timestep"])) > 1:
            return True
    return False
451313
def hash(self):
        '''
        
        '''
        hashed = super(Repeat, self).hash()
        return khash(hashed, self._min_times, self._max_times, self._step, self._repeats)
1250768
def _make_pairwise_matches(result: Dict) -> List[PairwiseMatch]:
        
        pairwise_matches = []
        for pairwise_match in result['matches']:
            pairwise_matches.append(
                PairwiseMatch(
                    reference=ICNode(**pairwise_match['a']),
                    match=ICNode(**pairwise_match['b']),
                    lcs=ICNode(**pairwise_match['lcs'])
                )
            )

        return pairwise_matches
119152
def generate_hashes(peaks, fan_value: int = DEFAULT_FAN_VALUE):
    
    if PEAK_SORT:
        peaks = sorted(peaks, key=lambda x: x[1])
        # peaks.sort(key=itemgetter(1))

    for i in range(len(peaks)):
        for j in range(1, fan_value):
            if (i + j) < len(peaks):

                freq1 = peaks[i][IDX_FREQ_I]
                freq2 = peaks[i + j][IDX_FREQ_I]
                t1 = peaks[i][IDX_TIME_J]
                t2 = peaks[i + j][IDX_TIME_J]
                t_delta = t2 - t1

                if MIN_HASH_TIME_DELTA <= t_delta <= MAX_HASH_TIME_DELTA:
                    key = "{}|{}|{}".format(freq1, freq2, t_delta)
                    h = hashlib.sha1(key.encode('utf-8'))
                    yield (h.hexdigest()[0:FINGERPRINT_REDUCTION], t1)
621752
def calculate_hashes(self):
        
        hashers = []
        if not self.mardata.signatures:
            return []

        for s in self.mardata.signatures.sigs:
            h = make_hasher(s.algorithm_id)
            hashers.append((s.algorithm_id, h))

        for block in get_signature_data(self.fileobj, self.mardata.signatures.filesize):
            [h.update(block) for (_, h) in hashers]

        return [(algo_id, h.finalize()) for (algo_id, h) in hashers]
299106
def parse_time
      s0 = @current_pos
      if match_str("(") != :failed
        match_spaces
        s3 = parse_ms
        if s3 != :failed
          match_spaces
          if match_str("/") != :failed
            match_spaces
            s5 = parse_hms
            s5 = parse_ms(with_hour: true) if s5 == :failed
            if s5 != :failed
              match_spaces
              if match_str(")") != :failed
                @reported_pos = s0
                s0 = { "now" => s3, "total" => s5 }
              else
                @current_pos = s0
                s0 = :failed
              end
            else
              @current_pos = s0
              s0 = :failed
            end
          else
            @current_pos = s0
            s0 = :failed
          end
        else
          @current_pos = s0
          s0 = :failed
        end
      else
        @current_pos = s0
        s0 = :failed
      end
      s0
    end
202878
def load_matches(self):
        
        if not self.exists():
            return []

        matches = []
        with open(self.location(), 'r') as f:
            for line in f.readlines():
                match_obj = json.loads(line.strip("\n"))
                if match_obj['processed']:
                    continue

                matches.append(match_obj)

        return matches
1173667
def sha_match?(file, gav, use_sha_file=false)
      if File.exists?(file)
        if gav.sha1.nil?
          gav.sha1 = gav_data(gav)['sha1']
        end
        sha(file,use_sha_file) == gav.sha1
      else
        false
      end
    end
278027
def get_consensus_hashes(cls, impl, working_dir, start_block_height=None, end_block_height=None, db_con=None, completeness_check=True):
        
        if (start_block_height is None and end_block_height is not None) or (start_block_height is not None and end_block_height is None):
            raise ValueError("Need either both or neither start/end block height")

        we_opened = False
        if db_con is not None:
            con = db_con

        else:
            assert impl and working_dir, 'Need impl and working_dir if db_con is not given'
            con = cls.db_open(impl, working_dir)
            we_opened = True

        range_query = ''
        range_args = ()

        if start_block_height and end_block_height:
            range_query += ' WHERE block_id >= ? AND block_id < ?'
            range_args += (start_block_height,end_block_height)

        query = 'SELECT block_id,consensus_hash FROM snapshots' + range_query + ';'
        args = range_args

        rows = cls.db_query_execute(con, query, range_args, verbose=False)
        ret = {}
        block_min = None
        block_max = None

        for r in rows:
            block_id = int(r['block_id'])
            ret[block_id] = r['consensus_hash']

            if block_min is None or block_min > block_id:
                block_min = block_id

            if block_max is None or block_max < block_id:
                block_max = block_id

        if we_opened:
            con.close()
       
        if completeness_check:
            # sanity check
            for i in range(block_min,block_max+1):
                ch = ret.get(i, None)

                assert ch is not None, 'Missing consensus hash for {}'.format(i)
                assert isinstance(ret[i], (str,unicode)), 'consensus hash for {} is type {}'.format(i, type(ret[i]))

        return ret
691546
def _unify_sources_and_hashes(source=None, source_hash=None,
                              sources=None, source_hashes=None):
    '''
    
    '''
    if sources is None:
        sources = []

    if source_hashes is None:
        source_hashes = []

    if source and sources:
        return (False,
                "source and sources are mutually exclusive", [])

    if source_hash and source_hashes:
        return (False,
                "source_hash and source_hashes are mutually exclusive", [])

    if source:
        return (True, '', [(source, source_hash)])

    # Make a nice neat list of tuples exactly len(sources) long..
    return True, '', list(zip_longest(sources, source_hashes[:len(sources)]))
140449
def verify_hash(self, hashed_data, compare_data):
        
        return self.security.hashing_context.verify(
            encode_string(compare_data), hashed_data)
1112164
def get_matching_blocks(self):
        """"""
        opcodes = self.get_opcodes()
        match_opcodes = filter(lambda x: x[0] == EQUAL, opcodes)
        return map(lambda opcode: [opcode[1], opcode[3], opcode[2] - opcode[1]],
                   match_opcodes)
466187
def normalize_match_data_captures(match_data)
      match_data.names.inject({}) do |mem, capture|
        mem[capture.gsub(/\d/,'')] = match_data[capture]
        break mem if mem.keys.length >= 2
        mem
      end
    end
1062376
def recentMatches(self, **criteria):
        """"""
        if not self.matches: return [] # no match history
        try: # maxMatches is a specially handled parameter (not true criteria)
            maxMatches = criteria["maxMatches"]
            del criteria["maxMatches"]
        except AttributeError:
            maxMatches = c.RECENT_MATCHES
        alLMatches = self.matchSubset(**criteria)
        matchTimes = [(m.endTime, m) for m in matches]
        selMatches = sorted(matchTimes)[:maxMatches] # slice off X most recet matches
        retMatches = [m for endTime,m in selMatches] # extract matches only
        return retMatches