<commit_before># Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

###############################################################################
## This program is to develop and test the new optimization target function,
## based on Lagrange multipliers.
###############################################################################

from pylab import *

import pdb

from fit_cone import *
import mpl_toolkits.mplot3d.axes3d as p3

from scipy.optimize import leastsq
from scipy.spatial import KDTree

ion()

def sys_eqs(pl, q, U, V):
  '''This function outputs a vector with the values of the functions from the
  big non-linear system of equations that we need to solve in order to fit the
  inextensible surface. The solution is found by minimizing the sums of the
  squares of these, e.g. using Levenberg-Marquards least-quares fitting. The
  sys_jacobian function provides the jacobian matrix of this function to make
  that better.'''

  assert (pl.shape[0] % 6) == 0

  ## Number of points
  N = pl.shape[0]/6

  ## Split pl into the p matrix with 3D coordinates of each point, and the l
  ## matrix with the 3 multipliers for the conditions over each point.

  ## First 3N values are the coordinates for the N points
  p = reshape(pl[:3*N], (N, -1))
  ## Last 3N values are the Lagrange multipliers ("lambdas"). Each point has 3
  ## corresponding restrictions, and each of these has one multiplier.
  l = reshape(pl[3*N:], (N, -1))

  ## Calculate the p derivatives (sum U_j^k p_k^w) into temporary arrays.
  p_u = dot(U, p)
  p_v = dot(V, p)

  ## Calculate "residue" function for each coordinate (p - q plus all the
  ## magical lambdas), and calculate the values of the restriction functions.

  ## The actual calculation of the "h" function, the decomposition of the
  ## gradient of the original objective function as a linear combination of the
  ## gradients of the "g" functions (constraints). The obscure l[:,3*[0]] is a
  ## matrix with the first column of l replicated 3 times.
  h = p - q + (dot(U.T, l[:,3*[0]] * p_u) +
               dot(V.T, l[:,3*[1]] * p_v) +
               (dot(U.T, l[:,3*[2]] * p_v) + dot(V.T, l[:,3*[2]] * p_u)) / 2)

  ## The restriction functions, pretty straight forward.
  g = c_[(p_u**2).sum(1) - 1,
         (p_v**2).sum(1) - 1,
         (p_u*p_v).sum(1)]

  return r_[ravel(h), ravel(g)]

def sys_jacobian(pl, q, U, V):
  '''This function returns the Jacobian matrix of the target function to fit an
  inextensible surface to given data. It receives q (associated measurements) as
  a parameter because it is necessary in sys_eqs, but it is never used in the
  Jacobian calculation. At least this is the case for this specific and simple
  distance function used...
  '''

  assert (pl.shape[0] % 6) == 0

  ## Number of points
  N = pl.shape[0]/6

  output = zeros((N,N))

  ## Split pl into the p matrix with 3D coordinates of each point, and the l
  ## matrix with the 3 multipliers for the conditions over each point.

  ## First 3N values are the coordinates for the N points
  p = reshape(pl[:3*N], (N, -1))
  ## Last 3N values are the Lagrange multipliers ("lambdas"). Each point has 3
  ## corresponding restrictions, and each of these has one multiplier.
  l = reshape(pl[3*N:], (N, -1))

  ## Calculate the p derivatives (sum U_j^k p_k^w) into temporary arrays.
  p_u = dot(U, p)
  p_v = dot(V, p)

  ## Derivative of the objective function (plus Lagrange stuff) relative to
  ## coordinates. It is zero for any different dimensions, and is the same for
  ## every three coordinates. So we can calculate the matrix once and replicate.
  dhdp_base = identity(Np) + (dot(dot(U.T, diag(l[:,0])), U) +
                              dot(dot(V.T, diag(l[:,1])), V) +
                              (dot(dot(U.T, diag(l[:,2])),V) +
                               dot(dot(V.T, diag(l[:,2])),U))/2)

  dhdp = zeros((3*N, 3*N))
  dhdp[0::3,0::3] = dhdp_base
  dhdp[1::3,1::3] = dhdp_base
  dhdp[2::3,2::3] = dhdp_base

  ## Calculate derivatives of restriction functions relative to
  ## coordinates. There is probably a smarter way to calculate all that. We need
  ## to figure out the really optimal ordering of all the variables, etc.
  dgdp = zeros((3*N, 3*N))
  dgudpx = 2 * dot(diag(p_u[:,0]), U)
  dgudpy = 2 * dot(diag(p_u[:,1]), U)
  dgudpz = 2 * dot(diag(p_u[:,2]), U)
  dgvdpx = 2 * dot(diag(p_v[:,0]), V)
  dgvdpy = 2 * dot(diag(p_v[:,1]), V)
  dgvdpz = 2 * dot(diag(p_v[:,2]), V)
  dguvdpx = dot(diag(p_v[:,0]), U) + dot(diag(p_u[:,0]), V)
  dguvdpy = dot(diag(p_v[:,1]), U) + dot(diag(p_u[:,1]), V)
  dguvdpz = dot(diag(p_v[:,2]), U) + dot(diag(p_u[:,2]), V)
  dgdp[0::3,0::3] = dgudpx
  dgdp[0::3,1::3] = dgudpy
  dgdp[0::3,2::3] = dgudpz
  dgdp[1::3,0::3] = dgvdpx
  dgdp[1::3,1::3] = dgvdpy
  dgdp[1::3,2::3] = dgvdpz
  dgdp[2::3,0::3] = dguvdpx
  dgdp[2::3,1::3] = dguvdpy
  dgdp[2::3,2::3] = dguvdpz

  ## Calculate derivatives of objective function gradient relative to Lagrange
  ## multipliers. It turns out it's just the transpose of the dgdp, scaled. That
  ## probably means something good.
  dhdl = 0.5*dgdp.T

  ## Derivatives of restriction functions relative to multipliers are just 0.
  dgdl = zeros((3*N, 3*N))

  ## Assemble result witht he four blocks
  jacobian = zeros((6*N, 6*N))
  jacobian[:3*N,:3*N] = dhdp
  jacobian[:3*N,3*N:] = dhdl
  jacobian[3*N:,:3*N] = dgdp
  jacobian[3*N:,3*N:] = dgdl

  return jacobian

def calculate_U_and_V(Nl,Nk):
  ## Initialize matrices with zeros.
  U = zeros((Nl*Nk,Nl*Nk))
  V = zeros((Nl*Nk,Nl*Nk))

  eight_neighborhood = array([-1-Nk, -Nk, 1-Nk, -1, 0, 1, -1+Nk, Nk, 1+Nk], dtype=int16)
  for l in range(Nl):
    for k in range(Nk):
      ## The point around which we are taking the derivative. index calculated
      ## using normal row-major order.
      ind = l*Nk+k
      ## The reference point ("Destination" index) around which we set the
      ## values of the Sobel operator, or whatever filter is chosen to calculate
      ## the derivatives. This is for the magic in the next lines
      dind = ind

      # if l>1 and l < Nl-1 and k>1 and k < Nk-1 : NOP
      ## The derivatives in the borders are the same values as the derivatives
      ## right inside the rectangle. So we just modify dind accordingly.
      if k == 0:
        dind += 1
      elif k == Nk-1:
        dind -= 1
      if l == 0:
        dind += Nk
      elif l == Nl-1:
        dind -= Nk

      ## Shigeru filter 3x3 doi://10.1109/34.841757
      U[ind, dind + eight_neighborhood] = array([-0.112737,0,0.112737,
                                                  -0.274526,0,0.274526,
                                                  -0.112737,0,0.112737])
      V[ind, dind + eight_neighborhood] = array([-0.112737,-0.274526,-0.112737,
                                                  0,0,0,
                                                  0.112737,0.274526,0.112737])
      ## Sobel filter
      #U[ind, dind + eight_neighborhood] = array([-1,0,1,-2,0,2,-1,0,1])/8.
      #V[ind, dind + eight_neighborhood] = array([-1,-2,-1,0,0,0,1,2,1])/8.
      ## Scharr filter
      #U[ind, dind + eight_neighborhood] = array([-3,0,3,-10,0,10,-3,0,3])/32.
      #V[ind, dind + eight_neighborhood] = array([-3,-10,-3,0,0,0,3,10,3])/32.

  return U, V

###############################################################################
## Main function, for testing.
if __name__ == '__main__':
  ## Size of the model, lines and columns
  Nl = 11
  Nk = 11
  Np = Nl*Nk # Total number of points

  ## Calculates the U and V matrices. (Partial derivatives on u and v directions).
  U, V = calculate_U_and_V(Nl, Nk)

  ## Generate points over a cylinder for test.
  oversample = 10
  Nko = Nk * oversample
  Nlo = Nl * oversample
  k = 6 # Curvature
  s = 15.0
  tt = 0.5*pi/3 # Angle between the mesh and cylinder axis
  #q_data = generate_cyl_points(k,s,tt,Nko)
  k = 11# Curvature
  s = 11
  tt = 0*0.5*pi/3 # Angle between the mesh and cylinder axis
  q_data = generate_elli_points(k,s,tt,Nko)

  ## Initial guess, Points over the xy plane
  pl0 = zeros(6*Np)
  p0 = .0 + mgrid[:Nk,:Nl,:1].reshape(3,-1).T
  p0 += array([-.5*(Nk-1), -.5*(Nl-1),0])
  # p0 = .0 + mgrid[:Nk,:Nl,:1].reshape(3,-1).T
  p0[:,2] = mean(q_data[:,2])
  # tt = 0.5*pi/3.2
  # p0 = dot(p0 - Nl/2, array([[cos(tt), -sin(tt), 0], [sin(tt), cos(tt), 0], [0,0,1]]))
  # p0 += Nl/2 + array([2.5,2.5,0])

  pl0[:3*Np] = p0.ravel()

  ## Taget points
  # q = c_[q_data[:,0].reshape(Nlo,Nko)[oversample/2::oversample,oversample/2::oversample].ravel(),
  #        q_data[:,1].reshape(Nlo,Nko)[oversample/2::oversample,oversample/2::oversample].ravel(),
  #        q_data[:,2].reshape(Nlo,Nko)[oversample/2::oversample,oversample/2::oversample].ravel(),
  #        ]
  xyz_tree = KDTree(q_data)
  q_query = xyz_tree.query(p0)
  q = q_data[q_query[1]]

  ## Run optimization
  pl_opt, success = scipy.optimize.leastsq(sys_eqs, pl0, args=(q,U,V), Dfun=sys_jacobian)

  Niter = 2
  for kk in range(Niter):
    q_query = xyz_tree.query(pl_opt.reshape(-1,3)[:Np])
    q = q_data[q_query[1]]
    pl_opt, success = scipy.optimize.leastsq(sys_eqs, pl_opt, args=(q,U,V), Dfun=sys_jacobian)

  ## Get the estimated coordinates, organize (and dump multipliers)
  p = pl_opt.reshape(-1,3)[:Np]

  #############################################################################
  ## Plot stuff

  ## Plot wireframes of input and resulting model
  fig = figure()
  ax = p3.Axes3D(fig, aspect='equal')
  title('Square mesh on 3D space', fontsize=20, fontweight='bold')
  ax.axis('equal')
  ax.plot_wireframe(q_data[:,0].reshape(Nl*oversample,Nk*oversample),q_data[:,1].reshape(Nl*oversample,Nk*oversample),q_data[:,2].reshape(Nl*oversample,Nk*oversample), color='#0000ff')
  #ax.plot_wireframe(p0[:,0].reshape(Nl,Nk),p0[:,1].reshape(Nl,Nk),p0[:,2].reshape(Nl,Nk), color='#008888')
  #ax.plot_wireframe(q[:,0].reshape(Nl,Nk),q[:,1].reshape(Nl,Nk),q[:,2].reshape(Nl,Nk), color='g')
  ax.plot_wireframe(p[:,0].reshape(Nl,Nk),p[:,1].reshape(Nl,Nk),p[:,2].reshape(Nl,Nk), color='r')

  mrang = max([p[:,0].max()-p[:,0].min(), p[:,1].max()-p[:,1].min(), p[:,2].max()-p[:,2].min()])/2
  midx = (p[:,0].max()+p[:,0].min())/2
  midy = (p[:,1].max()+p[:,1].min())/2
  midz = (p[:,2].max()+p[:,2].min())/2
  ax.set_xlim3d(midx-mrang, midx+mrang)
  ax.set_ylim3d(midy-mrang, midy+mrang)
  ax.set_zlim3d(midz-mrang, midz+mrang)
<commit_msg>Calculation of second derivative matrices, and the Laplacean matrix, used for regularization<commit_after># Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

###############################################################################
## This program is to develop and test the new optimization target function,
## based on Lagrange multipliers.
###############################################################################

from pylab import *

import pdb

from fit_cone import *
import mpl_toolkits.mplot3d.axes3d as p3

from scipy.optimize import leastsq
from scipy.spatial import KDTree

ion()

def sys_eqs(pl, q, U, V):
  '''This function outputs a vector with the values of the functions from the
  big non-linear system of equations that we need to solve in order to fit the
  inextensible surface. The solution is found by minimizing the sums of the
  squares of these, e.g. using Levenberg-Marquards least-quares fitting. The
  sys_jacobian function provides the jacobian matrix of this function to make
  that better.'''

  assert (pl.shape[0] % 6) == 0

  ## Number of points
  N = pl.shape[0]/6

  ## Split pl into the p matrix with 3D coordinates of each point, and the l
  ## matrix with the 3 multipliers for the conditions over each point.

  ## First 3N values are the coordinates for the N points
  p = reshape(pl[:3*N], (N, -1))
  ## Last 3N values are the Lagrange multipliers ("lambdas"). Each point has 3
  ## corresponding restrictions, and each of these has one multiplier.
  l = reshape(pl[3*N:], (N, -1))

  ## Calculate the p derivatives (sum U_j^k p_k^w) into temporary arrays.
  p_u = dot(U, p)
  p_v = dot(V, p)

  ## Calculate "residue" function for each coordinate (p - q plus all the
  ## magical lambdas), and calculate the values of the restriction functions.

  ## The actual calculation of the "h" function, the decomposition of the
  ## gradient of the original objective function as a linear combination of the
  ## gradients of the "g" functions (constraints). The obscure l[:,3*[0]] is a
  ## matrix with the first column of l replicated 3 times.
  h = p - q + (dot(U.T, l[:,3*[0]] * p_u) +
               dot(V.T, l[:,3*[1]] * p_v) +
               (dot(U.T, l[:,3*[2]] * p_v) + dot(V.T, l[:,3*[2]] * p_u)) / 2)

  ## The restriction functions, pretty straight forward.
  g = c_[(p_u**2).sum(1) - 1,
         (p_v**2).sum(1) - 1,
         (p_u*p_v).sum(1)]

  return r_[ravel(h), ravel(g)]

def sys_jacobian(pl, q, U, V):
  '''This function returns the Jacobian matrix of the target function to fit an
  inextensible surface to given data. It receives q (associated measurements) as
  a parameter because it is necessary in sys_eqs, but it is never used in the
  Jacobian calculation. At least this is the case for this specific and simple
  distance function used...
  '''

  assert (pl.shape[0] % 6) == 0

  ## Number of points
  N = pl.shape[0]/6

  output = zeros((N,N))

  ## Split pl into the p matrix with 3D coordinates of each point, and the l
  ## matrix with the 3 multipliers for the conditions over each point.

  ## First 3N values are the coordinates for the N points
  p = reshape(pl[:3*N], (N, -1))
  ## Last 3N values are the Lagrange multipliers ("lambdas"). Each point has 3
  ## corresponding restrictions, and each of these has one multiplier.
  l = reshape(pl[3*N:], (N, -1))

  ## Calculate the p derivatives (sum U_j^k p_k^w) into temporary arrays.
  p_u = dot(U, p)
  p_v = dot(V, p)

  ## Derivative of the objective function (plus Lagrange stuff) relative to
  ## coordinates. It is zero for any different dimensions, and is the same for
  ## every three coordinates. So we can calculate the matrix once and replicate.
  dhdp_base = identity(Np) + (dot(dot(U.T, diag(l[:,0])), U) +
                              dot(dot(V.T, diag(l[:,1])), V) +
                              (dot(dot(U.T, diag(l[:,2])),V) +
                               dot(dot(V.T, diag(l[:,2])),U))/2)

  dhdp = zeros((3*N, 3*N))
  dhdp[0::3,0::3] = dhdp_base
  dhdp[1::3,1::3] = dhdp_base
  dhdp[2::3,2::3] = dhdp_base

  ## Calculate derivatives of restriction functions relative to
  ## coordinates. There is probably a smarter way to calculate all that. We need
  ## to figure out the really optimal ordering of all the variables, etc.
  dgdp = zeros((3*N, 3*N))
  dgudpx = 2 * dot(diag(p_u[:,0]), U)
  dgudpy = 2 * dot(diag(p_u[:,1]), U)
  dgudpz = 2 * dot(diag(p_u[:,2]), U)
  dgvdpx = 2 * dot(diag(p_v[:,0]), V)
  dgvdpy = 2 * dot(diag(p_v[:,1]), V)
  dgvdpz = 2 * dot(diag(p_v[:,2]), V)
  dguvdpx = dot(diag(p_v[:,0]), U) + dot(diag(p_u[:,0]), V)
  dguvdpy = dot(diag(p_v[:,1]), U) + dot(diag(p_u[:,1]), V)
  dguvdpz = dot(diag(p_v[:,2]), U) + dot(diag(p_u[:,2]), V)
  dgdp[0::3,0::3] = dgudpx
  dgdp[0::3,1::3] = dgudpy
  dgdp[0::3,2::3] = dgudpz
  dgdp[1::3,0::3] = dgvdpx
  dgdp[1::3,1::3] = dgvdpy
  dgdp[1::3,2::3] = dgvdpz
  dgdp[2::3,0::3] = dguvdpx
  dgdp[2::3,1::3] = dguvdpy
  dgdp[2::3,2::3] = dguvdpz

  ## Calculate derivatives of objective function gradient relative to Lagrange
  ## multipliers. It turns out it's just the transpose of the dgdp, scaled. That
  ## probably means something good.
  dhdl = 0.5*dgdp.T

  ## Derivatives of restriction functions relative to multipliers are just 0.
  dgdl = zeros((3*N, 3*N))

  ## Assemble result witht he four blocks
  jacobian = zeros((6*N, 6*N))
  jacobian[:3*N,:3*N] = dhdp
  jacobian[:3*N,3*N:] = dhdl
  jacobian[3*N:,:3*N] = dgdp
  jacobian[3*N:,3*N:] = dgdl

  return jacobian

def calculate_U_and_V(Nl,Nk):
  ## Initialize matrices with zeros.
  U = zeros((Nl*Nk,Nl*Nk))
  V = zeros((Nl*Nk,Nl*Nk))

  eight_neighborhood = array([-1-Nk, -Nk, 1-Nk, -1, 0, 1, -1+Nk, Nk, 1+Nk], dtype=int16)
  for l in range(Nl):
    for k in range(Nk):
      ## The point around which we are taking the derivative. Index calculated
      ## using normal row-major order.
      ind = l*Nk+k
      ## The reference point ("Destination" index) around which we set the
      ## values of the Sobel operator, or whatever filter is chosen to calculate
      ## the derivatives. This is for the magic in the next lines
      dind = ind

      # if l>1 and l < Nl-1 and k>1 and k < Nk-1 : NOP
      ## The derivatives in the borders are the same values as the derivatives
      ## right inside the rectangle. So we just modify dind accordingly.
      if k == 0:
        dind += 1
      elif k == Nk-1:
        dind -= 1
      if l == 0:
        dind += Nk
      elif l == Nl-1:
        dind -= Nk

      ## Shigeru filter 3x3 doi://10.1109/34.841757
      U[ind, dind + eight_neighborhood] = array([-0.112737,0,0.112737,
                                                  -0.274526,0,0.274526,
                                                  -0.112737,0,0.112737])
      V[ind, dind + eight_neighborhood] = array([-0.112737,-0.274526,-0.112737,
                                                  0,0,0,
                                                  0.112737,0.274526,0.112737])
      ## Sobel filter
      #U[ind, dind + eight_neighborhood] = array([-1,0,1,-2,0,2,-1,0,1])/8.
      #V[ind, dind + eight_neighborhood] = array([-1,-2,-1,0,0,0,1,2,1])/8.
      ## Scharr filter
      #U[ind, dind + eight_neighborhood] = array([-3,0,3,-10,0,10,-3,0,3])/32.
      #V[ind, dind + eight_neighborhood] = array([-3,-10,-3,0,0,0,3,10,3])/32.

  return U, V

def calculate_2nd_devs(Nl,Nk):
  ## Initialize matrices with zeros.
  UU = zeros((Nl*Nk,Nl*Nk))
  VV = zeros((Nl*Nk,Nl*Nk))
  Laplace = zeros((Nl*Nk,Nl*Nk))

  u_neighborhood = array([-1, 0, 1], dtype=int16)
  v_neighborhood = array([-Nk, 0, Nk], dtype=int16)
  for l in range(Nl):
    for k in range(Nk):
      ## The point around which we are taking the derivative. Index calculated
      ## using normal row-major order.
      ind = l*Nk+k

      if k > 0 and k < Nk - 1:
        UU[ind, ind + u_neighborhood] = array([1,-2,1])
      if l > 0 and l < Nl - 1:
        VV[ind, ind + v_neighborhood] = array([1,-2,1])

  for l in range(Nl*Nk):
    for k in range(Nk*Nl):
      Laplace[l,k] = UU[l,l] * UU[l,k] + VV[l,l] * VV[l,k]

  return UU, VV, Laplace

###############################################################################
## Main function, for testing.
if __name__ == '__main__':
  ## Size of the model, lines and columns
  Nl = 11
  Nk = 11
  Np = Nl*Nk # Total number of points

  ## Calculates the U and V matrices. (Partial derivatives on u and v directions).
  U, V = calculate_U_and_V(Nl, Nk)
  UU, VV, Laplace = calculate_2nd_devs(Nl,Nk)

  ## Generate points over a cylinder for test.
  oversample = 10
  Nko = Nk * oversample
  Nlo = Nl * oversample
  k = 6 # Curvature
  s = 15.0
  tt = 0.5*pi/3 # Angle between the mesh and cylinder axis
  #q_data = generate_cyl_points(k,s,tt,Nko)
  k = 11# Curvature
  s = 11
  tt = 0*0.5*pi/3 # Angle between the mesh and cylinder axis
  q_data = generate_elli_points(k,s,tt,Nko)

  ## Initial guess, Points over the xy plane
  pl0 = zeros(6*Np)
  p0 = .0 + mgrid[:Nk,:Nl,:1].reshape(3,-1).T
  p0 += array([-.5*(Nk-1), -.5*(Nl-1),0])
  # p0 = .0 + mgrid[:Nk,:Nl,:1].reshape(3,-1).T
  p0[:,2] = mean(q_data[:,2])
  # tt = 0.5*pi/3.2
  # p0 = dot(p0 - Nl/2, array([[cos(tt), -sin(tt), 0], [sin(tt), cos(tt), 0], [0,0,1]]))
  # p0 += Nl/2 + array([2.5,2.5,0])

  pl0[:3*Np] = p0.ravel()

  ## Taget points
  # q = c_[q_data[:,0].reshape(Nlo,Nko)[oversample/2::oversample,oversample/2::oversample].ravel(),
  #        q_data[:,1].reshape(Nlo,Nko)[oversample/2::oversample,oversample/2::oversample].ravel(),
  #        q_data[:,2].reshape(Nlo,Nko)[oversample/2::oversample,oversample/2::oversample].ravel(),
  #        ]
  xyz_tree = KDTree(q_data)
  q_query = xyz_tree.query(p0)
  q = q_data[q_query[1]]

  ## Run optimization
  pl_opt, success = scipy.optimize.leastsq(sys_eqs, pl0, args=(q,U,V), Dfun=sys_jacobian)

  Niter = 2
  for kk in range(Niter):
    q_query = xyz_tree.query(pl_opt.reshape(-1,3)[:Np])
    q = q_data[q_query[1]]
    pl_opt, success = scipy.optimize.leastsq(sys_eqs, pl_opt, args=(q,U,V), Dfun=sys_jacobian)

  ## Get the estimated coordinates, organize (and dump multipliers)
  p = pl_opt.reshape(-1,3)[:Np]

  #############################################################################
  ## Plot stuff

  ## Plot wireframes of input and resulting model
  fig = figure()
  ax = p3.Axes3D(fig, aspect='equal')
  title('Square mesh on 3D space', fontsize=20, fontweight='bold')
  ax.axis('equal')
  ax.plot_wireframe(q_data[:,0].reshape(Nl*oversample,Nk*oversample),q_data[:,1].reshape(Nl*oversample,Nk*oversample),q_data[:,2].reshape(Nl*oversample,Nk*oversample), color='#0000ff')
  #ax.plot_wireframe(p0[:,0].reshape(Nl,Nk),p0[:,1].reshape(Nl,Nk),p0[:,2].reshape(Nl,Nk), color='#008888')
  #ax.plot_wireframe(q[:,0].reshape(Nl,Nk),q[:,1].reshape(Nl,Nk),q[:,2].reshape(Nl,Nk), color='g')
  ax.plot_wireframe(p[:,0].reshape(Nl,Nk),p[:,1].reshape(Nl,Nk),p[:,2].reshape(Nl,Nk), color='r')

  mrang = max([p[:,0].max()-p[:,0].min(), p[:,1].max()-p[:,1].min(), p[:,2].max()-p[:,2].min()])/2
  midx = (p[:,0].max()+p[:,0].min())/2
  midy = (p[:,1].max()+p[:,1].min())/2
  midz = (p[:,2].max()+p[:,2].min())/2
  ax.set_xlim3d(midx-mrang, midx+mrang)
  ax.set_ylim3d(midy-mrang, midy+mrang)
  ax.set_zlim3d(midz-mrang, midz+mrang)
<|endoftext|>


<commit_before>"""
Devices tests

time.sleep is used after net.start() to synch python interpreter with
the mininet init process.

POX prefixed ClassNames indicate controller coded into script/pox dir
and symlinked to ~/pox/pox/forwarding dir.
"""

from mininet.topo import LinearTopo
from mininet.net import Mininet
from mininet.util import dumpNodeConnections
from mininet.log import setLogLevel
from mininet.node import CPULimitedHost, RemoteController
from mininet.link import TCLink
from mininet.cli import CLI

import time
import logging
logger = logging.getLogger('minicps.devices')
setLogLevel(c.TEST_LOG_LEVEL)

<commit_msg>Remove devices_tests<commit_after><|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import math
import random
import os

ttot=200
xi=0
vi=1
temp=1
coeff=1
dtime=0.01
m=0.0001

def force_net(vi,coeff,temp,Uenergy,jk):

    # Normally use potential energy in the following format Uenergy[j]
    Fnet = ((-vi*coeff)+random.random()*math.sqrt(2*coeff*temp)-Uenergy[jk])
    return Fnet

# Define acceleration function
def acceleration(Fnet,m):

    accl=Fnet/m
    return accl

# Define velocity function
def velocity(vi,dtime,accl):

    vi=vi+dtime*accl
    return vi

# Define position function
def position(xi,dtime,vi):

    xi=xi+dtime*vi
    return xi

def potential_energy():
    with open("Parameter_List.txt") as f:
        f=[x.strip() for x in f if x.strip()]
        data=[tuple(map(float,x.split())) for x in f[0:]]
        Uenergy=[x[2] for x in data]
    return Uenergy

#Define function for writing output
def write_output(index_out,time_out,position_out,velocity_out):

    f = open("Output.txt", "w")
    #Note {0}, {1}, etc, only neede for py26
    for i in range(len(index_out)):
        f.write("{0} {1} {2} {3}\n".format(index_out[i], time_out[i],position_out[i],velocity_out[i]))
    f.close()

def lang_dynmcs(xi, vi, temp, m, coeff, dtime,ttot,jk):

    #Initiate Arrays for Output
    index_out=[]
    time_out=[]
    position_out=[]
    velocity_out=[]
    jk=0

    #Perform a loop for the computations
    for time in [(float(j) / 100) for j in range(0, ttot, 1)]:
        Uenergy=potential_energy()
        Fnet = force_net(xi,coeff,temp,Uenergy,jk)
        accl = acceleration(Fnet,m)
        vi = velocity(xi,dtime,accl)
        xi = position(xi,dtime,vi)
        index_out.append(jk)
        time_out.append(time)
        position_out.append(xi)
        velocity_out.append(vi)
        jk+=1

    write_output(index_out,time_out,position_out,velocity_out)

lang_dynmcs(xi, vi, temp, m, coeff, dtime,ttot,jk)
print ("End of Computations!")
<commit_msg>-Minor Edit to Main Function<commit_after># -*- coding: utf-8 -*-
import math
import random
import os

ttot=200
xi=0
vi=1
temp=1
coeff=1
dtime=0.01
m=0.0001

def force_net(vi,coeff,temp,Uenergy,jk):

    # Normally use potential energy in the following format Uenergy[j]
    Fnet = ((-vi*coeff)+random.random()*math.sqrt(2*coeff*temp)-Uenergy[jk])
    return Fnet

# Define acceleration function
def acceleration(Fnet,m):

    accl=Fnet/m
    return accl

# Define velocity function
def velocity(vi,dtime,accl):

    vi=vi+dtime*accl
    return vi

# Define position function
def position(xi,dtime,vi):

    xi=xi+dtime*vi
    return xi

def potential_energy():
    with open("Parameter_List.txt") as f:
        f=[x.strip() for x in f if x.strip()]
        data=[tuple(map(float,x.split())) for x in f[0:]]
        Uenergy=[x[2] for x in data]
    return Uenergy

#Define function for writing output
def write_output(index_out,time_out,position_out,velocity_out):

    f = open("Output.txt", "w")
    #Note {0}, {1}, etc, only neede for py26
    for i in range(len(index_out)):
        f.write("{0} {1} {2} {3}\n".format(index_out[i], time_out[i],position_out[i],velocity_out[i]))
    f.close()

def lang_dynmcs(xi, vi, temp, m, coeff, dtime,ttot):

    #Initiate Arrays for Output
    index_out=[]
    time_out=[]
    position_out=[]
    velocity_out=[]
    jk=0

    #Perform a loop for the computations
    for time in [(float(j) / 100) for j in range(0, ttot, 1)]:
        Uenergy=potential_energy()
        Fnet = force_net(xi,coeff,temp,Uenergy,jk)
        accl = acceleration(Fnet,m)
        vi = velocity(xi,dtime,accl)
        xi = position(xi,dtime,vi)
        index_out.append(jk)
        time_out.append(time)
        position_out.append(xi)
        velocity_out.append(vi)
        jk+=1

    write_output(index_out,time_out,position_out,velocity_out)

lang_dynmcs(xi, vi, temp, m, coeff, dtime,ttot)
print ("End of Computations!")
<|endoftext|>


<commit_before>from datetime import datetime

import pytz
from flask import abort, redirect, render_template, request, session, url_for
from flask_login import current_user

from app import (
    convert_to_boolean,
    current_service,
    service_api_client,
    zendesk_client,
)
from app.main import main
from app.main.forms import Feedback, Problem, SupportType, Triage

QUESTION_TICKET_TYPE = 'ask-question-give-feedback'
PROBLEM_TICKET_TYPE = "report-problem"

def get_prefilled_message():
    return {
        'agreement': (
            'Please can you tell me if there’s an agreement in place '
            'between GOV.UK Notify and my organisation?'
        ),
    }.get(
        request.args.get('body'), ''
    )

@main.route('/support', methods=['GET', 'POST'])
def support():
    form = SupportType()
    if form.validate_on_submit():
        return redirect(url_for(
            '.feedback',
            ticket_type=form.support_type.data,
        ))
    return render_template('views/support/index.html', form=form)

@main.route('/support/triage', methods=['GET', 'POST'])
def triage():
    form = Triage()
    if form.validate_on_submit():
        return redirect(url_for(
            '.feedback',
            ticket_type=PROBLEM_TICKET_TYPE,
            severe=form.severe.data
        ))
    return render_template(
        'views/support/triage.html',
        form=form
    )

@main.route('/support/<ticket_type>', methods=['GET', 'POST'])
def feedback(ticket_type):
    try:
        form = {
            QUESTION_TICKET_TYPE: Feedback,
            PROBLEM_TICKET_TYPE: Problem,
        }[ticket_type]()
    except KeyError:
        abort(404)

    if not form.feedback.data:
        form.feedback.data = session.pop('feedback_message', '')

    if request.args.get('severe') in ['yes', 'no']:
        severe = convert_to_boolean(request.args.get('severe'))
    else:
        severe = None

    p1 = False
    urgent = False

    if in_business_hours():
        # if we're in the office, it's urgent (aka we'll get back in 30 mins)
        urgent = True
    elif ticket_type == PROBLEM_TICKET_TYPE and severe:
        # out of hours, it's only a p1 and it's only urgent if it's a p1
        urgent = True
        p1 = True

    anonymous = (
        (not form.email_address.data) and
        (not current_user.is_authenticated)
    )

    if needs_triage(ticket_type, severe):
        session['feedback_message'] = form.feedback.data
        return redirect(url_for('.triage'))

    if needs_escalation(ticket_type, severe):
        return redirect(url_for('.bat_phone'))

    if current_user.is_authenticated:
        form.email_address.data = current_user.email_address
        form.name.data = current_user.name

    if form.validate_on_submit():
        user_email = form.email_address.data
        user_name = form.name.data or None
        if current_service:
            service_string = 'Service "{name}": {url}\n'.format(
                name=current_service['name'],
                url=url_for('main.service_dashboard', service_id=current_service['id'], _external=True)
            )
        else:
            service_string = ''

        feedback_msg = 'Environment: {}\n{}{}\n{}'.format(
            url_for('main.index', _external=True),
            service_string,
            '' if user_email else '{} (no email address supplied)'.format(form.name.data),
            form.feedback.data
        )

        zendesk_client.create_ticket(
            subject='Notify feedback',
            message=feedback_msg,
            ticket_type=ticket_type,
            p1=p1,
            user_email=user_email,
            user_name=user_name
        )
        return redirect(url_for('.thanks', urgent=urgent, anonymous=anonymous))

    if not form.feedback.data:
        form.feedback.data = get_prefilled_message()

    return render_template(
        'views/support/{}.html'.format(ticket_type),
        form=form,
        ticket_type=ticket_type,
    )

@main.route('/support/escalate', methods=['GET', 'POST'])
def bat_phone():

    if current_user.is_authenticated:
        return redirect(url_for('main.feedback', ticket_type=PROBLEM_TICKET_TYPE))

    return render_template('views/support/bat-phone.html')

@main.route('/support/thanks', methods=['GET', 'POST'])
def thanks():
    return render_template(
        'views/support/thanks.html',
        urgent=convert_to_boolean(request.args.get('urgent')),
        anonymous=convert_to_boolean(request.args.get('anonymous')),
        logged_in=current_user.is_authenticated,
    )

def in_business_hours():

    now = datetime.utcnow().replace(tzinfo=pytz.utc)

    if is_weekend(now) or is_bank_holiday(now):
        return False

    return london_time_today_as_utc(9, 30) <= now < london_time_today_as_utc(17, 30)

def london_time_today_as_utc(hour, minute):
    return pytz.timezone('Europe/London').localize(
        datetime.now().replace(hour=hour, minute=minute)
    ).astimezone(pytz.utc)

def is_weekend(time):
    return time.strftime('%A') in {
        'Saturday',
        'Sunday',
    }

def is_bank_holiday(time):
    return time.strftime('%Y-%m-%d') in {
        # taken from https://www.gov.uk/bank-holidays.json
        "2016-01-01",
        "2016-03-25",
        "2016-03-28",
        "2016-05-02",
        "2016-05-30",
        "2016-08-29",
        "2016-12-26",
        "2016-12-27",
        "2017-01-02",
        "2017-04-14",
        "2017-04-17",
        "2017-05-01",
        "2017-05-29",
        "2017-08-28",
        "2017-12-25",
        "2017-12-26",
        "2018-01-01",
        "2018-03-30",
        "2018-04-02",
        "2018-05-07",
        "2018-05-28",
        "2018-08-27",
        "2018-12-25",
        "2018-12-26",
        "2019-01-01",
        "2019-04-19",
        "2019-04-22",
        "2019-05-06",
        "2019-05-27",
        "2019-08-26",
        "2019-12-25",
        "2019-12-26",
    }

def has_live_services(user_id):
    return any(
        service['restricted'] is False
        for service in service_api_client.get_services({'user_id': user_id})['data']
    )

def needs_triage(ticket_type, severe):
    return all((
        ticket_type == PROBLEM_TICKET_TYPE,
        severe is None,
        (
            not current_user.is_authenticated or has_live_services(current_user.id)
        ),
        not in_business_hours(),
    ))

def needs_escalation(ticket_type, severe):
    return all((
        ticket_type == PROBLEM_TICKET_TYPE,
        severe,
        not current_user.is_authenticated,
        not in_business_hours(),
    ))
<commit_msg>Tidied up the formatting on the feedback tickets<commit_after>from datetime import datetime

import pytz
from flask import abort, redirect, render_template, request, session, url_for
from flask_login import current_user

from app import (
    convert_to_boolean,
    current_service,
    service_api_client,
    zendesk_client,
)
from app.main import main
from app.main.forms import Feedback, Problem, SupportType, Triage

QUESTION_TICKET_TYPE = 'ask-question-give-feedback'
PROBLEM_TICKET_TYPE = "report-problem"

def get_prefilled_message():
    return {
        'agreement': (
            'Please can you tell me if there’s an agreement in place '
            'between GOV.UK Notify and my organisation?'
        ),
    }.get(
        request.args.get('body'), ''
    )

@main.route('/support', methods=['GET', 'POST'])
def support():
    form = SupportType()
    if form.validate_on_submit():
        return redirect(url_for(
            '.feedback',
            ticket_type=form.support_type.data,
        ))
    return render_template('views/support/index.html', form=form)

@main.route('/support/triage', methods=['GET', 'POST'])
def triage():
    form = Triage()
    if form.validate_on_submit():
        return redirect(url_for(
            '.feedback',
            ticket_type=PROBLEM_TICKET_TYPE,
            severe=form.severe.data
        ))
    return render_template(
        'views/support/triage.html',
        form=form
    )

@main.route('/support/<ticket_type>', methods=['GET', 'POST'])
def feedback(ticket_type):
    try:
        form = {
            QUESTION_TICKET_TYPE: Feedback,
            PROBLEM_TICKET_TYPE: Problem,
        }[ticket_type]()
    except KeyError:
        abort(404)

    if not form.feedback.data:
        form.feedback.data = session.pop('feedback_message', '')

    if request.args.get('severe') in ['yes', 'no']:
        severe = convert_to_boolean(request.args.get('severe'))
    else:
        severe = None

    p1 = False
    urgent = False

    if in_business_hours():
        # if we're in the office, it's urgent (aka we'll get back in 30 mins)
        urgent = True
    elif ticket_type == PROBLEM_TICKET_TYPE and severe:
        # out of hours, it's only a p1 and it's only urgent if it's a p1
        urgent = True
        p1 = True

    anonymous = (
        (not form.email_address.data) and
        (not current_user.is_authenticated)
    )

    if needs_triage(ticket_type, severe):
        session['feedback_message'] = form.feedback.data
        return redirect(url_for('.triage'))

    if needs_escalation(ticket_type, severe):
        return redirect(url_for('.bat_phone'))

    if current_user.is_authenticated:
        form.email_address.data = current_user.email_address
        form.name.data = current_user.name

    if form.validate_on_submit():
        user_email = form.email_address.data
        user_name = form.name.data or None
        if current_service:
            service_string = 'Service: "{name}"\n{url}\n'.format(
                name=current_service['name'],
                url=url_for('main.service_dashboard', service_id=current_service['id'], _external=True)
            )
        else:
            service_string = ''

        feedback_msg = '{}\n{}{}'.format(
            form.feedback.data
            service_string,
            '' if user_email else '{} (no email address supplied)'.format(form.name.data),
        )

        zendesk_client.create_ticket(
            subject='Notify feedback',
            feedback_msg,
            ticket_type=ticket_type,
            p1=p1,
            user_email=user_email,
            user_name=user_name
        )
        return redirect(url_for('.thanks', urgent=urgent, anonymous=anonymous))

    if not form.feedback.data:
        form.feedback.data = get_prefilled_message()

    return render_template(
        'views/support/{}.html'.format(ticket_type),
        form=form,
        ticket_type=ticket_type,
    )

@main.route('/support/escalate', methods=['GET', 'POST'])
def bat_phone():

    if current_user.is_authenticated:
        return redirect(url_for('main.feedback', ticket_type=PROBLEM_TICKET_TYPE))

    return render_template('views/support/bat-phone.html')

@main.route('/support/thanks', methods=['GET', 'POST'])
def thanks():
    return render_template(
        'views/support/thanks.html',
        urgent=convert_to_boolean(request.args.get('urgent')),
        anonymous=convert_to_boolean(request.args.get('anonymous')),
        logged_in=current_user.is_authenticated,
    )

def in_business_hours():

    now = datetime.utcnow().replace(tzinfo=pytz.utc)

    if is_weekend(now) or is_bank_holiday(now):
        return False

    return london_time_today_as_utc(9, 30) <= now < london_time_today_as_utc(17, 30)

def london_time_today_as_utc(hour, minute):
    return pytz.timezone('Europe/London').localize(
        datetime.now().replace(hour=hour, minute=minute)
    ).astimezone(pytz.utc)

def is_weekend(time):
    return time.strftime('%A') in {
        'Saturday',
        'Sunday',
    }

def is_bank_holiday(time):
    return time.strftime('%Y-%m-%d') in {
        # taken from https://www.gov.uk/bank-holidays.json
        "2016-01-01",
        "2016-03-25",
        "2016-03-28",
        "2016-05-02",
        "2016-05-30",
        "2016-08-29",
        "2016-12-26",
        "2016-12-27",
        "2017-01-02",
        "2017-04-14",
        "2017-04-17",
        "2017-05-01",
        "2017-05-29",
        "2017-08-28",
        "2017-12-25",
        "2017-12-26",
        "2018-01-01",
        "2018-03-30",
        "2018-04-02",
        "2018-05-07",
        "2018-05-28",
        "2018-08-27",
        "2018-12-25",
        "2018-12-26",
        "2019-01-01",
        "2019-04-19",
        "2019-04-22",
        "2019-05-06",
        "2019-05-27",
        "2019-08-26",
        "2019-12-25",
        "2019-12-26",
    }

def has_live_services(user_id):
    return any(
        service['restricted'] is False
        for service in service_api_client.get_services({'user_id': user_id})['data']
    )

def needs_triage(ticket_type, severe):
    return all((
        ticket_type == PROBLEM_TICKET_TYPE,
        severe is None,
        (
            not current_user.is_authenticated or has_live_services(current_user.id)
        ),
        not in_business_hours(),
    ))

def needs_escalation(ticket_type, severe):
    return all((
        ticket_type == PROBLEM_TICKET_TYPE,
        severe,
        not current_user.is_authenticated,
        not in_business_hours(),
    ))
<|endoftext|>


<commit_before>from optparse import make_option

from django.conf import settings
from django.core.management.base import BaseCommand

from pillowtop.models import DjangoPillowCheckpoint

class Command(BaseCommand):
    """
    One off command to migrate pillow checkpoints after ES upgrade.
    """
    help = "Migrate the esupgrade checkpoints"

    option_list = BaseCommand.option_list + (
        make_option(
            '--check',
            action='store_true',
            dest='check',
            default=False,
            help="Just print the changes",
        ),
    )

    def handle(self, *args, **options):
        check = options['check']

        upgrade_checkpoints = DjangoPillowCheckpoint.objects.filter(checkpoint_id__endswith='esupgrade')
        for upgrade_cp in upgrade_checkpoints:
            prefix, _ = upgrade_cp.checkpoint_id.rsplit('.', 1)
            current_cp_id = '{}.{}'.format(prefix, settings.PILLOWTOP_MACHINE_ID)
            try:
                current_cp = DjangoPillowCheckpoint.objects.get(checkpoint_id=current_cp_id)
            except DjangoPillowCheckpoint.DoesNotExist:
                print('Matching checkpoint not found: {}'.format(upgrade_cp.checkpoint_id))
            else:
                print('Copying sequence from: {} -> {}'.format(
                    upgrade_cp.checkpoint_id, current_cp.checkpoint_id
                ))
                if check:
                    print('Old seq: {}'.format(current_cp.sequence))
                    print('New seq: {}'.format(upgrade_cp.sequence))
                else:
                    current_cp.old_sequence = current_cp.sequence
                    current_cp.sequence = upgrade_cp.sequence
                    current_cp.save()
<commit_msg>add option to undo<commit_after>from optparse import make_option

from django.conf import settings
from django.core.management.base import BaseCommand

from pillowtop.models import DjangoPillowCheckpoint

class Command(BaseCommand):
    """
    One off command to migrate pillow checkpoints after ES upgrade.
    """
    help = "Migrate the esupgrade checkpoints"

    option_list = BaseCommand.option_list + (
        make_option(
            '--check',
            action='store_true',
            dest='check',
            default=False,
            help="Just print the changes",
        ),
        make_option(
            '--undo',
            action='store_true',
            dest='undo',
            default=False,
            help="Undo the changes",
        ),
    )

    def handle(self, *args, **options):
        check = options['check']
        undo = options['undo']

        upgrade_checkpoints = DjangoPillowCheckpoint.objects.filter(checkpoint_id__endswith='esupgrade')
        for upgrade_cp in upgrade_checkpoints:
            prefix, _ = upgrade_cp.checkpoint_id.rsplit('.', 1)
            current_cp_id = '{}.{}'.format(prefix, settings.PILLOWTOP_MACHINE_ID)
            try:
                current_cp = DjangoPillowCheckpoint.objects.get(checkpoint_id=current_cp_id)
            except DjangoPillowCheckpoint.DoesNotExist:
                print('Matching checkpoint not found: {}'.format(upgrade_cp.checkpoint_id))
            else:
                if undo:
                    self.undo(current_cp, check)
                else:
                    self.migrate(upgrade_cp, current_cp, check)

    @staticmethod
    def migrate(upgrade_cp, current_cp, check):
        print('Copying sequence from: {} -> {}'.format(
            upgrade_cp.checkpoint_id, current_cp.checkpoint_id
        ))
        if check:
            print('Old seq: {}'.format(current_cp.sequence))
            print('New seq: {}'.format(upgrade_cp.sequence))
        else:
            current_cp.old_sequence = current_cp.sequence
            current_cp.sequence = upgrade_cp.sequence
            current_cp.save()

    @staticmethod
    def undo(current_cp, check):
        if not current_cp.old_sequence:
            print('Unable to revert empty to old sequence: {}'.format(current_cp.checkpoint_id))
            return

        print('Reverting to old sequence for: {}'.format(current_cp.checkpoint_id))
        if check:
            print('Old seq: {}'.format(current_cp.sequence))
            print('New seq: {}'.format(current_cp.old_sequence))
        else:
            current_cp.sequence = current_cp.old_sequence
            current_cp.old_sequence = None
            current_cp.save()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

import ctypes
from ctypes.util import find_library

libopus = ctypes.CDLL(find_library('opus'))

class Decoder(ctypes.Structure):
    """Opus decoder state.

    This contains the complete state of an Opus decoder.
    """

    pass

DecoderPointer = ctypes.POINTER(Decoder)

_get_size = libopus.opus_decoder_get_size
_get_size.argtypes = (ctypes.c_int,)
_get_size.restype = ctypes.c_int

def get_size(channels):
    """Gets the size of an OpusDecoder structure"""

    if not channels in (1, 2):
        raise ValueError()  # TODO: error message

    return _get_size(channels)

if __name__ == '__main__':
    print get_size(1)
    print get_size(2)
<commit_msg>`opus_decoder_create` and `opus_decoder_destroy` function bindings<commit_after># -*- coding: utf-8 -*-

import ctypes
from ctypes.util import find_library

libopus = ctypes.CDLL(find_library('opus'))
c_int_pointer = ctypes.POINTER(ctypes.c_int)

class Decoder(ctypes.Structure):
    """Opus decoder state.

    This contains the complete state of an Opus decoder.
    """

    pass

DecoderPointer = ctypes.POINTER(Decoder)

_get_size = libopus.opus_decoder_get_size
_get_size.argtypes = (ctypes.c_int,)
_get_size.restype = ctypes.c_int

def get_size(channels):
    """Gets the size of an OpusDecoder structure"""

    if not channels in (1, 2):
        raise ValueError()  # TODO: error message

    return _get_size(channels)

_create = libopus.opus_decoder_create
_create.argtypes = (ctypes.c_int, ctypes.c_int, c_int_pointer)
_create.restype = DecoderPointer

def create(fs, channels):
    """Allocates and initializes a decoder state"""

    if fs not in (8000, 12000, 16000, 24000, 48000):
        raise ValueError('Wrong fs value. Must be equal to 8000, 12000, 16000, 24000 or 48000')

    if not channels in (1, 2):
        raise ValueError('Wrong channels value. Must be equal to 1 or 2')

    result_code = ctypes.c_int()

    result = _create(fs, channels, ctypes.byref(result_code))
    # TODO: check for `result_code` value and raise an exception if needed

    return result

destroy = libopus.opus_decoder_destroy
destroy.argtypes = (DecoderPointer,)
destroy.restype = None
destroy.__doc__ = 'Frees an OpusDecoder allocated by opus_decoder_create()'

if __name__ == '__main__':
    decoder = create(12000, 2)
    print get_size(1)
    print get_size(2)
    destroy(decoder)
<|endoftext|>


<commit_before>from Config import *

# Not sure what this number does, but we need some threshold that we'd like to
# avoid crossing.
setOption("BadnessThreshold", 42)

# Ignore documentation issues.
addFilter('no-manual-page-for-binary')
addFilter('no-documentation')

# Ignore spelling errors unilt there's a support for custom dictionaries.
# TODO: add such support.
addFilter('spelling-error')

# Ignore unversioned bundled provides.
addFilter('unversioned-explicit-provides bundled\([a-z\-]+\)')

# Don't care about groups.
addFilter('non-standard-group')

# Ignore all lint warnings in submodules:
addFilter('third_party/submodules/')
# Ignore all lint warnings in symlinks from submodules.
addFilter('SPECS/cmake.spec')
addFilter('SPECS/gdb.spec')
addFilter('SPECS/gperftools.spec')
addFilter('libev-devel.x86_64')
addFilter('SPECS/libcomps.spec')
addFilter('nginx\.(spec|x86_64|src)')
addFilter('perl-common-sense.x86_64')
addFilter('perl-Compress-Raw-Bzip2.x86_64')
addFilter('perl-Data-OptList.src')
addFilter('perl-Data-Section.src')
addFilter('perl-GD.x86_64')
addFilter('perl-HTML-Parser.x86_64')
addFilter('perl-libintl\.(x86_64|src|spec)')
addFilter('perl-Mojolicious.src')
addFilter('perl-Params-Util.x86_64')
addFilter('perl-Pod-Coverage.spec')
addFilter('perl-Software-License\.(src|spec)')
addFilter('perl-Sub-Exporter\.(src|spec)')
addFilter('perl-Sub-Install.src')
addFilter('perl-Pod-Coverage.src')
addFilter('perl-libintl\.(x86_64|src)')
addFilter('perl-Test-Pod\.(src|spec)')
addFilter('perl-TermReadKey\.(x86_64|src)')
addFilter('perl-Test-Pod\.(src|spec)')
addFilter('perl-Text-Template.noarch')
addFilter('python(2|3)?-acme\.(src|noarch)')
addFilter('pyOpenSSL-doc.noarch')
addFilter('python-pyrfc3339.src')
addFilter('SPECS/puppet.spec')
addFilter('SPECS/python-iniparse.spec')
addFilter('python-pyrfc3339.src')
addFilter('SPECS/os-prober.spec')
addFilter('SPECS/puppet.spec')
addFilter('yum\.(spec|src)')

# Python is mostly third-party and has lots of warnings.
# TODO: clean those up.
addFilter('SPECS/python.spec')
addFilter('SPECS/python3.spec')
addFilter('third_party/subtrees/python/python.spec')
addFilter('third_party/subtrees/python3/python3.spec')
addFilter('python-debuginfo.x86_64')
addFilter('python-libs.x86_64')
addFilter('python-devel.x86_64')
addFilter('python-macros.noarch')
addFilter('python.x86_64')
addFilter('python3.src:[0-9]+: W: hardcoded-library-path')

# RPM is special, let's ignore warnings from it.
addFilter('SPECS/rpm.spec')
addFilter('third_party/subtrees/rpm/rpm.spec')

# DNF have a lot of weird stuff:
addFilter('dnf.spec.*libdir-macro-in-noarch-package')

# VIM: allow mixed space/tab usage in specific line.
addFilter('vim.spec:218: W: mixed-use-of-spaces-and-tabs')
# Ignore unversioned provide /bin/vi, versioning it triggers another lint
# warning.
addFilter('vim.spec:[0-9]+: W: unversioned-explicit-provides /bin/vi')

## Perl
# Perl packages are weird and often don't have -devel part.
addFilter('perl-Tk.x86_64: W: devel-file-in-non-devel-package')
# Some of them also depend on perl-devel
addFilter('perl-ExtUtils-Miniperl.noarch: W: devel-dependency')
# Perl-Tk has weird deps
addFilter('perl-Tk.spec:63: W: comparison-operator-in-deptoken')

## Let's encrypt:
# Allow pems in test files.
addFilter('python2-letsencrypt.noarch: W: pem-certificate /usr/lib/python2.7/site-packages/letsencrypt/tests/testdata/.*')
# Allow some nonstandard permissions
addFilter('letsencrypt.noarch: W: non-standard-dir-perm /var/log/letsencrypt 0')
addFilter('letsencrypt.noarch: W: non-standard-dir-perm /var/lib/letsencrypt 0')
addFilter('letsencrypt.noarch: W: non-standard-dir-perm /etc/letsencrypt 0')
# TODO: fix following
addFilter('letsencrypt.noarch: W: log-files-without-logrotate')

## Libcomps
# URL broken :(
addFilter('libcomps.spec: W: invalid-url Source0: https://github.com/midnightercz/libcomps/libcomps-0.1.7.tar.gz')

## GDB
# Following should be ok for debugger.
addFilter('gdb.spec:[0-9]+: W: unversioned-explicit-obsoletes devtoolset')
addFilter('gdb.x86_64: W: unstripped-binary-or-object /usr/bin/gdb')
addFilter('gdb-gdbserver.x86_64: W: unstripped-binary-or-object /usr/lib64/libinproctrace.so')
addFilter('gdb-gdbserver.x86_64: W: unstripped-binary-or-object /usr/bin/gdbserver')
addFilter('gdb-gdbserver.x86_64: W: shared-lib-calls-exit /usr/lib64/libinproctrace.so exit@GLIBC_2.2.5')
addFilter('gdb.x86_64: W: only-non-binary-in-usr-lib')
addFilter('gdb-gdbserver.x86_64: W: no-soname /usr/lib64/libinproctrace.so')
addFilter('gdb.spec:[0-9]+: W: hardcoded-library-path')
addFilter('gdb.x86_64: W: dangerous-command-in-%pre mv')
addFilter('gdb.x86_64: W: devel-file-in-non-devel-package /usr/include/gdb/jit-reader.h')
addFilter('gdb.src:[0-9]+: W: hardcoded-library-path')
# Snapshots dissapear quickly
addFilter('gdb.src: W: invalid-url Source0: ftp://sourceware.org/pub/gdb/snapshots/current/.*')

## Python-pip
addFilter('python(3|2)?-pip.noarch: W: non-executable-script /usr/lib/python.\../site-packages/pip/_vendor/requests/packages/chardet/chardetect.py')

## Cython
# There's no -devel package.
addFilter('(python3-)?Cython.x86_64: W: devel-file-in-non-devel-package')

## Perl
addFilter('perl.spec: W: %ifarch-applied-patch Patch3: perl-5.8.0-libdir64.patch')
<commit_msg>python-hypothesis: Ignore lint errors in the src rpm.<commit_after>from Config import *

# Not sure what this number does, but we need some threshold that we'd like to
# avoid crossing.
setOption("BadnessThreshold", 42)

# Ignore documentation issues.
addFilter('no-manual-page-for-binary')
addFilter('no-documentation')

# Ignore spelling errors unilt there's a support for custom dictionaries.
# TODO: add such support.
addFilter('spelling-error')

# Ignore unversioned bundled provides.
addFilter('unversioned-explicit-provides bundled\([a-z\-]+\)')

# Don't care about groups.
addFilter('non-standard-group')

# Ignore all lint warnings in submodules:
addFilter('third_party/submodules/')
# Ignore all lint warnings in symlinks from submodules.
addFilter('SPECS/cmake.spec')
addFilter('SPECS/gdb.spec')
addFilter('SPECS/gperftools.spec')
addFilter('libev-devel.x86_64')
addFilter('SPECS/libcomps.spec')
addFilter('nginx\.(spec|x86_64|src)')
addFilter('perl-common-sense.x86_64')
addFilter('perl-Compress-Raw-Bzip2.x86_64')
addFilter('perl-Data-OptList.src')
addFilter('perl-Data-Section.src')
addFilter('perl-GD.x86_64')
addFilter('perl-HTML-Parser.x86_64')
addFilter('perl-libintl\.(x86_64|src|spec)')
addFilter('perl-Mojolicious.src')
addFilter('perl-Params-Util.x86_64')
addFilter('perl-Pod-Coverage.spec')
addFilter('perl-Software-License\.(src|spec)')
addFilter('perl-Sub-Exporter\.(src|spec)')
addFilter('perl-Sub-Install.src')
addFilter('perl-Pod-Coverage.src')
addFilter('perl-libintl\.(x86_64|src)')
addFilter('perl-Test-Pod\.(src|spec)')
addFilter('perl-TermReadKey\.(x86_64|src)')
addFilter('perl-Test-Pod\.(src|spec)')
addFilter('perl-Text-Template.noarch')
addFilter('pyOpenSSL-doc.noarch')
addFilter('python(2|3)?-acme\.(src|noarch)')
addFilter('python-hypothesis.src')
addFilter('python-pyrfc3339.src')
addFilter('SPECS/puppet.spec')
addFilter('SPECS/python-iniparse.spec')
addFilter('python-pyrfc3339.src')
addFilter('SPECS/os-prober.spec')
addFilter('SPECS/puppet.spec')
addFilter('yum\.(spec|src)')

# Python is mostly third-party and has lots of warnings.
# TODO: clean those up.
addFilter('SPECS/python.spec')
addFilter('SPECS/python3.spec')
addFilter('third_party/subtrees/python/python.spec')
addFilter('third_party/subtrees/python3/python3.spec')
addFilter('python-debuginfo.x86_64')
addFilter('python-libs.x86_64')
addFilter('python-devel.x86_64')
addFilter('python-macros.noarch')
addFilter('python.x86_64')
addFilter('python3.src:[0-9]+: W: hardcoded-library-path')

# RPM is special, let's ignore warnings from it.
addFilter('SPECS/rpm.spec')
addFilter('third_party/subtrees/rpm/rpm.spec')

# DNF have a lot of weird stuff:
addFilter('dnf.spec.*libdir-macro-in-noarch-package')

# VIM: allow mixed space/tab usage in specific line.
addFilter('vim.spec:218: W: mixed-use-of-spaces-and-tabs')
# Ignore unversioned provide /bin/vi, versioning it triggers another lint
# warning.
addFilter('vim.spec:[0-9]+: W: unversioned-explicit-provides /bin/vi')

## Perl
# Perl packages are weird and often don't have -devel part.
addFilter('perl-Tk.x86_64: W: devel-file-in-non-devel-package')
# Some of them also depend on perl-devel
addFilter('perl-ExtUtils-Miniperl.noarch: W: devel-dependency')
# Perl-Tk has weird deps
addFilter('perl-Tk.spec:63: W: comparison-operator-in-deptoken')

## Let's encrypt:
# Allow pems in test files.
addFilter('python2-letsencrypt.noarch: W: pem-certificate /usr/lib/python2.7/site-packages/letsencrypt/tests/testdata/.*')
# Allow some nonstandard permissions
addFilter('letsencrypt.noarch: W: non-standard-dir-perm /var/log/letsencrypt 0')
addFilter('letsencrypt.noarch: W: non-standard-dir-perm /var/lib/letsencrypt 0')
addFilter('letsencrypt.noarch: W: non-standard-dir-perm /etc/letsencrypt 0')
# TODO: fix following
addFilter('letsencrypt.noarch: W: log-files-without-logrotate')

## Libcomps
# URL broken :(
addFilter('libcomps.spec: W: invalid-url Source0: https://github.com/midnightercz/libcomps/libcomps-0.1.7.tar.gz')

## GDB
# Following should be ok for debugger.
addFilter('gdb.spec:[0-9]+: W: unversioned-explicit-obsoletes devtoolset')
addFilter('gdb.x86_64: W: unstripped-binary-or-object /usr/bin/gdb')
addFilter('gdb-gdbserver.x86_64: W: unstripped-binary-or-object /usr/lib64/libinproctrace.so')
addFilter('gdb-gdbserver.x86_64: W: unstripped-binary-or-object /usr/bin/gdbserver')
addFilter('gdb-gdbserver.x86_64: W: shared-lib-calls-exit /usr/lib64/libinproctrace.so exit@GLIBC_2.2.5')
addFilter('gdb.x86_64: W: only-non-binary-in-usr-lib')
addFilter('gdb-gdbserver.x86_64: W: no-soname /usr/lib64/libinproctrace.so')
addFilter('gdb.spec:[0-9]+: W: hardcoded-library-path')
addFilter('gdb.x86_64: W: dangerous-command-in-%pre mv')
addFilter('gdb.x86_64: W: devel-file-in-non-devel-package /usr/include/gdb/jit-reader.h')
addFilter('gdb.src:[0-9]+: W: hardcoded-library-path')
# Snapshots dissapear quickly
addFilter('gdb.src: W: invalid-url Source0: ftp://sourceware.org/pub/gdb/snapshots/current/.*')

## Python-pip
addFilter('python(3|2)?-pip.noarch: W: non-executable-script /usr/lib/python.\../site-packages/pip/_vendor/requests/packages/chardet/chardetect.py')

## Cython
# There's no -devel package.
addFilter('(python3-)?Cython.x86_64: W: devel-file-in-non-devel-package')

## Perl
addFilter('perl.spec: W: %ifarch-applied-patch Patch3: perl-5.8.0-libdir64.patch')
<|endoftext|>


<commit_before>from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from member.models import Investigator
from django.core.urlresolvers import reverse
from model_utils.managers import InheritanceManager
from django.core.mail import EmailMultiAlternatives
from django.core.mail import BadHeaderError
from django.http import HttpResponse
from django.conf import settings

# Create your models here.

# Defining types of order
EVENT = 'e'
HARDWARE_SOFTWARE = 'h'
SERVICE = 's'
TICKET = 't'
DAILY_STIPEND = 'd'
REIMBURSEMENT = 'r'
ORDER_TYPE = (
    (EVENT, _('Scientific event')),
    (HARDWARE_SOFTWARE, _('Equipment / Supplies / Miscellaneous')),
    (SERVICE, _('Service')),
    (TICKET, _('Ticket')),
    (DAILY_STIPEND, _('Daily stipend')),
    (REIMBURSEMENT, _('Reimbursement')),
)

# Defining status of order
OPEN = 'o'
PENDING = 'p'
CANCELED = 'c'
APPROVED = 'a'
DENIED = 'd'
ORDER_STATUS = (
    (OPEN, _('Open')),
    (PENDING, _('Pending')),
    (CANCELED, _('Canceled')),
    (APPROVED, _('Approved')),
    (DENIED, _('Denied'))
)

class Order(models.Model):
    """

    '__unicode__'		Returns the requester.
    'class Meta'		Ordering of data by date modification.
    'id_order'          Show the IDs as a link to the order.
    'order_number'      Get ID and shows as order number.
    'save'              Send email to the requestor if the order status is changed.
                        Send email to users (NIRA Admin) informing that an order has changed.
                        Send email to users (NIRA Admin) informing that a new order was created.
    """
    requester = models.ForeignKey(Investigator, verbose_name=_('Investigator'))
    justification = models.TextField(_('Justification'), max_length=1000)
    order_date = models.DateTimeField(_('Order date'), auto_now_add=True, blank=True)
    date_modified = models.DateTimeField(_('Modified'), auto_now=True, blank=True)
    type_of_order = models.CharField(_('Type of order'), max_length=1, choices=ORDER_TYPE, blank=True)
    status = models.CharField(max_length=1, default=OPEN, choices=ORDER_STATUS, blank=True)
    protocol = models.IntegerField(_('Protocol'), blank=True, null=True)
    objects = InheritanceManager()

    def __unicode__(self):
        return u'%s' % self.requester

    class Meta:
        verbose_name = _('Order')
        verbose_name_plural = _('Orders')
        ordering = ('-date_modified', )

    def id_order(self):
        orders = Order.objects.filter(id=self.id).select_subclasses()
        order = orders[0]
        return '%s' % (reverse('admin:%s_%s_change' % (order._meta.app_label, order._meta.model_name),
                                                args=(order.id,)), order.id)
    id_order.allow_tags = True
    id_order.short_description = _('Order number')
    id_order.admin_order_field = '-id'

    def order_number(self):
        return self.id
    order_number.short_description = _('Order number')
    order_number.admin_order_field = '-id'

    def save(self, *args, **kwargs):
        # Info from settings_local file
        email_host_user = settings.EMAIL_HOST_USER
        nira_admin_email = settings.NIRA_ADMIN_EMAIL
        nira_website = settings.NIRA_WEBSITE
        contact_phone = settings.CONTACT_PHONE
        contact_email = settings.CONTACT_EMAIL

        if self.pk is not None:
            # Info about the order
            check_order = Order.objects.get(pk=self.pk)
            requester_name = check_order.requester
            requester_email = check_order.requester.user.email
            order_type = check_order.type_of_order

            # Check the type of request. It will be used to create the URL in the email that will be sent.
            try:
                if order_type == 'e':
                    order_type = 'event'
                elif order_type == 'h':
                    order_type = 'hardwaresoftware'
                elif order_type == 's':
                    order_type = 'service'
                elif order_type == 't':
                    order_type = 'ticket'
                elif order_type == 'd':
                    order_type = 'dailystipend'
                elif order_type == 'r':
                    order_type = 'reimbursement'
            except NameError:
                return HttpResponse('Invalid order type found.')

            if check_order.status != self.status:
                new_status = self.get_status_display()
                subject = 'NIRA - The status of your order has changed'
                from_email = email_host_user
                to = requester_email
                text_content = 'Hello %s. The status of your order has changed to "%s". See your order by accessing ' \
                               '%s. Please feel free to contact us at %s or %s if you have any questions. ' \
                               'With kind regards, the NIRA team.' \
                               % (requester_name, new_status, nira_website, contact_phone, contact_email)
                html_content = '
Hello %s,

The status of your order has changed to "%s". Click ' \
                               'here to see your request.
 ' \
                               '
Please feel free to contact us at %s or %s if you have any questions.
 ' \
                               '
With kind regards,

the NIRA team.
' \
                               % (requester_name, new_status, nira_website, order_type, check_order.id, contact_phone,
                                  contact_email)
                if subject and from_email and to:
                    try:
                        msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
                        msg.attach_alternative(html_content, "text/html")
                        msg.send()
                    except BadHeaderError:
                        return HttpResponse('Invalid header found.')

            else:
                subject, from_email, to = 'NIRA - Pedido alterado', email_host_user, nira_admin_email
                text_content = 'Um pedido foi alterado no sistema NIRA.'
                html_content = '
O(a) pesquisador(a) %s alterou o pedido de número %s do NIRA. Clique ' \
                               'aqui para ver este pedido.
' \
                               % (requester_name, check_order.id, nira_website, order_type, check_order.id)
                if subject and from_email and to:
                    try:
                        msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
                        msg.attach_alternative(html_content, "text/html")
                        msg.send()
                    except BadHeaderError:
                        return HttpResponse('Invalid header found.')

        else:
            subject, from_email, to = 'NIRA - Novo pedido', email_host_user, nira_admin_email
            text_content = 'Um novo pedido foi gerado no sistema NIRA.'
            html_content = '

Um novo pedido foi gerado no sistema NIRA. ' \
                           'Clique aqui para ver o pedido.
' % nira_website
            if subject and from_email and to:
                try:
                    msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
                    msg.attach_alternative(html_content, "text/html")
                    msg.send()
                except BadHeaderError:
                    return HttpResponse('Invalid header found.')

        super(Order, self).save(*args, **kwargs)

class Event(Order):
    """
    An instance of this class is a solicitation for inscription in an event.

    """
    name = models.CharField(_('Name'), max_length=200)
    url = models.URLField(_('URL'), max_length=50, blank=True, null=True)
    value = models.CharField(_('Value'), max_length=15, blank=True, null=True)
    start_date = models.DateField(_('Start date'))
    end_date = models.DateField(_('End date'))
    invitation = models.FileField(_('Invitation'))

    class Meta:
        verbose_name = _('Scientific event')
        verbose_name_plural = _('Scientific events')

    # Sets the type of order as event.
    def save(self, *args, **kwargs):
        self.type_of_order = EVENT
        super(Event, self).save(*args, **kwargs)

class HardwareSoftware(Order):
    """
    An instance of this class is a purchase request for a new permanent material or a consumable item.

    """
    type = models.TextField(_('Description'), max_length=500)
    quantity = models.IntegerField(_('Quantity'))
    url = models.URLField(_('URL'), max_length=255, blank=True, null=True,
                          help_text='Link to the product details. You may suggest an URL address of the manufacturer of'
                                    ' the product or any store that sells this product.')
    origin = models.CharField(_('Origin'), max_length=1, blank=True, null=True)
    category = models.CharField(_('Category'), max_length=1, blank=True, null=True)

    class Meta:
        verbose_name = _('Equipment / Supplies / Miscellaneous')
        verbose_name_plural = _('Equipment / Supplies / Miscellaneous')

    # Sets the type of order as equipment / supplies / miscellaneous
    def save(self, *args, **kwargs):
        self.type_of_order = HARDWARE_SOFTWARE
        super(HardwareSoftware, self).save(*args, **kwargs)

class Service(Order):
    """
    An instance of this class is a solicitation for a third party service.

    """
    type = models.TextField(_('Description'), max_length=500)
    origin = models.CharField(_('Origin'), max_length=1, blank=True, null=True)

    class Meta:
        verbose_name = _('Service')
        verbose_name_plural = _('Services')

    # Sets the type of order as service.
    def save(self, *args, **kwargs):
        self.type_of_order = SERVICE
        super(Service, self).save(*args, **kwargs)

class Ticket(Order):
    """
    An instance of this class is a solicitation for a new ticket.

    """
    origin = models.CharField(_('Origin'), max_length=200)
    destination = models.CharField(_('Destination'), max_length=200)
    outbound_date = models.DateField(_('Outbound Date'))
    outbound_date_preference = models.CharField(_('Outbound Preferred time'), max_length=10, blank=True, null=True)
    inbound_date = models.DateField(_('Inbound Date'), blank=True, null=True)
    inbound_date_preference = models.CharField(_('Inbound Preferred time'), max_length=10, blank=True, null=True)
    type = models.NullBooleanField(_('Type of Trip'))
    type_transportation = models.NullBooleanField(_('Type of transportation'))
    note = models.CharField(_('Note'), max_length=200, blank=True, null=True)

    class Meta:
        verbose_name = _('Ticket')
        verbose_name_plural = _('Tickets')

    # Sets the type of order as ticket.
    def save(self, *args, **kwargs):
        self.type_of_order = TICKET
        super(Ticket, self).save(*args, **kwargs)

class DailyStipend(Order):
    """
    An instance of this class is a solicitation for daily stipend.

    """
    origin = models.CharField(_('Origin'), max_length=200)
    destination = models.CharField(_('Destination'), max_length=200)
    departure = models.DateTimeField(_('Departure'))
    arrival = models.DateTimeField(_('Arrival'))

    class Meta:
        verbose_name = _('Daily stipend')
        verbose_name_plural = _('Daily stipends')

    # Sets the type of order as daily stipend.
    def save(self, *args, **kwargs):
        self.type_of_order = DAILY_STIPEND
        super(DailyStipend, self).save(*args, **kwargs)

class Reimbursement(Order):
    """
    An instance of this class is a reimbursement request.

    """
    why = models.TextField(_('Description'), max_length=500)

    class Meta:
        verbose_name = _('Reimbursement')
        verbose_name_plural = _('Reimbursements')

    # Sets the type of order as reimbursement.
    def save(self, *args, **kwargs):
        self.type_of_order = REIMBURSEMENT
        super(Reimbursement, self).save(*args, **kwargs)<commit_msg>Added institution and department fields in the HardwareSoftware class<commit_after>from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from member.models import Investigator, Institution, Department
from django.core.urlresolvers import reverse
from model_utils.managers import InheritanceManager
from django.core.mail import EmailMultiAlternatives
from django.core.mail import BadHeaderError
from django.http import HttpResponse
from django.conf import settings

# Create your models here.

# Defining types of order
EVENT = 'e'
HARDWARE_SOFTWARE = 'h'
SERVICE = 's'
TICKET = 't'
DAILY_STIPEND = 'd'
REIMBURSEMENT = 'r'
ORDER_TYPE = (
    (EVENT, _('Scientific event')),
    (HARDWARE_SOFTWARE, _('Equipment / Supplies / Miscellaneous')),
    (SERVICE, _('Service')),
    (TICKET, _('Ticket')),
    (DAILY_STIPEND, _('Daily stipend')),
    (REIMBURSEMENT, _('Reimbursement')),
)

# Defining status of order
OPEN = 'o'
PENDING = 'p'
CANCELED = 'c'
APPROVED = 'a'
DENIED = 'd'
FINISHED = 'f'
ORDER_STATUS = (
    (OPEN, _('Open')),
    (PENDING, _('Pending')),
    (CANCELED, _('Canceled')),
    (APPROVED, _('Approved')),
    (DENIED, _('Denied')),
    (FINISHED, _('Finished'))
)

class Order(models.Model):
    """

    '__unicode__'		Returns the requester.
    'class Meta'		Ordering of data by date modification.
    'id_order'          Show the IDs as a link to the order.
    'order_number'      Get ID and shows as order number.
    'save'              Send email to the requestor if the order status is changed.
                        Send email to users (NIRA Admin) informing that an order has changed.
                        Send email to users (NIRA Admin) informing that a new order was created.
    """
    requester = models.ForeignKey(Investigator, verbose_name=_('Investigator'))
    justification = models.TextField(_('Justification'), max_length=1000)
    order_date = models.DateTimeField(_('Order date'), auto_now_add=True, blank=True)
    date_modified = models.DateTimeField(_('Modified'), auto_now=True, blank=True)
    type_of_order = models.CharField(_('Type of order'), max_length=1, choices=ORDER_TYPE, blank=True)
    status = models.CharField(max_length=1, default=OPEN, choices=ORDER_STATUS, blank=True)
    protocol = models.IntegerField(_('Protocol'), blank=True, null=True)
    objects = InheritanceManager()

    def __unicode__(self):
        return u'%s' % self.requester

    class Meta:
        verbose_name = _('Order')
        verbose_name_plural = _('Orders')
        ordering = ('-date_modified', )

    def id_order(self):
        orders = Order.objects.filter(id=self.id).select_subclasses()
        order = orders[0]
        return '%s' % (reverse('admin:%s_%s_change' % (order._meta.app_label, order._meta.model_name),
                                                args=(order.id,)), order.id)
    id_order.allow_tags = True
    id_order.short_description = _('Order number')
    id_order.admin_order_field = '-id'

    def order_number(self):
        return self.id
    order_number.short_description = _('Order number')
    order_number.admin_order_field = '-id'

    def save(self, *args, **kwargs):
        # Info from settings_local file
        email_host_user = settings.EMAIL_HOST_USER
        nira_admin_email = settings.NIRA_ADMIN_EMAIL
        nira_website = settings.NIRA_WEBSITE
        contact_phone = settings.CONTACT_PHONE
        contact_email = settings.CONTACT_EMAIL

        if self.pk is not None:
            # Info about the order
            check_order = Order.objects.get(pk=self.pk)
            requester_name = check_order.requester
            requester_email = check_order.requester.user.email
            order_type = check_order.type_of_order

            # Check the type of request. It will be used to create the URL in the email that will be sent.
            try:
                if order_type == 'e':
                    order_type = 'event'
                elif order_type == 'h':
                    order_type = 'hardwaresoftware'
                elif order_type == 's':
                    order_type = 'service'
                elif order_type == 't':
                    order_type = 'ticket'
                elif order_type == 'd':
                    order_type = 'dailystipend'
                elif order_type == 'r':
                    order_type = 'reimbursement'
            except NameError:
                return HttpResponse('Invalid order type found.')

            if check_order.status != self.status:
                new_status = self.get_status_display()
                subject = 'NIRA - The status of your order has changed'
                from_email = email_host_user
                to = requester_email
                text_content = 'Hello %s. The status of your order has changed to "%s". See your order by accessing ' \
                               '%s. Please feel free to contact us at %s or %s if you have any questions. ' \
                               'With kind regards, the NIRA team.' \
                               % (requester_name, new_status, nira_website, contact_phone, contact_email)
                html_content = '
Hello %s,

The status of your order has changed to "%s". Click ' \
                               'here to see your request.
 ' \
                               '
Please feel free to contact us at %s or %s if you have any questions.
 ' \
                               '
With kind regards,

the NIRA team.
' \
                               % (requester_name, new_status, nira_website, order_type, check_order.id, contact_phone,
                                  contact_email)
                if subject and from_email and to:
                    try:
                        msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
                        msg.attach_alternative(html_content, "text/html")
                        msg.send()
                    except BadHeaderError:
                        return HttpResponse('Invalid header found.')

            else:
                subject, from_email, to = 'NIRA - Pedido alterado', email_host_user, nira_admin_email
                text_content = 'Um pedido foi alterado no sistema NIRA.'
                html_content = '
O(a) pesquisador(a) %s alterou o pedido de número %s do NIRA. Clique ' \
                               'aqui para ver este pedido.
' \
                               % (requester_name, check_order.id, nira_website, order_type, check_order.id)
                if subject and from_email and to:
                    try:
                        msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
                        msg.attach_alternative(html_content, "text/html")
                        msg.send()
                    except BadHeaderError:
                        return HttpResponse('Invalid header found.')

        else:
            subject, from_email, to = 'NIRA - Novo pedido', email_host_user, nira_admin_email
            text_content = 'Um novo pedido foi gerado no sistema NIRA.'
            html_content = '

Um novo pedido foi gerado no sistema NIRA. ' \
                           'Clique aqui para ver o pedido.
' % nira_website
            if subject and from_email and to:
                try:
                    msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
                    msg.attach_alternative(html_content, "text/html")
                    msg.send()
                except BadHeaderError:
                    return HttpResponse('Invalid header found.')

        super(Order, self).save(*args, **kwargs)

class Event(Order):
    """
    An instance of this class is a solicitation for inscription in an event.

    """
    name = models.CharField(_('Name'), max_length=200)
    url = models.URLField(_('URL'), max_length=50, blank=True, null=True)
    value = models.CharField(_('Value'), max_length=15, blank=True, null=True)
    start_date = models.DateField(_('Start date'))
    end_date = models.DateField(_('End date'))
    invitation = models.FileField(_('Invitation'))

    class Meta:
        verbose_name = _('Scientific event')
        verbose_name_plural = _('Scientific events')

    # Sets the type of order as event.
    def save(self, *args, **kwargs):
        self.type_of_order = EVENT
        super(Event, self).save(*args, **kwargs)

class HardwareSoftware(Order):
    """
    An instance of this class is a purchase request for a new permanent material or a consumable item.

    """
    type = models.TextField(_('Description'), max_length=500)
    quantity = models.IntegerField(_('Quantity'))
    url = models.URLField(_('URL'), max_length=255, blank=True, null=True,
                          help_text='Link to the product details. You may suggest an URL address of the manufacturer of'
                                    ' the product or any store that sells this product.')
    origin = models.CharField(_('Origin'), max_length=1, blank=True, null=True)
    category = models.CharField(_('Category'), max_length=1, blank=True, null=True)
    used_in_the_institution = models.ForeignKey(Institution, verbose_name=_('Institution'), blank=True, null=True)
    department_of_the_institution = models.ForeignKey(Department, verbose_name=_('Department'), blank=True, null=True)

    class Meta:
        verbose_name = _('Equipment / Supplies / Miscellaneous')
        verbose_name_plural = _('Equipment / Supplies / Miscellaneous')

    # Sets the type of order as equipment / supplies / miscellaneous
    def save(self, *args, **kwargs):
        self.type_of_order = HARDWARE_SOFTWARE
        super(HardwareSoftware, self).save(*args, **kwargs)

class Service(Order):
    """
    An instance of this class is a solicitation for a third party service.

    """
    type = models.TextField(_('Description'), max_length=500)
    origin = models.CharField(_('Origin'), max_length=1, blank=True, null=True)

    class Meta:
        verbose_name = _('Service')
        verbose_name_plural = _('Services')

    # Sets the type of order as service.
    def save(self, *args, **kwargs):
        self.type_of_order = SERVICE
        super(Service, self).save(*args, **kwargs)

class Ticket(Order):
    """
    An instance of this class is a solicitation for a new ticket.

    """
    origin = models.CharField(_('Origin'), max_length=200)
    destination = models.CharField(_('Destination'), max_length=200)
    outbound_date = models.DateField(_('Outbound Date'))
    outbound_date_preference = models.CharField(_('Outbound Preferred time'), max_length=10, blank=True, null=True)
    inbound_date = models.DateField(_('Inbound Date'), blank=True, null=True)
    inbound_date_preference = models.CharField(_('Inbound Preferred time'), max_length=10, blank=True, null=True)
    type = models.NullBooleanField(_('Type of Trip'))
    type_transportation = models.NullBooleanField(_('Type of transportation'))
    note = models.CharField(_('Note'), max_length=200, blank=True, null=True)

    class Meta:
        verbose_name = _('Ticket')
        verbose_name_plural = _('Tickets')

    # Sets the type of order as ticket.
    def save(self, *args, **kwargs):
        self.type_of_order = TICKET
        super(Ticket, self).save(*args, **kwargs)

class DailyStipend(Order):
    """
    An instance of this class is a solicitation for daily stipend.

    """
    origin = models.CharField(_('Origin'), max_length=200)
    destination = models.CharField(_('Destination'), max_length=200)
    departure = models.DateTimeField(_('Departure'))
    arrival = models.DateTimeField(_('Arrival'))

    class Meta:
        verbose_name = _('Daily stipend')
        verbose_name_plural = _('Daily stipends')

    # Sets the type of order as daily stipend.
    def save(self, *args, **kwargs):
        self.type_of_order = DAILY_STIPEND
        super(DailyStipend, self).save(*args, **kwargs)

class Reimbursement(Order):
    """
    An instance of this class is a reimbursement request.

    """
    why = models.TextField(_('Description'), max_length=500)

    class Meta:
        verbose_name = _('Reimbursement')
        verbose_name_plural = _('Reimbursements')

    # Sets the type of order as reimbursement.
    def save(self, *args, **kwargs):
        self.type_of_order = REIMBURSEMENT
        super(Reimbursement, self).save(*args, **kwargs)<|endoftext|>