#!/usr/bin/python
# Reference: see info in help.py;
# this module implements the stress calculation of bow-tie fibers
from __future__ import print_function
import numpy as np
import sys
import pylab as plt

class Stress:
    def __init__(self, x, y, u=None, param=None, blank_outside=True,
                 save=False, debug=False):
        self.debug = debug
        self.blank_outside = blank_outside
        self.u = u # implicit parameter that generates x and y (used for boundary check)

        # we assume x,y are numpy arrays
        self.x = x
        self.y = y
        self.param = param

        a = param['a'] # core radius
        self.a2 = a*a

        self.R2 = x**2 + y**2
        self.R  = np.sqrt(self.R2)
        self.th = np.arctan2(y, x)

        self.cs = np.cos(self.th)
        self.sn = np.sin(self.th)
        self.cs2 = self.cs**2
        self.sn2 = self.sn**2
        self.sncs = self.cs*self.sn

        # initialize
        self.ax_xy1 = None # plot for sigma_x
        self.ax_xy2 = None # plot for sigma_y
        self.ax_xy3 = None # plot for sigma_xy
        self.ax_rt1 = None # plot for sigma_r
        self.ax_rt2 = None # plot for sigma_theta

        self.cbar_xy1 = None # colorbars for each plot above
        self.cbar_xy2 = None
        self.cbar_xy3 = None
        self.cbar_rt1 = None
        self.cbar_rt2 = None

        # regions:
        self.r1 = param['r1']     # bow-tie radius r1
        self.r2 = param['r2']     # bow-tie radius r2
        btr1 = self.r1**2
        btr2 = self.r2**2

        self.w_outside = np.where( self.R2 > 1.0 )
        self.w_clad = np.where( self.R2 <= 1.0 )
        self.w_core = np.where( self.R2 > self.a2 )
        self.w_lt_r1 = np.where( self.R2 < btr1 )
        # give it a little margin...
        self.w_gt_r2 = np.where( np.logical_and(self.R2 > btr2, self.R2<1.05) )
        self.w_between = np.where( np.logical_and(self.R2 >=btr1, self.R2<=btr2) )

        # calculate stress distribution
        self.total(save=save)

        return

    # ----------------------------------------------------
    # we use this to calculate the stress potential contributions from
    # the core
    def core(self):
        # (xc,yc) is the center of the circular SAP region
        # a is the normalized radius (wrt cladding radius)
        xc, yc = 0, 0
        a = self.param['a']
        beta = self.param['beta1']

        x = self.x
        y = self.y
        Dx = (x - xc)
        Dy = (y - yc)
        rr2 = Dx**2 + Dy**2
        th2 = 2.0*np.arctan2(Dy, Dx)
        a2 = a**2

        cs2 = np.cos(th2)
        w = np.where( rr2 > a2 ) # outside core
        sx = -np.ones_like(x)
        sy = -np.ones_like(x)

        sr = -np.ones_like(x) # sigma_r; but r and theta are with respect to (xc,yc), not (0,0)!
        sr[w] = -a2/rr2[w]

        # sx[w] = sr[w] * cs2[w]  # sx[w] = -a2 * cs2[w]/rr2[w]
        # sy[w] = -sx[w]          # sy[w] = a2 * cs2[w]/rr2[w]

        sx[w] = -a2 * cs2[w]/rr2[w]
        sy[w] = a2 * cs2[w]/rr2[w]

        # we also need this to verify the boundary condition is good
        txy = np.zeros_like(x)
        txy[w] = sr[w]*np.sin(th2[w])

        param = self.param
        # multiply by E/(1+nu)*beta*DT/2.0;
        # beta is beta1 or beta3, depending on region
        E  = param['E']    # Young's modulus
        nu = param['nu']   # Poisson's ratio
        DT = -param['DT']   # difference between ambient and glass melting/drawing temperature
        C  = param['C']    # photoelastic coefficient
        # NOTE: we are calculating stress, but scaled to delta n; however
        # delta n is of opposite sign than stress!
        Q  = C*E/(1.0 + nu)*beta*DT/2.0 * 1e4

        sx = Q*sx
        sy = Q*sy
        txy = Q*txy # extra (see above)

        # now calculate sr (sigma_r) and tt (tau_r,theta) wrt to (0,0)
        th = self.th # np.arctan2(y, x)
        cs = self.cs # np.cos(th)
        sn = self.sn # np.sin(th)
        cs2 = self.cs2 # cs**2
        sn2 = self.sn2 # sn**2
        crs = self.sncs # cs*sn

        sr = sx*cs2 + sy*sn2 + 2.0*txy*crs  # sigma_r
        tt = (sy-sx)*np.sin( 2.0*th )/2.0 + txy*np.cos( 2.0*th )

        return sx, sy, txy, sr, tt

    # ----------------------------------------------------------
    # this calculates the stress contribution from the bow-tie SAP
    # regions
    def sap(self):
        header = "bowtie.sap(): "

        sr = np.zeros_like(self.R)
        st = np.zeros_like(self.R)
        tt = np.zeros_like(self.R)

        x = self.x
        y = self.y
        param = self.param
        N = param['N']

        beta3 = param['beta3'] # beta3 - beta2

        r1     = param['r1']     # bow-tie radius r1
        r2     = param['r2']     # bow-tie radius r2
        theta1 = param['theta1'] # bow-tie half-angle

        E     = param['E']     # Young's modulus
        nu    = param['nu']    # Poisson's ratio
        C     = param['C']     # Elasto-optic coefficient
        DT    = -param['DT']   # difference between ambient and glass melting/drawing temperature

        R2 = self.R2 # x**2 + y**2
        R  = self.R  # np.sqrt(R2)
        th = self.th # np.arctan2(y, x)

        r1sq = r1**2
        r2sq = r2**2

        th2 = 2.0*th
        theta_t = th2.copy()
        # NOTE: we keep th2 fixed, and only increment theta_t as we go through summation
        pw1 = 1.0
        pw2 = 1.0
        xth = theta1t = theta1*2

        fact_cos = np.zeros_like(x)
        fact_sin = np.zeros_like(x)
        xp1      = np.zeros_like(x)
        xp2      = np.zeros_like(x)

        # round one: r < r1 ...................................................
        w = self.w_lt_r1
        # for n == 1:
        tmp = -(np.log(r2) - np.log(r1)) * np.sin(xth)
        sr[w] = sr[w] + tmp * np.cos(th2[w])
        tt[w] = tt[w] - tmp * np.sin(th2[w])

        for n in range(2,N+1):
            # prep
            theta_t = theta_t + th2 # $2 n \theta$
            xth = xth + theta1t     # $2 n \theta_1$
            pw1 /= r1sq # $1/r_1^{2(n-1)}$
            pw2 /= r2sq # $1/r_2^{2(n-1)}$

            # calc
            mm = 0.5*(2*n-1)/float( n*(n-1) )
            common = mm*(pw2-pw1)*np.sin( xth )     # $(r_2^{2(n+1)} - r_1^{2(n+1)}) \sin( 2n\theta_1 )$
            fact_cos[w] = common* np.cos( theta_t[w] ) # $\cos(2 n \theta)$
            fact_sin[w] = common* np.sin( theta_t[w] ) # $\sin(2 n \theta)$

            xp1[w] = R2[w]**(n-1)

            sr[w] = sr[w] + fact_cos[w] *xp1[w]
            tt[w] = tt[w] - fact_sin[w] *xp1[w]

        st[w] = -sr[w] # note: r<r1 is outside the "source"

        # round two: r > r2 ...................................................
        w = self.w_gt_r2
        tmp = np.ones_like(x)
        tmp[w] = theta1*(r2sq-r1sq)/R2[w]
        sr[w] = sr[w] - tmp[w]
        st[w] = st[w] + tmp[w]

        theta_t = th2.copy()
        pw1 = r1sq
        pw2 = r2sq
        xth = theta1t = theta1*2

        for n in range(1,N+1):
            pw1 *= r1sq # $r_1^{2(n+1)}$
            pw2 *= r2sq # $r_2^{2(n+1)}$

            mm = 0.5*(2*n+1)/float( n*(n+1) )
            common = mm*(pw2-pw1)*np.sin( xth )     # $(r_2^{2(n+1)} - r_1^{2(n+1)}) \sin( 2n\theta_1 )$
            fact_cos[w] = common* np.cos( theta_t[w] ) # $\cos(2 n \theta)$
            fact_sin[w] = common* np.sin( theta_t[w] ) # $\sin(2 n \theta)$

            xp1[w] = 1.0/R2[w]**(n+1)

            sr[w] = sr[w] - fact_cos[w] *xp1[w]
            tt[w] = tt[w] - fact_sin[w] *xp1[w]

            # next round
            theta_t = theta_t + th2 # $2 n \theta$
            xth = xth + theta1t     # $2 n \theta_1$

        st[w] = -sr[w] # note r>r2 is outside the "source"

        # round thre: r1 < r < r2 ...................................................
        w = self.w_between
        sr[w] = sr[w] + theta1*( r1sq/R2[w] -1.0 )
        st[w] = st[w] - theta1*( r1sq/R2[w] +1.0 )

        theta_t = th2.copy()
        pw1 = r1sq
        pw2 = 1.0/r2sq
        xth = theta1t = theta1*2

        # for n == 1:
        sr[w] = sr[w] - ( np.log(r2)-np.log(R[w]) + 0.75*(1-r1**4/R2[w]**2) ) * np.sin(xth) * np.cos( th2[w] )
        st[w] = st[w] + ( np.log(r2)-np.log(R[w]) - 1.25 - 0.75 * r1**4/R2[w]**2 ) * np.sin(xth) * np.cos( th2[w] )
        tt[w] = tt[w] + ( np.log(r2)-np.log(R[w]) - 0.75*(1-r1**4/R2[w]**2) ) * np.sin(xth) * np.sin( th2[w] )

        for n in range(2,N+1):
            # prep
            theta_t = theta_t + th2 # $2 n \theta$
            xth = xth + theta1t     # $2 n \theta_1$

            pw1 *= r1sq # $r_1^{2(n+1)}$
            pw2 *= r2sq # $1/r_2^{2(n+1)}$

            xp1[w] = 1.0/R2[w]**(n+1)
            xp2[w] = R2[w]**(n-1)

            common = np.sin( xth ) # $\sin( 2n\theta_1 )$
            fact_cos[w] = common* np.cos( theta_t[w] ) # $\sin( 2n\theta_1 ) \cos(2 n \theta)$
            fact_sin[w] = common* np.sin( theta_t[w] ) # $\sin( 2n\theta_1 ) \sin(2 n \theta)$

            m11 = float( 2*n**2-1 )/float( n*(n**2 - 1) )
            m12 = -float(2*n+1)/float( 2*n*(n+1) )
            m13 = -float(2*n-1)/float( 2*n*(n-1) )

            m21 = 1.0/float(n*n**2-1)
            m22 = m12 # -float(2*n+1)/float( 2*n*(n+1) )
            m23 = m13 # -float(2*n-1)/float( 2*n*(n-1) )

            m31 = m21  # 1.0/float(n*n**2-1)
            m32 = -m12 # float(2*n+1)/float( 2*n*(n+1) )
            m33 = m13  # -float(2*n-1)/float( 2*n*(n-1) )

            sr[w] = sr[w] - (m11 + m12*pw1*xp1[w] + m13*pw2*xp2[w])* fact_cos[w]
            st[w] = st[w] + (m21 + m22*pw1*xp1[w] + m23*pw2*xp2[w])* fact_cos[w]
            tt[w] = tt[w] + (m31 + m32*pw1*xp1[w] + m33*pw2*xp2[w])* fact_sin[w]

        # NOTE: we are calculating stress, but scaled to delta n; however
        # delta n is of opposite sign than stress!
        Q  = C*E*DT/(1.0 + nu) * beta3/np.pi * 1e4
        sr = sr * Q
        st = st * Q
        tt = tt * Q

        # convert to x y components
        cs = self.cs # np.cos(th)
        sn = self.sn # np.sin(th)
        cs2 = self.cs2 # cs**2
        sn2 = self.sn2 # sn**2

        tmp = tt*2.0*self.sncs

        sx  = sr*cs2 + st*sn2 - tmp
        sy  = sr*sn2 + st*cs2 + tmp
        txy = (sr-st)*self.sncs + tt*(cs2 - sn2)

        return sx, sy, txy, sr, tt

    # ----------------------------------------------------
    # we use this to calculate the Airy stress function contribution
    def airy(self):
        # x,y are numpy arrays;
        # N is the order at which we truncate the sum
        # all dimensions normalized wrt cladding radius
        header = "bowtie.airy(): "

        x = self.x
        y = self.y
        param = self.param
        N = param['N']

        beta1 = param['beta1'] # beta1 - beta2
        beta3 = param['beta3'] # beta3 - beta2
        a     = param['a']     # core radius

        r1     = param['r1']     # bow-tie radius r1
        r2     = param['r2']     # bow-tie radius r2
        theta1 = param['theta1'] # bow-tie half-angle

        E     = param['E']     # Young's modulus
        nu    = param['nu']    # Poisson's ratio
        C     = param['C']     # Elasto-optic coefficient
        DT    = -param['DT']   # difference between ambient and glass melting/drawing temperature

        R2 = self.R2 # x**2 + y**2
        R  = self.R  # np.sqrt(R2)
        th = self.th # np.arctan2(y, x)

        sr = np.ones_like(x)  # sigma_r
        st = np.ones_like(x)  # sigma_theta
        tt = np.zeros_like(x) # tau_r,theta = sigma_r,theta

        r1sq = r1**2
        r2sq = r2**2
        th2 = 2.0*th
        theta_t = th2.copy()
        pw1 = r1sq
        pw2 = r2sq
        xth = theta1t = theta1*2

        tmp = theta1*(r2sq - r1sq)
        sr *= tmp
        st *= tmp

        for n in range(1,N+1):
            pw1 *= r1sq # $r_1^{2(n+1)}$
            pw2 *= r2sq # $r_2^{2(n+1)}$

            common = (pw2-pw1)*np.sin( xth )     # $(r_2^{2(n+1)} - r_1^{2(n+1)}) \sin( 2n\theta_1 )$
            fact_cos = common* np.cos( theta_t ) # $\cos(2 n \theta)$
            fact_sin = common* np.sin( theta_t ) # $\sin(2 n \theta)$

            m11 = float(4*n*n - 1)/float(2*n*(n+1))
            m12 = -float((n-1)*(2*n+1))/float( n*(n+1) )

            m21 = m11
            m22 = -float(2*n+1)/n

            m31 = m11
            m32 = -float(2*n+1)/(n+1)

            xp1 = R2**(n-1)
            xp2 = R2**n

            sr = sr + (m11*xp1 + m12*xp2)*fact_cos
            st = st - (m21*xp1 + m22*xp2)*fact_cos
            tt = tt - (m31*xp1 + m32*xp2)*fact_sin

            # next round
            theta_t = theta_t + th2 # $2 n \theta$
            xth = xth + theta1t     # $2 n \theta_1$

        # NOTE: we are calculating stress, but scaled to delta n; however
        # delta n is of opposite sign than stress!
        Q = C*E*DT/(1+nu) * 1e4
        ff = beta3/np.pi
        gg = 0.5*beta1*a*a

        sr = Q*( ff*sr + gg )
        st = Q*( ff*st + gg )
        tt = Q*( ff*tt )

        # convert to x y components
        cs = self.cs # np.cos(th)
        sn = self.sn # np.sin(th)
        cs2 = self.cs2 # cs**2
        sn2 = self.sn2 # sn**2
        # cr2 = 2.0*self.sncs # 2.0*cs*sn

        # components in cylindrical coordinates
        self.sr_a = sr # $\sigma_r$
        self.tt_a = tt # $\tau_{r,\theta} = \sigma_{r,\theta}$
        self.st_a = st # $\sigma_\theta$

        # convert to components in rectangular coordinates
        tmp = tt*2.0*self.sncs

        self.sx_a = sr*cs2 + st*sn2 - tmp
        self.sy_a = sr*sn2 + st*cs2 + tmp
        self.txy_a = (sr-st)*self.sncs + tt*(cs2 - sn2)

        return

    # ----------------------------------------------------
    # all all stress contributions
    def total(self, save=False):
        # total stress: contributions from the core, the SAP's, and the Airy function
        header = "stress.total(): "

        x = self.x
        y = self.y
        param = self.param
        N = param['N']
        blank_outside=self.blank_outside

        print( header," calculate core contribution" ) # ------------------------------------
        sys.stdout.flush()
        xc = 0.0
        yc = 0.0
        # param['beta'] = param['beta1']
        sx_core, sy_core, txy_core, sr_core, tt_core = self.core()

        print( header," calculate bow-tie SAP contribution" ) # ------------------------------------
        sys.stdout.flush()

        # print( header," SAP center ",param['d2']," radius ",param['d1'] )
        xc = param['d2']
        yc = 0.0
        sx_sap, sy_sap, txy_sap, sr_sap, tt_sap = self.sap()

        # ------------------------------------
        print( header," calculate Airy stress function (background), N=", N )
        sys.stdout.flush()
        self.airy()
        # results: self.sx_a, self.sy_a, self.sr_a, self.tt_a, self.st_a

        print( header," calculate total" ) # ------------------------------------
        sys.stdout.flush()
        sx  = sx_core + sx_sap + self.sx_a
        sy  = sy_core + sy_sap + self.sy_a
        txy = txy_core + txy_sap + self.txy_a

        self.sr = sr_core + sr_sap + self.sr_a
        self.tt = tt_core + tt_sap + self.tt_a

        # blank outside
        if blank_outside:
            # w = np.where( self.R2 > 1.0 )
            w = self.w_outside
            sx[w] = 0.0
            sy[w] = 0.0
            self.sr[w] = 0.0
            self.tt[w] = 0.0

        # clip sx,sy,txy values to +/- 3 sigma
        if blank_outside:
            mu    = np.mean( sx[self.w_clad] )
            sigma = np.std(  sx[self.w_clad] )
            vmin = mu - 3*sigma
            vmax = mu + 3*sigma
            w = np.where( sx > vmax )
            sx[w] = vmax
            w = np.where( sx < vmin )
            sx[w] = vmin

            mu    = np.mean( sy[self.w_clad] )
            sigma = np.std(  sy[self.w_clad] )
            vmin = mu - 3*sigma
            vmax = mu + 3*sigma
            w = np.where( sy > vmax )
            sy[w] = vmax
            w = np.where( sy < vmin )
            sy[w] = vmin

            mu    = np.mean( txy[self.w_clad] )
            sigma = np.std(  txy[self.w_clad] )
            vmin = mu - 3*sigma
            vmax = mu + 3*sigma
            w = np.where( txy > vmax )
            txy[w] = vmax
            w = np.where( txy < vmin )
            txy[w] = vmin

        vmin = sx.min()
        tmp  = sy.min()
        if vmin > tmp:
            vmin = tmp

        vmax = sx.max()
        tmp  = sy.max()
        if vmax < tmp:
            vmax = tmp

        # clip sr, tt to +/- 3 sigma (ignoring st)
        if blank_outside:
            mu    = np.mean( self.sr[self.w_clad] )
            sigma = np.std(  self.sr[self.w_clad] )
            vmin = mu - 3*sigma
            vmax = mu + 3*sigma
            w = np.where( self.sr > vmax )
            self.sr[w] = vmax
            w = np.where( self.sr < vmin )
            self.sr[w] = vmin

            mu    = np.mean( self.tt[self.w_clad] )
            sigma = np.std(  self.tt[self.w_clad] )
            vmin = mu - 3*sigma
            vmax = mu + 3*sigma
            w = np.where( self.tt > vmax )
            self.tt[w] = vmax
            w = np.where( self.tt < vmin )
            self.tt[w] = vmin

        vmin2 = self.sr.min()
        vmin3 = self.tt.min()

        vmax2 = self.sr.max()
        vmax3 = self.tt.max()

        # ... again...
        if blank_outside:
            w = self.w_outside
            sx[w] = vmin
            sy[w] = vmin
            self.sr[w] = vmin2
            self.tt[w] = vmin3

        self.vmin = vmin
        self.vmax = vmax

        self.vmin_r = vmin2
        self.vmax_r = vmax2

        self.vmin_t = vmin3
        self.vmax_t = vmax3

        print( header," clipped x-y val range ",vmin," to ",vmax )
        print( header," clipped r val range ",vmin2," to ",vmax2 )
        print( header," clipped t val range ",vmin3," to ",vmax3 )
        sys.stdout.flush()

        self.sx = sx
        self.sy = sy
        self.txy = txy

        if save:
            print( header," saving snapshot...." )
            np.save("snapshot", (self.sx, self.sy, self.txy))

        #  sx, sy, sr, tt, sr_a, tt_a, vmin, vmax
        return

    #---------------------------------------------------------
    def plot_bc(self, ax=None):
        if ax == None:
            return

        ax.cla()
        ax.set_xlabel(r'$\theta/\pi$')
        ax.set_ylabel(r'Birefringence ($\times 10^{-4}$)')

        ax.set_title("Birefringence along cladding boundary (with N=%d Airy stress function terms)" % self.param['N'])
        ax.plot(self.u, self.sr, label=r'$\sigma_r$')
        ax.plot(self.u, self.tt, label=r'$\sigma_{r\theta}$')
        ax.legend( loc='best' )

        ax.plot(self.u, self.sr_a, label=r'$\sigma_r$ (Airy)')
        ax.plot(self.u, self.tt_a, label=r'$\sigma_{r\theta}$ (Airy)')
        ax.legend( loc='best' )
        ax.figure.canvas.draw()

        return

    #---------------------------------------------------------
    def clear_xy_colorbars(self):
        if self.ax_xy1 != None:
            self.ax_xy1.figure.delaxes( self.cbar_xy1.ax )
            self.ax_xy1.figure.subplots_adjust(right=0.90)

        if self.ax_xy2 != None:
            self.ax_xy2.figure.delaxes( self.cbar_xy2.ax )
            self.ax_xy2.figure.subplots_adjust(right=0.90)

        if self.ax_xy3 != None:
            self.ax_xy3.figure.delaxes( self.cbar_xy3.ax )
            self.ax_xy3.figure.subplots_adjust(right=0.90)

        return

    def clear_rt_colorbars(self):
        if self.ax_rt1 != None:
            self.ax_rt1.figure.delaxes( self.cbar_rt1.ax )
            self.ax_rt1.figure.subplots_adjust(right=0.90)

        if self.ax_rt2 != None:
            self.ax_rt2.figure.delaxes( self.cbar_rt2.ax )
            self.ax_rt2.figure.subplots_adjust(right=0.90)

        return

    #---------------------------------------------------------
    def plot_xy(self, ax1=None, ax2=None, ax3=None, plotdn=True):
        rext = 1.1 # fixed
        mycmap = plt.cm.coolwarm
        # mycmap = plt.cm.afmhot
        # mycmap = plt.cm.jet

        param = self.param

        if plotdn:
            # parameters for calculating dn;
            # we divide by C because all stresses are already normalized by C
            AA = (param['C1'] + param['nu'] * param['C2']) / param['C']
            BB = (param['C2'] * ( 1.0 + param['nu'] )) / param['C']
            XSURF = np.zeros_like(self.x)
            YSURF = np.zeros_like(self.x)

            XSURF[self.w_clad] = -AA*self.sx[self.w_clad] - BB*self.sy[self.w_clad]
            YSURF[self.w_clad] = -BB*self.sx[self.w_clad] - AA*self.sy[self.w_clad]
            vmin = XSURF.min()
            tmp = YSURF.min()
            if tmp < vmin:
                vmin = tmp
            vmax = XSURF.max()
            tmp = YSURF.max()
            if tmp > vmax:
                vmax = tmp

            XSURF[self.w_outside] = vmin
            YSURF[self.w_outside] = vmin

            title_x = r'$\Delta n_x \times 10^{-4}$'
            title_y = r'$\Delta n_y \times 10^{-4}$'
        else:
            XSURF = self.sx
            YSURF = self.sy
            vmin = self.vmin
            vmax = self.vmax
            title_x = r'$\sigma_x$ stress (scaled to $\Delta n \times 10^{-4}$)'
            title_y = r'$\sigma_y$ stress (scaled to $\Delta n \times 10^{-4}$)'

        TSURF = np.zeros_like(self.x)
        TSURF[self.w_clad] = self.txy[self.w_clad]
        tmin = TSURF.min()
        tmax = TSURF.max()
        TSURF[self.w_outside] = tmin

        # ............ now plot ............................
        if ax1 != None:
            self.ax_xy1 = ax1
            ax1.cla()

            ax1.set_title(title_x)
            ax1.set_xlim(-rext,rext)
            ax1.set_ylim(-rext,rext)
            cax1 = ax1.pcolor(self.x, self.y, XSURF, cmap=mycmap, vmin=vmin, vmax=vmax )
            self.cbar_xy1 = ax1.figure.colorbar( cax1, ax=ax1, shrink=0.6, use_gridspec=False )
            ax1.figure.canvas.draw()

        if ax2 != None:
            self.ax_xy2 = ax2
            ax2.cla()

            ax2.set_title(title_y)
            ax2.set_xlim(-rext,rext)
            ax2.set_ylim(-rext,rext)
            cax2 = ax2.pcolor(self.x, self.y, YSURF, cmap=mycmap, vmin=vmin, vmax=vmax )
            self.cbar_xy2 = ax2.figure.colorbar( cax2, ax=ax2, shrink=0.6, use_gridspec=False )
            ax2.figure.canvas.draw()

        if ax3 != None:
            self.ax_xy3 = ax3
            ax3.cla()

            ax3.set_title(r'$\sigma_{xy}$ stress (scaled to $\Delta n \times 10^{-4}$)')
            ax3.set_xlim(-rext,rext)
            ax3.set_ylim(-rext,rext)
            cax3 = ax3.pcolor(self.x, self.y, TSURF, cmap=mycmap, vmin=tmin, vmax=tmax )
            self.cbar_xy3 = ax3.figure.colorbar( cax3, ax=ax3, shrink=0.6, use_gridspec=False )
            ax3.figure.canvas.draw()

        return

    #---------------------------------------------------------
    def plot_rt(self, ax1=None, ax2=None,
               vmin=None, vmax=None):
        rext = 1.1 # fixed
        mycmap = plt.cm.coolwarm
        # mycmap = plt.cm.afmhot
        # mycmap = plt.cm.jet

        if ax1 != None:
            self.ax_rt1 = ax1
            ax1.cla()

            if vmin == None:
                vmin = self.vmin_r
            if vmax == None:
                vmax = self.vmax_r

            ax1.set_title(r'$\sigma_r$ stress (scaled to $\Delta n \times 10^{-4}$)')
            ax1.set_xlim(-rext,rext)
            ax1.set_ylim(-rext,rext)
            cax1 = ax1.pcolor(self.x, self.y, self.sr, cmap=mycmap, vmin=vmin, vmax=vmax )
            self.cbar_rt1 = ax1.figure.colorbar( cax1, ax=ax1, shrink=0.8, use_gridspec=False )
            ax1.figure.canvas.draw()

        if ax2 != None:
            self.ax_rt2 = ax2
            ax2.cla()

            if vmin == None:
                vmin = self.vmin_t
            if vmax == None:
                vmax = self.vmax_t

            ax2.set_title(r'$\sigma_{r\theta}$ stress (scaled to $\Delta n \times 10^{-4}$)')
            ax2.set_xlim(-rext,rext)
            ax2.set_ylim(-rext,rext)
            cax2 = ax2.pcolor(self.x, self.y, self.tt, cmap=mycmap, vmin=vmin, vmax=vmax )
            self.cbar_rt2 = ax2.figure.colorbar( cax2, ax=ax2, shrink=0.8, use_gridspec=False )
            ax2.figure.canvas.draw()

        return

# =======================================
if __name__ == '__main__':
    print( "Test with test_bowtie.py" )


import json

class BestValueLogger:
    """
    Logs the best value and step for a dictionary of metrics.
    """
    def __init__(self, metrics: dict, log_step: bool = True):
        """
        names: dict with keys: metric names, values: bool whether the metric is increasing (larger is better)
        log_step: bool, if True also logs the best step for each metric that is tracked as "best_<metric>_step"
        Example:
        names = {'val_loss': False, 'val_auroc: True}
        """
        self.metrics = metrics
        self.log_step = log_step
        self.suffices = ['value', 'step'] if log_step else ['value']

        #self.increasing = dict(zip(names, increasing))
        self.best_values = {'_'.join(['best', name, suffix]):
                None for name in metrics.keys() for suffix in self.suffices}

    def __call__(self, values: list, step: int):
        """
        We assume that values refer to the names at init
        """
        assert len(values) == len(self.metrics)
        data = dict(zip(self.metrics.keys(), values))

        for name, value in data.items():
            self._update_metric(name, value, step)

    def _update_metric(self, name, value, step):
        """
        Check if current value is better than best before, if yes, update.
        """
        larger_better = int(self.metrics[name]) # convert bool to int
        larger_better = 2*larger_better - 1 # convert [1,0] to [1,-1]
        old_value = self.best_values[
            '_'.join(['best', name, 'value'])
        ]
        # init if empty at start:
        if old_value is None:
            old_value = 1e10 * (-larger_better)
        if larger_better * (value - old_value) > 0:
            for key_name, key in zip(['value','step'], [value, step]):
                if key_name in self.suffices:
                    key_name = '_'.join(['best', name, key_name])
                    self.best_values[key_name] = key
        return self

    def __repr__(self):
        m_dict = json.dumps(self.metrics, indent=4)
        v_dict = json.dumps(self.best_values, indent=4)
        step_str = ' and steps' if self.log_step else ''
        rep = [
            '::BestValueLogger:: ',
            'Tracking the best values of the following metrics:',
            f'{m_dict}',
            '(key: metric, value: bool if larger is better)',
            f'Best values{step_str}:',
            f'{v_dict}'
        ]
        return '\n'.join(rep)


# !/usr/anaconda3/bin python
# -*-coding:utf-8-*-
"""
@Project        :   project_manage
@FileName       :   urls.py
@Author         :   tangchaolizi
@Datetime       :   2020-06-16 13:04
@Software       :   PyCharm
@Show           :
"""
from django.conf.urls import url, include
from rest_framework import routers
from .views import *

router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'role', RoleViewSet)
router.register(r'userrole', UserRoleViewSet)
router.register(r'questioninfo', QuestionInfoViewSet)
router.register(r'optioninfo', OptionInfoViewSet)
router.register(r'examinationinfo', ExaminationInfoViewSet)
router.register(r'examinationinfoquestioninfoprofile', ExaminationInfoQuestionInfoProfileViewSet)

app_name = 'api'
urlpatterns = [
    url(r'^', include(router.urls)),
]


import orjson as orjson
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from sqlmodel import SQLModel
from sqlmodel.ext.asyncio.session import AsyncSession

from scr.backend.settings import settings

DATABASE_URL = settings.db_url

engine = create_async_engine(
    settings.db_url,
    echo=settings.db_echo,
    pool_size=settings.db_pool_size,
    pool_recycle=settings.db_pool_recycle,
    max_overflow=settings.db_max_overflow,
    pool_pre_ping=settings.db_pool_pre_ping,
    json_serializer=orjson.dumps,
    json_deserializer=orjson.loads,
    query_cache_size=settings.db_query_cache_size,
    pool_use_lifo=True,
    future=True,
)

async def init_db():
    async with engine.begin() as conn:
        await conn.run_sync(SQLModel.metadata.create_all)

async def get_session() -> AsyncSession:
    async_session = sessionmaker(
        engine, class_=AsyncSession, expire_on_commit=False
    )
    async with async_session() as session:
        yield session


"""
Author: FurWaz
https://furwaz.github.io/

This module contains the Screen element, that is used to create the Window
but also used to store the current displayed scene, get the events, update and draw the scene.
"""
from engine.gameconst import Constants
from typing import Any, Iterable
from engine.gamegraphs import GraphElement
from engine.gametypes import pygame, Vec2, Color

class Screen:
    dim = Vec2()
    dt = 0.016
    scene=None
    sceneCode=0
    monitorDims = Vec2()
    RES = [Vec2(640, 360), Vec2(1280, 720), Vec2(1600, 900), Vec2(1920, 1080), Vec2(2560, 1440)]
    RES_INDEX = 0
    def __init__(self, pos:Vec2=Vec2(), dim:Vec2=Vec2(640, 360), t:str="Title", i:GraphElement=GraphElement(), fps:int=60, fullscreen:bool=False) -> None:
        Screen.dim = dim
        Screen.dt = 0.016
        displayDims = pygame.display.Info()
        Screen.monitorDims = Vec2(displayDims.current_w, displayDims.current_h)
        self.fullscreen = fullscreen
        self.clock = pygame.time.Clock()
        self.pos = pos
        self.title = t
        self.icon = i
        self.fps = fps
        self.openWindow()
        self.surface = pygame.display.get_surface()
        self.isOpen = True

    def changeRes(self) -> None:
        if self.fullscreen: return
        Screen.RES_INDEX = (Screen.RES_INDEX+1) % len(Screen.RES)
        newRes = Screen.RES[Screen.RES_INDEX]
        self.setDimTo(newRes)

    def setIcon(self, i:GraphElement=None) -> None:
        if i == None: return
        pygame.display.set_icon(pygame.transform.scale(i.data, (32, 32)))

    def setTitle(self, t:str="Title") -> None:
        pygame.display.set_caption(t)

    def toogleFullscreen(self) -> None:
        self.fullscreen = not self.fullscreen
        self.openWindow()

    def setDimAndPos(self, dim:Vec2=Vec2(), pos:Vec2=Vec2()) -> None:
        Screen.dim = dim
        self.pos = pos
        self.resizeWindow()

    def setPosTo(self, pos:Vec2=Vec2()) -> None:
        self.pos = pos
        self.moveWindow()

    def changePosBy(self, delta:Vec2=Vec2()) -> None:
        self.pos = self.pos+delta
        self.moveWindow()

    def changeDimBy(self, delta:Vec2=Vec2()) -> None:
        Screen.dim = Screen.dim+delta
        self.resizeWindow()

    def setDimTo(self, dim:Vec2=Vec2()) -> None:
        Screen.dim = dim
        self.resizeWindow()

    def getEvents(self) -> Iterable[pygame.event.Event]:
        events = []
        if Screen.scene.askForQuit: self.closeWindow(); return []
        if Screen.scene.askForChangeRes: self.changeRes()
        if Screen.scene.askForFullscreen: self.toogleFullscreen(); self.scene.askForFullscreen = False
        for e in pygame.event.get():
            if e.type == pygame.QUIT: self.closeWindow()
            elif e.type == pygame.VIDEORESIZE:
                Screen.dim = Vec2(e.w, e.h)
                self.resizeWindow()
            else: events.append(e)
        return events

    def openWindow(self) -> None:
        self.moveWindow()
        self.resizeWindow()
        pygame.display.set_caption(self.title)
        pygame.display.set_icon(pygame.transform.scale(self.icon.data, (32, 32)))

    def moveWindow(self) -> None:
        #os.environ['SDL_VIDEO_WINDOW_POS'] = str(self.pos.x)+","+str(self.pos.y)
        #os.environ['SDL_VIDEO_CENTERED'] = "0"
        self.resizeWindow()

    def resizeWindow(self) -> None:
        if self.fullscreen: pygame.display.set_mode(Screen.monitorDims.toTuple(), pygame.FULLSCREEN)
        else: pygame.display.set_mode(Screen.RES[Screen.RES_INDEX].toTuple())
        Constants.FULLSCREEN = self.fullscreen
        Constants.RESOLUTION.fromTuple(pygame.display.get_surface().get_size())
        pygame.display.set_icon(pygame.transform.scale(self.icon.data, (32, 32)))
        try: Screen.scene.reloadScene()
        except: pass

    def closeWindow(self) -> None:
        self.isOpen = False;
        pygame.display.quit()

    def clear(self, color:Color=Color(0,0,0)) -> None:
        if not self.isOpen: return
        self.surface.fill(color.toTuple())

    def drawElement(self, element:GraphElement=None) -> None:
        if element == None: return
        if not self.isOpen: return
        self.surface.blit(element.data, element.pos.toTuple())

    def drawScene(self, scene:Any=None) -> None:
        if scene == None: return
        if not self.isOpen: return
        if scene.world != None:
            self.surface.blit(scene.world.data, (0, 0))
        if scene.player != None:
            self.surface.blit(scene.player.graph.data, (scene.player.graph.pos-scene.player.graph.dim/2).toTuple())
        for el in scene.hud.objects:
            self.surface.blit(el.data, (el.pos-el.dim/2).toTuple())

    def update(self) -> None:
        if not self.isOpen: return
        Screen.dt = self.clock.tick(self.fps) / 1000
        pygame.display.flip()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Jan  2 21:12:56 2022

@author: marijn

This script plots zernike polynomials from Mathematica script in same folder

In the mathematica file, the trig relation is Taylor expanded in 2nd and 4th
order terms in terms of the angle
"""

# %%imports

import numpy as np
import matplotlib.pyplot as plt

#%% variables

wavelength = 820e-9
k = 2 * np.pi / wavelength
n0 = 1
NA = 0.5

# Mitutoyo corrected for plate of
ncorr = 1.5105
dcorr = 3.5e-3

# our glass plate
nquartz = 1.453
dplate = 4e-3

#%% calculations

# angle variable
t = np.linspace(0, np.arcsin(NA), 101)
rho = np.linspace(0, 1, 101)

# path length difference because of 4 mm glass 1.453, not corrected
wavesGlass = 450.859 * t**2 + 122.595 * t**4

# path length difference after correction mitutoyo subtracted
wavesCorrected = 45.9178 * t**2 + 23.1342 * t**4

Z04 = 23.1342 * (np.arcsin(NA * 1))**4
Z04polynomial = Z04 / 6 * (1 - 6 * rho**2 + 6 * rho**4)

#%% plotting, saving

fig, (ax1, ax2, ax3) = plt.subplots(ncols = 3,
                               nrows = 1,
                               tight_layout = True,
                               figsize = (8, 3))

ax1.plot(t, wavesGlass, label = r'full aberration')
ax2.plot(t, wavesCorrected, label = r'mismatch $\delta \phi$')
ax3.plot(rho, Z04polynomial, label = r'only $R_4^0$')

# shared y axis labels
ax1.set_ylabel(r'$\phi(\alpha_0)/2\pi$', usetex = True)

# x labels
ax1.set_xlabel(r'$\alpha_0$ [rad]', usetex = True)
ax2.set_xlabel(r'$\alpha_0$ [rad]', usetex = True)
ax3.set_xlabel(r'$r^{\prime}/R$', usetex = True)

# legend
ax1.legend(loc = 'upper center')
ax2.legend(loc = 'upper center')
ax3.legend(loc = 'upper center')

# annotate
ax1.annotate("(a)", xy = (0.455, -0.3), xycoords = "axes fraction", fontweight = 'bold', fontsize = 9)
ax2.annotate("(b)", xy = (0.455, -0.3), xycoords = "axes fraction", fontweight = 'bold', fontsize = 9)
ax3.annotate("(c)", xy = (0.455, -0.3), xycoords = "axes fraction", fontweight = 'bold', fontsize = 9)

plt.savefig('exports/SphericalAberrationTerms.pdf',
            pad_inches = 0,
            bbox_inches = 'tight',
            dpi = 300)


from pymongo import MongoClient
from flask import Flask, render_template, jsonify, request
import math
app = Flask(__name__)

client = MongoClient('localhost', 27017)
db = client.dbsparta

@app.route('/')
def home():
    return render_template('index.html')

# API 역할을 하는 부분
@app.route('/api/list', methods=['GET'])
def writer_list() :
    page = request.args.get('page')
    sort = request.args.get('sort')
    PAGE_SIZE = 30
    START_IDX = PAGE_SIZE * (int(page) - 1)
    total_count = len(list(db.writer.find({},{'_id':False})))
    total_page = math.ceil(total_count / PAGE_SIZE)
    writers = list(db.writer.find({},{'_id':False}).skip(START_IDX).limit(PAGE_SIZE))

    return jsonify({'result': 'success','writer_list': writers, 'total_count': total_count, 'total_page': total_page})

if __name__ == '__main__':
    app.run('localhost', port=5000, debug=True)


# -*- coding: utf-8 -*-

'''
データの読み込みと確認
'''

# ライブラリのインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# ランダムシードの設定
import random
np.random.seed(1234)
random.seed(1234)

# データの読み込み
train = pd.read_csv('./data/train.tsv', sep='\t')
test = pd.read_csv('./data/test.tsv', sep='\t')
submission = pd.read_csv('./data/sample_submit.csv')

# データの確認
print(train.head())
print(train.dtypes)

'''
特徴量エンジニアリング
'''

# 説明変数と目的変数を指定
X_train = train.drop(['class', 'id'], axis=1)
Y_train = train['class']

# ラベルデータをone-hotベクトルに直す
labels = {
    'Iris-setosa': [1, 0, 0],
    'Iris-versicolor': [0, 1, 0],
    'Iris-virginica': [0, 0, 1]
}

Y_train_nums = np.array(list(map(lambda v : labels[v] , Y_train)))
X_train_nums = np.array(X_train)

'''
モデルの構築と評価
'''

# ライブラリのインポート
import tensorflow as tf
import tensorflow.keras as keras
from sklearn.model_selection import train_test_split

# 学習用とテスト用に分割する
x_train, x_valid, y_train, y_valid = train_test_split(X_train_nums, Y_train_nums,
                                                    train_size=0.8,
                                                    random_state=0)

# モデル構造の定義
Dense = keras.layers.Dense

from pylab import rcParams
plt.figure(figsize=(10,6),dpi=200)
plt.rcParams['figure.figsize'] = (10 ,6)

def fit(epochs):
    # モデルの構造を定義
    model = keras.models.Sequential()
    model.add(Dense(10, activation='relu', input_shape=(4,)))
    model.add(Dense(3, activation='softmax'))
    # モデルを構築
    model.compile(
        loss='categorical_crossentropy',
        optimizer='adam',
        metrics=['accuracy'])
    # 学習を実行
    result = model.fit(x_train, y_train,
        batch_size=20,
        epochs=epochs)
    # モデルを評価
    score = model.evaluate(x_valid, y_valid, verbose=1)
    print('正解率=', score[1], 'loss=', score[0])
    # グラフを描画
    plt.plot(range(1, epochs+1), result.history['accuracy'], label="training")
    plt.plot(range(1, epochs+1), result.history['loss'], label="loss")
    plt.xlabel('Epochs=' + str(epochs))
    plt.ylabel('Accuracy')
    plt.legend()
    plt.show()

fit(1000)


import argparse
import numpy as np
import json
import re
import random
import itertools
import torch
import torch.nn as nn
import torch.nn.functional as F

import data
import models
import utils

from tqdm import tqdm
from pathlib import Path
from torch.utils.data import DataLoader

def get_metrics(recalls):
    metrics = {}
    for name, value in recalls.items():
        if name == 'MR':
            metrics[name] = np.median(value)
        else:
            metrics[f'R@{name}'] = np.mean(value)*100
    return metrics

def evaluate(model, video_iterator, lang_iterator, annotations, device, preliminary=100,
                model_types=['model'], iou_thresholds=[0.5,0.7]):

    videos = {}
    # compute embeddings for all clips in each unique video in dataset
    for batch in tqdm(video_iterator):
        with torch.no_grad():
            videos[batch['video']] = model(batch['feature'].to(device))

    recalls = {(model_type, iou_thr): {1: [], 10: [], 100: [], 'MR':[]}
        for (model_type, iou_thr) in itertools.product(model_types, iou_thresholds)}
    moments = lang_iterator.batch_sampler.moments
    print('\nEvaluation:')
    # compute embeddings for all queries in dataset
    for li, batch in tqdm(enumerate(lang_iterator)):
        with torch.no_grad():
            lang_emb = model(batch['feature'].to(device), False, device)

        # ground truth: 1 if IoU between moment and at least 2 manual annotations is greater the threshold
        # for incorrect videos all IoU score are 0
        distances, predicts = [], {key: [] for key in recalls.keys()}
        for video in videos.keys():
            video_emb = videos[video]
            num_segments = video_emb.size(0)
            # for each query compute distance between query and clip embeddings
            dist = F.pairwise_distance(video_emb, lang_emb.repeat(num_segments, 1))
            # for each possible moment in video compute distance between moment and query
            # as sum of distances between clips in the moment and query (precomputed on prev step)
            # (15 possible moments for video of 5 clips, 21 - for 6 clips)
            for start_t, end_t in moments[num_segments]:
                distances.append(dist.index_select(0, torch.arange(start_t, end_t+1).to(device)).mean().item())
                if video == batch['video']:
                    ious = utils.get_iou(annotations[batch['annot_id']]['times'], start_t, end_t)
                    for iou_thr in iou_thresholds:
                        predicts[('model', iou_thr)].append(int(( ious > iou_thr ).sum() >= 2))
                else:
                    for iou_thr in iou_thresholds:
                        predicts[('model', iou_thr)].append(0)

        # sort all moments from all videos by distances
        ind_rand = np.random.choice(np.arange(len(distances)), size=len(distances), replace=False)
        for iou_thr in iou_thresholds:
            ground_truth = np.array(predicts[('model',iou_thr)], dtype=int)
            predicts[('model', iou_thr)] = ground_truth[np.argsort(distances)]
            predicts[('chance',iou_thr)] = ground_truth[ind_rand]
            for model_type in model_types:
                for k in recalls[(model_type, iou_thr)].keys():
                    if k == 'MR':
                        # median rank: index position of first correct moment
                        recalls[(model_type, iou_thr)][k].append(np.where(predicts[(model_type, iou_thr)] == 1)[0][0])
                    else:
                        # Recall@K: 1 if correct moment is among in top-K moments, 0 otherwise
                        recalls[(model_type, iou_thr)][k].append(int(predicts[(model_type, iou_thr)][:k].sum() > 0))

        if (li % preliminary == 0) and (li != 0):
            print()
            for (model_type, iou_thr) in recalls.keys():
                print(f'{model_type}, IoU={iou_thr}:\t', ''.join([f'{name}: {value:.4f}\t'
                    for name, value in get_metrics(recalls[(model_type, iou_thr)]).items()]))
            print()

    return {f'{model_type}, IoU={iou_thr}': get_metrics(recalls[(model_type, iou_thr)])
                            for (model_type, iou_thr) in recalls.keys()}

if __name__ == '__main__':

    torch.random.manual_seed(123)
    random.seed(123)
    np.random.seed(123)

    parser = argparse.ArgumentParser()
    parser.add_argument("--features_dir", type=str, default='features/')
    parser.add_argument("--embedding_dir", type=str, default='glove_pretrained/')
    parser.add_argument("--dataset_dir", type=str, default='dataset/')
    parser.add_argument("--experiment_dir", type=str, default='experiment/')
    parser.add_argument("--missed_videos", type=str, default='../')
    parser.add_argument("--device", type=str, default=None)
    parser.add_argument("--validation", type=str, default='val')
    parser.add_argument("--preliminary_print", type=int, default=100)
    parser.add_argument("--iou", type=float, default=0.5)
    parser.add_argument("--model_types", type=str, nargs='+', default=[])
    parser.add_argument("--normalize_lang", type=utils.str2bool, default=False)
    args = parser.parse_args()

    FT_DIRECTORY = args.features_dir
    EMB_DIRECTORY = args.embedding_dir
    DATASET_DIRECTORY = args.dataset_dir
    EXPER_DIRECTORY = args.experiment_dir
    DATASET_TYPE = args.validation

    if args.device in ['cpu','cuda']:
        DEVICE = args.device
    else:
        if torch.cuda.is_available():
            DEVICE = torch.device('cuda')
        else:
            DEVICE = torch.device('cpu')

    print('Loading word embeddings:')
    word_indexer = data.WordIndexer(EMB_DIRECTORY)

    # load state dict
    state = torch.load(Path(EXPER_DIRECTORY).joinpath('last.pth'))
    FEATURE_TYPE = state['params']['feature_type']
    POOLING = state['params']['pooling']
    normalize_lang = state['params']['normalize_lang']
    normalize_loss = state['params']['normalize_loss']
    MODEL_TYPES = [model_type for model_type in args.model_types
                            if model_type in ['model','chance']]
    if MODEL_TYPES == []:
        MODEL_TYPES = ['model']
    print(DEVICE, FEATURE_TYPE, DATASET_TYPE, args.iou, MODEL_TYPES)

    moment_frequency = {}
    if 'prior' in MODEL_TYPES:

        print('Loading train dataset:')
        train_annotations, train_videos = utils.load_dataset_info('train', DATASET_DIRECTORY, args.missed_videos)
        train_dataset = data.CustomDataset(
            train_videos, train_annotations, word_indexer, FT_DIRECTORY, FEATURE_TYPE, pooling=POOLING)

        for _, annot_info in train_annotations.items():
            num_segments = train_dataset.num_segments_info[annot_info['video']]
            if num_segments not in moment_frequency.keys():
                moment_frequency[num_segments] = {tuple(moment): 0 for moment in utils.generate_moments(num_segments)}
                moment_frequency[num_segments]['total'] = 0
            else:
                for t in annot_info['times']:
                    moment_frequency[num_segments][tuple(t)] += 1
                    moment_frequency[num_segments]['total'] += 1

        for num_segments in moment_frequency.keys():
            moment_frequency[num_segments] = [freq / moment_frequency[num_segments]['total']
                        for moment, freq in moment_frequency[num_segments].items() if moment != 'total']

    print('Loading validation dataset:')
    val_annotations, val_videos = utils.load_dataset_info(DATASET_TYPE, DATASET_DIRECTORY, args.missed_videos)

    val_dataset = data.CustomDataset(val_videos, val_annotations, word_indexer, FT_DIRECTORY, FEATURE_TYPE, validate=True)
    val_video_iter = DataLoader(val_dataset, shuffle=False, collate_fn=data.validate_collate,
        batch_sampler=data.VideoBatchSampler(val_videos, val_dataset.num_segments_info))
    val_lang_iter = DataLoader(val_dataset, shuffle=False, collate_fn=data.validate_collate,
        batch_sampler=data.LanguageBatchSampler(val_annotations, val_dataset.num_segments_info))

    model = models.CALModel(
        pretrained_emb=word_indexer.get_embeddings(),
        visual_input_dim=data.FEATURE_DIM[FEATURE_TYPE]*2+2,
        emb_dim=data.EMBEDDING_DIM,
        normalize_lang=args.normalize_lang
    )
    model.load_state_dict(state['model_state_dict'])
    model = model.to(DEVICE)
    model.eval()

    # evaluate model with exhaustive search
    metrics = evaluate(
        model, val_video_iter, val_lang_iter, val_annotations, DEVICE, args.preliminary_print, MODEL_TYPES)

    for model_type in metrics.keys():
        print(f'{model_type}\t',''.join([f'{name}: {value:.4f}\t'
            for name, value in metrics[model_type].items()]))

    with open(Path(EXPER_DIRECTORY).joinpath('metrics.json'), 'w') as f:
        json.dump(metrics, f)


import matplotlib.pyplot as plt
import numpy as np

class Zero(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.ebv = 0
        self.cbv = 0
        self.tbv = 0

    def __repr__(self):
        return "-"

class Waste(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.ebv = -(2.5*(y-1)+4)
        self.cbv = None
        self.tbv = None

    def __repr__(self):
        return "W"

class Ore(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.ebv = 66 - (2.5*(y-1)+4) -27
        self.cbv = None
        self.tbv = None

    def __repr__(self):
        return "O"

## 20 column (including zero blocks)
## 12 row (including zero blocks)

## Initiates our 2d array which will hold the block objects
real = [[0 for z in range(20)] for g in range(12)]

## Filling first row and first column with zero blocks
## Their their cbv and tbv values will used as a foundation
## when calculating the rest

## Fills the first column with Zero blocks
for i in range(20):
    real[0][i] = Zero(i,0)

## Fills the first row with Zero blocks
for i in range(12):
    real[i][0] = Zero(0,i)

## Stores the block objects in a 2d array while
## calculating their ebv, cbv and tbv values.
## We have to do it column by to column to be able to
## make tbv calculation.
## Later(ln. 90) we will pull the data from this objects to
## put in subplots, which is the way we present the data.
for i in range(1,20):
    for k in range(1,12):
        if (8<=i<=12) and (k>=3):
            real[k][i] = Ore(i,k)
            real[k][i].cbv = real[k][i].ebv + real[k-1][i].cbv
            if k==11:
                real[k][i].tbv = real[k][i].cbv + max(real[k-1][i-1].tbv, real[k][i-1].tbv)
            else:
                real[k][i].tbv = real[k][i].cbv + max(real[k-1][i-1].tbv, real[k][i-1].tbv, real[k+1][i-1].tbv)
        else:
            real[k][i] = Waste(i,k)
            real[k][i].cbv = real[k][i].ebv + real[k-1][i].cbv
            if k==11:
                real[k][i].tbv = real[k][i].cbv + max(real[k-1][i-1].tbv, real[k][i-1].tbv)
            else:
                real[k][i].tbv = real[k][i].cbv + max(real[k-1][i-1].tbv, real[k][i-1].tbv, real[k+1][i-1].tbv)

                    ####
## To present the data in an eye pleasing way plotlib library has been used
## Shows the ebv, cbv and tbv values of every block in a seperate subplot.
## Margin is set to 0 so that all thing looks like a grid
                    ####

## Creates a 2d array to store subplots
layout = [[0 for z in range(20)] for g in range(12)]

# plot counter
i=1

## Takes the relevant data from the block objects and
## puts them in subplots
for y in range(12):
    for x in range(20):
        layout[y][x] = plt.subplot(12,20,i)
        layout[y][x].text(0.1, 0.8, "EBV: "+str(real[y][x].ebv),
                          size=9, alpha=1.0 )
        layout[y][x].text(0.1, 0.6, "CBV: "+str(real[y][x].cbv),
                          size=9, alpha=1.0 )
        layout[y][x].text(0.1, 0.4, "TBV: "+str(real[y][x].tbv),
                          size=9, alpha=1.0 )
        layout[y][x].set_xticklabels([])
        layout[y][x].set_yticklabels([])
        ## color the ore part
        if (8<=x<=12) and (y>=3):
            layout[y][x].set_facecolor("grey")
        ## color the zero boxes that we add as padding
        ## (which was necessary for the calculations of course)
        elif (x==0) or (y==0):
            layout[y][x].set_facecolor("beige")
        i+=1

plt.xticks(())
plt.yticks(())
plt.subplots_adjust(wspace=0, hspace=0)
plt.show()


import django

from apps.users.views import UserInfoView,UploadImageView,ChangePwdView,MyCourseView
from apps.users.views import MyFavOrgView,MyFavTeacherView,MyFavCourseView,MyMessageView

if django.VERSION >= (3, 1, 0):
    from django.urls import re_path as url
else:
    from django.conf.urls import url

urlpatterns = [
    url(
        r'^info/$',
        UserInfoView.as_view(),
        name="info"
    ),
    url(
        r'^image/upload/$',
        UploadImageView.as_view(),
        name="image"
    ),
    url(
        r'^update/pwd/$',
        ChangePwdView.as_view(),
        name="update_pwd"
    ),
    url(
        r'^mycourses/$',
        MyCourseView.as_view(),
        name="mycourses"
    ),
    url(
        r'^myfavorg/$',
        MyFavOrgView.as_view(),
        name="myfavorg"
    ),
    url(
        r'^myfavteacher/$',
        MyFavTeacherView.as_view(),
        name="myfavteacher"
    ),
    url(
        r'^myfavcourse/$',
        MyFavCourseView.as_view(),
        name="myfavcourse"
    ),
    url(
        r'^messages/$',
        MyMessageView.as_view(),
        name="messages"
    ),

]


import time
import serial
from absl import app, flags, logging
from absl.flags import FLAGS
#Tensorflow 에서 제공하는 flags 객체를 사용하면 고정값으로 되어 있는 기본적인 데이터를 편리하게 사용 가능
#flags 객체는 int, float, boolean, string 의 값을 저장하고, 가져다 사용하기 쉽게 해주는 기능
import cv2 #opencv
import tensorflow as tf
from yolov3_tf2.models import (
    YoloV3, YoloV3Tiny
)
from yolov3_tf2.dataset import transform_images
from yolov3_tf2.utils import draw_outputs

#DEFINE_*** 로 시작되는 함수를 통해서 key, value 형식과 비슷하게 원하는 데이터를 정의
flags.DEFINE_string('classes', 'C:\\Users\\wnsru\\Desktop\\2020-1-OSSP1-SJSS-4-master\\blocklyduino\\demos\\code\\data\\coco.names', 'path to classes file')
flags.DEFINE_string('weights', 'C:\\Users\\wnsru\\Desktop\\2020-1-OSSP1-SJSS-4-master\\blocklyduino\\demos\\code\\checkpoints\\yolov3.tf',
                    'path to weights file')
flags.DEFINE_boolean('tiny', False, 'yolov3 or yolov3-tiny')
flags.DEFINE_integer('size', 416, 'resize images to')
flags.DEFINE_string('video', './data/video.mp4',
                    'path to video file or number for webcam)')
flags.DEFINE_string('output', None, 'path to output video')
flags.DEFINE_string('output_format', 'XVID', 'codec used in VideoWriter when saving video to file')
flags.DEFINE_integer('num_classes', 80, 'number of classes in the model')
#위와 같이 정의된 값들은 flags.FLAGS 를 통해서 어디에서든지 호출하여 사용 가능

def main(_argv):
    physical_devices = tf.config.experimental.list_physical_devices('GPU')
    for physical_device in physical_devices:
        tf.config.experimental.set_memory_growth(physical_device, True)

    if FLAGS.tiny:
        yolo = YoloV3Tiny(classes=FLAGS.num_classes)
    else:
        yolo = YoloV3(classes=FLAGS.num_classes)

    yolo.load_weights(FLAGS.weights)#가중치 파일 로드
    logging.info('weights loaded')#로드 완료 시 확인 용

    class_names = [c.strip() for c in open(FLAGS.classes).readlines()]#classes파일 로드
    logging.info('classes loaded')#로드 완료 시 확인 용

    times = [] #t2-t1다루기 위한 배열

    #cv2.VideoCapture()를 사용해 비디오 캡쳐 객체를 생성
    #안의 숫자는 장치 인덱스(어떤 카메라를 사용할 것인가)를 의미
    #1개만 부착되어 있으면 0, 2개 이상이면 첫 웹캠은 0, 두번째 웹캠은 1으로 지정
    #try:
    #    vid = cv2.VideoCapture(int(FLAGS.video))
    #except:
    #    vid = cv2.VideoCapture(FLAGS.video)

    vid = cv2.VideoCapture(0)
    out = None

    if FLAGS.output:
        # by default VideoCapture returns float instead of int
        width = int(vid.get(cv2.CAP_PROP_FRAME_WIDTH))#프레임의 너비
        height = int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))#프레임의 높이
        fps = int(vid.get(cv2.CAP_PROP_FPS))#프레임 속도
        #vidowriter 비디오를 저장
        #cv2.VideoWriter(outputFile, fourcc, frame, size) : fourcc는 코덱 정보, frame은 초당 저장될 프레임, size는 저장될 사이즈
        codec = cv2.VideoWriter_fourcc(*FLAGS.output_format)
        out = cv2.VideoWriter(FLAGS.output, codec, fps, (width, height))

    while True:
        _, img = vid.read()

        if img is None:
            logging.warning("Empty Frame")
            time.sleep(0.1)
            #sleep():일정 시간 동안 실행 지연 -> 0.1초 지연
            continue

        img_in = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#(원본이미지, 색상 변환 코드), 이미지의 색상공간을 변경할 수 있음
        #Red, Green, Blue 채널

        img_in = tf.expand_dims(img_in, 0) #차원을 추가하여 확장함, img_in이 주어졌을 때, 이 함수는 크기가 1인 차원을 img_in의 구조에서 차원 인덱스(0)에 삽입.
        img_in = transform_images(img_in, FLAGS.size)

        t1 = time.time()#현재 Unix timestamp을 소수로 리턴. 정수부는 초단위이고, 소수부는 마이크로(micro) 초단위
        boxes, scores, classes, nums = yolo.predict(img_in)
        #model.predict(): 훈련 된 모델이 주어지면 새로운 데이터 세트의 레이블을 예측한다. 이 메소드는 새로운 데이터 X_new(예 :) model.predict(X_new)와 같은 하나의 인수를 허용하고 배열의 각 객체에 대해 학습된 레이블을 반환
        t2 = time.time()#현재 Unix timestamp을 소수로 리턴. 정수부는 초단위이고, 소수부는 마이크로(micro) 초단위
        times.append(t2-t1)#배열에 t2-t1값 추가
        times = times[-20:]# times[-20] = *(times-20)

        img = draw_outputs(img, (boxes, scores, classes, nums), class_names)#인식된 박스

        if FLAGS.output:
            out.write(img)
        cv2.imshow('output', img)#imshow 는 이미지 보기
        #'output'은 윈도우 창의 제목을 의미하며 img는 cv2.imread() 의 return값
        if cv2.waitKey(1) == ord('q'):#q 입력 시 종료
            break
        #arduino= serial.Serial('COM3', 9600)
        #for i in range(4):
        #    c = obj[i]
        #    c=c.encode('utf-8')
        #   arduino.write(c)

    cv2.destroyAllWindows()
    #화면에 나타난 윈도우를 종료

if __name__ == '__main__':
    try:
        app.run(main)
    except SystemExit:
        pass


import threading
import time

# create a thread with each list within the input.
#  iterate through that list suming all the values between the start and end of the list.
# create a total array that will hold each of the summed values.
# sum the total array to get the total sum.

threading.Thread()
def runner(num, start, end):
    # """ Thread running function. """

    # for i in range(start, end):
    #     print(f"Running: {name} {i}")
    #     time.sleep(0.2)  # seconds
    print(num, start, end)
    total = 0
    for i in range(start, end + 1):
        total += i

    # print(total)
    result[num] = total

ex_input = [
    [10, 20],
    [1, 5],
    [70, 80],
    [27, 92],
    [0, 16]
]
thread_count = len(ex_input)
threads = []
total = []
result = [0] * thread_count

for i in range(thread_count):

    # Give them a name
    name = f"Thread{i}"

    # Set up the thread object. We're going to run the function called
    # "runner" and pass it two arguments: the thread's name and count:
    t = threading.Thread(target=runner, args=(i, ex_input[i][0], ex_input[i][1]), daemon=True)

    # The thread won't start executing until we call `start()`:
    t.start()

    # Keep track of this thread so we can join() it later.
    threads.append(t)

# Join all the threads back up to this, the main thread. The main thread
# will block on the join() call until the thread is complete. If the
# thread is already complete, the join() returns immediately.

for t in threads:
    t.join()
print(sum(result))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Aug  4 19:07:01 2019

@author: jannik wiessler
"""

def autolog(message,logger):
    "Automatically log the current function details."
    import inspect
    # Get the previous frame in the stack, otherwise it would
    # be this function!!!
    func = inspect.currentframe().f_back.f_code
    # Dump the message + the name of this function to the log.
    logger.debug("message: %s in %s in %s, line: %i" % (
        message,
        func.co_name,
        func.co_filename,
        func.co_firstlineno
    ))


#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class FileFilter(Gtk.FileChooserDialog):
    def __init__(self):
        Gtk.FileChooserDialog.__init__(self)
        self.set_title("FileFilter")
        self.add_button("_Cancel", Gtk.ResponseType.CLOSE)
        self.add_button("_Open", Gtk.ResponseType.OK)
        self.connect("response", self.on_response)

        filefilter = Gtk.FileFilter()
        filefilter.set_name("All Items")
        filefilter.add_pattern("*")
        self.add_filter(filefilter)

        filefilter = Gtk.FileFilter()
        filefilter.set_name("Audio")
        filefilter.add_mime_type("audio/flac")
        filefilter.add_mime_type("audio/ogg")
        self.add_filter(filefilter)

        filefilter = Gtk.FileFilter()
        filefilter.set_name("Images")
        filefilter.add_pattern("*.png")
        filefilter.add_pattern("*.jpg")
        filefilter.add_pattern("*.bmp")
        self.add_filter(filefilter)

    def on_response(self, filechooserdialog, response):
        filechooserdialog.destroy()

dialog = FileFilter()
dialog.run()


import six

from valet.engine.app_manager.group import FLAVOR_TYPES

class Server(object):
    """Container to keep requested server (e.g., VM)."""

    def __init__(self, _id, _orch_id):
        """Define server info and parameters."""

        # ID consists of stack_name + ":" + server_name,
        # where stack_name = datacenter_id + ":" + tenant_id + ":" + vf_module_name
        self.vid = _id

        # ID in stack
        self.orch_id = _orch_id

        # one given in Heat stack
        self.name = None

        # Affinity group object
        self.surgroup = None

        self.diversity_groups = {}
        self.quorum_diversity_groups = {}
        self.exclusivity_groups = {}

        self.availability_zone = None

        self.flavor = None
        self.image = None

        self.vCPUs = 0
        self.mem = 0                  # MB
        self.local_volume_size = 0    # GB
        self.extra_specs_list = []

        self.vCPU_weight = -1
        self.mem_weight = -1
        self.local_volume_weight = -1

        # To return placement.
        # If stack is nested, should point the index to distinguish
        self.host_assignment_variable = None
        self.host_assignment_inx = -1

        # Placement result
        self.host_group = None    # e.g., rack
        self.host = None
        self.numa = None

        # Request state is 'create', 'migrate', 'rebuild', 'delete'
        # 'created', 'migrated', 'rebuilt'
        self.state = "plan"

        # To inform if the current placement violates rules and requirements
        self.status = "valid"

        self.sort_base = -1

    def get_exclusivities(self, _level):
        """Return exclusivity group requested with a level (host or rack).

        Note: each server must have a single exclusivity group of the level.
        """

        exclusivities = {}

        for exk, group in self.exclusivity_groups.items():
            if group.level == _level:
                exclusivities[exk] = group

        return exclusivities

    def need_numa_alignment(self):
        """Check if this server requires NUMA alignment."""

        if len(self.extra_specs_list) > 0:
            for es in self.extra_specs_list:
                for key, req in six.iteritems(es):
                    if key == "hw:numa_nodes" and int(req) == 1:
                        return True

        return False

    def get_flavor_types(self):
        flavor_type_list = []

        for extra_specs in self.extra_specs_list:
            for k, v in extra_specs.items():
                k_elements = k.split(':')
                if len(k_elements) > 1:
                    if k_elements[0] == "aggregate_instance_extra_specs":
                        if k_elements[1].lower() in FLAVOR_TYPES:
                            if v == "true":
                                flavor_type_list.append(k_elements[1])

        return flavor_type_list

    def get_json_info(self):
        """Format server info as JSON."""

        if self.surgroup is None:
            surgroup_id = "none"
        else:
            surgroup_id = self.surgroup.vid

        diversity_groups = []
        for divk in self.diversity_groups.keys():
            diversity_groups.append(divk)

        quorum_diversity_groups = []
        for divk in self.quorum_diversity_groups.keys():
            quorum_diversity_groups.append(divk)

        exclusivity_groups = []
        for exk in self.exclusivity_groups.keys():
            exclusivity_groups.append(exk)

        if self.availability_zone is None:
            availability_zone = "none"
        else:
            availability_zone = self.availability_zone

        if self.host_group is None:
            host_group = "none"
        else:
            host_group = self.host_group

        if self.numa is None:
            numa = "none"
        else:
            numa = self.numa

        return {'name': self.name,
                'orch_id': self.orch_id,
                'surgroup': surgroup_id,
                'diversity_groups': diversity_groups,
                'quorum_diversity_groups': quorum_diversity_groups,
                'exclusivity_groups': exclusivity_groups,
                'availability_zones': availability_zone,
                'extra_specs_list': self.extra_specs_list,
                'flavor': self.flavor,
                'image': self.image,
                'cpus': self.vCPUs,
                'mem': self.mem,
                'local_volume': self.local_volume_size,
                'host_group': host_group,
                'host': self.host,
                'numa': numa,
                'state': self.state,
                'status': self.status}


different_letter = {'я':'йа',
                    'ю':'йу',
                    'ё':'йо'}
def replace_letter(word):
    for letter in word:
        if letter in different_letter:
            word = word.replace(letter, str(different_letter.get(letter)))
    return

str_continue = 'continue'
str_break = 'break'

posessiveness_general = {
    'ны', 'ни', 'ну', 'нү',
    'ды', 'ди', 'ду', 'дү',
    'ты', 'ти', 'ту', 'тү'
}
half_of_ending_for_general_possessiveness = ['кы', 'ки', 'ку', 'кү']
ending_of_gerund = ['уу','үү','оо','өө']
ending_of_gerund_pres = ['аш','ыш','иш','уш', 'үш','өш','ош']
ending_of_chakchyl = ['ып','ип','уп','үп','ап']
v_voice_all_ending = {
    'ын', 'ан', 'ун', 'үн', 'ың',   #эгин жүгүнөт
    'ыл', 'ол', 'өл', 'ул', 'үл',
    'ыш', 'иш',     #кылышты
    'аш', 'еш', 'уш', 'үш', #иштештик
    'ыр', 'ир', 'ур', 'үр',
    'ил'
}
case = ['gen','dat','acc','loc','abl']
voice = ['ref','coop','pass','caus']
mood = ['pres','past_def','past_indf','past_evid','past_iter','fut_def', 'fut_aor','fut_indf_neg','cnd','fut_indf']
non_finite_verb_forms = ['ger','gna_perf','ger_impf','gpr_perf','gpr_fut_neg','gpr_impf', 'gpr_pres', 'gpr_past', 'ger_pres',
                         'ger_pres']

face = ['p1sg','p1pl','p2sg','p2pl']

num_symbols = ['num_ord', 'num_top','num_appr1','num_appr2', 'num_appr3']
consonants_kg = {
    'б', 'в', 'г', 'д', 'ж', 'з', 'й', 'к', 'л', 'м', 'н', 'ң', 'п', 'р', 'с', 'т', 'ф', 'х', 'ц', 'ч', 'ш', 'щ'
}
special_vowel = {
    'и', 'ы', 'у', 'ү'
}
vowels_kg = {
    'а', 'о', 'ө', 'э', 'и', 'ы', 'у', 'ү', 'аа', 'оо', 'өө', 'ээ', 'уу', 'үү', 'я', 'ю', 'ё', 'е'
}
narrow_vowels = ['э','е','и','ү','ө']#ичке үндүлөр
wide_vowels = ['а','ы','о','у']#жоон үндүлөр
all_punctuation_marks = ['.',',','?','!','"',';',':','{','}','`',
                         '«', '»', '/', '(', ')', '#', '№', '$',
                         '^', '&', '*', '_', '-', '–', '+','=', '~', "|"]
sentence_end_p_m = ['. ','! ','? ']

half_of_ending_for_ordinal_numeral = ['чы', 'чи' , 'чу' , 'чү']
half_of_ending_for_not_sure_numeral = ['гон', 'гөн', 'ген', 'ган']

special_pronoun = ['менин','сенин','анын', 'мага','сага','ага', 'мени',
                   'сени','аны', 'анда', 'андан', 'муну', 'мунун', 'буга', 'мында', 'мындан','меники','аныкы','сеники']
prn_gen = {'менин','сенин','анын', 'мунун'}
prn_dat = {'мага','сага','ага', 'буга'}
prn_acc = {'мени','сени','аны', 'муну'}
prn_loc = {'анда', 'мында'}
prn_abl = {'андан', 'мындан'}
prn_xp = {'меники','аныкы','сеники'}
faces = ['p1sg', 'p2sg', 'p2sgf', 'p1pl', 'p2pl', 'p2plf']
all_faces = ['p1sg', 'p2sg', 'p2sgf', 'p1pl', 'p2pl', 'p2plf', 'p3sg', 'p3pl']
possessiveness = ['px1sg', 'px2sg', 'px2sgf', 'px3sg', 'px1pl', 'px2pl', 'px2plf']
plural = 'pl'
ques = 'ques'
agent_noun = 'agnt'
p2sgf_str = 'p2sgf'
poss_general = 'xp'
for_poss = ['p1pl','px2pl', 'p2sgf', 'px2sgf']
all_sg = ['sg','p3sg']
gerunds = ['ger','ger_pres','ger_fut','fut_opt']
chakchyl = ['gna_perf','gna_purp','gna_cnd','gna_irre','advv_cont']
atoochtuk = ['gpr_aor_neg','gpr','gpr_impf','gpr_pres']
verb_pres = ['да','до','дө']
inf1_2 = ['ger']
for_pst_evid = ['тыр','тир','тур','түр']
gna_perf = 'gna_perf'
for_pst_evid2 = ['ып','ип','уп','үп','п']
negative_ending_verb = ['ба', 'бе', 'бө', 'бо', 'па', 'пе', 'пө', 'по']
imp_pl_1 = ['кы','ки','ку','кү','гы','ги','гу','гү']
imp_pl_2 = ['ла','ле','ло','лө']
fut_indf_endings = ['а','е','о','ө']
two_sgf = 'p2sgf'
two_sgf_ending = ['ыңыз','иңиз','уңуз','үңүз']
imp_p2sgf = ['ңыз','ңиз','ңуз','ңүз']
ger_pres = ['ыш','иш','уш','үш','ш']
fut_indf_1pl = ['лы','ли','лу','лү']
hor_pl2 = ['лык','лик','лук','лүк']
hor_pl3 = ['алы','ели','олу','өлү','йлы','йли','йлу','йлү']
hor_pl4 = ['алык','елик','олук','өлүк','йлык','йлик','йлук','йлүк']
neg_str = 'neg'
fut_indf_str = 'fut_indf'
deside2 = ['макчы','мекчи','мокчу','мөкчү']
inf_5_1sg = ['гым','гим','гум','гүм','кым','ким','кум','күм']
inf_5_2sg = ['гың','гиң','гуң','гүң','кың','киң','куң','күң']

past_def = ['ты','ти','ту','тү','ды','ди','ду','дү']
neg_pres2 = ['оодо','өөдө']
neg_pre1 = ['б','п']
fut_aor = ['ар','ер','ор','өр']
fut_indf_neg = 'fut_indf_neg'
advv_int1 = ['ны','ни','ну','нү']
advv_int2 = ['га','ге','го','гө', 'ка','ке','ко','кө']
gna_cnd = ['майынча','мейинче','мойунча','мөйүнчө']
num_appr1 = 'num_appr1'
advv_suc1 = ['кыча','киче','куча','күчө','гыча','гиче','гуча','гүчө']
advv_suc2 = ['ганча','генче','гончо','гөнчө','канча','кенче','кончо','көнчө']
hor_sg_str = 'fut_indf'
advv_neg2 = ['майын','мейин','мойун','мөйүн']
past_iter = 'past_iter'
gpr_1 = ['оочу','уучу','өөчү','үүчү']

num_appr2 = 'num_appr2'
pcp_fut_def1 = ['гыдай','гидей','гудай','гүдөй']
pcp_fut_def2 = ['чудай','чидей','чыдай','чүдөй']
pcp_fut_def3 = ['гандай','гендей','гондой','гөндөй']
gpr_pres1 = ['сан','сен','сон','сөн']
gpr_pres2 = ['максан','мексен','моксон','мөксөн']
two_sgf_verb = ['сыз','сиз','суз','сүз']
pst_def_1_sg = ['тым','тим','тум','түм','дым','дим','дум','дүм']
pst_def_2_sg = ['тың','тиң','туң','түң','дың','диң','дуң','дүң']
pst_def_1_pl = ['тык','тик','тук','түк','дык','дик','дук','дүк']
shortcut_face_1sg = 'м'
shortcut_face_2sg = 'ң'
shortcut_face_1pl = 'к'

shortcut_ending_poss = ['м','ң']
shortcut_acc = ['ын','ин']

shortcut_ending_with_1_sg = ['ам','ем','ом','өм']
shortcut_ending_with_3_sg = ['ат','ет','от','өт']
fut_def_faces = ['та','те','то','тө','да','де','до','дө']
dat = 'dat'
pst_iter_1sg = ['чум','чүм']
pst_iter_2sg = ['чуң','чүң']
pst_iter_1pl = ['чук','чүк']

imp_together_tags = ['v','ques','neg','act','imp', 'iv', 'tv']
gerunds_together_tags = ['v','nom','gen','dat','acc','loc','abl', 'sg','pl','p1sg', 'p2sg', 'p2sgf', 'p1pl', 'p2pl', 'p2plf',
                  'p3sg','p3pl','px1sg', 'px2sg', 'px2sgf', 'px3sg', 'px1pl', 'px2pl', 'px2plf',
                  'ques','neg','xp','imp','act', 'iv', 'tv']
pcp_together_tags = ['v','pl','imp','act', 'nom','gen','dat','acc','loc','abl', 'sg','pl','p1sg', 'p2sg', 'p2sgf', 'p1pl', 'p2pl', 'p2plf',
                  'p3sg','p3pl','px1sg', 'px2sg', 'px2sgf', 'px3sg', 'px1pl', 'px2pl', 'px2plf',
                  'ques','neg','xp', 'iv', 'tv']
advv_together_tags = ['v','imp','act', 'iv', 'tv']
mood_together_tags = ['v','act','imp','neg','ques','p1sg', 'p2sg', 'p2sgf', 'p1pl', 'p2pl', 'p2plf',
                  'p3sg','p3pl', 'iv', 'tv']
prec_1_together_tags = ['v','act','imp','neg', 'iv', 'tv']
comp_together_tags = ['adj','pst','attr']

opt_together_tags = ['v','iv','tv','act','imp','neg','p1sg', 'p2sg', 'p2sgf', 'p1pl', 'p2pl', 'p2plf', 'p3sg','p3pl','px3sg']
advv_tags = ['gna_perf', 'advv_cont','gna_purp', 'gna_cnd','gna_irre']
gerunds_tags = ['ger','ger_pres','ger_fut','fut_opt']
pcp_tags = ['gpr','gpr_impf','gpr_aor_neg','gpr_pres']
verb_mood = ['pres','past_def','past_indf','past_evid','past_iter','fut_def', 'fut_aor','fut_indf_neg','cnd','fut_indf']
imp_tags = ['imp']
tags_with_noun = ['n','nom','gen','dat','acc','loc','abl', 'sg','pl','p1sg', 'p2sg', 'p2sgf', 'p1pl', 'p2pl', 'p2plf',
                  'p3sg','p3pl','px1sg', 'px2sg', 'px2sgf', 'px3sg', 'px1pl', 'px2pl', 'px2plf',
                  'ques','agnt','neg','xp']
tags_with_numeral = ['num','num_card','nom','gen','dat','acc','loc','abl', 'sg','pl','p1sg', 'p2sg', 'p2sgf', 'p1pl', 'p2pl', 'p2plf',
                  'p3sg','p3pl','px1sg', 'px2sg', 'px2sgf', 'px3sg', 'px1pl', 'px2pl', 'px2plf',
                  'ques','neg','xp']
numeral_tags = ['num_card','num_ord','num_coll','num_top','num_appr1','num_appr2','num_appr3']
adj_ending_tags = ['comp']
adj_tags = ['pst']
tags_with_adj = ['adj','pst','nom','gen','dat','acc','loc','abl', 'sg','pl','p1sg', 'p2sg', 'p2sgf', 'p1pl', 'p2pl', 'p2plf',
                  'p3sg','p3pl','px1sg', 'px2sg', 'px2sgf', 'px3sg', 'px1pl', 'px2pl', 'px2plf',
                  'ques','neg','xp', 'attr']

fut_def_special = ['йм']
fut_def_special_negative = ['бай', 'бей', 'бөй', 'бой', 'пай', 'пей', 'пөй', 'пой']
cond_1sg = ['сам','сем','сом','сөм']
cond_2sg = ['саң','сең','соң','сөң']
cond_1pl = ['сак','сек','сок','сөк']

optative_mood_1sg_1pl = ['fut_indf','fut_indf']

hor_together_tags = ['v','ques','neg']
inf_1_inf_2_with_shortcut_faces = ['оом','уум','өөм','үүм', 'ооң','ууң','өөң','үүң']
inf_1_with_shortcut_1sg = ['оом', 'өөм']
inf_2_with_shortcut_1sg = ['уум', 'үүм']
inf_1_with_shortcut_2sg = ['ооң', 'өөң']
inf_2_with_shortcut_2sg = ['ууң', 'үүң']

poss_1sg_2sg = ['px1sg', 'px2sg']
advv_acc_latest_letter = 'п'
plural_ending = ['дар', 'дер', 'дор', 'дөр', 'тар', 'тер', 'тор', 'төр', 'лар', 'лер', 'лор', 'лөр']
pcp_pr_1 = ['уучу','оочу','үүчү','өөчү']
past_indf = 'past_indf'
change_tags_without_faces = ['pl', 'px1sg', 'px2sg', 'px2sgf', 'px3sg', 'px1pl', 'px2pl', 'px2plf',
               'gen','dat','acc','loc','abl', 'xp']
gpr_2 = ['гон', 'гөн', 'ген', 'ган','кон', 'көн', 'кен', 'кан']
fut_indf_neg_str = 'fut_indf_neg'
inf_1_ending = ['оо','өө']
inf_2_ending = ['уу','үү']
fut_aor_str = 'fut_aor'
fut_opt = ['кы','ки','ку','кү','гы','ги','гу','гү']
pst_iter_str = 'past_iter'

prec_1_str = 'prec_1'
num_ord = ['ынчы', 'инчи', 'үнчү', 'унчу']
num_ord_short = ['нчы', 'нчи', 'нчү', 'нчу']
num_word_special = ['үчүнчү', 'алтынчы','кыркча','кырктай','кырктан','кырктаган','бирөө','экөө','үчөө','төртөө',
                    'бешөө','алтоо','жетөө','сегизөө']

adj_word_special = ['жакшыраак']

part_of_speech_tags = ['post']
abl_str = 'abl'
num_appr3 = ['догон', 'дөгөн', 'деген', 'даган',
    'тогон', 'төгөн', 'теген', 'таган']

comp_str = 'comp'
POS_without_ending_tags = ['ij','ideo','conj','post','mod','part']
shortcut_poss_3sg_ending = ['ы','и','у','ү']
poss_1sg_2sg_endings = ['ым','им','ум','үм','ың','иң','уң','үң']
poss_1sg_endings = ['ым','им','ум','үм']
poss_2sg_endings = ['ың','иң','уң','үң']
px2sgf_endings = ['ңыз','ңиз','ңуз','ңүз']
px1pl_endings = ['быз','биз','буз','бүз']
px2pl_endings = ['ңар','ңер','ңор','ңөр']
comp_endings = ['ы','и','у','ү']
verb_default_tags = ['v', 'act', 'iv', 'tv', 'imp', 'caus','coop', 'ref', 'pass' , 'cop_ger', 'cop_ifi', 'cop_neg']
POS = ['n', 'v', 'adj', 'adv', 'prn', 'num', 'ij', 'ideo', 'mod', 'part', 'conj', 'post']


import time
import matplotlib.pyplot as plt
from scipy import stats
import numpy as np
from sequences import *
import itertools

subst_matrix = {
    'A': {'A': 5, 'C': -1, 'G': -2, 'T': -1, '-': -3},
    'C': {'A': -1, 'C': 5, 'G': -3, 'T': -2, '-': -4},
    'G': {'A': -2, 'C': -3, 'G': 5, 'T': -2, '-': -2},
    'T': {'A': -1, 'C': -2, 'G': -2, 'T': 5, '-': -1},
    '-': {'A': -3, 'C': -4, 'G': -2, 'T': -1, '-': 0},
}

def match(n, m, A, B):
    # recursive function for match
    global subst_matrix
    sum = 0
    c = 5

    # one of the strings is empty
    if n == 0:
        for i in range(0, m):
            sum += subst_matrix['-'][B[i]]
        return sum

    if m == 0:
        for i in range(0, n):
            sum += subst_matrix[A[i]]['-']
        return sum

    l = subst_matrix[A[n - 1]]['-']
    r = subst_matrix['-'][B[m - 1]]

    if (A[n - 1] != B[m - 1]):
        c = subst_matrix[A[n - 1]][B[m - 1]]

    return max(match(n - 1, m, A, B) + l,  # delete from A
               match(n, m - 1, A, B) + r,  # delete from B
               match(n - 1, m - 1, A, B) + c)  # substitute

def matchDP(A, B):
    # DP code for match
    global subst_matrix
    n = len(A)
    m = len(B)
    cache = np.array([[0 for i in range(0, m + 1)] for j in range(0, n + 1)])
    sum = 0
    c = 5

    # fill in the base cases
    for j in range(1, m + 1):
        sum = sum + subst_matrix['-'][B[j - 1]]
        # print(i)
        cache[0][j] = sum
    sum = 0

    for i in range(1, n + 1):
        # print(j)
        sum = sum + subst_matrix[A[i - 1]]['-']
        cache[i][0] = sum

    for i in range(1, n + 1):
        for j in range(1, m + 1):
            c = 5
            l = subst_matrix[A[i - 1]]['-']
            r = subst_matrix['-'][B[j - 1]]
            if (A[i - 1] != B[j - 1]):
                c = subst_matrix[A[i - 1]][B[j - 1]]  # update c if characters dont match.

            cache[i][j] = max(cache[i - 1][j] + l, cache[i][j - 1] + r, cache[i - 1][j - 1] + c)

        # uncomment this only to do traceback
        # if(cache[n][m] == 0):
        #     print("no output")
        # else:
    x = tracebackIter(n, m, A, B, cache)
    f = open("output.txt", "w")
    for i in range(len(x)):
        f.write(x[i] + "\n")
        f.write("score, " + str(cache[n][m]))
        f.close()

    return cache[n][m]

def traceback(n, m, A, B, cache):
    # recursive traceback
    global subst_matrix
    c = 5
    if n == 0 and m == 0:
        return []

    if n == 0:
        for j in range(m - 1, -1, -1):
            print("%s - %s" % ('_', B[j]))
        return

    if m == 0:
        for i in range(n - 1, -1, -1):
            print("%s - %s" % (A[i], '_'))
        return

    l = subst_matrix[A[n - 1]]['-']
    r = subst_matrix['-'][B[m - 1]]
    if (cache[n][m] == cache[n - 1][m] + l):
        print("%s - %s" % (A[n - 1], '_'))
        return traceback(n - 1, m, A, B, cache)

    if (cache[n][m] == cache[n][m - 1] + r):
        print("%s - %s" % ('_', B[m - 1]))
        return traceback(n, m - 1, A, B, cache)
    if (A[n - 1] != B[m - 1]):
        c = subst_matrix[A[n - 1]][B[m - 1]]
    if (cache[n][m] == cache[n - 1][m - 1] + c):
        print("%s - %s" % (A[n - 1], B[m - 1]))
        return traceback(n - 1, m - 1, A, B, cache)

def tracebackIter(n, m, A, B, cache):
    # iterative traceback
    global subst_matrix
    a1 = []
    i = m
    j = n
    c = 5

    while True:
        if (i == 0 and j == 0):
            break
        l = subst_matrix[A[j - 1]]['-']
        r = subst_matrix['-'][B[i - 1]]
        if (A[j - 1] == B[i - 1]):
            a1.append("%s - %s" % (A[j - 1], B[i - 1]))
            i = i - 1
            j = j - 1
        if (cache[j][i] == cache[j - 1][i] + l):
            a1.append("%s - %s" % (A[j - 1], '_'))
            j = j - 1
        if (cache[j][i] == cache[j][i - 1] + r):
            a1.append("%s - %s" % ('_', B[i - 1]))
            i = i - 1
        if (A[j - 1] != B[i - 1]):
            c = subst_matrix[A[j - 1]][B[i - 1]]
        if (cache[j][i] == cache[j - 1][i - 1] + c):
            a1.append("%s - %s" % (A[j - 1], B[i - 1]))
            i = i - 1
            j = j - 1
    return a1

# code for trying timing function.
def genStr(n):
    return (sequence1[1:n + 1], sequence2[1:n + 1])

def generateProblems(start, end, increment):
    # generates problems described as (size, (randstring, randstring))
    a = [(i, genStr(i)) for i in range(start, end, increment)]
    return a

def timeProblems(problemList, function, init=None, fit='exponential'):
    # Calculates the time taken by each function call and generates graph
    timeLine = []
    values = []
    for (size, args) in problemList:
        start_time = time.time()
        function(*args)  # use the * to unpack the tuple into arguments to the function
        elapsed = (time.time() - start_time) * 1000.0
        if elapsed > 0.0:
            timeLine.append(elapsed)
            values.append(size)

    plt.plot(values, timeLine, 'g')
    plt.xlabel("Problem size")
    plt.yscale('log')
    if fit == 'polynomial':
        plt.xscale('log')
    plt.ylabel("time in milliseconds")
    plt.rcParams["figure.figsize"] = [16, 9]
    plt.show()
    if fit == 'exponential':  # fit a straight line to n and log time
        slope, intercept, _, _, _ = stats.linregress([values], [np.log(t) for t in timeLine])
        print("time = %.6f %.3f ^ n" % (np.exp(intercept), np.exp(slope)))
    elif fit == 'polynomial':  # fit a straight line to log n and log time
        slope, intercept, _, _, _ = stats.linregress([np.log(v) for v in values], [np.log(t) for t in timeLine])
        print("time = %.6f n ^ %.3f" % (np.exp(intercept), slope))
    plt.savefig('graph_Final.png')

# code to match first 5 sequences amongst themselves.
def findsubsets(s, n):
    return list(itertools.combinations(s, n))

def getScore():
    s = {sequence1[0:5001], sequence2[0:5001], sequence3[0:5001], sequence4[0:5001], sequence5[0:5001]}
    n = 2
    sequence_subset = findsubsets(s, n)
    for i in range(len(sequence_subset)):
        strs = sequence_subset[i]
        print(strs)
        print(matchDP(strs[0], strs[1]))
        print("\n")

# match a sequence with itself.
def getScoreWithItself():
    # find score of a sequence with itself.
    print(matchDP(sequence1, sequence1))
    print(matchDP(sequence2, sequence2))
    print(matchDP(sequence3, sequence3))
    print(matchDP(sequence4, sequence4))
    print(matchDP(sequence5, sequence5))

# timeProblems(generateProblems(1,10000,100), matchDP, fit = 'polynomial')
# getScore()
# getScoreWithItself()
# matchDP(sequence1[0:10001],sequence2[0:10001])
matchDP(sequence1[0:101], sequence2[0:101])


import pandas as pd
import logging
import pickle
import math
import matplotlib.pyplot as plt
import numpy as np

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s - %(pathname)s: line %(lineno)d'))
logger.addHandler(handler)

def convert_age_from_days_to_years(age_in_days: pd.Series) -> int:
    """Convert age in days into age in years"""
    age_in_years = age_in_days['age'] / 365
    return math.floor(age_in_years)

def extractqrcode(row: pd.Series) -> str:
    """Extract just the qrcode from them path"""
    return row['storage_path'].split('/')[1]

def draw_age_distribution(scans: pd.DataFrame):
    value_counts = scans['Years'].value_counts().sort_index(ascending=True)
    age_ax = value_counts.plot(kind='bar')
    age_ax.set_xlabel('age')
    age_ax.set_ylabel('no. of scans')
    print(value_counts)

def draw_sex_distribution(scans: pd.DataFrame):
    value_counts = scans['sex'].value_counts().sort_index(ascending=True)
    ax = value_counts.plot(kind='bar')
    ax.set_xlabel('gender')
    ax.set_ylabel('no. of scans')
    print(value_counts)

def _count_rows_per_age_bucket(artifacts):
    age_buckets = list(range(5))
    count_per_age_group = [artifacts[artifacts['Years'] == age].shape[0] for age in age_buckets]
    df_out = pd.DataFrame(count_per_age_group)
    df_out = df_out.T
    df_out.columns = age_buckets
    return df_out

def calculate_code_age_distribution(artifacts: pd.DataFrame, scan_type_colname: str) -> pd.DataFrame:
    logger.info(scan_type_colname)
    codes = list(artifacts[scan_type_colname].unique())
    dfs = []
    for code in codes:
        df = _count_rows_per_age_bucket(artifacts[artifacts[scan_type_colname] == code])
        df.rename(index={0: code}, inplace=True)
        dfs.append(df)
    result = pd.concat(dfs)
    result.index.name = 'codes'
    return result

def find_outliers(df: pd.DataFrame, column: str, condition: str, data_id_name: str) -> list:
    combined_condition = '@df.' + column + condition
    print(f'Running the following query: {combined_condition}')
    outlier_artifacts = df.query(combined_condition)
    unique_outliers = outlier_artifacts.drop_duplicates(subset=data_id_name, keep='first')
    outliers = unique_outliers[data_id_name].tolist()
    print(f'No. of outliers: {len(outliers)}')
    return outliers

def display_images(images: list, grid_size: int, axes):
    current_file_number = 0
    for image_filename in images:
        x_position = current_file_number % grid_size
        y_position = current_file_number // grid_size
        plt_image = plt.imread(image_filename)
        rot_image = np.rot90(plt_image, 3)
        axes[x_position, y_position].imshow(rot_image)
        current_file_number += 1
    plt.subplots_adjust(left=0.0, right=1.0, bottom=0.0, top=1.0)

def display_depthmaps(depth: list, grid_size: int, axes):
    current_file_number = 0
    for depth_filename in depth:
        x_position = current_file_number % grid_size
        y_position = current_file_number // grid_size
        infile = open(depth_filename, 'rb')
        depthmap = pickle.load(infile)
        axes[x_position, y_position].imshow(np.squeeze(depthmap[0]))
        current_file_number += 1
    plt.subplots_adjust(left=0.0, right=1.0, bottom=0.0, top=1.0)