def _new_adb(self): """ :: Make a new audioDB instance in the adb_path location Make database L2norm and Power compliant """ self.adb_path = self._gen_adb_path() if self.adb_path == None: print("self.adb_path must have a string value") raise error.BregmanError() else: f = None try: f = open(self.adb_path, "rb") except: print("Making new audioDB database: ", self.adb_path) finally: if f: f.close() print("AudioDB database already exists: ", self.adb_path) return 0 # create a NEW audiodb database instance command = [ "audioDB", "--NEW", "-d", self.adb_path, "--datasize", "%d" % self.adb_data_size, "--ntracks", "%d" % self.adb_ntracks ] self._do_subprocess(command) # make L2NORM compliant command = ["audioDB", "--L2NORM", "-d", self.adb_path] self._do_subprocess(command) # make POWER compliant command = ["audioDB", "--POWER", "-d", self.adb_path] self._do_subprocess(command) return 1
def rank_by_distance_bhatt(self, qkeys, ikeys, rkeys, dists): """ :: Reduce timbre-channel distances to ranks list by ground-truth key indices Bhattacharyya distance on timbre-channel probabilities and Kullback distances """ # timbre-channel search using pre-computed distances ranks_list = [] t_keys, t_lens = self.get_adb_lists(0) rdists = pylab.ones(len(t_keys)) * float('inf') qk = self._get_probs_tc(qkeys) for i in range(len(ikeys[0])): # number of include keys ikey = [] dk = pylab.zeros(self.timbre_channels) for t_chan in range(self.timbre_channels): # timbre channels ikey.append(ikeys[t_chan][i]) try: # find dist of key i for query i_idx = rkeys[t_chan].index( ikey[t_chan]) # dataset include-key match # the reduced distance function in include_keys order # distance is Bhattacharyya distance on probs and dists dk[t_chan] = dists[t_chan][i_idx] except: print "Key not found in result list: ", ikey, "for query:", qkeys[ t_chan] raise error.BregmanError() rk = self._get_probs_tc(ikey) a_idx = t_keys.index(ikey[0]) # audiodb include-key index rdists[a_idx] = distance.bhatt(pylab.sqrt(pylab.absolute(dk)), pylab.sqrt(pylab.absolute(qk * rk))) #search for the index of the relevant keys rdists = pylab.absolute(rdists) sort_idx = pylab.argsort(rdists) # Sort fields into database order for r in self.ground_truth: # relevant keys ranks_list.append( pylab.where(sort_idx == r)[0][0]) # Rank of the relevant key return ranks_list, rdists
def _get_extract_lists(self, key=None, keyrepl=None, wave_suffix=".wav"): """ :: Map from self.audio_collection to aList, fList, pList, kList """ # The audio queue aList = list(self.audio_collection) aList.sort() # The keys that will identify managed items if key == None: kList = aList # use the audio file names as keys else: # replace keyrepl with key as database key if not keyrepl: print "key requires keyrepl for filename substitution" raise error.BregmanError() kList = [a.replace(keyrepl,key) for a in aList] feature_suffix= self._get_feature_suffix() power_suffix=self.feature_params['power_ext'] fList = [k.replace(wave_suffix, feature_suffix) for k in kList] pList = [k.replace(wave_suffix, power_suffix) for k in kList] return (aList, fList, pList, kList)
def rank_by_distance_avg(self, qkeys, ikeys, rkeys, dists): """ :: Reduce timbre-channel distances to ranks list by ground-truth key indices Kullback distances """ # timbre-channel search using pre-computed distances ranks_list = [] t_keys, t_lens = self.get_adb_lists(0) rdists = pylab.ones(len(t_keys)) * float('inf') for t_chan in range(self.timbre_channels): # timbre channels t_keys, t_lens = self.get_adb_lists(t_chan) for i, ikey in enumerate(ikeys[t_chan]): # include keys, results try: # find dist of key i for query i_idx = rkeys[t_chan].index( ikey) # lower_bounded include-key index a_idx = t_keys.index(ikey) # audiodb include-key index # the reduced distance function in include_keys order # distance is the sum for now if t_chan: rdists[a_idx] += dists[t_chan][i_idx] else: rdists[a_idx] = dists[t_chan][i_idx] except: print "Key not found in result list: ", ikey, "for query:", qkeys[ t_chan] raise error.BregmanError() #search for the index of the relevant keys rdists = pylab.absolute(rdists) sort_idx = pylab.argsort(rdists) # Sort fields into database order for r in self.ground_truth: # relevant keys ranks_list.append( pylab.where(sort_idx == r)[0][0]) # Rank of the relevant key return ranks_list, rdists
def _extract_error(self): error.BregmanError("unrecognized feature in Features.extract()")
def evaluate(self, seq_length=None, query_duration=None, tempo=1.0, gt_only=True, ground_truth=None, res_name=None): """ :: Evaluate ranks and distances for each ground-truth pattern for retrieval of other GT patterns. Overridden method from Evaluator for timbre channels Map distances and weights for each query in each channel Reduce using Bhattacharyya distance metric and base-line averaging metric. Sets self.ranks_list, self.dists_list Display ranked results as in print_results() Returns a tuple (ranks,dists) Each element of the tuple contains len(test_set_list) lists, each list contains ground-truth ranks, and whole-dataset distances, of each test-set in the test_set_list """ if ground_truth is None: ground_truth = self.ground_truth if not tempo: tempo = 1.0 self.seq_length = self.set_seq_length(seq_length, query_duration) self.avg_ranks = [] self.bhatt_ranks = [] self.avg_dists = [] self.bhatt_dists = [] qkeys, qlens = zip(*self.adb.liszt()) for gt_item in ground_truth: t_qkeys = [] t_ikeys = [] t_rkeys = [] t_dists = [] print "Evaluating gt_item: ", gt_item for t_chan in range(self.timbre_channels): print "\tc ", t_chan qkey = qkeys[t_chan::self.timbre_channels][ gt_item] # gt query timbre-channel key qlen = qlens[t_chan::self.timbre_channels][ gt_item] # gt query timbre-channel len t_qkeys.append(qkey) self.initialize_search(t_chan, min( [self.seq_length, qlen]), tempo) # setup per-timbre-channel include list t_ikeys.append(self.adb.configQuery['includeKeys'] ) # timbre-channel search keys res = self.adb.query( key=qkey).rawData # get the search results if len(res): rkeys, dst, qpos, rpos = zip(*res) t_rkeys.append( rkeys) # timbre-channel distance-sorted keys t_dists.append(dst) # All result distances else: print "Empty result list: ", qkey raise error.BregmanError() avg_ranks, avg_dists = self.rank_by_distance_avg( t_qkeys, t_ikeys, t_rkeys, t_dists) bhatt_ranks, bhatt_dists = self.rank_by_distance_bhatt( t_qkeys, t_ikeys, t_rkeys, t_dists) self.avg_ranks.append(avg_ranks) self.avg_dists.append(avg_dists) self.bhatt_ranks.append(bhatt_ranks) self.bhatt_dists.append(bhatt_dists) if res_name is None: res_name = tempfile.mktemp(suffix=".dat", prefix="results_", dir=".") f = open(res_name, "w") pickle.dump((self.avg_ranks, self.avg_dists, self.bhatt_ranks, self.bhatt_dists), f) f.close() return True