def SGD(a, lab, Q, lr):
    for i in range(20):
        iterations = 1
        for tau in range(len(a)):
            if a[tau] > 0:
                wx = a @ Q[:,tau]
                a[tau] *= (1 - 1/iterations)
                if(lab[tau]*wx < 1):
                    a[tau] += lab[tau]/(lr * iterations)
                iterations += 1
    return a def dsvm_low_a(a):
    a[a < 0] = 0.0
    return a def dsvm_high_a(a, cw, c):
    a = np.array([min(a[i], c * cw[i] * cw[i]) if a[i] > 0 else a[i] for i in range(len(a))])
    return a def es(a, lab, features):
    if any(a > 0.0):                                               
        return np.median((lab[a > 0.0] - np.sum(a[a > 0.0] * lab[a > 0.0] * features[a > 0.0].T).T * features[a > 0.0].T).T)
    else:
        return 0 def same_time(x, y):                                                   
    x_tempo = librosa.beat.beat_track(x)[0]                           
    y_tempo = librosa.beat.beat_track(y)[0]                           
    if x_tempo < y_tempo:                                             
        y = librosa.effects.time_stretch(y, x_tempo/y_tempo)           
        if y.size < x.size:                                            
            y = np.resize(y, x.size)                                   
        else:                                                         
            x = np.resize(x, y.size)                                  
    else:                                                             
        x = librosa.effects.time_stretch(x, y_tempo/x_tempo)          
        if x.size < y.size:                                            
            x = np.resize(x, y.size)                                   
        else:                                                          
            y = np.resize(y, x.size)                                   
    return x, y  def get_files(files_dir):
    """                                                           
    return a list of .json files to read
    :param files_dir: directory where sounds are located
    """
    try:                                                    
        for subdir, dirs, files in os.walk(files_dir+'/descriptores'):
            files_list = [f for f in files]
        return files_list                                     
    except:                                              
        if not os.path.exists(files_dir+'/descriptores'):
            print ("No .json files found in " + str(files_dir)) def get_dics(files_dir):
    """                                                           
    return a list containing all descriptions of tag directory reading the .json files
    :param files_dir: directory where sounds are located
    """
    dics = []
    try:                                        
        for subdir, dirs, files in os.walk(files_dir+'/descriptores'):
            for f in files:
                with open(subdir + '/' + f) as read:          
                    dics.append(json.load(read))
    except:                                              
        if not os.path.exists(files_dir+'/descriptores'):
            print ("No readable MIR data found")
    return dics class desc_pair():                                     
    """                           
    obtain an array of descriptors                                                      
    :param files: list of files                    
    :param dics: list of .json files corresponding to files
    """          
    def __init__(self, files, dics):            
        self._files = files         
        self._dics = dics           
        self.descriptors = ['lowlevel.mfcc_bands.mean', 'metadata.duration.mean', 'lowlevel.hfc.mean', 'rhythm.bpm_ticks.mean', 'lowlevel.mfcc.mean', 'sfx.inharmonicity.mean', 'rhythm.bpm.mean', 'lowlevel.spectral_contrast.mean', 'sfx.logattacktime.mean', 'loudness.level.mean', 'lowlevel.spectral_valleys.mean', 'lowlevel.spectral_centroid.mean', 'lowlevel.dissonance.mean'] # modify according to features_and_keys

        selector = [np.any(np.isnan(np.float64(list(x.values())))) == False for x in self._dics]                        
        self._files_features = list(filter(lambda x: np.any(np.isnan(np.float64(list(x.values())))) == False, self._dics))
        indexes = list(compress(selector, self._dics))
        self._files = np.array(self._files)[indexes]

        self._features = []                
        for i in range(len(self._files_features)):
            self._features.append(list(self._files_features[i].values()))

        self._features = np.vstack(np.float64(self._features))
        self.keys = [i for i,x in enumerate(self.descriptors)]  def read_file(f, data_dir):
    """ 
    Open the text file containing deep learning classification results for files. The decision variables is automatically opened from utils folder
    :param f: text filename          
    :returns:                                                                                                         
      - sounds: sounds that were analyzed
      - lc: labels for each sound
    """
    classes = pandas.read_csv(f).values
    sounds = np.array(classes)[:,1]
    lc = np.array(classes)[:,2]
    decisions = pandas.read_csv(data_dir+'/data.csv').values[:,(1,2,3,4)]
    return sounds, lc, decisions def read_attention_file(data_dir):                 
    attention_variables = pandas.read_csv(data_dir+'/attention.csv').values.T[1:]
    return attention_variables, pandas.read_csv(data_dir+'/attention.csv').keys() def read_good_labels(data_dir):                 
    good_labels = pandas.read_csv(data_dir+'/attention_labels.csv').values
    return good_labels def morph(x, y, H, smoothing_factor, balance_factor):
    L = int(x.size / H)
    pin = 0
    ysong = sonify(y, 44100)
    xsong = sonify(x, 44100)
    xsong.N = 1024
    xsong.M = 512
    xsong.H = 256
    ysong = sonify(x, 44100)
    ysong.N = 1024
    ysong.M = 512
    ysong.H = 256
    selection = H
    z = np.zeros(x.size)
    for i in range(L):
        xsong.frame = x[pin:selection]
        ysong.frame = y[pin:selection]
        xsong.window()
        ysong.window()
        xsong.Spectrum()
        ysong.Spectrum()
        xmag = xsong.magnitude_spectrum
        ymag = ysong.magnitude_spectrum
        ymag_smoothed = resample(np.maximum(1e-10, ymag), round(ymag.size * smoothing_factor))
        ymag = resample(ymag_smoothed, xmag.size)
        output_mag = balance_factor * ymag + (1 - balance_factor) * xmag
        xsong.phase = np.angle(xsong.fft(xsong.windowed_x))[:257].ravel()
        invert = xsong.ISTFT(output_mag)
        z[pin:selection] += invert
        pin += H
        selection += H
    return z  def write_file(filename, fs, data):           
    write(filename+'.wav', fs, data) 
    call(['ffmpeg', '-i', filename+'.wav', filename+'.ogg', '-y'])
    call(['rm', '-f', filename+'.wav']) def hfc_onsets(audio):
    """
    Find onsets in music based on High Frequency Content
    :param audio: the input signal                                                                         
    :returns:                                                                                                         
      - hfcs = onsets locations in seconds
    """
    song = sonify(audio, 44100)
    hfcs = []                          
    for frame in song.FrameGenerator():
        song.window()    
        song.Spectrum()    
        hfcs.append(song.hfc())   
    hfcs /= max(hfcs) 
    song.hfcs = hfcs
    fir = firwin(11, 1.0 / 8, window = "hamming")
    song.filtered = np.convolve(hfcs, fir, mode="same")
    song.climb_hills() 
    return np.array([i for i, x in enumerate(song.Filtered) if x > 0]) * song.N
from ..utils.dj import *
from ..machine_learning.cross_validation import *
from ..gradients.descent import SGD
from ..constraints.bounds import dsvm_low_a as la
from ..constraints.bounds import dsvm_high_a as ha
from ..constraints.bounds import es
from ..constraints.tempo import same_time
from ..constraints.time_freq import *
from ..gradients.subproblem import *
from ..utils.data import get_files, get_dics, desc_pair, read_file, read_attention_file, read_good_labels
from ..utils.algorithms import morph
from collections import Counter, defaultdict
from itertools import combinations, permutations
from ..sonification.Sonification import write_file, hfc_onsets
from soundfile import read  
from sklearn.preprocessing import StandardScaler as sc
from sklearn.preprocessing import LabelBinarizer as lab_bin
from sklearn.preprocessing import LabelEncoder as le
from sklearn.preprocessing import MinMaxScaler
from sklearn.decomposition.pca import PCA as pca
from sklearn.cluster import KMeans
from random import *
from sklearn.utils.extmath import safe_sparse_dot as ssd
from librosa.core import stft
from transitions import Machine
import time
import numpy as np                                                      
import matplotlib.pyplot as plt                                   
import os, sys 
import json                                                          
import pandas                                   
import shutil
import logging
import warnings
import random
import subprocess
        k2 = np.mat(np.ones((mat1.shape[0], 1), dtype=np.float64)) * trnorms2.T          
                   
        rbfk = k1 + k2 #sum products together
        rbfk -= 2 * np.mat(mat1 * mat2.T) #dot product of x and y transposed                                         
        rbfk *= - 1./(2 * np.power(gamma, 2)) #radial basis
        np.exp(rbfk,rbfk)
        return np.array(rbfk)

    def fit_model(self, features,labels, kernel1, kernel2, C, reg_param, gamma, learning_rate):
        """
        Fit your data for classification. Attributes such as alpha, the bias, the weight, and the support vectors can be accessed after training. 
        :param features: your features dataset            
        :param labels: your labels dataset                 
        :param kernel1: the kernel used for predictive task         
        :param kernel2: the kernel used to solve the min-max problem
        :param C: cost, also called penalty parameter    
        :param reg_param: tolerance, used for convergence
        :param gamma: determines a reach            
        *What you can have access to after computing
          - w: the weight coefficient         
          - a: resolutions to min-max problems                          
          - dual_coefficients: stacked alphas of the support vectors appearing in all of the problems of its class
          - svs: find out which index of your features is a support vector                                                                    
          - nvs: number of support vectors in each class              
          - ns: where your support vectors are from your input dataset
          - bias: a helper
        """ 
        self.kernel1 = kernel1
        self.kernel2 = kernel2
        self.gamma = gamma
        self.C = C
        self.learning_rate = learning_rate

        features = np.ascontiguousarray(features)

        multiclass = False

        if not 0 in labels:                                      
            raise IndexError("Targets must start from 0")

        self.targets = labels

        self.n_class = len(np.bincount(self.targets))

        if self.n_class == 1:                                      
            raise Exception("There has to be two or more targets")

        if reg_param == 0:                                      
            raise ValueError("There's no such 0 tolerance")

        if self.n_class > 2:                                      
            multiclass = True
        if not self.n_class > 2:                                      
            raise Exception("Two labels classification for music is not allowed here")

        if multiclass == True:
            self.instances = list(combinations(range(self.n_class), 2))
            self.classes = np.unique(self.targets)
            self.classifications = len(self.instances)
            self.classesm = defaultdict(list) 
            self.trained_features = defaultdict(list) 
            self.indices_features = defaultdict(list) 
            self.a = defaultdict(list)
            self.svs = defaultdict(list)
            self.ns = defaultdict(list)
            self.nvs = defaultdict(list)
            self.dual_coefficients = [[] for i in range(self.n_class - 1)]

        for c in range(self.classifications):   

            self.classesm[c] = np.concatenate((self.targets[self.targets==self.instances[c][0]],self.targets[self.targets==self.instances[c][1]]))
            self.indices_features[c] = np.concatenate((np.where(self.targets==self.instances[c][0]),np.where(self.targets==self.instances[c][1])), axis = 1)[0]
            self.trained_features[c] = np.ascontiguousarray(np.concatenate((features[self.targets==self.instances[c][0]],features[self.targets==self.instances[c][1]])))

            self.classesm[c] = lab_bin(0,1).fit_transform(self.classesm[c]).T[0]

            n_f = len(self.trained_features[c])
            n_f0 = len(self.classesm[c][self.classesm[c]==0])
                                                                     
            lab = self.classesm[c] * 2 - 1
                                                                   
            if self.kernel2 == "linear":                                                                      
                kernel = self.linear_kernel_matrix
                self.Q = kernel(self.trained_features[c], self.trained_features[c].T) * lab            
            if self.kernel2 == "poly":                                
                kernel = self.polynomial_kernel
                self.Q = kernel(self.trained_features[c], self.trained_features[c], self.gamma) * lab        
            if self.kernel2 == "rbf":                                                                      
                kernel = self.rbf_kernel
                self.Q = kernel(self.trained_features[c], self.trained_features[c], self.gamma) * lab              
            if self.kernel2 == "sigmoid":                             
                kernel = self.sigmoid_kernel 
                self.Q = kernel(self.trained_features[c], self.trained_features[c], self.gamma) * lab          
            if self.kernel2 == None:                                  
                print ("Apply a kernel")
                                                                      
            class_weight = float(n_f)/(2 * np.bincount(self.classesm[c]))

            a = np.zeros(n_f)

            p1 = np.argsort([self.Q[i,i] for i in range(n_f0-1)])
            p2 = np.argsort([self.Q[i,i] for i in range(n_f0, n_f)])+n_f0  

            iterations = 0                                            
            diff = 1. + reg_param 
            for i in range(20):
                a0 = a.copy()
                for j in range(min(p1.size, p2.size)): 
                    g1 = g(lab[p1[j]], a, self.Q[p1[j]])
                    g2 = g(lab[p2[j]], a, self.Q[p2[j]])
                    w0 = es(a, lab, self.trained_features[c]) 
                    direction_grad = self.learning_rate * ((w0 * g2) + ((1 - w0) * g1))

                    if (direction_grad * (g1 + g2) <= 0.):        
                        break

                    a[p1[j]] += direction_grad #do step
                    a[p2[j]] += direction_grad #do step

                a = la(a) #satisfy constraints for lower As

                a = ha(a, class_weight[self.classesm[c]], self.C) #satisfy constraints for higher As using class weights