#!/usr/bin/env python
from __future__ import division
from __future__ import print_function
from builtins import str
from builtins import range
from past.utils import old_div
import sys
import scipy
import copy
import os
from pmagpy import pmag

def main(command_line=True, **kwargs):
    """
    NAME
        generic_magic.py

    DESCRIPTION
        converts magnetometer files in generic format to MagIC measurements format

    SYNTAX
        generic_magic.py [command line options]

    OPTIONS
        -h
            prints the help message and quits.
        -usr USER
            identify user, default is ""
        -f FILE:
            specify path to input file, required
        -fsa SAMPFILE:
            specify the samples file for sample orientation data. default is er_samples.txt
        -F FILE
            specify output file, default is magic_measurements.txt

        -Fsa FILE
            specify output file, default is er_samples.txt

        -exp EXPERIMENT-TYPE
            Demag:
                AF and/or Thermal
            PI:
                paleointenisty thermal experiment (ZI/IZ/IZZI/TT)
            ATRM n:

                ATRM in n positions (n=6)

            AARM n:
                AARM in n positions
            CR:
                cooling rate experiment
                The treatment coding of the measurement file should be: XXX.00,XXX.10, XXX.20 ...XX.70 etc. (XXX.00 is optional)
                where XXX in the temperature and .10,.20... are running numbers of the cooling rates steps.
                XXX.00 is optional zerofield baseline. XXX.70 is alteration check.
                syntax in sio_magic is: -LP CR xxx,yyy,zzz,.....xx -A
                where xx, yyy,zzz...xxx  are cooling rates in [K/minutes], seperated by comma, ordered at the same order as XXX.10,XXX.20 ...XX.70

                No need to specify the cooling rate for the zerofield
                It is important to add to the command line the -A option so the measurements will not be averaged.
                But users need to make sure that there are no duplicate meaurements in the file

            NLT:
                non-linear-TRM experiment

        -samp X Y
            specimen-sample naming convention.
            X determines which kind of convention (initial characters, terminal characters, or delimiter
            Y determines how many characters to remove to go from specimen --> sample OR which delimiter to use
            X=0 Y=n: specimen is distinguished from sample by n initial characters.
                     (example: "generic_magic.py -samp 0 4"
                      if n=4 then and specimen = mgf13a then sample = mgf13)
            X=1 Y=n: specimen is distiguished from sample by n terminate characters.
                     (example: "generic_magic.py -samp 1 1)
                      if n=1 then and specimen = mgf13a then sample = mgf13)
            X=2 Y=c: specimen is distinguishing from sample by a delimiter.
                     (example: "generic_magic.py -samp 2 -"
                      if c=- then and specimen = mgf13-a then sample = mgf13)
            default: sample is the same as specimen name

        -site X Y
            sample-site naming convention.
            X determines which kind of convention (initial characters, terminal characters, or delimiter
            Y determines how many characters to remove to go from sample --> site OR which delimiter to use
            X=0 Y=n: sample is distiguished from site by n initial characters.
                     (example: "generic_magic.py --site 0 3"
                      if n=3 then and sample = mgf13 then sample = mgf)
            X=1 Y=n: sample is distiguished from site by n terminate characters.
                     (example: "generic_magic.py --site 1 2"
                      if n=2 and sample = mgf13 then site = mgf)
            X=2 Y=c: specimen is distiguishing from sample by a delimiter.
                     (example: "generic_magic.py -site 2 -"
                      if c='-' and sample = 'mgf-13' then site = mgf)
            default: site name is the same as sample name

        -loc LOCNAM
            specify location/study name.

        -dc B PHI THETA:
            B: dc lab field (in micro tesla)
            PHI (declination). takes numbers from 0 to 360
            THETA (inclination). takes numbers from -90 to 90

            NB: use PHI, THETA = -1 -1 to signal that it changes, i.e. in anisotropy experiment.

        -A: don't average replicate measurements. Take the last measurement from replicate measurements.

        -WD working directory

    INPUT

        A generic file is a tab-delimited file. Each column should have a header.
        The file must include the following headers (the order of the columns is not important):

            specimen
                string specifying specimen name

            treatment:
                a number with one or two decimal point (X.Y)
                coding for thermal demagnetization:
                    0.0 or 0 is NRM.
                    X is temperature in celsius
                    Y is always 0
                coding for AF demagnetization:
                    0.0 or 0 is NRM.
                    X is AF peak field in mT
                    Y is always 0
                coding for Thellier-type experiment:
                    0.0 or 0 is NRM
                    X is temperature in celsius
                    Y=0: zerofield
                    Y=1: infield (IZZI, IZ, ZI, and Thellier protocol- first infield)
                    Y=2: pTRM check
                    Y=3: pTRM tail check
                    Y=4: Additivity check
                    Y=5: Thellier protocol: second infield
                coding for ATRM experiment (6 poitions):
                    X is temperature in celsius
                    Y=0: zerofield baseline to be subtracted
                    Y=1: +x
                    Y=2: -x
                    Y=3: +y
                    Y=4: -y
                    Y=5: +z
                    Y=6: -z
                    Y=7: alteration check
                coding for NLT experiment:
                    X is temperature in celsius
                    Y=0: zerofield baseline to be subtracted
                    Y!=0: oven field  in microT
                coding for CR experiment:
                    see "OPTIONS" list above

            treatment_type:
                N: NRM
                A: AF
                T: Thermal

            moment:
                magnetic moment in emu !!

        In addition, at least one of the following headers are required:

            dec_s:
                declination in specimen coordinate system (0 to 360)
            inc_s:
                inclination in specimen coordinate system (-90 to 90)

            dec_g:
                declination in geographic coordinate system (0 to 360)
            inc_g:
                inclination in geographic coordinate system (-90 to 90)

            dec_t:
                declination in tilt-corrected coordinate system (0 to 360)
            inc_t:
                inclination in tilt-corrected coordinate system (-90 to 90)

    """

    #--------------------------------------
    # functions
    #--------------------------------------

    def sort_magic_file(path,ignore_lines_n,sort_by_this_name):
        '''
        reads a file with headers. Each line is stored as a dictionary following the headers.
        Lines are sorted in DATA by the sort_by_this_name header
        DATA[sort_by_this_name]=[dictionary1,dictionary2,...]
        '''
        DATA={}
        fin=open(path,'r')
        #ignore first lines
        for i in range(ignore_lines_n):
            fin.readline()
        #header
        line=fin.readline()
        header=line.strip('\n').split('\t')
        #print header
        for line in fin.readlines():
            if line[0]=="#":
                continue
            tmp_data={}
            tmp_line=line.strip('\n').split('\t')
            #print tmp_line
            for i in range(len(tmp_line)):
                if i>= len(header):
                    continue
                tmp_data[header[i]]=tmp_line[i]
            DATA[tmp_data[sort_by_this_name]]=tmp_data
        fin.close()
        return(DATA)

    def read_generic_file(path,average_replicates):
        '''
        reads a generic file format. If average_replicates==True average replicate measurements.
        Rrturns a Data dictionary with measurements line sorted by specimen
        Data[specimen_name][dict1,dict2,...]
        '''
        Data={}
        Fin=open(path,'r')
        header=Fin.readline().strip('\n').split('\t')
        duplicates=[]
        for line in Fin.readlines():
            tmp_data={}
            #found_duplicate=False
            l=line.strip('\n').split('\t')
            for i in range(min(len(header),len(l))):
                tmp_data[header[i]]=l[i]
            specimen=tmp_data['specimen']
            if specimen not in list(Data.keys()):
                Data[specimen]=[]
            Data[specimen].append(tmp_data)
        # search fro duplicates
        for specimen in list(Data.keys()):
            x=len(Data[specimen])-1
            new_data=[]
            duplicates=[]
            for i in range(1,x):
                while i< len(Data[specimen]) and Data[specimen][i]['treatment']==Data[specimen][i-1]['treatment'] and Data[specimen][i]['treatment_type']==Data[specimen][i-1]['treatment_type']:
                   duplicates.append(Data[specimen][i])
                   del(Data[specimen][i])
                if len(duplicates)>0:
                   if average_replicates:
                       duplicates.append(Data[specimen][i-1])
                       Data[specimen][i-1]=average_duplicates(duplicates)
                       print("-W- WARNING: averaging %i duplicates for specimen %s treatmant %s"%(len(duplicates),specimen,duplicates[-1]['treatment']))
                       duplicates=[]
                   else:
                       Data[specimen][i-1]=duplicates[-1]
                       print("-W- WARNING: found %i duplicates for specimen %s treatmant %s. Taking the last measurement only"%(len(duplicates),specimen,duplicates[-1]['treatment']))
                       duplicates=[]

                if i==len(Data[specimen])-1:
                    break

            #    if tmp_data['treatment']==Data[specimen][-1]['treatment'] and tmp_data['treatment_type']==Data[specimen][-1]['treatment_type']:
            #
            ## check replicates
            #if tmp_data['treatment']==Data[specimen][-1]['treatment'] and tmp_data['treatment_type']==Data[specimen][-1]['treatment_type']:
            #    #found_duplicate=True
            #    duplicates.append(Data[specimen][-1])
            #    duplicates.append(tmp_data)
            #    del(Data[specimen][-1])
            #    continue
            #else:
            #    if len(duplicates)>0:
            #        if average_replicates:
            #            Data[specimen].append(average_duplicates(duplicates))
            #            print "-W- WARNING: averaging %i duplicates for specimen %s treatmant %s"%(len(duplicates),specimen,duplicates[-1]['treatment'])
            #        else:
            #            Data[specimen].append(duplicates[-1])
            #            print "-W- WARNING: found %i duplicates for specimen %s treatmant %s. Taking the last measurement only"%(len(duplicates),specimen,duplicates[-1]['treatment'])
            #    duplicates=[]
            #    Data[specimen].append(tmp_data)

        return(Data)

    def average_duplicates(duplicates):
        '''
        avarage replicate measurements.
        '''
        carts_s,carts_g,carts_t=[],[],[]
        for rec in duplicates:
            moment=float(rec['moment'])
            if 'dec_s' in list(rec.keys()) and 'inc_s' in list(rec.keys()):
                if rec['dec_s']!="" and rec['inc_s']!="":
                    dec_s=float(rec['dec_s'])
                    inc_s=float(rec['inc_s'])
                    cart_s=pmag.dir2cart([dec_s,inc_s,moment])
                    carts_s.append(cart_s)
            if 'dec_g' in list(rec.keys()) and 'inc_g' in list(rec.keys()):
                if rec['dec_g']!="" and rec['inc_g']!="":
                    dec_g=float(rec['dec_g'])
                    inc_g=float(rec['inc_g'])
                    cart_g=pmag.dir2cart([dec_g,inc_g,moment])
                    carts_g.append(cart_g)
            if 'dec_t' in list(rec.keys()) and 'inc_t' in list(rec.keys()):
                if rec['dec_t']!="" and rec['inc_t']!="":
                    dec_t=float(rec['dec_t'])
                    inc_t=float(rec['inc_t'])
                    cart_t=pmag.dir2cart([dec_t,inc_t,moment])
                    carts_t.append(cart_t)
        if len(carts_s)>0:
            carts=scipy.array(carts_s)
            x_mean=scipy.mean(carts[:,0])
            y_mean=scipy.mean(carts[:,1])
            z_mean=scipy.mean(carts[:,2])
            mean_dir=pmag.cart2dir([x_mean,y_mean,z_mean])
            mean_dec_s="%.2f"%mean_dir[0]
            mean_inc_s="%.2f"%mean_dir[1]
            mean_moment="%10.3e"%mean_dir[2]
        else:
            mean_dec_s,mean_inc_s="",""
        if len(carts_g)>0:
            carts=scipy.array(carts_g)
            x_mean=scipy.mean(carts[:,0])
            y_mean=scipy.mean(carts[:,1])
            z_mean=scipy.mean(carts[:,2])
            mean_dir=pmag.cart2dir([x_mean,y_mean,z_mean])
            mean_dec_g="%.2f"%mean_dir[0]
            mean_inc_g="%.2f"%mean_dir[1]
            mean_moment="%10.3e"%mean_dir[2]
        else:
            mean_dec_g,mean_inc_g="",""

        if len(carts_t)>0:
            carts=scipy.array(carts_t)
            x_mean=scipy.mean(carts[:,0])
            y_mean=scipy.mean(carts[:,1])
            z_mean=scipy.mean(carts[:,2])
            mean_dir=pmag.cart2dir([x_mean,y_mean,z_mean])
            mean_dec_t="%.2f"%mean_dir[0]
            mean_inc_t="%.2f"%mean_dir[1]
            mean_moment="%10.3e"%mean_dir[2]
        else:
            mean_dec_t,mean_inc_t="",""

        meanrec={}
        for key in list(duplicates[0].keys()):
            if key in ['dec_s','inc_s','dec_g','inc_g','dec_t','inc_t','moment']:
                continue
            else:
                meanrec[key]=duplicates[0][key]
        meanrec['dec_s']=mean_dec_s
        meanrec['dec_g']=mean_dec_g
        meanrec['dec_t']=mean_dec_t
        meanrec['inc_s']=mean_inc_s
        meanrec['inc_g']=mean_inc_g
        meanrec['inc_t']=mean_inc_t
        meanrec['moment']=mean_moment
        return meanrec

    def get_upper_level_name(name,nc):
        '''
        get sample/site name from specimen/sample using naming convention
        '''
        if float(nc[0])==0:
            if float(nc[1])!=0:
                number_of_char=int(nc[1])
                high_name=name[:number_of_char]
            else:
                high_name=name
        elif float(nc[0])==1:
            if float(nc[1])!=0:
                number_of_char=int(nc[1])*-1
                high_name=name[:number_of_char]
            else:
                high_name=name
        elif float(nc[0])==2:
            d=str(nc[1])
            name_splitted=name.split(d)
            if len(name_splitted)==1:
                high_name=name_splitted[0]
            else:
                high_name=d.join(name_splitted[:-1])
        else:
            high_name=name
        return high_name

    def merge_pmag_recs(old_recs):
        recs={}
        recs=copy.deepcopy(old_recs)
        headers=[]
        for rec in recs:
            for key in list(rec.keys()):
                if key not in headers:
                    headers.append(key)
        for rec in recs:
            for header in headers:
                if header not in list(rec.keys()):
                    rec[header]=""
        return recs

    # initialize some variables
    experiment = ''
    sample_nc = [1, 0]
    site_nc = [1, 0]
    meas_file = "magic_measurements.txt"
    labfield = 0

    #--------------------------------------
    # get command line arguments
    #--------------------------------------

    if command_line:
        args=sys.argv
        user=""
        if "-h" in args:
            print(main.__doc__)
            return False
        if "-usr" in args:
            ind=args.index("-usr")
            user=args[ind+1]
        else:
            user=""
        if '-F' in args:
            ind=args.index("-F")
            meas_file=args[ind+1]
        if '-Fsa' in args:
            ind=args.index("-Fsa")
            samp_file=args[ind+1]
        else:
            samp_file="er_samples.txt"

        if '-f' in args:
            ind=args.index("-f")
            magfile=args[ind+1]

        if "-dc" in args:
            ind=args.index("-dc")
            labfield=float(args[ind+1])*1e-6
            labfield_phi=float(args[ind+2])
            labfield_theta=float(args[ind+3])
        if '-exp' in args:
            ind=args.index("-exp")
            experiment=args[ind+1]
        if "-samp" in args:
            ind=args.index("-samp")
            sample_nc=[]
            sample_nc.append(args[ind+1])
            sample_nc.append(args[ind+2])
        if "-site" in args:
            ind=args.index("-site")
            site_nc=[]
            site_nc.append(args[ind+1])
            site_nc.append(args[ind+2])
        if "-loc" in args:
            ind=args.index("-loc")
            er_location_name=args[ind+1]
        else:
            er_location_name=""
        if "-A" in args:
            noave=1
        else:
            noave=0

        if "-WD" in args:
            ind=args.index("-WD")
            WD=args[ind+1]
            os.chdir(WD)

    # unpack keyword args if using as module
    if not command_line:
        user = kwargs.get('user', '')
        meas_file = kwargs.get('meas_file', 'magic_measurements.txt')
        samp_file = kwargs.get('samp_file', 'er_samples.txt')
        magfile = kwargs.get('magfile', '')
        labfield = int(kwargs.get('labfield', 0))
        if labfield:
            labfield *= 1e-6
        labfield_phi = int(kwargs.get('labfield_phi', 0))
        labfield_theta = int(kwargs.get('labfield_theta', 0))
        experiment = kwargs.get('experiment', '')
        cooling_times = kwargs.get('cooling_times_list', '')
        sample_nc = kwargs.get('sample_nc', [1, 0])
        site_nc = kwargs.get('site_nc', [1, 0])
        er_location_name = kwargs.get('er_location_name', '')
        noave = kwargs.get('noave', 0) # 0 is default, means do average
        WD = kwargs.get('WD', '.')
        #os.chdir(WD)

    # format and validate variables
    if magfile:
        try:
            input=open(magfile,'r')
        except:
            print("bad mag file:",magfile)
            return False, "bad mag file"
    else:
        print("mag_file field is required option")
        print(main.__doc__)
        return False, "mag_file field is required option"

    if not experiment:
        print("-exp is required option. Please provide experiment type of: Demag, PI, ATRM n (n of positions), CR (see below for format), NLT")
        print(main.__doc__)
        return False, "-exp is required option"

    if experiment=='ATRM':
        if command_line:
            ind=args.index("ATRM")
            atrm_n_pos=int(args[ind+1])
        else:
            atrm_n_pos = 6

    if experiment=='AARM':
        if command_line:
            ind=args.index("AARM")
            aarm_n_pos=int(args[ind+1])
        else:
            aarm_n_pos = 6

    if  experiment=='CR':
        if command_line:
            ind=args.index("CR")
            cooling_times=args[ind+1]
        cooling_times_list=cooling_times.split(',')
        # if not command line, cooling_times_list is already set

    #--------------------------------------
    # read data from er_samples.txt
    #--------------------------------------

    #if "-fsa" in args:
    #   ind=args.index("-fsa")
    #    er_sample_file=args[ind+1]
    #else:
    #    er_sample_file="er_samples.txt"

    er_sample_data={}
    #er_sample_data=sort_magic_file(samp_file,1,'er_sample_name')
    try:
        er_sample_data=sort_magic_file(samp_file,1,'er_sample_name')
        print("-I- Found er_samples.txt")
        print('-I- sample information will be appended to existing er_samples.txt file')
    except:
        print("-I- Cant find file er_samples.txt")
        print('-I- sample information will be stored in new er_samples.txt file')

    #--------------------------------------
    # read data from generic file
    #--------------------------------------

    if  noave:
        mag_data=read_generic_file(magfile,False)
    else:
        mag_data=read_generic_file(magfile,True)

    #--------------------------------------
    # for each specimen get the data, and translate it to MagIC format
    #--------------------------------------

    ErSamplesRecs=[]
    MagRecs=[]
    specimens_list=list(mag_data.keys())
    specimens_list.sort()
    for specimen in specimens_list:
        measurement_running_number=0
        this_specimen_treatments=[] # a list of all treatments
        MagRecs_this_specimen=[]
        LP_this_specimen=[] # a list of all lab protocols
        IZ,ZI=0,0 # counter for IZ and ZI steps

        for meas_line in mag_data[specimen]:

            #------------------
            # trivial MagRec data
            #------------------

            MagRec={}
            MagRec['er_citation_names']="This study"
            MagRec["er_specimen_name"]=meas_line['specimen']
            MagRec["er_sample_name"]=get_upper_level_name(MagRec["er_specimen_name"],sample_nc)
            MagRec["er_site_name"]=get_upper_level_name(MagRec["er_sample_name"],site_nc)
            MagRec['er_location_name']=er_location_name
            MagRec['er_analyst_mail_names']=user
            MagRec["magic_instrument_codes"]=""
            MagRec["measurement_flag"]='g'
            MagRec["measurement_number"]="%i"%measurement_running_number

            MagRec["measurement_magn_moment"]='%10.3e'%(float(meas_line["moment"])*1e-3) # in Am^2
            MagRec["measurement_temp"]='273.' # room temp in kelvin

            #------------------
            #  decode treatments from treatment column in the generic file
            #------------------

            treatment=[]
            treatment_code=str(meas_line['treatment']).split(".")
            treatment.append(float(treatment_code[0]))
            if len(treatment_code)==1:
                treatment.append(0)
            else:
                treatment.append(float(treatment_code[1]))

            #------------------
            #  lab field direction
            #------------------

            if experiment in ['PI','NLT','CR']:

                if float(treatment[1])==0:
                    MagRec["treatment_dc_field"]="0"
                    MagRec["treatment_dc_field_phi"]="0"
                    MagRec["treatment_dc_field_theta"]="0"
                elif not labfield:
                    print("-W- WARNING: labfield (-dc) is a required argument for this experiment type")
                    return False, "labfield (-dc) is a required argument for this experiment type"

                else:
                    MagRec["treatment_dc_field"]='%8.3e'%(float(labfield))
                    MagRec["treatment_dc_field_phi"]="%.2f"%(float(labfield_phi))
                    MagRec["treatment_dc_field_theta"]="%.2f"%(float(labfield_theta))
            else:
                MagRec["treatment_dc_field"]=""
                MagRec["treatment_dc_field_phi"]=""
                MagRec["treatment_dc_field_theta"]=""

            #------------------
            # treatment temperature/peak field
            #------------------

            if experiment == 'Demag':
                if meas_line['treatment_type']=='A':
                    MagRec['treatment_temp']="273."
                    MagRec["treatment_ac_field"]="%.3e"%(treatment[0]*1e-3)
                elif meas_line['treatment_type']=='N':
                    MagRec['treatment_temp']="273."
                    MagRec["treatment_ac_field"]=""
                else:
                    MagRec['treatment_temp']="%.2f"%(treatment[0]+273.)
                    MagRec["treatment_ac_field"]=""
            else:
                    MagRec['treatment_temp']="%.2f"%(treatment[0]+273.)
                    MagRec["treatment_ac_field"]=""

            #---------------------
            # Lab treatment
            # Lab protocol
            #---------------------

            #---------------------
            # Lab treatment and lab protocoal for NRM:
            #---------------------

            if float(meas_line['treatment'])==0:
                LT="LT-NO"
                LP="" # will be filled later after finishing reading all measurements line

            #---------------------
            # Lab treatment and lab protocoal for paleointensity experiment
            #---------------------

            elif experiment =='PI':
                LP="LP-PI-TRM"
                if treatment[1]==0:
                    LT="LT-T-Z"
                elif  treatment[1]==1 or treatment[1]==10: # infield
                    LT="LT-T-I"
                elif treatment[1]==2 or treatment[1]==20:  # pTRM check
                    LT="LT-PTRM-I"
                    LP=LP+":"+"LP-PI-ALT-PTRM"
                elif treatment[1]==3 or treatment[1]==30: # Tail check
                    LT="LT-PTRM-MD"
                    LP=LP+":"+"LP-PI-BT-MD"
                elif treatment[1]==4 or treatment[1]==40: # Additivity check
                    LT="LT-PTRM-AC"
                    LP=LP+":"+"LP-PI-BT-MD"
                elif treatment[1]==5 or treatment[1]==50: # Thellier protocol, second infield step
                    LT="LT-T-I"
                    LP=LP+":"+"LP-PI-II"

                    # adjust field direction in thellier protocol
                    MagRec["treatment_dc_field_phi"]="%.2f"%( (float(labfield_phi) +180.0)%360.    )
                    MagRec["treatment_dc_field_theta"]="%.2f"%( float(labfield_theta)*-1 )

                else:
                    print("-E- unknown measurement code specimen %s treatmemt %s"%(meas_line['specimen'],meas_line['treatment']))
                    MagRec={}
                    continue
                # save all treatment in a list
                # we will use this later to distinguidh between ZI / IZ / and IZZI

                this_specimen_treatments.append(float(meas_line['treatment']))
                if LT=="LT-T-Z":
                    if float(treatment[0]+0.1) in this_specimen_treatments:
                        LP=LP+":"+"LP-PI-IZ"
                if LT=="LT-T-I":
                    if float(treatment[0]+0.0) in this_specimen_treatments:
                        LP=LP+":"+"LP-PI-ZI"
            #---------------------
            # Lab treatment and lab protocoal for demag experiment
            #---------------------

            elif "Demag" in experiment:
                if meas_line['treatment_type']=='A':
                    LT="LT-AF-Z"
                    LP="LP-DIR-AF"
                else:
                    LT="LT-T-Z"
                    LP="LP-DIR-T"

            #---------------------
            # Lab treatment and lab protocoal for ATRM experiment
            #---------------------

            elif experiment in ['ATRM','AARM']:

                if experiment=='ATRM':
                    LP="LP-AN-TRM"
                    n_pos=atrm_n_pos
                    if n_pos!=6:
                        print("the program does not support ATRM in %i position."%n_pos)
                        continue

                if experiment=='AARM':
                    #MagRec['treatment_temp']="273."
                    #MagRec["treatment_ac_field"]=""
                    LP="LP-AN-ARM"
                    n_pos=aarm_n_pos
                    if n_pos!=6:
                        print("the program does not support AARM in %i position."%n_pos)
                        continue

                if treatment[1]==0:
                    if experiment=='ATRM':
                        LT="LT-T-Z"
                        MagRec['treatment_temp']="%.2f"%(treatment[0]+273.)
                        MagRec["treatment_ac_field"]=""

                    else:
                        LT="LT-AF-Z"
                        MagRec['treatment_temp']="273."
                        MagRec["treatment_ac_field"]="%.3e"%(treatment[0]*1e-3)
                    MagRec["treatment_dc_field"]='0'
                    MagRec["treatment_dc_field_phi"]='0'
                    MagRec["treatment_dc_field_theta"]='0'
                else:
                    if experiment=='ATRM':
                        if float(treatment[1])==70 or float(treatment[1])==7: # alteration check as final measurement
                            LT="LT-PTRM-I"
                        else:
                            LT="LT-T-I"
                    else:
                        LT="LT-AF-I"
                    MagRec["treatment_dc_field"]='%8.3e'%(float(labfield))

                    # find the direction of the lab field in two ways:

                    # (1) using the treatment coding (XX.1=+x, XX.2=+y, XX.3=+z, XX.4=-x, XX.5=-y, XX.6=-z)
                    tdec=[0,90,0,180,270,0,0,90,0]
                    tinc=[0,0,90,0,0,-90,0,0,90]
                    if treatment[1] < 10:
                        ipos_code=int(treatment[1])-1
                    else:
                        ipos_code=int(old_div(treatment[1],10))-1

                    # (2) using the magnetization
                    if meas_line["dec_s"]!="":
                        DEC=float(meas_line["dec_s"])
                        INC=float(meas_line["inc_s"])
                    elif meas_line["dec_g"]!="":
                        DEC=float(meas_line["dec_g"])
                        INC=float(meas_line["inc_g"])
                    elif meas_line["dec_t"]!="":
                        DEC=float(meas_line["dec_t"])
                        INC=float(meas_line["inc_t"])
                    if DEC<0 and DEC>-359:
                        DEC=360.+DEC

                    if INC < 45 and INC > -45:
                        if DEC>315  or DEC<45: ipos_guess=0
                        if DEC>45 and DEC<135: ipos_guess=1
                        if DEC>135 and DEC<225: ipos_guess=3
                        if DEC>225 and DEC<315: ipos_guess=4
                    else:
                        if INC >45: ipos_guess=2
                        if INC <-45: ipos_guess=5
                    # prefer the guess over the code
                    ipos=ipos_guess
                    # check it
                    if treatment[1]!= 7 and treatment[1]!= 70:
                        if ipos_guess!=ipos_code:
                            print("-W- WARNING: check specimen %s step %s, anistropy measurements, coding does not match the direction of the lab field"%(specimen,meas_line['treatment']))
                    MagRec["treatment_dc_field_phi"]='%7.1f' %(tdec[ipos])
                    MagRec["treatment_dc_field_theta"]='%7.1f'% (tinc[ipos])

            #---------------------
            # Lab treatment and lab protocoal for cooling rate experiment
            #---------------------

            elif experiment == "CR":

                cooling_times_list
                LP="LP-CR-TRM"
                MagRec["treatment_temp"]='%8.3e' % (float(treatment[0])+273.) # temp in kelvin

                if treatment[1]==0:
                    LT="LT-T-Z"
                    MagRec["treatment_dc_field"]="0"
                    MagRec["treatment_dc_field_phi"]='0'
                    MagRec["treatment_dc_field_theta"]='0'
                else:
                    if treatment[1]==7: # alteration check as final measurement
                            LT="LT-PTRM-I"
                    else:
                            LT="LT-T-I"
                    MagRec["treatment_dc_field"]='%8.3e'%(labfield)
                    MagRec["treatment_dc_field_phi"]='%7.1f' % (labfield_phi) # labfield phi
                    MagRec["treatment_dc_field_theta"]='%7.1f' % (labfield_theta) # labfield theta

                    indx=int(treatment[1])-1
                    # alteration check matjed as 0.7 in the measurement file
                    if indx==6:
                        cooling_time= cooling_times_list[-1]
                    else:
                        cooling_time=cooling_times_list[indx]
                    MagRec["measurement_description"]="cooling_rate"+":"+cooling_time+":"+"K/min"

            #---------------------
            # Lab treatment and lab protocoal for NLT experiment
            #---------------------

            elif 'NLT' in experiment :
                print("Dont support yet NLT rate experiment file. Contact rshaar@ucsd.edu")

            #---------------------
            # magic_method_codes for this measurement only
            # LP will be fixed after all measurement lines are read
            #---------------------

            MagRec["magic_method_codes"]=LT+":"+LP

            #---------------------
            # Demag experiments only:
            # search if orientation data exists in er_samples.txt
            # if not: create one and save
            #---------------------

            # see if core azimuth and tilt-corrected data are in er_samples.txt
            sample=MagRec["er_sample_name"]
            found_sample_azimuth,found_sample_dip,found_sample_bed_dip_direction,found_sample_bed_dip=False,False,False,False
            if sample in list(er_sample_data.keys()):
                if "sample_azimuth" in list(er_sample_data[sample].keys()) and er_sample_data[sample]['sample_azimuth'] !="":
                    sample_azimuth=float(er_sample_data[sample]['sample_azimuth'])
                    found_sample_azimuth=True
                if "sample_dip" in list(er_sample_data[sample].keys()) and er_sample_data[sample]['sample_dip']!="":
                    sample_dip=float(er_sample_data[sample]['sample_dip'])
                    found_sample_dip=True
                if "sample_bed_dip_direction" in list(er_sample_data[sample].keys()) and er_sample_data[sample]['sample_bed_dip_direction']!="":
                    sample_bed_dip_direction=float(er_sample_data[sample]['sample_bed_dip_direction'])
                    found_sample_bed_dip_direction=True
                if "sample_bed_dip" in list(er_sample_data[sample].keys()) and er_sample_data[sample]['sample_bed_dip']!="":
                    sample_bed_dip=float(er_sample_data[sample]['sample_bed_dip'])
                    found_sample_bed_dip=True
            else:
                er_sample_data[sample]={}

            #--------------------
            # deal with specimen orientation and different coordinate system
            #--------------------

            found_s,found_geo,found_tilt=False,False,False
            if "dec_s" in list(meas_line.keys()) and "inc_s" in list(meas_line.keys()):
                if meas_line["dec_s"]!="" and meas_line["inc_s"]!="":
                    found_s=True
                MagRec["measurement_dec"]=meas_line["dec_s"]
                MagRec["measurement_inc"]=meas_line["inc_s"]
            if "dec_g" in list(meas_line.keys()) and "inc_g" in list(meas_line.keys()):
                if meas_line["dec_g"]!="" and meas_line["inc_g"]!="":
                    found_geo=True
            if "dec_t" in list(meas_line.keys()) and "inc_t" in list(meas_line.keys()):
                if meas_line["dec_t"]!="" and meas_line["inc_t"]!="":
                    found_tilt=True

            #-----------------------------
            # specimen coordinates: no
            # geographic coordinates: yes
            #-----------------------------

            if found_geo and not found_s:
                MagRec["measurement_dec"]=meas_line["dec_g"]
                MagRec["measurement_inc"]=meas_line["inc_g"]

                # core azimuth/plunge is not in er_samples.txt
                if not found_sample_dip or not found_sample_azimuth:
                    er_sample_data[sample]['sample_azimuth']="0"
                    er_sample_data[sample]['sample_dip']="0"

                # core azimuth/plunge is in er_samples.txt
                else:
                    sample_azimuth=float(er_sample_data[sample]['sample_azimuth'])
                    sample_dip=float(er_sample_data[sample]['sample_dip'])
                    if sample_azimuth!=0 and sample_dip!=0:
                        print("-W- WARNING: delete core azimuth/plunge in er_samples.txt\n\
                        becasue dec_s and inc_s are unavaialable")

            #-----------------------------
            # specimen coordinates: no
            # geographic coordinates: no
            #-----------------------------
            if not found_geo and not found_s:
                print("-E- ERROR: sample %s does not have dec_s/inc_s or dec_g/inc_g. Ignore specimen %s "%(sample,specimen))
                break

            #-----------------------------
            # specimen coordinates: yes
            # geographic coordinates: yes
            #
            # commant: Ron, this need to be tested !!
            #-----------------------------
            if found_geo and found_s:

                cdec,cinc=float(meas_line["dec_s"]),float(meas_line["inc_s"])
                gdec,ginc=float(meas_line["dec_g"]),float(meas_line["inc_g"])
                az,pl=pmag.get_azpl(cdec,cinc,gdec,ginc)

                # core azimuth/plunge is not in er_samples.txt:
                # calculate core az/pl and add it to er_samples.txt
                if not found_sample_dip or not found_sample_azimuth:
                    er_sample_data[sample]['sample_azimuth']="%.1f"%az
                    er_sample_data[sample]['sample_dip']="%.1f"%pl

                # core azimuth/plunge is in er_samples.txt
                else:
                    if float(er_sample_data[sample]['sample_azimuth'])!= az:
                        print("-E- ERROR in sample_azimuth sample %s. Check it! using the value in er_samples.txt"%sample)

                    if float(er_sample_data[sample]['sample_dip'])!= pl:
                        print("-E- ERROR in sample_dip sample %s. Check it! using the value in er_samples.txt"%sample)

            #-----------------------------
            # specimen coordinates: yes
            # geographic coordinates: no
            #-----------------------------
            if not found_geo and found_s:
                if found_sample_dip and found_sample_azimuth:
                    pass
                    # (nothing to do)
                else:
                    if "Demag" in experiment:
                        print("-W- WARNING: missing sample_dip or sample_azimuth for sample %s"%sample)

            #-----------------------------
            # tilt-corrected coordinates: yes
            # geographic coordinates: no
            #-----------------------------
            if found_tilt and not found_geo:
                    print("-E- ERROR: missing geographic data for sample %s. Ignoring tilt-corrected data "%sample)
            if found_tilt and found_geo:
                dec_geo,inc_geo=float(meas_line["dec_g"]),float(meas_line["inc_g"])
                dec_tilt,inc_tilt=float(meas_line["dec_t"]),float(meas_line["inc_t"])
                if dec_geo==dec_tilt and inc_geo==inc_tilt:
                    DipDir,Dip=0.,0.
                else:
                    DipDir,Dip=pmag.get_tilt(dec_geo,inc_geo,dec_tilt,inc_tilt)

                if not found_sample_bed_dip_direction or not found_sample_bed_dip:
                    print("-I- calculating dip and dip direction used for tilt correction sample %s. results are put in er_samples.txt"%sample)
                    er_sample_data[sample]['sample_bed_dip_direction']="%.1f"%DipDir
                    er_sample_data[sample]['sample_bed_dip']="%.1f"%Dip

            #-----------------------------
            # er_samples method codes
            # geographic coordinates: no
            #-----------------------------
            if found_tilt or found_geo:
                er_sample_data[sample]['magic_method_codes']="SO-NO"

            #-----------------
            # er_samples_data
            #-----------------
            if sample in list(er_sample_data.keys()):
                er_sample_data[sample]['er_sample_name']=sample
                er_sample_data[sample]['er_site_name']=MagRec["er_site_name"]
                er_sample_data[sample]['er_location_name']=MagRec["er_location_name"]

            #MagRec["magic_method_codes"]=LT
            MagRecs_this_specimen.append(MagRec)

            #if LP!="" and LP not in LP_this_specimen:
            #    LP_this_specimen.append(LP)

            measurement_running_number+=1
            #-------

        #-------
        # after reading all the measurements lines for this specimen
        # 1) add magic_experiment_name
        # 2) fix magic_method_codes with the correct lab protocol
        #-------
        LP_this_specimen=[]
        for MagRec in MagRecs_this_specimen:
            magic_method_codes=MagRec["magic_method_codes"].split(":")
            for code in magic_method_codes:
                if "LP" in code and code not in LP_this_specimen:
                    LP_this_specimen.append(code)
        # check IZ/ZI/IZZI
        if "LP-PI-ZI" in   LP_this_specimen and "LP-PI-IZ" in   LP_this_specimen:
            LP_this_specimen.remove("LP-PI-ZI")
            LP_this_specimen.remove("LP-PI-IZ")
            LP_this_specimen.append("LP-PI-BT-IZZI")

        # add the right LP codes and fix experiment name
        for MagRec in MagRecs_this_specimen:
            MagRec["magic_experiment_name"]=MagRec["er_specimen_name"]+":"+":".join(LP_this_specimen)
            magic_method_codes=MagRec["magic_method_codes"].split(":")
            LT=""
            for code in magic_method_codes:
                if code[:3]=="LT-":
                    LT=code;
                    break
            MagRec["magic_method_codes"]=LT+":"+":".join(LP_this_specimen)

            MagRecs.append(MagRec)

    #--
    # write magic_measurements.txt
    #--
    MagRecs_fixed=merge_pmag_recs(MagRecs)
    pmag.magic_write(meas_file,MagRecs_fixed,'magic_measurements')
    print("-I- MagIC file is saved in  %s"%meas_file)

    #--
    # write er_samples.txt
    #--
    ErSamplesRecs=[]
    samples=list(er_sample_data.keys())
    samples.sort()
    for sample in samples:
        ErSamplesRecs.append(er_sample_data[sample])
    ErSamplesRecs_fixed=merge_pmag_recs(ErSamplesRecs)
    pmag.magic_write(samp_file,ErSamplesRecs_fixed,'er_samples')
    return True, meas_file

def do_help():
    return main.__doc__

if __name__ == '__main__':
    main()


#!/usr/bin/env python
"""
Initialize for multi-plane peak finding and fitting with arbitrary PSFs.

Hazen 01/18
"""
import os
import pickle
import numpy
import tifffile

import storm_analysis.multi_plane.fitting_mp as fittingMp
import storm_analysis.multi_plane.mp_fit_arb_c as mpFitArbC
import storm_analysis.multi_plane.mp_utilities as mpUtil

import storm_analysis.sa_library.analysis_io as analysisIO

import storm_analysis.psf_fft.psf_fn as psfFn
import storm_analysis.pupilfn.pupil_fn as pupilFn
import storm_analysis.spliner.spline_to_psf as splineToPSF

def initFitter(margin, parameters, psf_objects, rqes, variances):
    """
    Create and return a mpFitArbC.MPXXFit object.
    """
    # This fitter only supports 'MLE'
    assert (parameters.getAttr("fit_error_model") == 'MLE'), "Only MLE fitting is supported."

    assert(len(psf_objects) == len(variances))
    #
    # FIXME: Not sure having two z ranges, one from the spline
    #        and one in the parameters is a good idea.
    #
    # Create the fitter object which will do the actual fitting. Unless specified
    # the fit for each channel is forced to have the same height.
    #
    if isinstance(psf_objects[0], psfFn.PSFFn):
        mfitter = mpFitArbC.MPPSFFnFit(independent_heights = parameters.getAttr("independent_heights", 0),
                                       psf_objects = psf_objects)

    elif isinstance(psf_objects[0], pupilFn.PupilFunction):
        mfitter = mpFitArbC.MPPupilFnFit(independent_heights = parameters.getAttr("independent_heights", 0),
                                         psf_objects = psf_objects)

    elif isinstance(psf_objects[0], splineToPSF.SplineToPSF3D):
        mfitter = mpFitArbC.MPSplineFit(independent_heights = parameters.getAttr("independent_heights", 0),
                                        psf_objects = psf_objects)

    # Initialize fitters for each channel.
    #
    for i in range(len(variances)):
        mfitter.initializeChannel(rqes[i], variances[i], i)

    # Load mappings.
    #
    if parameters.hasAttr("mapping"):
        if os.path.exists(parameters.getAttr("mapping")):
            mapping_filename = parameters.getAttr("mapping")
        else:
            raise Exception("Mapping file", parameters.getAttr("mapping"), "does not exist.")

        mfitter.setMapping(*mpUtil.loadMappings(mapping_filename, margin))

    # Load channel Cramer-Rao weights if available.
    #
    weights = None
    if parameters.hasAttr("weights"):
        with open(parameters.getAttr("weights"), 'rb') as fp:
            weights = pickle.load(fp)
    mfitter.setWeights(weights)

    return mfitter

def initPSFObjects(parameters):
    """
    Create and return the PSF objects (spline, pupil function or psf FFT).
    """
    psf_objects = []

    # Try PSF FFT.
    #
    if (len(mpUtil.getPSFFFTAttrs(parameters)) > 0):

        # Create PSF FFT PSF objects.
        for psf_fft_attr in mpUtil.getPSFFFTAttrs(parameters):
            psf_objects.append(psfFn.PSFFn(psf_filename = parameters.getAttr(psf_fft_attr)))

        # All the PSF FFT objects have to have the same Z range.
        for i in range(1, len(psf_objects)):
            assert (psf_objects[0].getZMin() == psf_objects[i].getZMin())
            assert (psf_objects[0].getZMax() == psf_objects[i].getZMax())

    # Try pupil functions.
    #
    elif (len(mpUtil.getPupilFnAttrs(parameters)) > 0):

        # Get fitting Z range (this is in microns).
        [min_z, max_z] = parameters.getZRange()

        # Create pupil function PSF objects.
        for pupil_fn_attr in mpUtil.getPupilFnAttrs(parameters):
            psf_objects.append(pupilFn.PupilFunction(pf_filename = parameters.getAttr(pupil_fn_attr),
                                                     zmin = min_z * 1.0e+3,
                                                     zmax = max_z * 1.0e+3))

    # Try splines.
    #
    elif (len(mpUtil.getSplineAttrs(parameters)) > 0):

        # Create Spline PSF objects.
        for spline_attr in mpUtil.getSplineAttrs(parameters):
            psf_objects.append(splineToPSF.SplineToPSF3D(spline_file = parameters.getAttr(spline_attr)))

        # All the splines have to have the same Z range.
        for i in range(1, len(psf_objects)):
            assert (psf_objects[0].getZMin() == psf_objects[i].getZMin())
            assert (psf_objects[0].getZMax() == psf_objects[i].getZMax())

    else:
        raise Exception("No PSF objects found.")

    return psf_objects

def initFindAndFit(parameters):
    """
    Create and return a fittingMp.MPFinderFitter object.
    """
    # Create PSF objects.
    psf_objects = initPSFObjects(parameters)

    # Create peak finder.
    finder = fittingMp.MPPeakFinderArb(parameters = parameters,
                                       psf_objects = psf_objects)

    # Load sCMOS calibration data.
    #
    # Note: Gain is expected to be in units of ADU per photo-electron.
    #
    rqes = []
    variances = []
    for calib_name in mpUtil.getCalibrationAttrs(parameters):
        [offset, variance, gain, rqe] = analysisIO.loadCMOSCalibration(parameters.getAttr(calib_name))
        variances.append(variance/(gain*gain))
        rqes.append(rqe)

    # Set variance in the peak finder. This method also pads the variance
    # to the correct size and performs additional initializations.
    #
    variances = finder.setVariances(variances)

    # Pad the rqes to the correct size.
    rqes = list(map(lambda x: finder.padArray(x), rqes))

    # Create mpFitC.MPFit object.
    #
    mfitter = initFitter(finder.margin,
                         parameters,
                         psf_objects,
                         rqes,
                         variances)

    # Create peak fitter.
    #
    fitter = fittingMp.MPPeakFitterArb(mfitter = mfitter,
                                       parameters = parameters)

    # Specify which properties we want (for each channel) from the
    # analysis. Note that some of these may be duplicates of each
    # other, for example if the heights are not independent.
    #
    properties = ["background", "error", "height", "iterations", "significance", "sum", "x", "y", "z"]

    return fittingMp.MPFinderFitter(peak_finder = finder,
                                    peak_fitter = fitter,
                                    properties = properties)


# third party libraries
import pytest
import numpy as np
# project libraries
from speech.utils import data_helpers
from speech.utils.wave import array_from_wave
from speech.utils.signal_augment import inject_noise_sample
from speech import dataset_info
import utils

def test_all_noise_audio():
    all_datasets = dataset_info.AllDatasets()
    noise_dataset = dataset_info.NoiseDataset()
    # inputs to inject_noise
    noise_files = noise_dataset.get_audio_files()
    logger = None
    noise_levels = (0,0.5)
    # run through each dataset and test each file
    for dataset in all_datasets.dataset_list:
        audio_files = dataset.get_audio_files()
        for audio_file in audio_files:
            if data_helpers.skip_file(dataset.corpus_name, audio_file):
                print(f"skipping: {audio_file}")
                continue
            audio_data, samp_rate = wave.array_from_wave(audio_file)
            noise_file = np.random.choice(noise_files)
            noise_level = np.random.uniform(*noise_levels)
            try:
                inject_noise_sample(audio_data, samp_rate, noise_file, noise_level,logger=None)
            except AssertionError:
                raise AssertionError(f"audio: {audio_file}, noise: {noise_path}, noise_level: {noise_level}")
            except FileNotFoundError:
                raise FileNotFoundError(f"audio: {audio_file}, noise: {noise_path}, noise_level: {noise_level}")


# -*- coding:utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from scipy import misc
import sys
import os
import argparse
import tensorflow as tf
import numpy as np
import facenet
import align.detect_face
import random
from time import sleep
import numpy as np
import cv2
import align.detect_face
import time

import math
import pickle
from sklearn.svm import SVC

#--------------Argument------------------------------------------------
modeldir='/Users/xqu/datasets/pretrain/20180402-114759.pb'
classifier_filename_exp='/Users/xqu/datasets/mymodels/lfw_classifier.pkl'
FaceImW=160
FaceImH=160
WindowWidth=600
WindowHight=400
interval=10
MAXface=20

#----------------------------------------------------------------------

def main():
    i = 0
    with tf.Graph().as_default():
        gpu_options = tf.compat.v1.GPUOptions(per_process_gpu_memory_fraction=0)
        sess = tf.compat.v1.Session(config=tf.compat.v1.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
        with sess.as_default():
            pnet, rnet, onet = align.detect_face.create_mtcnn(sess, None)
    minsize = 20 # minimum size of face
    threshold = [ 0.6, 0.7, 0.7 ]  # three steps's threshold
    factor = 0.709 # scale factor

#-------------set Video-----------------------------

    #cap = cv2.VideoCapture('/home/razer/Documents/facenet/facenet/src/align/1.mpg')
    cap = cv2.VideoCapture(0)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH,WindowWidth)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT,WindowHight)
    # cap.set(cv2.CAP_PROP_FPS,20)
    # ft=cap.get(cv2.CAP_PROP_FPS)

#--------------------------------------------------------

    with tf.Graph().as_default():
        with tf.Session() as sess:
            print('\n\n----Loading feature extraction model----')
            facenet.load_model(modeldir)
            print('\nFinish Loading feature extraction model----')

            # Get input and output tensors
            images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
            embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
            phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
            embedding_size = embeddings.get_shape()[1]

            # Run forward pass to calculate embeddings
            print('Calculating features for images')

            print('\nTesting classifier\n')
            with open(classifier_filename_exp, 'rb') as infile:
                (model, class_names) = pickle.load(infile)
            print('Loaded classifier model from file "%s"' % classifier_filename_exp)

            # x=0
            # Pdata=[str(x) for x in range(MAXface)]
            while(cap.isOpened()):

                # if x%interval==0:
                #     find_results=[]

                ret, frame = cap.read()
                img=frame

                bounding_boxes, _ = align.detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor)
                nrof_faces = bounding_boxes.shape[0]

                if nrof_faces > 1:
                	print('multiple faces detected...please show one face at a time')
                else:
	                for face_position in bounding_boxes:
	                    face_position=face_position.astype(int)

	                    crop=img[face_position[1]:face_position[3],face_position[0]:face_position[2],]
	                    #crop = cv2.resize(crop, (FaceImW, FaceImH), interpolation=cv2.INTER_CUBIC )
	                    #print ('crop',crop.shape)
	                    try:
	                    	# scaled = misc.imresize(crop, (FaceImW, FaceImH), interp='bilinear')
	                        scaled = cv2.resize(crop, (FaceImW, FaceImH))
	                    except:
	                    	print ('Face angle is not good, please face the camera..')
	                    	#find_results.append('Can not find face.\nPlease face to camera...')
	                    	continue
	                    #print ('scaled',scaled.shape)
	                    #cv2.FaceImWrite('/home/razer/Pictures/face/'+str(a)+'1_'+'.jpg', scaled)

	                    images = np.zeros((1, FaceImW, FaceImH, 3))

	                    if scaled.ndim == 2:
	                        scaled = facenet.to_rgb(scaled)

	                    scaled = facenet.prewhiten(scaled)

	                    images[0,:,:,:]=scaled
	                    #print ('images',images.shape)

	                    cv2.rectangle(frame, (face_position[0],
	                                face_position[1]),
	                          (face_position[2], face_position[3]),
	                          (0, 255, 0), 2)

	                    #print (images.shape)

	                    #predictions part---------------------------------------------------------------------                    #print (images.shape)

	                    feed_dict = { images_placeholder:images, phase_train_placeholder:False }
	                    emb_array = sess.run(embeddings, feed_dict=feed_dict)

	                    predictions = model.predict_proba(emb_array)

	                    best_class_indices = np.argmax(predictions, axis=1)
	                    print(best_class_indices[0])
	                    sig_test = list(predictions[0])
	                    # del sig_test[best_class_indices[0]]

	                    arrstd = np.std(sig_test)
	                    arrmean = np.mean(sig_test)
	                    left = arrmean-4*arrstd
	                    right = arrmean+4*arrstd
	                    print(arrmean,arrstd)
	                    print(right)

	                    best_class_probabilities = predictions[np.arange(len(best_class_indices)), best_class_indices]
	                    print (best_class_probabilities)
	                    if best_class_probabilities[0] > 0.3 and right < best_class_probabilities[0]:

		                    pre=float(best_class_probabilities[i])*100
		                    pre= round(pre,2)
		                    pre=str(pre)+'%'

		                    a=class_names[best_class_indices[i]].split(' ')
		                    result=a[0]
		                    # print(a)
		                    #find_results.append(result+' '+p)

		                    cv2.putText(frame,'{}'.format(result+' '+pre), (face_position[0],
		                                face_position[1]-15),
		                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255 ,0),
		                    thickness = 2, lineType = 1)
	                    else:
		                    cv2.putText(frame,'{}'.format('UNKNOWN'), (face_position[0],
		                                face_position[1]-15),
		                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255 ,0),
		                    thickness = 2, lineType = 1)

	                # x=x+1

	                     #predictions--- end ---------------------------------------------------------------------

                cv2.imshow('frame',frame)
                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break

            cap.release()
            cv2.destroyAllWindows()

if __name__ == '__main__':
    main()


from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.animation import FuncAnimation
from resemblyzer import sampling_rate
from matplotlib import cm, colors
from time import sleep, perf_counter as timer
from umap import UMAP
from sys import stderr
import matplotlib.pyplot as plt
import numpy as np
import datetime

# speakers
karinTime = 0
sandroTime = 0

# needed to multiply frames by time
timeFrameMultiplier = 0.0625

_default_colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
_my_colors = np.array([
    [0, 127, 70],
    [255, 0, 0],
    [255, 217, 38],
    [0, 135, 255],
    [165, 0, 165],
    [255, 167, 255],
    [97, 142, 151],
    [0, 255, 255],
    [255, 96, 38],
    [142, 76, 0],
    [33, 0, 127],
    [0, 0, 0],
    [183, 183, 183],
    [76, 255, 0],
], dtype=np.float) / 255

def play_wav(wav, blocking=True):
    try:
        import sounddevice as sd
        # Small bug with sounddevice.play: the audio is cut 0.5 second too early. We pad it to
        # make up for that
        wav = np.concatenate((wav, np.zeros(sampling_rate // 2)))
        sd.play(wav, sampling_rate, blocking=blocking)
    except Exception as e:
        print("Failed to play audio: %s" % repr(e))

def interactive_diarization(similarity_dict, wav, wav_splits, x_crop=5, show_time=True):
    fig, (ax, pie) = plt.subplots(1, 2)
    lines = [ax.plot([], [], label=name)[0] for name in similarity_dict.keys()]
    text = ax.text(0, 0, "", fontsize=10)

    def init():
        ax.set_ylim(0.4, 1)
        ax.set_ylabel("Similarity")
        if show_time:
            ax.set_xlabel("Time (seconds)")
        else:
            ax.set_xticks([])
        fig.suptitle("Diarization by Patrik, Dejan & Robin", fontsize=14, fontweight='bold')
        ax.set_title("Speaker Diarization")
        ax.legend(loc="lower right")
        return lines + [text]

    times = [((s.start + s.stop) / 2) / sampling_rate for s in wav_splits]
    rate = 1 / (times[1] - times[0])
    crop_range = int(np.round(x_crop * rate))
    ticks = np.arange(0, len(wav_splits), rate)
    ref_time = timer()

    def update(i):
        global sandroTime
        global karinTime
        labels = 'Sandro Botz, Moderator', 'Karin Keller-Sutter, Bundesrätin'
        nums = [sandroTime, karinTime]
        # Crop plot
        crop = (max(i - crop_range // 2, 0), i + crop_range // 2)
        ax.set_xlim(i - crop_range // 2, crop[1])
        if show_time:
            crop_ticks = ticks[(crop[0] <= ticks) * (ticks <= crop[1])]
            ax.set_xticks(crop_ticks)
            ax.set_xticklabels(np.round(crop_ticks / rate).astype(np.int))

        # Plot the prediction
        similarities = [s[i] for s in similarity_dict.values()]
        best = np.argmax(similarities)
        name, similarity = list(similarity_dict.keys())[best], similarities[best]

        pie
        pie.clear()
        pie.axis('equal')
        pie.pie(nums, autopct='%1.1f%%', shadow=True, startangle=140)
        pie.set_title("Sprechverteilung")
        # Place a legend to the right of this smaller subplot.
        pie.legend(bbox_to_anchor=(0.5, 0.95), loc='upper left', borderaxespad=0., labels=labels)
        pie.text(-1, -1.3, 'Total Talk Time:', fontsize=15)
        pie.text(-1, -1.5, 'Sandro Botz: ' + str(datetime.timedelta(seconds=(sandroTime * timeFrameMultiplier)))[:-4] + " Sekunden", style='italic', bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})
        pie.text(-1, -1.7, 'Karin Keller-Sutter: ' + str(datetime.timedelta(seconds=(karinTime * timeFrameMultiplier)))[:-4] + " Sekunden", style='italic', bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})

        if similarity > 0.75:
            message = "Speaker: %s (confident)" % name
            color = _default_colors[best]
            # print name and frametimestamp each update
            if name == "Sandro Botz, Moderator":
                sandroTime += 1
                print(sandroTime)
            if name == "Karin Keller-Sutter, Bundesrätin":
                karinTime += 1
                print(karinTime)
            print(name) # print the name of the speaker every update
        elif similarity > 0.65:
            message = "Speaker: %s (uncertain)" % name
            color = _default_colors[best]
            # print name and frametimestamp each update
            if name == "Sandro Botz, Moderator":
                sandroTime += 1
                print(sandroTime)
            if name == "Karin Keller-Sutter, Bundesrätin":
                karinTime += 1
                print(karinTime)
            print(name) # print the name of the speaker every update
        else:
            message = "Unknown/No speaker"
            color = "black"
        text.set_text(message)
        text.set_c(color)
        text.set_position((i, 0.96))

        # Plot data
        for line, (name, similarities) in zip(lines, similarity_dict.items()):
            line.set_data(range(crop[0], i + 1), similarities[crop[0]:i + 1])

        # Block to synchronize with the audio (interval is not reliable)
        current_time = timer() - ref_time
        if current_time < times[i]:
            sleep(times[i] - current_time)
        elif current_time - 0.2 > times[i]:
            print("Animation is delayed further than 200ms!", file=stderr)
        return lines + [text]

        # #Pie Chart

    ani = FuncAnimation(fig, update, frames=len(wav_splits), init_func=init, blit=not show_time,
                        repeat=False, interval=1)
    play_wav(wav, blocking=False)

    plt.show()

    # print total amount of talked seconds each candidate
    global karinTime
    global sandroTime
    print(karinTime * timeFrameMultiplier)
    print(sandroTime * timeFrameMultiplier)


# -*- coding: utf-8 -*-
#
# shape of sound buffers:
# array([[0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        [0., 0.],
#        ...
#        ])

import sys
import os
import random

import sounddevice as sd
import soundfile as sf
import pygame
import struct
import math
import pyaudio
import numpy as np
from itertools import count

from hsampler.ui import ModeButton, construct_test_button, Command

SAMPLE_DIR = "/home/hb9/projects/music/samples"

pa = pyaudio.PyAudio()

FORMAT = pyaudio.paFloat32
CHANNELS = 2
RATE = 44100

OUTPUT_BLOCK_TIME = 0.005
OUTPUT_FRAMES_PER_BLOCK = int(RATE * OUTPUT_BLOCK_TIME)

frame_counter = 0

KEY_SELECTED_RAW_SAMPLE = "selected_raw_sample"
KEY_RAW_SAMPLE_LIB = "raw_sample_lib"
KEY_SAMPLE_LIB = "sample_lib"
KEY_PLAYING_SAMPLES = "playing_samples"
KEY_SID = "sid"
KEY_LOOP = "loop"
KEY_SID_EDIT = "sid_edit"
KEY_SID_RESAMPLE = "sid_resample"
KEY_TRIM_STEP = "trim_step"
KEY_EDIT_MODE = "edit_mode"

PARAM_COL_OFFSET = 200

TRIM_STEP_ADJUST_STEP = 10
TRIM_STEP_DEFAULT = 300
MODE_TRIM_START = "trim_start"
MODE_TRIM_END = "trim_end"
MODE_TRIM_STEP = "trim_step"
EDIT_MODES = [
    MODE_TRIM_START,
    MODE_TRIM_END,
    MODE_TRIM_STEP
]

APPCFG = {
    "screen_width": 1024,
    "screen_height": 786,
    "btn_fn": {
        "args": {
            "pos_x": 10,
            "pos_y": 10,
            "width": 50,
            "height": 18,
            "title": "TAB",
        },
        "key": "TAB",
    },
    "btn_sample": [
        {
            "args": {
                "pos_x": 10,
                "pos_y": 50,
                "width": 50,
                "height": 18,
                "title": "Q",
            },
            "key": "q",
        },
        {
            "args": {
                "pos_x": 100,
                "pos_y": 50,
                "width": 50,
                "height": 18,
                "title": "W",
            },
            "key": "w",
        },
        {
            "args": {
                "pos_x": 200,
                "pos_y": 50,
                "width": 50,
                "height": 18,
                "title": "E",
            },
            "key": "e",
        },
        {
            "args": {
                "pos_x": 10,
                "pos_y": 100,
                "width": 50,
                "height": 18,
                "title": "A",
            },
            "key": "a",
        },
        {
            "args": {
                "pos_x": 100,
                "pos_y": 100,
                "width": 50,
                "height": 18,
                "title": "S",
            },
            "key": "s",
        },
        {
            "args": {
                "pos_x": 200,
                "pos_y": 100,
                "width": 50,
                "height": 18,
                "title": "D",
            },
            "key": "d",
        },
    ],
    "btn_previous_raw_sample": {
        "args": {
            "pos_x": 10,
            "pos_y": 720,
            "width": 130,
            "height": 18,
            "title": "<- PAGE UP",
        },
        "key": "PAGE_UP",
    },
    "btn_next_raw_sample": {
        "args": {
            "pos_x": 150,
            "pos_y": 720,
            "width": 130,
            "height": 18,
            "title": "PAGE DOWN ->",
        },
        "key": "PAGE_DOWN",
    },
    "btn_load_raw_sample": {
        "args": {
            "pos_x": 300,
            "pos_y": 720,
            "width": 50,
            "height": 18,
            "title": "load",
        },
        "key": "l",
    },
    "btn_toggle_loop": {
        "args": {
            "pos_x": 100,
            "pos_y": 10,
            "width": 60,
            "height": 18,
            "title": "LOOP .",
        },
        "key": "PERIOD",
    },
    "btn_toggle_edit": {
        "args": {
            "pos_x": 180,
            "pos_y": 10,
            "width": 50,
            "height": 18,
            "title": "EDIT -",
        },
        "key": "MINUS",
    },
    "btn_resample": {
        "args": {
            "pos_x": 250,
            "pos_y": 10,
            "width": 90,
            "height": 18,
            "title": "RESAMPLE ,",
        },
        "key": "COMMA",
    },
    "btn_edit_up": {
        "args": {
            "pos_x": 900,
            "pos_y": 700,
            "width": 50,
            "height": 18,
            "title": "UP",
        },
        "key": "UP",
    },
    "btn_edit_down": {
        "args": {
            "pos_x": 900,
            "pos_y": 740,
            "width": 50,
            "height": 18,
            "title": "DOWN",
        },
        "key": "DOWN",
    },
    "btn_edit_left": {
        "args": {
            "pos_x": 850,
            "pos_y": 720,
            "width": 50,
            "height": 18,
            "title": "LEFT",
        },
        "key": "LEFT",
    },
    "btn_edit_right": {
        "args": {
            "pos_x": 950,
            "pos_y": 720,
            "width": 50,
            "height": 18,
            "title": "RIGHT",
        },
        "key": "RIGHT",
    },
}

KEY_PYGAME_KEY_MAPPING = {
    "TAB": pygame.K_TAB,
    "q": pygame.K_q,
    "w": pygame.K_w,
    "e": pygame.K_e,
    "a": pygame.K_a,
    "s": pygame.K_s,
    "d": pygame.K_d,
    "l": pygame.K_l,
    "PAGE_UP": pygame.K_PAGEUP,
    "PAGE_DOWN": pygame.K_PAGEDOWN,
    "PERIOD": pygame.K_PERIOD,
    "MINUS": pygame.K_MINUS,
    "UP": pygame.K_UP,
    "DOWN": pygame.K_DOWN,
    "LEFT": pygame.K_LEFT,
    "RIGHT": pygame.K_RIGHT,
    "COMMA": pygame.K_COMMA,
}

class RawSample:
    def __init__(self, data, samplerate, file_name):
        self.data = data
        self.samplerate = samplerate
        self.file_name = file_name

    def num_frames(self):
        return len(self.data)

class Sample:
    def __init__(self, data, sid=None):
        self._data = data
        if sid is None:
            self.sid = random.randint(0, 9999999)
        else:
            self.sid = sid
        self.frame_start = 0
        self.frame_end = len(self.data)
        self.frame_end_raw = len(self.data)

    @property
    def data(self):
        return self._data

    @property
    def title(self):
        return f"sample_{self.sid}"

class Tape:
    def __init__(self):
        self.sid = random.randint(0, 9999999)
        self.blocks = []

    @property
    def title(self):
        return f"sample_{self.sid}"

    def add_block(self, block):
        self.blocks.append(block)

    def to_sample(self):
        data = np.concatenate(self.blocks)
        sample = Sample(data[:], sid=self.sid)
        return sample

class PlayingSample:
    def __init__(self, sample, loop=False):
        self.sample = sample
        self.loop = loop
        self._main_current_frame = self.sample.frame_start

    def reset(self, loop=None):
        if loop is not None:
            self.loop = loop
        self._main_current_frame = self.sample.frame_start

    def stop(self):
        self._main_current_frame = self.sample.frame_end
        self.loop = False

    def add_block_to(self, block):
        if self.sample.frame_end - self._main_current_frame < OUTPUT_FRAMES_PER_BLOCK:
            if self.loop:
                self._main_current_frame = self.sample.frame_start
            else:
                return

        block += self.sample.data[
            self._main_current_frame : self._main_current_frame + OUTPUT_FRAMES_PER_BLOCK
        ]
        self._main_current_frame += OUTPUT_FRAMES_PER_BLOCK

class SampleCommand(Command):
    pass

class PlaySampleCommand(SampleCommand):
    def execute(self, bid: int, context: dict):
        try:
            sample = context[KEY_SAMPLE_LIB][self.arguments.get(KEY_SID)]
        except KeyError:
            return

        try:
            context[KEY_PLAYING_SAMPLES][sample.sid].reset(self.arguments.get(KEY_LOOP, False))
        except KeyError:
            context[KEY_PLAYING_SAMPLES][sample.sid] = PlayingSample(
                sample, self.arguments.get(KEY_LOOP, False)
            )

class ReleaseSampleCommand(SampleCommand):
    def execute(self, bid: int, context: dict):
        if self.arguments.get(KEY_LOOP, False):
            context[KEY_PLAYING_SAMPLES][self.arguments[KEY_SID]].stop()

class ContextFnCommand(Command):
    def __init__(self, cmd_name, fn, arguments={}):
        self.fn = fn
        super().__init__(cmd_name, arguments)

    def execute(self, bid, context):
        self.fn(bid, context)

class SampleContextFnCommand(SampleCommand, ContextFnCommand):
    pass

class App:

    def __init__(self, sample_dir=SAMPLE_DIR, cfg=APPCFG):
        pygame.init()
        self.cfg = cfg
        self.screen = pygame.display.set_mode((self.cfg["screen_width"], self.cfg["screen_height"]))
        self.keys = {}
        self._main_stream = pa.open(format=FORMAT, channels=CHANNELS, rate=RATE, output=True)
        self._samples = {}
        self._playing_samples = {}

        self._keys_down = []
        self._keys_up = []

        self._buffer = np.zeros((OUTPUT_FRAMES_PER_BLOCK, CHANNELS))

        self._key_code_button = {}
        self.context = {
            "screen": self.screen,
            "font_main": pygame.font.SysFont("arial", 14),
            "font_sub": pygame.font.SysFont("arial", 10),
            "buttons": self._key_code_button,
            KEY_SID_EDIT: None,
            KEY_SID_RESAMPLE: None,
            KEY_RAW_SAMPLE_LIB: [],
            KEY_SAMPLE_LIB: {},
            KEY_PLAYING_SAMPLES: {},
            KEY_SELECTED_RAW_SAMPLE: 0,
            KEY_TRIM_STEP: TRIM_STEP_DEFAULT,
            KEY_EDIT_MODE: 0
        }

        self._load_raw_samples(sample_dir)
        self._construct_buttons()

    def _construct_buttons(self):
        # FN button
        current_btn_cfg = self.cfg["btn_fn"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=Command.cmd_nop(),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])

        # sample buttons
        for current_btn_cfg in self.cfg["btn_sample"]:
            current_btn = ModeButton(
                bid=self.num_buttons,
                cmd_push=PlaySampleCommand("play_sample", {}),
                cmd_release=ReleaseSampleCommand("release_sample", {}),
                **current_btn_cfg["args"]
            )
            self._add_button(current_btn, current_btn_cfg["key"])

        # raw sample navigation
        current_btn_cfg = self.cfg["btn_previous_raw_sample"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=ContextFnCommand("previous_raw_sample", previous_raw_sample),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])
        current_btn_cfg = self.cfg["btn_next_raw_sample"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=ContextFnCommand("next_raw_sample", next_raw_sample),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])
        current_btn_cfg = self.cfg["btn_load_raw_sample"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=ContextFnCommand("load_raw_sample", load_raw_sample),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])
        current_btn_cfg = self.cfg["btn_toggle_loop"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=ContextFnCommand("toggle_loop", toggle_loop),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])
        current_btn_cfg = self.cfg["btn_toggle_edit"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=ContextFnCommand("toggle_edit", toggle_edit),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])
        current_btn_cfg = self.cfg["btn_edit_up"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=ContextFnCommand("toggle_edit", edit_up),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])
        current_btn_cfg = self.cfg["btn_edit_down"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=ContextFnCommand("toggle_edit", edit_down),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])
        current_btn_cfg = self.cfg["btn_edit_left"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=ContextFnCommand("toggle_edit", edit_left),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])
        current_btn_cfg = self.cfg["btn_edit_right"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=ContextFnCommand("toggle_edit", edit_right),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])
        current_btn_cfg = self.cfg["btn_resample"]
        current_btn = ModeButton(
            bid=self.num_buttons,
            cmd_push=ContextFnCommand("toggle_resample", toggle_resample),
            cmd_release=Command.cmd_nop(),
            **current_btn_cfg["args"]
        )
        self._add_button(current_btn, current_btn_cfg["key"])

    def _add_button(self, btn: ModeButton, key_name: str):
        self._key_code_button[KEY_PYGAME_KEY_MAPPING[key_name]] = btn

    @property
    def num_buttons(self):
        return len(self._key_code_button.keys())

    def _load_raw_samples(self, sample_dir):
        for file_name in os.listdir(sample_dir):
            complete_path = os.path.join(sample_dir, file_name)

            data, samplerate = sf.read(complete_path)
            if not samplerate == RATE:
                raise RuntimeError(f"Samplerate of {file_name} is {samplerate}!")
            raw_sample = RawSample(data, samplerate, file_name)
            self.context[KEY_RAW_SAMPLE_LIB].append(raw_sample)
            print(f"loaded {file_name}")

    def _handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                self._keys_down.append(event.key)
            if event.type == pygame.KEYUP:
                self._keys_up.append(event.key)

            if event.type == pygame.QUIT:
                # if it is quit the game
                pygame.quit()
                exit(0)
        return self._keys_down, self._keys_up

    def _print_selected_raw_sample(self):
        text_current_sample = self.context[KEY_RAW_SAMPLE_LIB][
            self.context[KEY_SELECTED_RAW_SAMPLE]
        ].file_name
        text = self.context["font_main"].render(text_current_sample, True, (255, 255, 255))
        self.screen.blit(text, (10, self.cfg["screen_height"] - 30))

    def _print_params(self):
        self._render_text(
            "edit mode: {}".format(EDIT_MODES[self.context.get(KEY_EDIT_MODE)]),
            pos_x=(self.cfg["screen_width"] - PARAM_COL_OFFSET),
            pos_y=10,
        )

        self._render_text(
            "resample sid: {}".format(self.context.get(KEY_SID_RESAMPLE)),
            pos_x=(self.cfg["screen_width"] - PARAM_COL_OFFSET),
            pos_y=40,
        )

        self._render_text(
            "edit sid: {}".format(self.context.get(KEY_SID_EDIT)),
            pos_x=(self.cfg["screen_width"] - PARAM_COL_OFFSET),
            pos_y=70,
        )

        self._render_text(
            "trim step: {}".format(self.context.get(KEY_TRIM_STEP)),
            pos_x=(self.cfg["screen_width"] - PARAM_COL_OFFSET),
            pos_y=100,
        )

        if (
            EDIT_MODES[self.context[KEY_EDIT_MODE]] in (MODE_TRIM_START, MODE_TRIM_END)
            and self.context[KEY_SID_EDIT] is not None
        ):
            sample = self.context[KEY_SAMPLE_LIB][self.context[KEY_SID_EDIT]]
            self._render_text(
                "start: {}".format(sample.frame_start),
                pos_x=(self.cfg["screen_width"] - PARAM_COL_OFFSET),
                pos_y=130,
            )
            self._render_text(
                "end: {}".format(sample.frame_end),
                pos_x=(self.cfg["screen_width"] - PARAM_COL_OFFSET),
                pos_y=160,
            )

    def _render_text(self, text, pos_x, pos_y, color=(255, 255, 255)):
        text_element = self.context["font_main"].render(text, True, (255, 255, 255))
        self.screen.blit(text_element, (pos_x, pos_y))

    def run(self):

        # for i, block in enumerate(sine_gen()):
        while True:

            self.screen.fill((0, 0, 0))
            keys_down, keys_up = self._handle_events()

            for key in keys_down:
                btn = self._key_code_button.get(key, None)
                if btn:
                    btn.push(self.context)
            for key in keys_up:
                btn = self._key_code_button.get(key, None)
                if btn:
                    btn.release(self.context)

            for btn in self._key_code_button.values():
                btn.draw(self.context)

            self._print_selected_raw_sample()
            self._print_params()

            pygame.display.flip()
            self._keys_down.clear()
            self._keys_up.clear()

            self._buffer.fill(0)
            for sample in self.context[KEY_PLAYING_SAMPLES].values():
                sample.add_block_to(self._buffer)

            if self.context[KEY_SID_RESAMPLE] is not None:
                self.context[KEY_SAMPLE_LIB][self.context[KEY_SID_RESAMPLE]].add_block(
                    np.copy(self._buffer)
                )

            data = self._buffer.reshape((OUTPUT_FRAMES_PER_BLOCK * 2, 1)).squeeze(1)
            data = data.astype(np.float32).tostring()
            self._main_stream.write(data)

def button_by_bid(bid, context):
    for btn in context["buttons"].values():
        if btn.bid == bid:
            return btn

def reset_buttons(context):
    for btn in context["buttons"].values():
        btn.reset()

def load_raw_sample(bid, context):
    load_cmd = SampleContextFnCommand("load_into", load_raw_sample_into, arguments={})
    for btn in context["buttons"].values():
        if not isinstance(btn.default_cmd_push, SampleCommand):
            continue

        btn.set_cmd_push(load_cmd)

def toggle_loop(bid, context):
    toggle_cmd = SampleContextFnCommand("toggle_loop", do_toggle_loop, arguments={})
    for btn in context["buttons"].values():
        if not isinstance(btn.default_cmd_push, SampleCommand):
            continue

        btn.set_cmd_push(toggle_cmd)

def toggle_edit(bid, context):

    if context[KEY_SID_EDIT] is not None:
        context[KEY_SID_EDIT] = None
        return

    toggle_cmd = SampleContextFnCommand("toggle_edit", do_toggle_edit, arguments={})
    for btn in context["buttons"].values():
        if not isinstance(btn.default_cmd_push, SampleCommand):
            continue

        btn.set_cmd_push(toggle_cmd)

def toggle_resample(bid, context):

    if context[KEY_SID_RESAMPLE] is not None:
        tape = context[KEY_SAMPLE_LIB][context[KEY_SID_RESAMPLE]]
        context[KEY_SID_RESAMPLE] = None
        sample = tape.to_sample()
        context[KEY_SAMPLE_LIB][sample.sid] = sample
        return

    toggle_cmd = SampleContextFnCommand("toggle_resample", do_toggle_resample, arguments={})
    for btn in context["buttons"].values():
        if not isinstance(btn.default_cmd_push, SampleCommand):
            continue

        btn.set_cmd_push(toggle_cmd)

def load_raw_sample_into(bid, context):
    reset_buttons(context)
    sample = Sample(context[KEY_RAW_SAMPLE_LIB][context[KEY_SELECTED_RAW_SAMPLE]].data[:])
    context[KEY_SAMPLE_LIB][sample.sid] = sample
    btn = button_by_bid(bid, context)
    btn.default_cmd_push.arguments[KEY_SID] = sample.sid
    btn.default_cmd_release.arguments[KEY_SID] = sample.sid

def next_raw_sample(bid, context):
    context[KEY_SELECTED_RAW_SAMPLE] += 1
    if context[KEY_SELECTED_RAW_SAMPLE] >= len(context[KEY_RAW_SAMPLE_LIB]):
        context[KEY_SELECTED_RAW_SAMPLE] = 0

def previous_raw_sample(bid, context):
    context[KEY_SELECTED_RAW_SAMPLE] -= 1
    if context[KEY_SELECTED_RAW_SAMPLE] < 0:
        context[KEY_SELECTED_RAW_SAMPLE] = len(context[KEY_RAW_SAMPLE_LIB]) - 1

def play_sample(bid, context):
    context[KEY_SELECTED_RAW_SAMPLE] -= 1
    if context[KEY_SELECTED_RAW_SAMPLE] < 0:
        context[KEY_SELECTED_RAW_SAMPLE] = len(context[KEY_RAW_SAMPLE_LIB]) - 1

def do_toggle_loop(bid, context):
    reset_buttons(context)
    btn = button_by_bid(bid, context)
    old_value = btn.default_cmd_push.arguments.get(KEY_LOOP, False)
    btn.default_cmd_push.arguments[KEY_LOOP] = not old_value
    btn.default_cmd_release.arguments[KEY_LOOP] = not old_value

def do_toggle_edit(bid, context):
    reset_buttons(context)
    btn = button_by_bid(bid, context)
    context[KEY_SID_EDIT] = btn.default_cmd_push.arguments.get(KEY_SID, None)

def do_toggle_resample(bid, context):
    reset_buttons(context)
    btn = button_by_bid(bid, context)

    # load sample
    tape = Tape()
    context[KEY_SAMPLE_LIB][tape.sid] = tape
    btn.default_cmd_push.arguments[KEY_SID] = tape.sid
    btn.default_cmd_release.arguments[KEY_SID] = tape.sid
    btn.default_cmd_push.arguments[KEY_LOOP] = False
    btn.default_cmd_release.arguments[KEY_LOOP] = False
    context[KEY_SID_RESAMPLE] = tape.sid

def edit_up(bid, context):
    context[KEY_EDIT_MODE] -= 1
    if context[KEY_EDIT_MODE] < 0:
        context[KEY_EDIT_MODE] = len(EDIT_MODES) - 1

def edit_down(bid, context):
    context[KEY_EDIT_MODE] += 1
    if context[KEY_EDIT_MODE] >= len(EDIT_MODES):
        context[KEY_EDIT_MODE] = 0

def edit_left(bid, context):
    if EDIT_MODES[context[KEY_EDIT_MODE]] == MODE_TRIM_STEP:
        context[KEY_TRIM_STEP] -= TRIM_STEP_ADJUST_STEP

        if context[KEY_TRIM_STEP] < 0:
            context[KEY_TRIM_STEP] = 0

    if EDIT_MODES[context[KEY_EDIT_MODE]] == MODE_TRIM_START and context[KEY_SID_EDIT] is not None:
        sample = context[KEY_SAMPLE_LIB][context[KEY_SID_EDIT]]
        sample.frame_start -= context[KEY_TRIM_STEP]
        if sample.frame_start < 0:
            sample.frame_start = 0

    if EDIT_MODES[context[KEY_EDIT_MODE]] == MODE_TRIM_END and context[KEY_SID_EDIT] is not None:
        sample = context[KEY_SAMPLE_LIB][context[KEY_SID_EDIT]]
        sample.frame_end -= context[KEY_TRIM_STEP]
        if sample.frame_end < sample.frame_start:
            sample.frame_end = sample.frame_start

def edit_right(bid, context):
    if EDIT_MODES[context[KEY_EDIT_MODE]] == MODE_TRIM_STEP:
        context[KEY_TRIM_STEP] += TRIM_STEP_ADJUST_STEP

    if EDIT_MODES[context[KEY_EDIT_MODE]] == MODE_TRIM_START and context[KEY_SID_EDIT] is not None:
        sample = context[KEY_SAMPLE_LIB][context[KEY_SID_EDIT]]
        sample.frame_start += context[KEY_TRIM_STEP]
        if sample.frame_start > sample.frame_end:
            sample.frame_start = sample.frame_end

    if EDIT_MODES[context[KEY_EDIT_MODE]] == MODE_TRIM_END and context[KEY_SID_EDIT] is not None:
        sample = context[KEY_SAMPLE_LIB][context[KEY_SID_EDIT]]
        sample.frame_end += context[KEY_TRIM_STEP]
        if sample.frame_end > sample.frame_end_raw:
            sample.frame_end = sample.frame_end_raw

if __name__ == "__main__":
    app = App()
    app.run()


from __future__ import print_function
import sys
import numpy as np
from scipy import stats
import scipy.sparse as sparse
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer

# Base method
class FeatureObjective(object):
    '''
        FeatureObjective: Base class for all other feature-based submodular
                          selection methods.

        Inputs (required): wordlist -- A list of words from which n-gram
                            statistics are extracted. These statistics are then
                            used to select words, from a set
                            (potentially the same) of words in an optimal order
                            according to the submodular objective used.

        Inputs (optional): test_wordlist
                                type: array
                                description: A list of word from which to select
                                default: None
                           n_order
                                type: int
                                description: ngram order
                                default: 4
                           append_ngrams
                                type: bool
                                description: Also use statistics from all lower-order ngrams
                                default: True
                           binarize_counts
                                type: bool
                                description: Count any ngram once per word
                                default: False
                            g
                                type: func
                                description: The submodular function to use
                                default: np.sqrt
                            vectorizer
                                type: str
                                description: Weight applied to ngram counts (tfidf or count)
                                default: 'count'

    '''
    def __init__(self, wordlist, test_wordlist=None, n_order=4,
                append_ngrams=True, binarize_counts=False,
                g=np.sqrt, vectorizer='count'):
        self.wordlist = wordlist

        if not test_wordlist:
            self.test_wordlist = wordlist
        else:
            self.test_wordlist = test_wordlist

        self._ngram_vectorizer = None

        self.n_order = n_order
        self.append_ngrams = append_ngrams
        self.binarize_counts = binarize_counts

        if vectorizer == 'count':
            self.vectorizer = CountVectorizer
        else:
            self.vectorizer = TfidfVectorizer

        self.word_features = None
        self.subset = None
        self.p = None

        self.get_vectorizer()
        self.get_word_features()

    def get_vectorizer(self):
        '''
            Description: Sets a vectorizer which can generate a sparse matrix of counts
                    from a corpus. where each row is a "document" in the corpus,
                    and each column is a feature seen in the corpus self.wordlist
        '''
        min_ngram = self.n_order
        if self.append_ngrams:
            min_ngram = 1
        ngram_range = (min_ngram, self.n_order)

        vectorizer = self.vectorizer(analyzer="char_wb",
                                    encoding="utf-8",
                                    strip_accents='unicode',
                                    ngram_range=ngram_range)

        wordlist = self.test_wordlist
        if not self.test_wordlist:
            wordlist = self.wordlist
        vectorizer.fit(wordlist)
        self._ngram_vectorizer = vectorizer

    def set_subset(self, idxs):
        '''
            Sets the subset (sum of hitherto selected words) to the sum of
            those words in self.wordlist indexed by idxs.

            Input: idxs -- list of indicies into self.test_wordlist
        '''
        self.subset = self.word_features[idxs,:].sum(axis=0)

    def add_to_subset(self, idx):
        '''
            Add to the subset the counts from the word corresponding to the
            single index (idx)

            Input: idx -- index of single entry in self.test_wordlist
        '''
        self.subset += self.word_features[idx, :]

    def run(self, idx_new):
        '''
            Return the submodular objective obtained by the addition of the word
            indexed by idx_new

            Input: idx_new -- the index of a single new word from
                              self.test_wordlist
        '''
        return self._g(self.word_features[idx_new, :] + self.subset).sum()

    def get_word_features(self):
        '''
            Precompute all the word features (ngram statistics basically) for
            the words from both self.wordlist as well as the words in
            self.test_wordlist.
        '''
        wordlist = self.test_wordlist
        if not self.test_wordlist:
            wordlist = self.wordlist

        self.word_features = self._ngram_vectorizer.transform(wordlist)
        train_word_features = self._ngram_vectorizer.transform(self.wordlist)

        if self.binarize_counts:
            train_word_features[train_word_features > 0] = 1.0
            self.word_features[self.word_features > 0 ] = 1.0

        self.total_counts = train_word_features.sum(axis=0)
        self.p = self.total_counts / float(train_word_features.sum())

    def compute_kl(self, lam=0.000001):
        '''
            Compute the KL-Divergence between the feature distribution induced
            by the currently selected subset and the empirical distribution of
            the words in self.wordlist
        '''
        prob_vec = (lam + self.subset) / (float(self.subset.sum()) + lam * self.subset.shape[1])
        #return np.multiply(prob_vec, np.log2(prob_vec + sys.float_info.epsilon) - np.log2(self.p)).sum()
        return np.multiply(self.p, np.log2(self.p + sys.float_info.epsilon) - np.log2(prob_vec + sys.float_info.epsilon)).sum()

# Coverage Method
class FeatureCoverageObjective(FeatureObjective):
    '''
        Modifies the method from Kim 2013 https://www.aclweb.org/anthology/N13-1139.pdf
        to be a submodular function.
    '''

    def __init__(self, *args, **kwargs):
        self.total_counts = None
        self.K = None
        kwargs["binarize_counts"] = True
        super(FeatureCoverageObjective, self).__init__(*args, **kwargs)

    def get_word_features(self):
        super(FeatureCoverageObjective, self).get_word_features()

        test_word_counts = self.word_features.sum()
        self.total_counts = (float(test_word_counts) * self.total_counts) / float(self.total_counts.sum())
        self.K = test_word_counts

    def run(self, idx_new):
        vec = self.subset + self.word_features[idx_new, :]
        p_vec = np.squeeze(np.asarray(self.total_counts))
        vec = np.squeeze(np.asarray(vec))
        # 8.0 is a magic number. Anything in (2, 10) seems to work well.
        return self.K - np.multiply(p_vec, (1.0 / (8.0 ** vec))).sum()


#!/usr/bin/env python3
"""Play some random bleeps.

This example shows the feature of playing a buffer at a given absolute time.
Since all play_buffer() invocations are (deliberately) done at once, this puts
some strain on the "action queue".
The "qsize" has to be increased in order to handle this.

This example also shows that NumPy arrays can be used, as long as they are
C-contiguous and use the 'float32' data type.

"""

from __future__ import division  # Only needed for Python 2.x
import numpy as np
import rtmixer
import sounddevice as sd

seed = 99

device = None
blocksize = 0
latency = 'low'
samplerate = 44100

bleeps = 300
qsize = 512  # Must be a power of 2

attack = 0.005
release = 0.1
pitch_min = 40
pitch_max = 80
duration_min = 0.2
duration_max = 0.6
amplitude_min = 0.05
amplitude_max = 0.15
start_min = 0
start_max = 10
channels = None

if duration_min < max(attack, release):
    raise ValueError('minimum duration is too short')

fade_in = np.linspace(0, 1, num=int(samplerate * attack))
fade_out = np.linspace(1, 0, num=int(samplerate * release))

r = np.random.RandomState(seed)

bleeplist = []

if channels is None:
    channels = sd.default.channels['output']
    if channels is None:
        channels = sd.query_devices(device, 'output')['max_output_channels']

for _ in range(bleeps):
    duration = r.uniform(duration_min, duration_max)
    amplitude = r.uniform(amplitude_min, amplitude_max)
    pitch = r.uniform(pitch_min, pitch_max)
    # Convert MIDI pitch (https://en.wikipedia.org/wiki/MIDI_Tuning_Standard)
    frequency = 2 ** ((pitch - 69) / 12) * 440
    t = np.arange(int(samplerate * duration)) / samplerate
    bleep = amplitude * np.sin(2 * np.pi * frequency * t, dtype='float32')
    bleep[:len(fade_in)] *= fade_in
    bleep[-len(fade_out):] *= fade_out

    # Note: Arrays must be 32-bit float and C contiguous!
    assert bleep.dtype == 'float32'
    assert bleep.flags.c_contiguous
    bleeplist.append(bleep)

with rtmixer.Mixer(device=device, channels=channels, blocksize=blocksize,
                   samplerate=samplerate, latency=latency, qsize=qsize) as m:
    start_time = m.time
    for bleep in bleeplist:
        m.play_buffer(bleep,
                      channels=[r.randint(channels) + 1],
                      start=start_time + r.uniform(start_min, start_max))
    while m.actions:
        sd.sleep(100)
    # TODO: get list of actions and check if all were started on time?
print('{0} buffer underflows in {1} processed audio blocks'.format(
    m.stats.output_underflows, m.stats.blocks))