from __future__ import absolute_import #NEEDS TO STAY AS TOP LEVEL MODULE FOR Py2-3 COMPATIBILITY
import vtk
import sys

from vmtk import pypes

class vmtkNetworkWriter(pypes.pypeScript):

    def __init__(self):

        pypes.pypeScript.__init__(self)

        self.Format = ''
        self.GuessFormat = 1
        self.OutputFileName = ''
        self.Network = None
        self.Input = None
        self.InputUnits = 'mm'

        self.RadiusArrayName = 'Radius'
        self.LabelsArrayName = 'Labels'

        self.SetScriptName('vmtknetworkwriter')
        self.SetScriptDoc('write network to disk')
        self.SetInputMembers([
            ['Network','i','vtkPolyData',1,'','the input network','vmtksurfacereader'],
            ['Format','f','str',1,'["vtkxml","vtk","arch"]','file format'],
            ['InputUnits','u','str',1,'["mm","cm","m"]','units in which the input network is represented'],
            ['GuessFormat','guessformat','bool',1,'','guess file format from extension'],
            ['RadiusArrayName','radiusarray','str',1,'','name of the point data array where radius is stored (arch format)'],
            ['LabelsArrayName','labelsarray','str',1,'','name of the cell data array where labels are stored (arch format)'],
            ['OutputFileName','ofile','str',1,'','output file name'],
            ['OutputFileName','o','str',1,'','output file name (deprecated: use -ofile)']
            ])
        self.SetOutputMembers([])

    def WriteVTKNetworkFile(self):
        if self.OutputFileName == '':
            self.PrintError('Error: no OutputFileName.')
        self.PrintLog('Writing VTK network file.')
        writer = vtk.vtkPolyDataWriter()
        writer.SetInputData(self.Network)
        writer.SetFileName(self.OutputFileName)
        writer.Write()

    def WriteVTKXMLNetworkFile(self):
        if self.OutputFileName == '':
            self.PrintError('Error: no OutputFileName.')
        self.PrintLog('Writing VTK XML network file.')
        writer = vtk.vtkXMLPolyDataWriter()
        writer.SetInputData(self.Network)
        writer.SetFileName(self.OutputFileName)
        #writer.SetDataModeToAscii()
        writer.Write()

    def WriteARCHNetworkFile(self):
        if self.OutputFileName == '':
            self.PrintError('Error: no OutputFileName.')
        self.PrintLog('Writing ARCH network file.')

        factor = 1.0
        if self.InputUnits == 'cm':
          factor = 0.01
        elif self.InputUnits == 'mm':
          factor = 0.001

        radiusArray = None
        if self.RadiusArrayName:
            radiusArray = self.Network.GetPointData().GetArray(self.RadiusArrayName)

        labelsArray = None
        if self.LabelsArrayName != '':
            labelsArray = vtk.vtkStringArray.SafeDownCast(self.Network.GetCellData().GetAbstractArray(self.LabelsArrayName))

        from xml.dom import minidom
        xmlDocument = minidom.Document()
        xmlNetworkGraph = xmlDocument.appendChild(xmlDocument.createElement('NetworkGraph'))
        xmlNetworkGraph.setAttribute('id','1')
        xmlNetworkGraph.setAttribute('version','3.0')
        xmlNetworkGraph.setAttribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance')
        xmlNetworkGraph.setAttribute('xsi:noNamespaceSchemaLocation','vascular_network_v2.3.xsd')
        xmlCase = xmlNetworkGraph.appendChild(xmlDocument.createElement('case'))
        xmlPatientId = xmlCase.appendChild(xmlDocument.createElement('patient_id'))
        xmlPatientId.appendChild(xmlDocument.createTextNode('00000'))
        xmlVisit = xmlCase.appendChild(xmlDocument.createElement('visit'))
        xmlVisit.appendChild(xmlDocument.createTextNode('other'))

        nodeMap = {}
        edgeCellIds = []
        edges = []
        for i in range(self.Network.GetNumberOfCells()):
            cell = self.Network.GetCell(i)
            if not (cell.GetCellType() in (3,4)):
                continue
            pointId0 = cell.GetPointId(0)
            pointId1 = cell.GetPointId(cell.GetNumberOfPoints()-1)
            if pointId0 not in nodeMap:
                nodeId = len(nodeMap)
                nodeMap[pointId0] = nodeId
            if pointId1 not in nodeMap:
                nodeId = len(nodeMap)
                nodeMap[pointId1] = nodeId
            edgeId = len(edges)
            edgeCellIds.append(edgeId)
            edges.append((nodeMap[pointId0],nodeMap[pointId1]))
        nodes = list(nodeMap.values())[:]
        nodes.sort()

        xmlNodes = xmlNetworkGraph.appendChild(xmlDocument.createElement('nodes'))

        for node in nodes:
            xmlNode = xmlNodes.appendChild(xmlDocument.createElement('node'))
            xmlNode.setAttribute('id','%d' % node)
            #xmlNodeClassification = xmlNode.appendChild(xmlDocument.createElement('node_classification'))

        xmlEdges = xmlNetworkGraph.appendChild(xmlDocument.createElement('edges'))

        for i in range(len(edges)):
            edge = edges[i]
            xmlEdge = xmlEdges.appendChild(xmlDocument.createElement('edge'))
            xmlEdge.setAttribute('id','%d' % i)
            xmlEdge.setAttribute('node1_id','%d' % edge[0])
            xmlEdge.setAttribute('node2_id','%d' % edge[1])
            if labelsArray:
               label = labelsArray.GetValue(edgeCellIds[i])
               if 'aorta' in label or 'artery' in label or 'art' in label or 'a.' in label:
                   xmlEdge.setAttribute('side','arterial')
               if 'vena' in label or 'vein' in label or 'v.' in label:
                   xmlEdge.setAttribute('side','venous')
               xmlEdge.setAttribute('name',label)
            else:
               xmlEdge.setAttribute('side','arterial')
               xmlEdge.setAttribute('name','edge%d' % i)

            #xmlEdgeClassification = xmlEdge.appendChild(xmlDocument.createElement('edge_classification'))
            #if labelsArray:
            #    label = labelsArray.GetValue(edgeCellIds[i])
            #    if 'aorta' in label or 'artery' in label or 'art' in label or 'a.' in label:
            #        xmlEdgeClassification.setAttribute('side','arterial')
            #    if 'vena' in label or 'vein' in label or 'v.' in label:
            #        xmlEdgeClassification.setAttribute('side','venous')
            #    xmlEdgeClassification.appendChild(xmlDocument.createTextNode(label))
            xmlGeometry = xmlEdge.appendChild(xmlDocument.createElement('geometry'))

            length = 0.0
            cell = self.Network.GetCell(edgeCellIds[i])
            cellPoints = cell.GetPoints()
            prevPoint = cellPoints.GetPoint(0)
            abscissas = [0.0]
            coordinates = [[factor*el for el in prevPoint]]
            for j in range(1,cell.GetNumberOfPoints()):
                point = cellPoints.GetPoint(j)
                length += factor * vtk.vtkMath.Distance2BetweenPoints(prevPoint,point)**0.5
                abscissas.append(length)
                coordinates.append([factor*el for el in point])
                prevPoint = point

            xmlLength = xmlGeometry.appendChild(xmlDocument.createElement('length'))
            xmlLength.setAttribute('unit','m')
            xmlScalar = xmlLength.appendChild(xmlDocument.createElement('scalar'))
            xmlScalar.appendChild(xmlDocument.createTextNode('%f' % length))
            xmlCoordinatesArray = xmlGeometry.appendChild(xmlDocument.createElement('coordinates_array'))
            for j in range(len(abscissas)):
                xmlCoordinates = xmlCoordinatesArray.appendChild(xmlDocument.createElement('coordinates'))
                #TODO: check for length == 0
                xmlCoordinates.setAttribute('s','%f' % (abscissas[j]/length))
                xmlCoordinates.setAttribute('x','%f' % coordinates[j][0])
                xmlCoordinates.setAttribute('y','%f' % coordinates[j][1])
                xmlCoordinates.setAttribute('z','%f' % coordinates[j][2])

            xmlProperties = xmlEdge.appendChild(xmlDocument.createElement('properties'))

            if radiusArray:
                xmlRadiusArray = xmlProperties.appendChild(xmlDocument.createElement('radius_array'))
                xmlRadiusArray.setAttribute('unit','m')
                for j in range(cell.GetNumberOfPoints()):
                    pointId = cell.GetPointId(j)
                    radius = factor * radiusArray.GetTuple1(pointId)
                    xmlValue = xmlRadiusArray.appendChild(xmlDocument.createElement('value'))
                    xmlValue.setAttribute('s','%f' % (abscissas[j]/length))
                    xmlScalar = xmlValue.appendChild(xmlDocument.createElement('scalar'))
                    xmlScalar.appendChild(xmlDocument.createTextNode('%f' % radius))

        #xmlTransformations = xmlNetworkGraph.appendChild(xmlDocument.createElement('transformations'))

        xmlFile = open(self.OutputFileName,'w')
        xmlFile.write(xmlDocument.toprettyxml())
        xmlFile.close()

    def Execute(self):

        if self.Network == None:
            if self.Input == None:
                self.PrintError('Error: no Network.')
            self.Network = self.Input

        extensionFormats = {'vtp':'vtkxml',
                            'vtkxml':'vtkxml',
                            'xml':'arch'}

        if self.OutputFileName == 'BROWSER':
            import tkinter.filedialog
            import os.path
            initialDir = pypes.pypeScript.lastVisitedPath
            self.OutputFileName = tkinter.filedialog.asksaveasfilename(title="Output network",initialdir=initialDir)
            pypes.pypeScript.lastVisitedPath = os.path.dirname(self.OutputFileName)
            if not self.OutputFileName:
                self.PrintError('Error: no OutputFileName.')

        if self.GuessFormat and self.OutputFileName and not self.Format:
            import os.path
            extension = os.path.splitext(self.OutputFileName)[1]
            if extension:
                extension = extension[1:]
                if extension in list(extensionFormats.keys()):
                    self.Format = extensionFormats[extension]

        if (self.Format == 'vtk'):
            self.WriteVTKNetworkFile()
        elif (self.Format == 'vtkxml'):
            self.WriteVTKXMLNetworkFile()
        elif (self.Format == 'arch'):
            self.WriteARCHNetworkFile()
        else:
            self.PrintError('Error: unsupported format '+ self.Format + '.')

if __name__=='__main__':
    main = pypes.pypeMain()
    main.Arguments = sys.argv
    main.Execute()


#!/usr/bin/env python

"""
Method of Characteristics Code
Written by Paul Romano for MIT 22.212

The workhorse of this MOC code is the MOC class itself. All the
representation of the geometry is handled external to this module in
the geometry.py file.
"""

from __future__ import division, print_function

from numpy import *
from scipy import *
from matplotlib.pyplot import *

import geometry as geom

class MOC(object):
    """
    Main method of characteristics class which can solve fixed source
    and eigenvalue problems.

    Attributes:
      nangle    = number of azimuthal angles in (0,2*pi)
      delta     = desired track spacing
      boundary  = boundary condition (e.g. 'reflective')
      geometry  = associated <Geometry> object
      polarquad = associated <Quadrature> object
      tracks    = list of tracks indexed by angle

    Physics Methods:
      makeTracks     = generate cyclic tracks over a rectangular region
      makeReflective = create references from track to track for reflective BCs
      makePeriodic   = create references from track to track for periodic BCs
      makeSegments   = divide tracks into segments based on geometry
      solve          = solve a fixed source problem
      solveKeff      = solve an eigenvalue problem

    Other Methods:
      __init__       = initialize an <MOC> object
      __iter__       = ability to loop over all tracks
      setup          = generate tracks, BCs, and segments all at once
      execute        = run a method and display OK if it didn't fail
      drawSegments   = use matplotlib to draw all segments
      findRegion     = find a region by name
    """

    def __init__(self, geometry = None):
        """Create a <MOC> object with the given geometry and set
        default parameters for number of azimuthal angles, track spacing,
        """

        self.nangle = 16
        self.delta = 0.05
        self.boundary = 'periodic'
        self.geometry = geometry

        self.polarquad = Quadrature()
        self.polarquad.TabuchiYamamoto(3)

    def makeTracks(self):
        """Generate tracks based on the specified number of azimuthal
        angle, subdivisions, and track spacing.
        """

        # Geometry preliminaries
        w = self.geometry.width            # Width of 2D domain
        h = self.geometry.height           # Height of 2D domain
        if self.boundary == 'reflective':  # Azimuthal angle subdivision, e.g. div=2 is (0,pi)
            self.div = 2
        elif self.boundary == 'periodic' or self.boundary == 'white':
            self.div = 4
        nangle = self.nangle//self.div     # Num of azimuthal angles followed

        #Determine azimuthal angles
        intv = vectorize(int)
        p = 2*pi/self.nangle*(0.5+arange(nangle))      # Desired angles
        self.nx = intv(abs(w/self.delta*sin(p)) + 1)   # Num of intersections along x-axis
        self.ny = intv(abs(h/self.delta*cos(p)) + 1)   # Num of intersections along y-axis
        self.nt = self.nx + self.ny                    # Total num of tracks for each angle
        self.phi = arctan(h*self.nx/(w*self.ny))       # Actual angle
        for i, angle in enumerate(self.phi):
            if p[i] > pi/2:
                self.phi[i] = pi - self.phi[i]         # Fix angles in (pi/2, pi)

        # Determine track spacing
        xprime = w/self.nx                             # Spacing between points along x-axis
        yprime = h/self.ny                             # Spacing between points along y-axis
        self.dels = xprime*sin(self.phi)               # Actual track spacing

        # Determine azimuthal weights
        temp1 = concatenate((self.phi,[2*pi/self.div]+self.phi[0]))
        temp2 = concatenate((-self.phi[0:1],self.phi))
        x1 = 0.5*(temp1[1:]-temp1[:-1])
        x2 = 0.5*(temp2[1:]-temp2[:-1])
        self.wgta = (x1 + x2)/(2*pi)*self.dels*self.div

        # Determine coordinates
        self.tracks = []
        for i in range(nangle):
            xin = zeros(self.nt[i])
            yin = zeros(self.nt[i])

            phi = self.phi[i]
            xin[:self.nx[i]] = xprime[i]*(0.5 + arange(self.nx[i]))
            yin[:self.nx[i]] = 0
            yin[self.nx[i]:] = yprime[i]*(0.5 + arange(self.ny[i]))
            if sin(phi) > 0 and cos(phi) > 0:
                xin[self.nx[i]:] = 0
            elif sin(phi) > 0 and cos(phi) < 0:
                xin[self.nx[i]:] = w
            self.tracks.append([])
            for x,y in zip(xin,yin):
                r_in = geom.Vector2D(x,y)
                r_out = self.geometry.endpoint(r_in,phi)
                newTrack = Track2D(r_in, r_out, phi)
                newTrack.weight = self.wgta[i]          # Could make index on track to get rid of this
                self.tracks[i].append(newTrack)

    def makeReflective(self):
        """Determine the outgoing and incoming tracks for each track
        for the purpose of treating reflective boundary
        conditions. Also, we need to determine whether the flux going
        out of one track will go into the beginning or the end of the
        outgoing track.

        track            <---- current track
        track.track_out  <---- outgoing track
        track.track_in   <---- incoming track
        track.refl_in    <---- outgoing flux (when tracking in reverse)
                               at start (0)/end (1) of incoming track
        track.refl_out   <---- outgoing flux at start/end of outgoing track
        """

        nangle = self.nangle//2

        # Determine reflected tracks -- we only need to loop over half
        # the angles because we are going to set pointers for
        # connecting tracks as well
        for i in range(nangle//2):
            nx = self.nx[i]
            ny = self.ny[i]
            nt = self.nt[i]
            tracks_refl = self.tracks[-(i+1)]

            for j,track in enumerate(self.tracks[i]):
                # More points along y-axis
                if nx <= ny:
                    if j < nx:
                        # Bottom to right side
                        track.track_in          = tracks_refl[j]
                        track.track_in.track_in = track
                        track.refl_in           = 0
                        track.track_in.refl_in  = 0

                        track.track_out          = tracks_refl[2*nx-1-j]
                        track.track_out.track_in = track
                        track.refl_out           = 0
                        track.track_out.refl_in  = 1
                    elif j < ny:
                        # Left side to right side
                        track.track_in           = tracks_refl[j-nx]
                        track.track_in.track_out = track
                        track.refl_in            = 1
                        track.track_in.refl_out  = 0

                        track.track_out          = tracks_refl[j+nx]
                        track.track_out.track_in = track
                        track.refl_out           = 0
                        track.track_out.refl_in  = 1
                    else:
                        # Left side to top side
                        track.track_in           = tracks_refl[j-nx]
                        track.track_in.track_out = track
                        track.refl_in            = 1
                        track.track_in.refl_out  = 0

                        track.track_out           = tracks_refl[-(nx-(nt-j)+1)]
                        track.track_out.track_out = track
                        track.refl_out            = 1
                        track.track_out.refl_out  = 1

                # More points along x-axis
                else:
                    if j < nx - ny:
                        # Bottom to top
                        track.track_in          = tracks_refl[j]
                        track.track_in.track_in = track
                        track.refl_in           = 0
                        track.track_in.refl_in  = 0

                        track.track_out           = tracks_refl[nt-(nx-ny)+j]
                        track.track_out.track_out = track
                        track.refl_out            = 1
                        track.track_out.refl_out  = 1
                    elif j < nx:
                        # Bottom to right side
                        track.track_in          = tracks_refl[j]
                        track.track_in.track_in = track
                        track.refl_in           = 0
                        track.track_in.refl_in  = 0

                        track.track_out          = tracks_refl[nx+(nx-j)-1]
                        track.track_out.track_in = track
                        track.refl_out           = 0
                        track.track_out.refl_in  = 1
                    else:
                        # Left side to top
                        track.track_in           = tracks_refl[j-nx]
                        track.track_in.track_out = track
                        track.refl_in            = 1
                        track.track_in.refl_out  = 0

                        track.track_out           = tracks_refl[ny+(nt-j)-1]
                        track.track_out.track_out = track
                        track.refl_out            = 1
                        track.track_out.refl_out  = 1

    def makePeriodic(self):
        """Determine the outgoing track for each track for the purpose
        of treating periodic (or white) boundary conditions.

        track            <---- current track
        track.track_out  <---- outgoing track
        """

        nangle = self.nangle//4

        # Determine reflected tracks
        for i in range(nangle):
            nx = self.nx[i]
            ny = self.ny[i]
            nt = self.nt[i]
            tracks = self.tracks[i]

            for j,track in enumerate(tracks):
                # Always pass flux to beginning of next track
                track.refl_out = 0

                # More points along y-axis
                if nx <= ny:
                    if j < nx:
                        # Bottom to right side
                        track.track_out = tracks[2*nx-1-j]
                    elif j < ny:
                        # Left side to right side
                        track.track_out = tracks[j+nx]
                    else:
                        # Left side to top side
                        track.track_out = tracks[nt-1-j]

                # More points along x-axis
                else:
                    if j < nx - ny:
                        # Bottom to top
                        track.track_out = tracks[ny+j]
                    elif j < nx:
                        # Bottom to right side
                        track.track_out = tracks[nx+(nx-j)-1]
                    else:
                        # Left side to top
                        track.track_out = tracks[nt-1-j]

    def makeSegments(self):
        """Generate a segment for each part of each track that goes
        through a different flat source region. This method is not
        completely general right now and takes advantage of the fact
        that I know I only have two regions
        """

        fuel = self.findRegion('fuel')
        water = self.findRegion('water')
        circle = fuel.cell.surface

        for r in self.geometry:
            r.volume_calc = 0
            r.segments = []

        nangle = self.nangle//self.div
        for i in range(nangle):
            phi = self.phi[i]
            delta = self.dels[i]
            for track in self.tracks[i]:
                phi = track.phi
                r_in = track.r_in
                r_out = track.r_out
                intersect = circle.intersectLine(r_in,phi)
                intersect.insert(0, r_in)
                intersect.append(r_out)
                self.pairs = zip(intersect[:-1], intersect[1:])
                for r0, r1 in self.pairs:
                    if (r0 != r_in and r1 != r_out):
                        s = Segment(fuel, r0, r1)
                    else:
                        s = Segment(water, r0, r1)
                    track.segments.append(s)
                    s.region.segments.append(s)

                    # Calculate volume based on tracks
                    s.region.volume_calc += s.length*track.weight

        # Correct segment lengths based on tracking error
        for r in self.geometry:
            r.factor = r.volume / r.volume_calc
            for s in r.segments:
                s.length *= r.factor

    def solve(self):
        """Solve the backwards characteristic form of the transport
        equation over the domain with a fixed source (assumed to be
        flat in each region). We start by assuming that the fluxes on
        all the boundaries are zero and then iterate until they
        converge."""

        fuel = self.findRegion('fuel')
        water = self.findRegion('water')

        # Precompute exponential factor and set incoming fluxes to zero
        for track in self:
            track.flux_in = zeros((2,3))
            for s in track:
                sigma = s.region.sigma_t
                sintheta = self.polarquad.sin
                s.factor = 1.0 - exp(-sigma*s.length/sintheta)

        # Iterate on incoming fluxes on domain boundary
        max_iterations = 100
        for i_boundary in range(max_iterations):
            #print("Inner iteration {0}".format(i_boundary))

            # Initialize volume flux to zero
            for r in self.geometry:
                r.flux = 0

            # Loop over polar angles
            for j, (sintheta, wgtp) in enumerate(self.polarquad):

                # Loop over each track
                for track in self:
                    # Need to divide total weight for each track by 2
                    # since we are tracking forwards and backwards
                    weight = 4*pi*track.weight*wgtp*sintheta

                    # Loop over each segment in track
                    flux = track.flux_in[0,j]
                    if i_boundary == 0:
                        flux = 0
                    for s in track:
                        r = s.region
                        delta = (flux - r.source/r.sigma_t)*s.factor[j]
                        r.flux += delta*weight
                        flux -= delta

                    # Transfer flux to outgoing track
                    track.track_out.flux_in[track.refl_out,j] = flux

                    # Now traverse this track in reverse for reflective
                    if self.boundary == "reflective":
                        flux = track.flux_in[1,j]
                        if i_boundary == 0:
                            flux = 0
                        for s in track.segments[::-1]:
                            r = s.region
                            delta = (flux - r.source/r.sigma_t)*s.factor[j]
                            r.flux += delta*weight
                            flux -= delta

                        # Transfer flux to incoming track
                        track.track_in.flux_in[track.refl_in,j] = flux

            if self.boundary == 'white':
                # Find average angular flux on boundary
                totalFlux = 0
                for track in self:
                        totalFlux += sum(track.flux_in[0,:])
                ntrack = len([t for t in self])*len(self.polarquad)
                averageFlux = totalFlux/ntrack

                # Set boundary fluxes to average flux
                for track in self:
                    track.flux_in[0,:] = averageFlux

            # Add in source and normalize to volume
            for r in self.geometry:
                if self.boundary == "reflective":
                    r.flux /= 2
                r.flux = 4*pi*r.source/r.sigma_t + r.flux/(r.sigma_t*r.volume)

            # Save source in fuel for Dancoff factor
            if i_boundary == 0:
                fuel.flux0 = fuel.flux

            # Check if converged
            fluxv = array([r.flux for r in self.geometry])
            if i_boundary > 0:
                if all(abs((fluxv - fluxvold)/fluxvold) < 1e-10):
                    return
            fluxvold = fluxv

    def solveKeff(self, max_outer = 1000):
        """Using the fixed source kernel from above, iterate on the
        scattering and fission sources until they converge (outer
        iterations)."""

        # Initial guess
        S_old = {}
        S = {}
        for r in self.geometry:
            S_old[r] = 1
        k_old = 1.0

        # Loop over outer iterations
        for i_outer in range(max_outer):
            # Inner iteration
            for r in self.geometry:
                scatter = r.sigma_s*r.flux/(4*pi)
                r.source = 1/(4*pi*k_old)*S_old[r] + scatter
            self.solve()

            # Outer iteration
            for r in self.geometry:
                S[r] = r.nusigma_f*r.flux
            keff = k_old*sum(S.values())/sum(S_old.values())

            print("i = {0}, keff = {1}".format(i_outer, keff))
            if abs(keff - k_old) < 1e-7:
                break

            # Update source
            k_old = keff
            for r in self.geometry:
                S_old[r] = S[r]

    def setup(self, output=True):
        """Generate tracks, segments, and link tracks together for
        treating boundary conditions"""

        # Determine which routine to use for boundary conditions
        if self.boundary == 'reflective':
            makeBCs = self.makeReflective
        elif self.boundary == 'periodic' or self.boundary == 'white':
            makeBCs = self.makePeriodic

        # Generate tracks, BCs, segments
        if output:
            self.execute(self.makeTracks, 'Generating tracks...')
            self.execute(makeBCs, 'Generating boundary conditions...')
            self.execute(self.makeSegments, 'Generating segments...')
        else:
            self.makeTracks()
            makeBCs()
            self.makeSegments()

    def execute(self, func, output):
        """Run a subroutine with the specified output and indicate
        whether the subroutine ran to completion (OK) or failed
        (FAILED).
        """

        print(output, end='')
        try:
            func()
        except:
            print('\x1b[40G[ \x1b[31mFAILED\x1b[0m ]')
            raise
        print('\x1b[40G[   \x1b[32mOK\x1b[0m   ]')

    def drawSegments(self):
        """Draw all the segments over the domain. If the segment is in
        the fuel, it is represented by a black line whereas segments
        in the moderator are represented by blue lines.
        """

        for track in self:
            for s in track:
                if s.region == self.findRegion('fuel'):
                    s.plot()
                else:
                    s.plot('b-')

    def findRegion(self, name):
        """Find a region by its name"""

        return self.geometry.regionsByName[name]

    def __iter__(self):
        for i in range(len(self.phi)):
            for track in self.tracks[i]:
                yield track

class Track2D(object):
    """
    A single characteristic track drawn through the geometry. Each
    track is made up of segments in each flat source region.

    Attributes:
      r_in      = <Vector2D> object representing the starting coordinates
      r_out     = <Vector2D> object representing the ending coordinates
      track_in  = <Track2D> object that connects at end of this track
      track_out = <Track2D> object that connects at beginning of this track
      segments  = a list of all the segments in this track
      phi       = azimuthal angle
      weight    = weight for this track

    Methods:
      plot     = draw the track based on r_in and r_out
      __iter__ = enable ability to iterate over segments in a track
      __repr__ = text representation of track
    """

    def __init__(self, r_in, r_out, phi):
        """Create a 2D track within problem domain"""

        self.r_in      = r_in  # Incoming coordinates
        self.r_out     = r_out # Outgoing coordinates
        self.track_in  = None  # Incoming track for boundary conditions
        self.track_out = None  # Outgoing track for boundary conditions
        self.segments  = []    # Segments within track

        # Could get rid of these and replace with index since the
        # weight is linked to angle
        self.phi      = phi   # Angle
        self.weight   = 0     # Weight of track

    def plot(self, linespec = 'k-'):
        """Draw the track with optionally specified linespec"""

        plot([self.r_in.x, self.r_out.x],
             [self.r_in.y, self.r_out.y],
             linespec)

    def __iter__(self):
        for segment in self.segments:
            yield segment

    def __repr__(self):
        return "<Track2D: ({0.x},{0.y}) --> ({1.x},{1.y}), phi = {2}>".format(
            self.r_in, self.r_out, self.phi)

class Segment(object):
    """
    A single segment over one flat source region. Each track has a
    list of these segments.

    Attributes:
      length = length of the track in centimeters
      region = reference to the flat source <Region> object
      r0     = <Vector2D> object of starting coordinates
      r1     = <Vector2D> object of ending coordinates

    Methods:
      plot     = draw the segment
      __init__ = initialize a segment
      __repr__ = text representation of segment
    """

    def __init__(self, region, r0, r1):
        self.region = region
        self.r0 = r0
        self.r1 = r1
        self.length = self.r0.distance(self.r1)

    def plot(self, linespec = 'k-'):
        """Draw the segment with optionally specified linespec"""

        plot([self.r0.x, self.r1.x],
             [self.r0.y, self.r1.y],
             linespec)

    def __repr__(self):
        return "<Segment: {0}>".format(self.length)

class Quadrature(object):
    """
    Polar quadrature used for method of characteristics. Right now the
    only options are to use the Leonard optimized quadrature of the
    Tabuchi-Yamamoto quadrature.

    Attributes:
      sin    = sin of the polar angle (measured from z-axis)
      weight = corresponding polar weight

    Methods:
      TabuchiYamamoto = set quadrature to a TY quadrature
      Leonard         = set quadrature to Leonard optimized quadrature
      __init__        = initialize quadrature
      __iter__        = enable ability to iterate over pairs of (sin, weight)
    """

    def __init__(self):
        self.sin = []
        self.weight = []

    def __iter__(self):
        for i in range(len(self.sin)):
            yield (self.sin[i], self.weight[i])

    def __len__(self):
        return len(self.sin)

    def TabuchiYamamoto(self, n):
        """
        Set the polar angles and weights according to the
        Tabuchi-Yamamoto polar quadrature derived in A. Yamamoto et
        al., "Derivation of Optimum Polar Angle Quadrature Set for the
        Method of Characteristics Based on Approximation Error for the
        Bickley Function," J. Nucl. Sci. Tech., 44 (2), pp. 129-136
        (2007).
        """

        if n == 1:
            self.sin = array([0.798184])
            self.weight = array([1.0])
        elif n == 2:
            self.sin = array([0.363900, 0.899900])
            self.weight = array([0.212854, 0.787146])
        elif n == 3:
            self.sin = array([0.166648, 0.537707, 0.932954])
            self.weight = array([0.046233, 0.283619, 0.670148])

    def Leonard(self, n):
        """
        Set the polar angles and weights according to the Leonord
        Optimized polar quadrature from A. Leonard and C. McDaniel,
        "Optimal Polar Angles and Weight for the Characteristics
        Method," Trans. Am. Nucl. Soc., 73, pp. 172-173 (1995) as well
        as R. Le Tellier and A. Hebert, "Anisotropy and Particle
        Conservation for Trajectory-Based Deterministic Methods,"
        Nucl. Sci. Eng., 158, pp. 28-39 (2008).
        """

        if n == 2:
            self.sin = array([0.273658, 0.865714])
            self.weight = array([0.139473, 0.860527])
        elif n == 3:
            self.sin = array([0.099812, 0.395534, 0.891439])
            self.weight = array([0.017620, 0.188561, 0.793819])

################################################################################
######################### Subroutines for HW problems ##########################
################################################################################

def Problem1Part1():
    """Create table of fuel/coolant flux ratio as a function of ray
    spacing and number of azimuthal angles for fuel xs = 1.0 and
    coolant xs = 0.1
    """

    g = makeGeometry()
    m = MOC(g)

    # Adjust fuel cross-sections
    fuel = m.findRegion('fuel')
    fuel.sigma_t = 1
    fuel.source = 1./(4*pi)

    # Adjust moderator cross-sections
    water = m.findRegion('water')
    water.sigma_t = 0.1
    water.source = 0.

    for bc in ['periodic', 'white']:
        m.boundary == bc
        for nangle in [16,32,64,128,256,512]:
            for spacing in [0.10, 0.05, 0.02, 0.01]:
                m.nangle = nangle
                m.delta = spacing
                m.setup(output=False)
                m.solve()
                print("{0} {1} {2} {3}".format(bc, nangle, spacing,
                                               fuel.flux/water.flux))

def Problem1Part2():
    """Make six tables of Dancoff factor (fuel xs = infinity) and
    coolant xs = 0, 1, and infinity as a function of ray spacing and
    number of azimuthal angles
    """

    g = makeGeometry()
    m = MOC(g)

    # Adjust fuel cross-sections
    fuel = m.findRegion('fuel')
    fuel.sigma_t = 1e5
    fuel.source = 1./(4*pi)

    # Adjust moderator cross-sections
    water = m.findRegion('water')
    water.source = 0.

    for bc in ['periodic', 'white']:
        m.boundary = bc
        for sigma_t in [1e-5, 1, 1e5]:
            water.sigma_t = sigma_t
            for nangle in [16,32,64,128,256,512]:
                m.nangle = nangle
                for spacing in [0.10, 0.05, 0.02, 0.01]:
                    m.delta = spacing
                    m.setup(output=False)
                    m.solve()
                    dancoff = (1 - (fuel.source/fuel.sigma_t*4*pi - fuel.flux)/
                               (fuel.source/fuel.sigma_t*4*pi - fuel.flux0))
                    print("{0} {1} {2} {3} {4}".format(
                            bc, sigma_t, nangle, spacing, dancoff))

def Problem2():
    """Using the code from problem 1 and the 1-group xs data of HW2,
    write an eigenvalue solver for the pin-cell geometry with
    reflective boundary conditions and compare your results to the
    ones obtained with your CPM code.
    """

    g = makeGeometry()
    m = MOC(g)
    m.boundary = 'reflective'
    m.nangle = 128

    # Adjust fuel cross-sections
    fuel = m.findRegion('fuel')
    fuel.sigma_t = 4.52648699E-01
    fuel.sigma_s = 3.83259177E-01
    fuel.nusigma_f = 9.94076580E-02

    # Adjust moderator cross-sections
    water = m.findRegion('water')
    water.sigma_t = 8.41545641E-01
    water.sigma_s = 8.37794542E-01
    water.nusigma_f = 0.

    # Solve eigenvalue problem
    m.setup(output=False)
    m.solveKeff()

def makeGeometry():
    pitch = 1.27
    circle = geom.Circle(pitch/2, pitch/2, 0.4)
    fuelCell = geom.SurfaceNode(circle, False)
    waterCell = geom.SurfaceNode(circle, True)

    fuel = geom.Region('fuel')
    fuel.cell = fuelCell
    fuel.volume = circle.area()

    water = geom.Region('water')
    water.cell = waterCell
    water.volume = pitch**2 - circle.area()

    g = geom.Geometry(pitch, pitch)
    g.addRegion(fuel)
    g.addRegion(water)
    return g


#!/usr/local/bin/python3
#-*- coding: utf-8 -*-
# Глава 15. Сервер PyMailCGI.
# Вспомогательные модули.
# Внешние компоненты и настройки.
# Пример 16.11 (Лутц Т2 стр.644)
"""
# ---------------------------------------------------------------------------- #
Пользовательские настройки для различных почтовых программ
(версия для PyMailCGI);
Сценарии для работы с электронной почтой получают имена серверов и другие
параметры из этого модуля: измените модуль так, чтобы он отражал имена
ваших серверов, вашу подпись и предпочтение;
# ---------------------------------------------------------------------------- #
"""

# from Tom2.ch14.myconfig import * 				# использовать настройки из главы 13
from Tom2.ch13.mailtools.resolvingConfig import mailconfig

fetchlimit = 50									# 4E: максимальное число загружаемых заголовков/сообщений
												# (по умолчанию = 25)

if __name__ == "__main__":
	import sys
	print(dir(mailconfig))
	# print(dir(__name__))
	for attr in dir(mailconfig):
		if not attr.startswith('__'):
			# print(attr, '=>', getattr(mailconfig, attr))
			setattr(sys.modules[__name__], attr, getattr(mailconfig, attr))
	print(smtpuser)


import time
import datetime
import numpy as np
from flask     import Flask
from threading import Thread
start = time.time()
update_dts = []
update_time = time.time()

app = Flask("")

@app.route("/")
def home():
  global update_time
  print("1: ", update_dts)
  print("2: ", start)
  print("3: ", update_time)
  update_dts.append(time.time() - update_time)
  update_time = time.time()

  now = datetime.datetime.today()
  now = str(now.year) + "-" + str(now.month)  + "-" + str(now.day) + " " + \
        str(now.hour) + "-" + str(now.minute) + "-" + str(now.second)

  text  = "I've been running for " + str(time.time()-start) + " seconds"
  text += "\nLast updated: " + now
  text += "\nMaximum time (in seconds) between updates: " + \
          str(np.max(np.array(update_dts)))

  return text
# end def home

def run():
  app.run(host="0.0.0.0", port=8080)

def keep_alive():
  t = Thread(target=run)
  t.start()


from sqlalchemy import create_engine
from Common import Log

Logger = Log.Logger(logger_name='检测库是否存在')
log = Logger.get_logger()

class Ku_Name:

    def Ku_(url,ku_name):
        try:
            engine = create_engine(url)
            conn = engine.connect()
            conn.execute("create database %s"%ku_name)
            conn.close()
            log.info("----->>数据库不存在---->>创建库")
        except Exception as e:
            log.error("----->>库已存在")
            return e


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

import csv

def read_csv():
    with open("Clase 1.csv") as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')
        line_count = 0
        #Lista con tuplas (correctas, total)
        list_students = list()

        for row in csv_reader:
            list_students.append(row[1])

        return list_students

def read_csv_2():
    with open("Asistencia obra Ballet.csv") as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')

        f = open("Asistencia Ballet.csv", "a")
        for row in csv_reader:
            f.write("{},{}\n".format(row[2],row[5]))
        f.close()


#  -*-  coding: utf-8  -*-
class Solution:
    def reverse(self, x: int) -> int:
        min_INF = -2147483648
        max_INF = 2147483647

        sign = -1 if x < 0 else 1

        ans = []
        x = abs(x)
        if x == 0:
            return x

        while x > 0:
            ans.append(x % 10)
            x = x // 10

        n = len(ans)
        total = 0
        tmp = 1
        for i in range(n - 1, -1, -1):
            total += ans[i] * tmp
            tmp *= 10

        if sign < 0:
            return 0 if -total < min_INF else -total
        else:
            return  0 if total > max_INF else total


import torch
import numpy as np
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
import math
from torch.autograd import Variable
import torchvision
from matplotlib.backends.backend_pdf import PdfPages

def group_product(xs, ys):
    """
    the inner product of two lists of variables xs,ys
    :param xs:
    :param ys:
    :return:
    """
    return sum([torch.sum(x * y) for (x, y) in zip(xs, ys)])

def group_add(params, update, alpha=1):
    """
    params = params + update*alpha
    :param params: list of variable
    :param update: list of data
    :return:
    """
    for i, p in enumerate(params):
        params[i].data.add_(update[i] * alpha)
    return params

def normalization(v):
    """
    normalization of a list of vectors
    return: normalized vectors v
    """
    s = group_product(v, v)
    s = s**0.5
    s = s.cpu().item()
    v = [vi / (s + 1e-6) for vi in v]
    return v

def get_params_grad(model):
    """
    get model parameters and corresponding gradients
    """
    params = []
    grads = []
    # for param in model.parameters():
    #     if not param.requires_grad:
    #         continue
    #     params.append(param)
    #     grads.append(0. if param.grad is None else param.grad + 0.)
    for name, param in model.named_parameters():
        if not param.requires_grad:
            continue
        if name.find('conv.weight') != -1 or name.find('fc.weight') != -1:
            params.append(param)
            grads.append(0. if param.grad is None else param.grad + 0.)
    return params, grads

def hessian_vector_product(gradsH, params, v):
    """
    compute the hessian vector product of Hv, where
    gradsH is the gradient at the current point,
    params is the corresponding variables,
    v is the vector.
    """
    hv = torch.autograd.grad(gradsH,
                             params,
                             grad_outputs=v,
                             only_inputs=True,
                             retain_graph=True)
    return hv

def orthnormal(w, v_list):
    """
    make vector w orthogonal to each vector in v_list.
    afterwards, normalize the output w
    """
    for v in v_list:
        w = group_add(w, v, alpha=-group_product(w, v))
    return normalization(w)

class hessian():
    """
    The class used to compute :
        i) the top 1 (n) eigenvalue(s) of the neural network
        ii) the trace of the entire neural network
        iii) the estimated eigenvalue density
    """

    def __init__(self, model, criterion, data=None, dataloader=None, cuda=True):
        """
        model: the model that needs Hessain information
        criterion: the loss function
        data: a single batch of data, including inputs and its corresponding labels
        dataloader: the data loader including bunch of batches of data
        """

        # make sure we either pass a single batch or a dataloader
        assert (data != None and dataloader == None) or (data == None and
                                                         dataloader != None)

        self.model = model.eval()  # make model is in evaluation model
        self.criterion = criterion

        if data != None:
            self.data = data
            self.full_dataset = False
        else:
            self.data = dataloader
            self.full_dataset = True

        if cuda:
            self.device = 'cuda'
        else:
            self.device = 'cpu'

        # pre-processing for single batch case to simplify the computation.
        if not self.full_dataset:
            self.inputs, self.targets = self.data
            if self.device == 'cuda':
                self.inputs, self.targets = self.inputs.cuda(
                ), self.targets.cuda()

            # if we only compute the Hessian information for a single batch data, we can re-use the gradients.
            outputs = self.model(self.inputs)
            loss = self.criterion(outputs, self.targets)
            loss.backward(create_graph=True)

        # this step is used to extract the parameters from the model
        params, gradsH = get_params_grad(self.model)
        self.params = params
        self.gradsH = gradsH  # gradient used for Hessian computation

    def dataloader_hv_product(self, v):

        device = self.device
        num_data = 0  # count the number of datum points in the dataloader

        THv = [torch.zeros(p.size()).to(device) for p in self.params
              ]  # accumulate result
        for inputs, targets in self.data:
            self.model.zero_grad()
            tmp_num_data = inputs.size(0)
            outputs = self.model(inputs.to(device))
            loss = self.criterion(outputs, targets.to(device))
            loss.backward(create_graph=True)
            params, gradsH = get_params_grad(self.model)
            self.model.zero_grad()
            Hv = torch.autograd.grad(gradsH,
                                     params,
                                     grad_outputs=v,
                                     only_inputs=True,
                                     retain_graph=False)
            THv = [
                THv1 + Hv1 * float(tmp_num_data) + 0.
                for THv1, Hv1 in zip(THv, Hv)
            ]
            num_data += float(tmp_num_data)

        THv = [THv1 / float(num_data) for THv1 in THv]
        eigenvalue = group_product(THv, v).cpu().item()
        return eigenvalue, THv

    def density(self, iter, n_v, param, gradsH):
        """
        compute estimated eigenvalue density using stochastic lanczos algorithm (SLQ)
        iter: number of iterations used to compute trace
        n_v: number of SLQ runs
        """

        device = self.device
        eigen_list_full = []
        weight_list_full = []

        for k in range(n_v):
            v = [
                torch.randint_like(p, high=2, device=device)
                for p in param
            ]
            # generate Rademacher random variables
            for v_i in v:
                v_i[v_i == 0] = -1
            v = normalization(v)

            # standard lanczos algorithm initlization
            v_list = [v]
            w_list = []
            alpha_list = []
            beta_list = []
            ############### Lanczos
            for i in range(iter):
                self.model.zero_grad()
                w_prime = [torch.zeros(p.size()).to(device) for p in param]
                if i == 0:
                    if self.full_dataset:
                        _, w_prime = self.dataloader_hv_product(v)
                    else:
                        w_prime = hessian_vector_product(
                            gradsH, param, v)
                    alpha = group_product(w_prime, v)
                    alpha_list.append(alpha.cpu().item())
                    w = group_add(w_prime, v, alpha=-alpha)
                    w_list.append(w)
                else:
                    beta = torch.sqrt(group_product(w, w))
                    beta_list.append(beta.cpu().item())
                    if beta_list[-1] != 0.:
                        # We should re-orth it
                        v = orthnormal(w, v_list)
                        v_list.append(v)
                    else:
                        # generate a new vector
                        w = [torch.randn(p.size()).to(device) for p in param]
                        v = orthnormal(w, v_list)
                        v_list.append(v)
                    if self.full_dataset:
                        _, w_prime = self.dataloader_hv_product(v)
                    else:
                        w_prime = hessian_vector_product(
                            gradsH, param, v)
                    alpha = group_product(w_prime, v)
                    alpha_list.append(alpha.cpu().item())
                    w_tmp = group_add(w_prime, v, alpha=-alpha)
                    w = group_add(w_tmp, v_list[-2], alpha=-beta)

            T = torch.zeros(iter, iter).to(device)
            for i in range(len(alpha_list)):
                T[i, i] = alpha_list[i]
                if i < len(alpha_list) - 1:
                    T[i + 1, i] = beta_list[i]
                    T[i, i + 1] = beta_list[i]
            a_, b_ = torch.eig(T, eigenvectors=True)

            eigen_list = a_[:, 0]
            weight_list = b_[0, :]**2
            eigen_list_full.append(list(eigen_list.cpu().numpy()))
            weight_list_full.append(list(weight_list.cpu().numpy()))

        return eigen_list_full, weight_list_full

    def separate_plot(self, pdf, epoch, iter=100, n_v=1):
        num = len(self.params)
        fig = plt.figure(figsize=(5*num,4))

        for i in range(num):
            eigen, weight = self.density(iter, n_v, [self.params[i]], [self.gradsH[i]])
            fig.add_subplot(1, num, i+1)
            get_esd_plot(eigen, weight, epoch, i+1)
        plt.tight_layout()
        pdf.savefig()
        plt.close()

def get_esd_plot(eigenvalues, weight, epoch, layer):
    density, grids = density_generate(eigenvalues, weight)
    # print(density.shape, grids.shape)
    # plt.semilogy(grids, density + 1.0e-7)
    plt.plot(grids, density)
    plt.ylabel('Density (Log Scale)', fontsize=8, labelpad=8)
    plt.xlabel('Eigenvlaue', fontsize=8, labelpad=8)
    plt.axis([np.min(eigenvalues) - 1, np.max(eigenvalues) + 1, None, None])
    plt.title('Epoch '+str(epoch)+' Layer ' + str(layer))
    # plt.savefig('./graph/example.pdf')

def density_generate(eigenvalues,
                     weights,
                     num_bins=10000,
                     sigma_squared=1e-5,
                     overhead=0.01):

    eigenvalues = np.array(eigenvalues)
    weights = np.array(weights)

    lambda_max = np.mean(np.max(eigenvalues, axis=1), axis=0) + overhead
    lambda_min = np.mean(np.min(eigenvalues, axis=1), axis=0) - overhead

    grids = np.linspace(lambda_min, lambda_max, num=num_bins)
    sigma = sigma_squared * max(1, (lambda_max - lambda_min))

    num_runs = eigenvalues.shape[0]
    density_output = np.zeros((num_runs, num_bins))

    for i in range(num_runs):
        for j in range(num_bins):
            x = grids[j]
            tmp_result = gaussian(eigenvalues[i, :], x, sigma)
            density_output[i, j] = np.sum(tmp_result * weights[i, :])
    density = np.mean(density_output, axis=0)
    normalization = np.sum(density) * (grids[1] - grids[0])
    density = density / normalization
    return density, grids

def gaussian(x, x0, sigma_squared):
    return np.exp(-(x0 - x)**2 /
                  (2.0 * sigma_squared)) / np.sqrt(2 * np.pi * sigma_squared)

# if __name__ == '__main__':
    # model = LeNet().cuda()
    # model.load_state_dict(torch.load("./checkpoint/minst_lenet.pkl"))
    # criterion = torch.nn.CrossEntropyLoss()
    # batch_size = 64
    # train_dataset = torchvision.datasets.MNIST(root='./data/', train=True, transform=torchvision.transforms.ToTensor())
    # train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
    # for inputs, labels in train_loader:
    #     hessian_dataloader = (inputs, labels)
    #     break

    # ######################################################
    # # Begin the computation
    # ######################################################

    # # turn model to eval mode
    # model.eval()
    # hessian_comp = hessian(model,
    #                     criterion,
    #                     data=hessian_dataloader)

    # print('********** finish data londing and begin Hessian computation **********')
    # # [100]
    # density_eigen, density_weight = hessian_comp.density()

    # get_esd_plot(density_eigen, density_weight)
    # # [10000]


import math

class EuclideanDistTracker:
    def __init__(self, time, scale):
        # Store the center positions of the objects
        self.center_points = {}
        # Keep the count of the IDs
        # each time a new object id detected, the count will increase by one
        self.id_count = 0

        self.t = time
        self.scale = scale

    def update(self, objects_rect):
        # Initialise empty array to store box parameters and ids
        objects_bbs_ids = []

        # Get center point of new object
        for rect in objects_rect:
            x, y, w, h, vel = rect
            cx = (x + x + w) // 2
            cy = (y + y + h) // 2

            # Find out if that object was detected already
            # Loops through existing center points stored in array and checks if current parsed new box and center
            # point is within 80 pixels of a center point that is currently stored
            same_object_detected = False
            for id, pt in self.center_points.items():
                dist = math.hypot(cx - pt[0], cy - pt[1])

                # If distance is less than 80 pixels, assume the newly detected particle is this old stored one and
                # add it back to new array with existing particle ID
                if dist < 80:
                    self.center_points[id] = (cx, cy)
                    # print(self.center_points)
                    vel = ((cx - pt[0]) * self.scale) / self.t
                    objects_bbs_ids.append([x, y, w, h, id, vel])
                    same_object_detected = True
                    break

            # New object is detected we assign the ID to that object
            if same_object_detected is False:
                self.center_points[self.id_count] = (cx, cy)
                objects_bbs_ids.append([x, y, w, h, self.id_count, 0])
                self.id_count += 1

        # Clean the dictionary by center points to remove IDS not used anymore
        new_center_points = {}
        for obj_bb_id in objects_bbs_ids:
            _, _, _, _, object_id, _ = obj_bb_id
            center = self.center_points[object_id]
            new_center_points[object_id] = center

        # Update dictionary with IDs not used removed
        self.center_points = new_center_points.copy()
        return objects_bbs_ids


#packages
import os
import yaml
from dataclasses import dataclass
from dacite import from_dict

#stuff
def get_bin_dir():
    """Returns the bin directory of this package"""
    return os.path.abspath(os.path.join(os.path.dirname(__file__), 'bin'))

def load_config_yaml(config, input_dir, output_dir):

    with open(f"{config}", 'r') as stream:
        try:
            settingsMap = yaml.load(stream)
        except yaml.YAMLError as exc:
            print(exc)

    # set the bin, data and analysis dir
    settingsMap['bin_dir'] = get_bin_dir()
    print (settingsMap['bin_dir'])
    settingsMap['analysis_dir_base'] = os.path.abspath(f"{output_dir}")
    settingsMap['data_dir_base'] = os.path.abspath(f"{input_dir}")
    system_name = f"{settingsMap['system']['structure']['name']}"
    settingsMap['system_dir'] = f"{settingsMap['analysis_dir_base']}/{system_name}"
    settingsMap['system']['name'] = system_name

    return settingsMap

class CodeBlock():

    def __init__(self, head, block):
        self.head = head
        self.block = block

    def __str__(self, indent=""):
        result = indent + self.head + ':\n'
        indent += '    '
        for block in self.block:
            if isinstance(block, CodeBlock):
                result += block.__str__(indent)
            else:
                result += indent + block + '\n'
        return result

def class_code(configuration, total_code, in_secondary_loop = False):
    if isinstance(configuration, dict):
        for key, value in configuration.items():
            head = '@dataclass' + '\n' + 'class ' + str(key)
            block = []
            if isinstance(value, dict):
                for key1, value1 in value.items():
                    if isinstance(value1, dict):
                        block.append(str(key1) + ':' + ' ' + str(key1))
                    elif not isinstance(value1, dict):
                        value_type = str(type(value1)).split("'")[1]
                        block.append(str(key1) + ':' + ' ' + value_type)
                total_code = str(CodeBlock(head,block)) + total_code
                total_code = class_code(value,total_code='', in_secondary_loop = True) + total_code
                in_secondary_loop = False
            elif not isinstance(value, dict):
                pass
                #if in_secondary_loop == False:
                    #value_type = str(type(value)).split("'")[1]
                    #block.append(str(key) + ':' + ' ' + value_type)
                    #total_code = str(CodeBlock(head,block)) + total_code
                #else:
                    #pass
            else:
                print ('type error')
                #logger.info("Unsupported Type")
    return total_code

class create_dataclass_file(object):

    def __init__(self, configuration):
        self.configuration = configuration
        self.results = self.__structure__(self.configuration)
        self.__parser__(self.results)

    def __structure__(self, configuration):
        self.total_code = ''
        self.code = str(class_code(self.configuration,self.total_code))
        self.setup = 'from dataclasses import dataclass' + '\n' + '\n' + '#dataclass' + '\n'
        self.results = self.setup + self.code
        return self.results

    def __parser__(self, results):
        file_path = os.getcwd()
        file_name = '/constph/bin/dataclass.py'
        tmp_path = file_path + file_name

        try:
            with open(tmp_path, 'w') as f:
                f.write(self.results)
                f.close()
        except IOError:
            print(f"Data class could not be created: {file_name}")
            #logger.info(f"Data class could not be created: {file_name}")
            pass

def fill_dataclass(input_dataclass,configuration):
    filled_class = from_dict(data_class=input_dataclass, data=configuration)
    return filled_class


import sys
import time

answer = {}
with open("../data/euler_answer.txt", "r") as f:
    for line in f.readlines():
        a = line.split('. ')
        num = int(a[0])
        value = a[1].rstrip()
        answer[num] = value

answer_func = {}
def register_solution(proj, f):
    answer_func[proj] = f

def solution(proj, f):
    start_time = time.clock()
    value = f()
    elapsed_time = time.clock() - start_time
    print("[Proj {0:>3}] : {1}, {2:>15}, Time : {3}".format(str(proj),
                    str(value) == answer[proj], str(value), elapsed_time))
    sys.stdout.flush()

def solution_all():
    a_list = []
    for k in answer_func: a_list.append((k, answer_func[k]))
    a_list.sort()
    start_time = time.clock()
    for pair in a_list:
        proj = pair[0]
        solution(proj, answer_func[proj])
    time_elapsed = time.clock() - start_time
    print("[total number] : %d, [total time] : %f" % (len(a_list), time_elapsed))

#--------------------------------------------
# Utility functions
#--------------------------------------------
def fib_seq(): # fibonacci number generator
    a , b = 1, 1
    while True:
        yield a
        a, b = a + b, a
def prime_seq():
    from itertools import count

    yield 2
    for value in count(3, 2):
        if is_prime(value): yield value
def triangle_seq():
    from itertools import count

    value = 1
    for i in count(2, 1):
        yield value
        value += i
def is_prime(value):
    from math import sqrt

    if value == 2: return True
    if value < 2 or value % 2 == 0: return False
    flag = True
    for i in range(3, int(sqrt(value)) + 1, 2):
        if value % i == 0:
            flag = False
            break
    return flag
def is_palindrome(x):
    s1 = int(str(x)[::-1])
    return s1 == x
def prime_factors(value):
    factors = []
    for i in prime_seq():
        while value % i == 0:
            value = value // i
            factors.append(i)
        if value == 1:
            return factors
def divisor_list(value):
    from itertools import combinations
    from functools import reduce

    a_list = prime_factors(value)
    divisors = set(a_list)
    divisors.add(1)
    for i in range(2, len(a_list)+1):
        for pair in combinations(a_list, i):
            divisors.add(reduce(lambda x, y: x * y, pair))
    return divisors

#--------------------------------------------
# project euler 1 : 233168
# Find the sum of all the multiples of 3 or 5 below 1000.
#--------------------------------------------
def solution_1():
    return sum([ x for x in range(1, 1000) if (x % 3) == 0 or (x % 5) == 0 ])
register_solution(1, solution_1)

#--------------------------------------------
# project euler 2 : 4613732
# Find the sum of the even-valued fibonacci numbers under 4000000.
#--------------------------------------------
def solution_2():
    from itertools import takewhile

    even_fib = (i for i in fib_seq() if i % 2 == 0)
    return sum(takewhile(lambda x: x <= 4000000, even_fib))
answer_func[2] = solution_2

#--------------------------------------------
# project euler 3 : 6857
# What is the largest prime factor of the number 600851475143?
#--------------------------------------------
def solution_3():
    value = 600851475143
    for i in prime_seq():
        while value % i == 0:
            value = value // i
        if value == 1:
            return i
answer_func[3] = solution_3

#--------------------------------------------
# project euler 4 : [993, 913, 906609]
# Find the largest palindrome made from the product of two 3-digit numbers.
#--------------------------------------------
def solution_4():
    product_list = ((i, j, i*j) for i in range(100, 1000) for j in range(i, 1000))
    max_value = 0
    for i, j, p in product_list:
        if is_palindrome(p) and max_value < max(p, max_value):
            max_value = p
    return max_value
answer_func[4] = solution_4

#--------------------------------------------
# project euler 5 : 232792560
# What is the smallest positive number that is evenly divisible
# by all of the numbers from 1 to 20?
#--------------------------------------------
def scm(x, y):
    a, b, result = x, y, 1
    for p in prime_seq():
        if p > a or p > b:
            result = a * b * result
            break
        while a % p == 0 and b % p == 0:
            result *= p
            a = a // p
            b = b // p
    return result

def solution_5():
    from functools import reduce
    return reduce(scm, range(2, 21))
answer_func[5] = solution_5
#--------------------------------------------
# project euler 6 : 25164150
# Find the difference between the sum of the squares of
# the first one hundred natural numbers and the square of the sum.
#--------------------------------------------
def solution_6():
    square = lambda x: x*x
    return square(sum(range(1,101))) - sum(map(square, range(1,101)))
answer_func[6] = solution_6

#--------------------------------------------
# project euler 7 : 104743
# What is the 10001st prime number?
#--------------------------------------------
def solution_7():
    from itertools import islice
    return next(islice(prime_seq(), 10000, 10001))
answer_func[7] = solution_7

#--------------------------------------------
# project euler 8 : 40824
# Find the greatest product of five consecutive digits
# in the 1000-digit number.
#--------------------------------------------
def solution_8():
    digits = """
        73167176531330624919225119674426574742355349194934
        96983520312774506326239578318016984801869478851843
        85861560789112949495459501737958331952853208805511
        12540698747158523863050715693290963295227443043557
        66896648950445244523161731856403098711121722383113
        62229893423380308135336276614282806444486645238749
        30358907296290491560440772390713810515859307960866
        70172427121883998797908792274921901699720888093776
        65727333001053367881220235421809751254540594752243
        52584907711670556013604839586446706324415722155397
        53697817977846174064955149290862569321978468622482
        83972241375657056057490261407972968652414535100474
        82166370484403199890008895243450658541227588666881
        16427171479924442928230863465674813919123162824586
        17866458359124566529476545682848912883142607690042
        24219022671055626321111109370544217506941658960408
        07198403850962455444362981230987879927244284909188
        84580156166097919133875499200524063689912560717606
        05886116467109405077541002256983155200055935729725
        71636269561882670428252483600823257530420752963450
    """
    digits = ''.join(digits.split())
    digits = list(digits)

    elements = []
    for i, e in enumerate(digits):
        product = 1
        for j in range(i, i+5):
            try:
                product *= int(digits[j])
            except IndexError:
                pass
        elements.append(product)

    return max(elements)
answer_func[8] = solution_8

#--------------------------------------------
# project euler 9 : 31875000
# There exists exactly one Pythagorean triplet for which a + b + c = 1000.
# Find the product abc.
#--------------------------------------------
def solution_9():
    from functools import reduce
    for a in range(2, 1000):
        for c in range(a, 1000):
            t1 = 1000 - a
            t2 = a * a
            if 2 * c == t1 + (t2 / t1):
                pairs = (a, 1000-(a+c), c)
                return reduce(lambda x, y: x * y, pairs)
answer_func[9] = solution_9

#--------------------------------------------
# project euler 10 : 142913828922
# Find the sum of all the primes below two million.
#--------------------------------------------
def solution_10():
    from itertools import takewhile

    return sum(takewhile(lambda x: x <= 2000000, prime_seq()))
answer_func[10] = solution_10

#--------------------------------------------
# project euler 11 : 70600674
# What is the greatest product of four adjacent numbers
# in the same direction (up, down, left, right, or diagonally) in the 20×20 grid?
#--------------------------------------------
def solution_11():
    grid = []
    with open("../data/20x20.txt", "r") as f:
        for i in range(3): grid.append([1 for j in range(26)])
        for line in f.readlines():
            row = [1, 1, 1]
            row += [int(i) for i in line.strip().split(' ')]
            row += [1, 1, 1]
            grid.append(row)
        for i in range(3): grid.append([1 for j in range(26)])

    a_list = []
    for i in range(3, 23):
        for j in range(3, 23):
            row_p, col_p, rdia_p, ldia_p = 1, 1, 1, 1
            for k in range(0, 4):
                row_p *= grid[i][j+k]
                col_p *= grid[i+k][j]
                rdia_p *= grid[i+k][j+k]
                ldia_p *= grid[i+k][j-k]
            a_list.append(max([row_p, col_p, rdia_p, ldia_p]))
    return max(a_list)
answer_func[11] = solution_11

#--------------------------------------------
# project euler 12 : 76576500
# What is the value of the first triangle number
# to have over five hundred divisors?
#--------------------------------------------
def solution_12():
    for value in triangle_seq():
        if len(divisor_list(value)) > 500: return value

answer_func[12] = solution_12

#--------------------------------------------
# project euler 13 : 5537376230
# Work out the first ten digits of the sum of the following
# one-hundred 50-digit numbers.
#--------------------------------------------
def solution_13():
    num_list = [ int(x) for x in open("../data/numbers.txt").readlines() ]
    return int(str(sum(num_list))[0:10])
answer_func[13] = solution_13

#--------------------------------------------
# project euler 14 : 837799
# n → n/2 (n is even)
# n → 3n + 1 (n is odd)
# Which starting number, under one million, produces the longest chain?
#--------------------------------------------
def solution_14():
    cache = {1 : 4}
    def collatz(num):
        count = 1
        n = num
        while n > 1:
            if n in cache:
                cache[num] = count + cache[n]
                return cache[num]
            else:
                count += 1
                n = (n >> 1 if (n & 1) == 0 else (3*n) + 1)
        cache[num] = count
        return cache[num]
    max_t = 4
    for i in range(1000000):
        t = collatz(i)
        if max_t < t:
            max_t = t
            result = i
    return result
register_solution(14, solution_14)

#--------------------------------------------
# project euler 15 : 137846528820
# Lattice paths, How many such routes are there through a 20×20 grid?
#--------------------------------------------
def solution_15():
    cache = {}
    def paths(x, y):
        if x == 0 or y == 0: return 1
        else:
            if not (x,y) in cache: cache[(x,y)] = paths(x-1, y) + paths(x, y-1)
        return cache[(x,y)]
    return paths(20, 20)
answer_func[15] = solution_15

#--------------------------------------------
# project euler 16 : 1366
# What is the sum of the digits of the number 2**1000?
#--------------------------------------------
def solution_16():
    from operator import add
    from functools import reduce

    return reduce(add, map(int, list(str(pow(2, 1000)))))
register_solution(16, solution_16)

#--------------------------------------------
# project euler 17 : 21124
# If all the numbers from 1 to 1000 (one thousand) inclusive were written out
# in words, how many letters would be used?
#--------------------------------------------
def solution_17():
    pairs = {
        1: "one",
        2: "two",
        3: "three",
        4: "four",
        5: "five",
        6: "six",
        7: "seven",
        8: "eight",
        9: "nine",
        10: "ten",
        11: "eleven",
        12: "twelve",
        13: "thirteen",
        14: "fourteen",
        15: "fifteen",
        16: "sixteen",
        17: "seventeen",
        18: "eighteen",
        19: "nineteen",
        20: "twenty",
        30: "thirty",
        40: "forty",
        50: "fifty",
        60: "sixty",
        70: "seventy",
        80: "eighty",
        90: "ninety",
        100: "hundred",
        1000: "thousand"
    }

    def convert(num):
        s = ''
        x = num
        for i in [100, 10, 1]:
            digit = x // i
            if digit > 0:
                if i == 100:
                    s += pairs[digit] + pairs[100]
                    s += "and" if (x % i) != 0 else ""
                elif i == 10:
                    if digit == 1: s += pairs[x]; break
                    else: s += pairs[digit * 10]
                else: s += pairs[digit]
            x %= i
            if x == 0: break
        s = "onethousand" if num == 1000 else s
        return s
    return len(''.join([convert(num) for num in range(1, 1001)]))
answer_func[17] = solution_17

#--------------------------------------------
# project euler 18 : 1074
# Find the maximum total from top to bottom of the triangle below:
#--------------------------------------------
def solution_18():
    def max_path(t):
        if len(t) == 1: return t[0][0]
        else:
            top = t.pop(0)[0]
            tl = [ row[:-1] for row in t ]
            tr = [ row[1:] for row in t ]
            return max([top + max_path(tl), top + max_path(tr)])
    triangle = []
    with open("../data/triangle_15.txt", "r") as f:
        for line in f.readlines():
            triangle.append([int(s) for s in line.rstrip().split(' ')])
    return max_path(triangle)
register_solution(18, solution_18)

#--------------------------------------------
# project euler 19 : 171
# How many Sundays fell on the first of the month
# during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
#--------------------------------------------
def solution_19():
    days_in_month = {
        31 : [1, 3, 5, 7, 8, 10, 12],
        30 : [4, 6, 9, 11],
        28 : [2]
    }
    weekdays = ['Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat', 'Sun']

    def weekdayOfMonth(year, month, day):
        def leapYear(year):
            (year % 4 == 0 and not year % 100 == 0) or year % 400 == 0

        def daysOfMonth(year, month):
            for k in days_in_month:
                if month in days_in_month[k]:
                    return 29 if leapYear(year) and month == 2 else k

        y_diff, m_diff, d_diff = 0, 0, 0
        y_diff = sum([366 if leapYear(y) else 365 for y in range(1900, year)])
        m_diff = sum([daysOfMonth(year, m) for m in range(1, month)])
        d_diff = day - 1

        total_diff = y_diff + m_diff + d_diff
        result = ''
        while total_diff > 0:
            for x in weekdays:
                if total_diff == 0:
                    result = x
                    break
                total_diff -= 1
        return result
    return len([(year, month, 1) for year in range(1901, 2001) for month in range(1, 13) if weekdayOfMonth(year, month, 1) == 'Sun'])
answer_func[19] = solution_19

#--------------------------------------------
# project euler 20 : 648
# Find the sum of the digits in the number 100!
#--------------------------------------------
def solution_20():
    from math import factorial

    digits = list(str(factorial(100)))
    return sum([int(x) for x in digits])
answer_func[20] = solution_20

#--------------------------------------------
# project euler 21 : 31626
# Evaluate the sum of all the amicable numbers under 10000.
#--------------------------------------------
def solution_21():
    def d(n):
        divisors = divisor_list(n)
        divisors.remove(n)
        return sum(divisors)
    result = 0
    for a in range(2, 10000):
        b = d(a)
        if a == d(b) and a != b: result += a
    return result
register_solution(21, solution_21)

#--------------------------------------------
# project euler 22 : 871198282
# What is the total of all the name scores in the file?
#--------------------------------------------
def solution_22():
    def name_score(s):
        return sum([ord(c) - 64 for c in list(s)])
    with open("../data/names.txt", "r") as f:
        names = f.readline().split(',')
        names = sorted([name[1:-1] for name in names])
    return sum([(idx+1) * name_score(name) for idx, name in enumerate(names)])
register_solution(22, solution_22)

#--------------------------------------------
# project euler 23 : 4179871
# Find the sum of all the positive integers
# which cannot be written as the sum of two abundant numbers.
#--------------------------------------------
def solution_23():
    def abundant_list(n):
        return list(filter(lambda x: 2 * x < sum(divisor_list(x)), range(12, n)))
    num_set = set(range(1, 28123))
    a_list = abundant_list(28123)
    a_set = set([x+y for x in a_list for y in a_list])
    return sum(num_set - a_set)
register_solution(23, solution_23)

#--------------------------------------------
# project euler 24 : 2783915460
# What is the millionth lexicographic permutation of the digits
# 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?
#--------------------------------------------
def solution_24():
    from functools import reduce

    def f(n):
        return reduce(lambda x, y: x*y, range(1, n+1))
    perm = list(range(0, 10))
    level = 1
    which = 1000000
    while f(level) < which:
        level += 1

    digits = perm[10-level:]
    for i in range(level-1, 0, -1):
        count = 0
        while which - f(i) > 0:
            count += 1
            which -= f(i)
        perm[10-(i+1)] = digits[count]
        digits.pop(count)

    perm = perm[:-len(digits)] + digits
    return ''.join([str(x) for x in perm])
register_solution(24, solution_24)

#--------------------------------------------
# project euler 25 : 4782
# What is the first term in the Fibonacci sequence to contain 1000 digits?
#--------------------------------------------
def solution_25():
    for idx, fib in enumerate(fib_seq()):
        if len(str(fib)) == 1000: return idx + 2
register_solution(25, solution_25)

#--------------------------------------------
# project euler 26 : 983
# Find the value of d < 1000 for which 1/d contains
# the longest recurring cycle in its decimal fraction part.
#--------------------------------------------
def solution_26():
    result = 0
    max = 0
    for d in range(2, 1000):
        re_list = []
        remainder = 1 % d
        while True:
            if remainder == 0: break
            elif remainder in re_list:
                start = re_list.index(remainder)
                length = len(re_list[start:])
                if max < length:
                    max = length
                    result = d
                break
            else: re_list.append(remainder)
            remainder = (10*remainder) % d
    return result
register_solution(26, solution_26)

#--------------------------------------------
# project euler 27 : -59231
# n² + an + b, where |a| < 1000 and |b| < 1000
# Find the product of the coefficients, a and b, for the quadratic expression
# that produces the maximum number of primes for consecutive values of n, starting with n = 0.
#--------------------------------------------
def solution_27():
    from itertools import takewhile
    from itertools import count

    max_t = (0, 0, 0)
    a = range(-999, 1000)
    b = takewhile(lambda x: x < 1000, prime_seq())
    coeff = [[y, x] for x in b for y in a]
    for a, b in coeff:
        cnt = 0
        for n in count(0, 1):
            value = n*n + a*n + b
            if is_prime(value):
                cnt += 1
            else: break
        if max_t[0] < cnt: max_t = (cnt, a, b)
    return max_t[1] * max_t[2]
register_solution(27, solution_27)

#--------------------------------------------
# project euler 28 : 669171001
# What is the sum of the numbers on the diagonals
# in a 1001 by 1001 spiral formed in the same way?
#--------------------------------------------
def solution_28():
    def f(n):
        if n == 1: return [1]
        else:
            start = f(n-2)[-1] + (n-1)
            return [start + (n-1)*i for i in range(4)]
    return sum([sum(f(x)) for x in range(1, 1002, 2)])
register_solution(28, solution_28)

#--------------------------------------------
# project euler 29 : 9183
# How many distinct terms are in the sequence generated by
# a**b for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100?
#--------------------------------------------
def solution_29():
    from itertools import product

    a_list = [x for x in range(2, 101)]
    b_list = sorted([pow(pair[0], pair[1]) for pair in product(a_list, a_list)])
    return len(set(b_list))
register_solution(29, solution_29)

#--------------------------------------------
# project euler 30 : 443839
# Find the sum of all the numbers that can be written as
# the sum of fifth powers of their digits.
#--------------------------------------------
def solution_30():
    sums = 0
    for n in range(2, 354295):
        seq = map(int, list(str(n)))
        if n == sum([pow(num, 5) for num in seq]): sums += n
    return sums
register_solution(30, solution_30)

if __name__ == "__main__":
    proj = int(input("Input Problem Number : "))
    if proj == 0: solution_all()
    else: solution(proj, answer_func[proj])


import tensorflow as tf
from PIL import Image
from time import time
import numpy as np
from ops import *
import parameters
import os

dict = parameters.import_parameters( 'PARAMETERS.txt' )

NUM_BLOCKS = int( dict['num_blocks'] )
ALPHA = int( dict['alpha'] )
FIRST_CHANNELS = int( dict['first_channels'] )
SCALE = int( dict['scale'] )

input = tf.placeholder( tf.float32 , [ None , None , None , 3 ] )
network_output = build_network( input , NUM_BLOCKS , alpha = ALPHA , first_channels = FIRST_CHANNELS )

with tf.Session() as sess :

    saver = tf.train.Saver()
    model_path = 'Models/best_model'
    saver.restore( sess , model_path )

    os.system('rm -r output_images')
    os.system('mkdir output_images')

    img = Image.open('input.tif')
    inputs = np.array( [ np.array(img) ] ).astype(np.float32)
    img.close()

    start_time = time()

    network_images = sess.run( network_output , feed_dict = { input : inputs } )

    network = np.clip( network_images[0] , 0 , 255 ).astype('uint8')

    Image.fromarray( network ).save( 'output_images/network.bmp' )

print( time() - start_time , "sec" )


from aiogram import types, Dispatcher
from zp.create_bot import bot, dp
from zp.keyboards import conf_settings, other_kb, mk_confirm

async def file_excel_loader(message : types.Message):
    'для отправки файла excel'
    try:
        await message.reply_document(open('excel/write_only.xlsx', 'rb'), reply_markup=other_kb.start_kb)
    except FileNotFoundError as ex:
        await bot.send_message(message.chat.id, "Файл еще не создан!")

def register_handlers_excel(dp: Dispatcher):
    dp.register_message_handler(file_excel_loader, text='Получить отчет! 📄')


import db_connector
from Survey.Retrieve import RetrieveSurveyById
from flask import request

def deleteSurvey(email, id):

    # Access the Database
    mydb = db_connector.dbConnector()
    mycursor = mydb.cursor()

    exists = RetrieveSurveyById.retrieveSurveyById(id, email)
    if (exists == "Error 404, This survey does not exist!"):
        return "survey not exists"

    # Select only the rows that have our requested "email"
    query = "DELETE FROM Surveys WHERE email = %s AND id = %s"
    values = (email, id)
    mycursor.execute(query, values)
    mydb.commit()
    print("Surveys Table: ", mycursor.rowcount, "record(s) deleted")

    # Delete from Questions
    query = "DELETE FROM Questions WHERE survey_id = %s"
    values = (id,)
    mycursor.execute(query, values)
    mydb.commit()
    print("Questions Table: ", mycursor.rowcount, "record(s) deleted")

    # Delete from Survey_Question table
    query = "DELETE FROM Survey_Questions WHERE survey_id = %s"
    values = (id,)
    mycursor.execute(query, values)
    mydb.commit()
    print("Survey_Questions: ", mycursor.rowcount, "record(s) deleted")

    # Delete from Response table
    query = "DELETE FROM Response WHERE survey_id = %s"
    values = (id, )
    mycursor.execute(query, values)
    mydb.commit()
    print("Response Table: ", mycursor.rowcount, "record(s) deleted")
    # Retrieve all surveys
    # Select only the rows that have our requested "email"
    query = "SELECT * FROM Surveys WHERE email = %s"
    user_email = (email, )

    # Execute our MySQL Query to get what we want
    mycursor.execute(query, user_email)
    # fetch all the matching rows
    result = mycursor.fetchall()

    counter = 1
    if len(result) != 0:
        for survey in result:
            survey_id = survey[0]
            update_surveys_id = "UPDATE Surveys SET surveys_id = %s WHERE id = %s"
            val = (counter, survey_id)
            mycursor.execute(update_surveys_id, val)
            mydb.commit()
            unique_string = survey[9]
            #Generate the full unique url
            unique_url = request.host_url + 'survey/respond/' + str(counter) + '/' + unique_string
            update_unique_url = "UPDATE Surveys SET unique_url = %s WHERE id = %s"
            val = (unique_url, survey_id)
            mycursor.execute(update_unique_url, val)
            mydb.commit()
            counter+=1

    return ("Survey has been deleted for email: {} with survey_id = {}").format(email, id)


from itertools import product
import numpy as np

def interior_mask_as_ndarray(shape):
    ndims = len(shape)
    mask = np.zeros(shape, dtype=bool)
    mask[tuple([slice(1, -1)] * ndims)] = True
    return mask

def all_index_tuples_as_list(shape):
    ndims = len(shape)
    return list(product(*tuple([list(range(shape[k])) for k in range(ndims)])))

def long_indices_as_ndarray(shape):
    return np.array(list(range(np.prod(shape)))).reshape(shape)

def to_long_index(idx, shape):
    ndims = len(shape)
    long_idx = 0
    siz = 1
    for axis in range(ndims):
        long_idx += idx[ndims-1-axis] * siz
        siz *= shape[ndims-1-axis]
    return long_idx

def to_index_tuple(long_idx, shape):
    ndims = len(shape)
    idx = np.zeros(ndims)
    for k in range(ndims):
        s = np.prod(shape[k+1:])
        idx[k] = long_idx // s
        long_idx = long_idx - s * idx[k]

    return tuple(idx)


# /Users/gilad/Code/rapyd/reconciliation_engine/exec.py
# parameters: payment_instructions_job cli
# environment variables: reconciliation_env=dev;reconciliation_debug_level=INFO

#

def foo():
	from multiprocessing import Manager
	print('before')
	multiprocessing_manager = Manager()
	print('after')

if __name__ == '__main__':
	foo()