import os
import shutil
import sys

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '.')))

from LayeredLithographyIRPolarizationParameters import *
import LayeredLithographyIRPolarizationDevice

import imp
# imp.load_source( "lumapi", "/central/home/gdrobert/Develompent/lumerical/2020a/api/python/lumapi.py" )
# imp.load_source( "lumapi", "/Applications/Lumerical 2020a.app/Contents/API/Python/lumapi.py" )
imp.load_source( "lumapi", "/central/home/gdrobert/Develompent/lumerical/2020a_r6/api/python/lumapi.py" )

import lumapi

import functools
import h5py
import matplotlib.pyplot as plt
import numpy as np
import time

import queue

import subprocess

import platform

import re

def get_slurm_node_list( slurm_job_env_variable=None ):
	if slurm_job_env_variable is None:
		slurm_job_env_variable = os.getenv('SLURM_JOB_NODELIST')
	if slurm_job_env_variable is None:
		raise ValueError('Environment variable does not exist.')

	solo_node_pattern = r'hpc-\d\d-[\w]+'
	cluster_node_pattern = r'hpc-\d\d-\[.*?\]'
	solo_nodes = re.findall(solo_node_pattern, slurm_job_env_variable)
	cluster_nodes = re.findall(cluster_node_pattern, slurm_job_env_variable)
	inner_bracket_pattern = r'\[(.*?)\]'

	output_arr = solo_nodes
	for cluster_node in cluster_nodes:
		prefix = cluster_node.split('[')[0]
		inside_brackets = re.findall(inner_bracket_pattern, cluster_node)[0]
		# Split at commas and iterate through results
		for group in inside_brackets.split(','):
			# Split at hypen. Get first and last number. Create string in range
			# from first to last.
			node_clump_split = group.split('-')
			starting_number = int(node_clump_split[0])
			try:
				ending_number = int(node_clump_split[1])
			except IndexError:
				ending_number = starting_number
			for i in range(starting_number, ending_number+1):
				# Can use print("{:02d}".format(1)) to turn a 1 into a '01'
				# string. 111 -> 111 still, in case nodes hit triple-digits.
				output_arr.append(prefix + "{:02d}".format(i))
	return output_arr

num_nodes_available = int( sys.argv[ 1 ] )
num_cpus_per_node = 8
cluster_hostnames = get_slurm_node_list()

#
# Qij is the the electric field j'th polarization component at a focal point due to an input beam polarized along the i'th direction
#
# This function expects the data to be organized first by the focal spot (corresponding to the given Jones analyzer vector laid out in the
# parameters file) and then by wavelength.  It will optimize for broadband performance.
#
# The figure of merit here is intended to be minimized.  The function will also provide information for performance-based gradient weightings,
# but the figure of merit here will be computed as an evenly weighted average.
#
'''
def figure_of_merit( Qxx, Qxy, Qyx, Qyy ):

	total_fom = 0
	fom_by_focal_spot_by_type_by_wavelength = np.zeros( ( num_focal_spots, 3, num_design_frequency_points ) )

	for focal_spot_idx in range( 0, num_focal_spots ):
		alpha = jones_sorting_vectors[ focal_spot_idx ][ 0 ]
		beta = jones_sorting_vectors[ focal_spot_idx ][ 1 ]
		alpha_prime = jones_orthogonal_vectors[ focal_spot_idx ][ 0 ]
		beta_prime = jones_orthogonal_vectors[ focal_spot_idx ][ 1 ]

		Qxx_focal_spot = Qxx[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qxy_focal_spot = Qxy[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qyx_focal_spot = Qyx[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qyy_focal_spot = Qyy[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )

		orthogonal_cancel_x = np.abs( Qyx_focal_spot + ( alpha_prime / beta_prime ) * Qxx_focal_spot )**2
		orthogonal_cancel_y = np.abs( Qxy_focal_spot + ( beta_prime / alpha_prime ) * Qyy_focal_spot )**2

		parallel = np.minimum( np.abs( alpha )**2, np.abs( beta )**2 ) * np.maximum(
			parallel_fom_bound - np.abs( Qxx_focal_spot / alpha )**2 - np.abs( Qyy_focal_spot / beta )**2,
			0 )

		total_fom += ( 1 / num_focal_spots ) * np.mean( orthogonal_cancel_x + orthogonal_cancel_y + parallel )

		fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, 0, : ] = orthogonal_cancel_x
		fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, 1, : ] = orthogonal_cancel_y
		fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, 2, : ] = parallel

	return total_fom, fom_by_focal_spot_by_type_by_wavelength
'''

def figure_of_merit( Qxx, Qxy, Qyx, Qyy ):

	total_fom = 0
	fom_by_focal_spot_by_type_by_wavelength = np.zeros( ( num_focal_spots, 3, num_design_frequency_points ) )

	for focal_spot_idx in range( 0, num_focal_spots ):
		alpha = jones_sorting_vectors[ focal_spot_idx ][ 0 ]
		beta = jones_sorting_vectors[ focal_spot_idx ][ 1 ]
		alpha_prime = jones_orthogonal_vectors[ focal_spot_idx ][ 0 ]
		beta_prime = jones_orthogonal_vectors[ focal_spot_idx ][ 1 ]

		Qxx_focal_spot = Qxx[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qxy_focal_spot = Qxy[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qyx_focal_spot = Qyx[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qyy_focal_spot = Qyy[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )

		orthogonal_cancel_x = np.abs( Qyx_focal_spot + ( alpha_prime / beta_prime ) * Qxx_focal_spot )**2
		orthogonal_cancel_y = np.abs( Qxy_focal_spot + ( beta_prime / alpha_prime ) * Qyy_focal_spot )**2

		parallel_x_term = np.abs( alpha * Qxx_focal_spot + beta * Qyx_focal_spot )**2
		parallel_y_term = np.abs( alpha * Qxy_focal_spot + beta * Qyy_focal_spot )**2
		# parallel = np.maximum( parallel_fom_bound - parallel_x_term - parallel_y_term, 0 )

		orthogonal_x_term = np.abs( alpha_prime * Qxx_focal_spot + beta_prime * Qyx_focal_spot )**2
		orthogonal_y_term = np.abs( alpha_prime * Qxy_focal_spot + beta_prime * Qyy_focal_spot )**2

		parallel_intensity = parallel_x_term + parallel_y_term
		orthogonal_intensity = orthogonal_x_term + orthogonal_y_term

		parallel_fom = np.minimum( parallel_fom_bound, parallel_intensity )
		orthogonal_fom = np.maximum( 1 - orthogonal_intensity, 0 )
		product_fom = parallel_fom * orthogonal_fom

		# total_fom += ( 1 / num_focal_spots ) * np.mean( orthogonal_cancel_x + orthogonal_cancel_y + parallel )
		# total_fom += ( 1 / num_focal_spots ) * np.mean( parallel_fom )
		total_fom += ( 1. / num_focal_spots ) * np.mean( product_fom )

		fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, 0, : ] = orthogonal_cancel_x
		fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, 1, : ] = orthogonal_cancel_y
		# fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, 2, : ] = parallel
		fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, 2, : ] = product_fom

	return total_fom, fom_by_focal_spot_by_type_by_wavelength

'''

def gradient(
	fom_by_focal_spot_by_type_by_wavelength,
	Ex_forward_fields, Ey_forward_fields,
	Ex_adjoint_fields_by_focal_spot, Ey_adjoint_fields_by_focal_spot,
	Qxx, Qxy, Qyx, Qyy ):

	num_total_fom = num_focal_spots * 3 * num_design_frequency_points
	rearrange_figures_of_merit = np.zeros( num_total_fom )

	for focal_spot_idx in range( 0, num_focal_spots ):
		for fom_type_idx in range( 0, 3 ):
			for wl_idx in range( 0, num_design_frequency_points ):
				rearrange_figures_of_merit[
					focal_spot_idx * 3 * num_design_frequency_points +
					fom_type_idx * num_design_frequency_points +
					wl_idx
				] = fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, fom_type_idx, wl_idx ]

	fom_weightings = ( 2. / num_total_fom ) - rearrange_figures_of_merit**2 / np.sum( rearrange_figures_of_merit )
	fom_weightings = np.maximum( fom_weightings, 0 )
	fom_weightings /= np.sum( fom_weightings )

	gradient_shape = Ex_forward_fields[ 0, 0 ].shape
	gradient = np.zeros( gradient_shape )

	for focal_spot_idx in range( 0, num_focal_spots ):

		alpha = jones_sorting_vectors[ focal_spot_idx ][ 0 ]
		beta = jones_sorting_vectors[ focal_spot_idx ][ 1 ]
		alpha_prime = jones_orthogonal_vectors[ focal_spot_idx ][ 0 ]
		beta_prime = jones_orthogonal_vectors[ focal_spot_idx ][ 1 ]

		Qxx_focal_spot = Qxx[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qxy_focal_spot = Qxy[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qyx_focal_spot = Qyx[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qyy_focal_spot = Qyy[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )

		for fom_type_idx in range( 0, 3 ):
			weighting_start_idx = focal_spot_idx * 3 * num_design_frequency_points + fom_type_idx * num_design_frequency_points
			weighting_end_idx = weighting_start_idx + num_design_frequency_points

			get_weightings = fom_weightings[ weighting_start_idx : weighting_end_idx ]

			if fom_type_idx == 0:
				d_dQxx_0 = np.abs( alpha_prime / beta_prime )**2 * np.conj( Qxx_focal_spot ) + ( alpha_prime / beta_prime ) * np.conj( Qyx_focal_spot )
				d_dQyx_0 = np.conj( Qyx_focal_spot ) + np.conj( alpha_prime / beta_prime ) * np.conj( Qxx_focal_spot )

				for wl_idx in range( 0, num_design_frequency_points ):
					gradient_component_0_xx = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQxx_0[ wl_idx ] * Ex_forward_fields[ :, wl_idx, :, :, : ] * Ex_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, wl_idx, :, :, : ],
							axis=0
						)
					)

					gradient_component_0_yx = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQyx_0[ wl_idx ] * Ey_forward_fields[ :, wl_idx, :, :, : ] * Ex_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, wl_idx, :, :, : ],
							axis=0
						)
					)

					gradient += ( gradient_component_0_xx + gradient_component_0_yx )

			elif fom_type_idx == 1:
				d_dQyy_1 = np.abs( beta_prime / alpha_prime )**2 * np.conj( Qyy_focal_spot ) + ( beta_prime / alpha_prime ) * np.conj( Qxy_focal_spot )
				d_dQxy_1 = np.conj( Qxy_focal_spot ) + np.conj( beta_prime / alpha_prime ) * np.conj( Qyy_focal_spot )

				for wl_idx in range( 0, num_design_frequency_points ):
					gradient_component_1_yy = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQyy_1[ wl_idx ] * Ey_forward_fields[ :, wl_idx, :, :, : ] * Ey_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, wl_idx, :, :, : ],
							axis=0
						)
					)

					gradient_component_1_xy = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQxy_1[ wl_idx ] * Ex_forward_fields[ :, wl_idx, :, :, : ] * Ey_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, wl_idx, :, :, : ],
							axis=0
						)
					)

					gradient += ( gradient_component_1_yy + gradient_component_1_xy )

			else:
				d_dQxx_2 = -np.minimum( np.abs( alpha )**2, np.abs( beta )**2 ) * np.conj( Qxx_focal_spot ) / np.abs( alpha )**2
				d_dQyy_2 = -np.minimum( np.abs( alpha )**2, np.abs( beta )**2 ) * np.conj( Qyy_focal_spot ) / np.abs( beta )**2

				for wl_idx in range( 0, num_design_frequency_points ):
					gradient_component_2_xx = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQxx_2[ wl_idx ] * Ex_forward_fields[ :, wl_idx, :, :, : ] * Ex_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, wl_idx, :, :, : ],
							axis=0
						)
					)

					gradient_component_2_yy = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQyy_2[ wl_idx ] * Ey_forward_fields[ :, wl_idx, :, :, : ] * Ey_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, wl_idx, :, :, : ],
							axis=0
						)
					)

					if fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, fom_type_idx, wl_idx ] > 0:
						gradient += ( gradient_component_2_xx + gradient_component_2_yy )

	return gradient

'''

def gradient(
	fom_by_focal_spot_by_type_by_wavelength,
	Ex_forward_fields, Ey_forward_fields,
	Ex_adjoint_fields_by_focal_spot, Ey_adjoint_fields_by_focal_spot,
	Qxx, Qxy, Qyx, Qyy ):

	num_total_fom = num_focal_spots * 3 * num_design_frequency_points
	rearrange_figures_of_merit = np.zeros( num_total_fom )
	weighting_mask = np.zeros( num_total_fom )

	for focal_spot_idx in range( 0, num_focal_spots ):
		for fom_type_idx in range( 0, 3 ):
			for wl_idx in range( 0, num_design_frequency_points ):
				rearrange_figures_of_merit[
					focal_spot_idx * 3 * num_design_frequency_points +
					fom_type_idx * num_design_frequency_points +
					wl_idx
				] = fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, fom_type_idx, wl_idx ]

				if fom_type_idx == 2:
					if focal_spot_idx in optimized_focal_spots:
						weighting_mask[ focal_spot_idx * 3 * num_design_frequency_points +
							fom_type_idx * num_design_frequency_points +
							wl_idx ] = 1

	select_fom = []
	for idx in range( 0, num_total_fom ):
		if weighting_mask[ idx ] > 0:
			select_fom.append( rearrange_figures_of_merit[ idx ] )
	num_important_fom = len( select_fom )
	select_fom = np.array( select_fom )

	selected_weightings = ( 2. / num_important_fom ) - select_fom**2 / np.sum( select_fom**2 )
	selected_weightings = np.maximum( selected_weightings, 0 )
	selected_weightings /= np.sum( selected_weightings )

	fom_weightings = np.zeros( num_total_fom )
	cur_weighting_idx = 0
	for idx in range( 0, num_total_fom ):
		if weighting_mask[ idx ] > 0:
			fom_weightings[ idx ] = selected_weightings[ cur_weighting_idx ]
			cur_weighting_idx += 1

	# fom_weightings = ( 2. / num_total_fom ) - rearrange_figures_of_merit**2 / np.sum( rearrange_figures_of_merit )
	# fom_weightings = np.maximum( fom_weightings, 0 )
	# fom_weightings *= weighting_mask
	# fom_weightings /= np.sum( fom_weightings )

	#
	# This is because we are actually minimizing all three figures of merit, so we would like to flip the orientation
	# of the weightings (i.e. - a small figure of merit means you are doing well in this optimization)
	#
	# fom_weightings = 1 - fom_weightings
	# fom_weightings *= weighting_mask
	# Renormalize, so they add to 1
	# fom_weightings /= np.sum( fom_weightings )

	gradient_shape = Ex_forward_fields[ 0, :, :, :, 0 ].shape
	gradient = np.zeros( gradient_shape )

	for focal_spot_idx in range( 0, num_focal_spots ):

		alpha = jones_sorting_vectors[ focal_spot_idx ][ 0 ]
		beta = jones_sorting_vectors[ focal_spot_idx ][ 1 ]
		alpha_prime = jones_orthogonal_vectors[ focal_spot_idx ][ 0 ]
		beta_prime = jones_orthogonal_vectors[ focal_spot_idx ][ 1 ]

		Qxx_focal_spot = Qxx[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qxy_focal_spot = Qxy[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qyx_focal_spot = Qyx[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )
		Qyy_focal_spot = Qyy[ focal_spot_idx, : ] / np.sqrt( max_intensity_by_wavelength )

		parallel_x_term = np.abs( alpha * Qxx_focal_spot + beta * Qyx_focal_spot )**2
		parallel_y_term = np.abs( alpha * Qxy_focal_spot + beta * Qyy_focal_spot )**2

		orthogonal_x_term = np.abs( alpha_prime * Qxx_focal_spot + beta_prime * Qyx_focal_spot )**2
		orthogonal_y_term = np.abs( alpha_prime * Qxy_focal_spot + beta_prime * Qyy_focal_spot )**2

		parallel_intensity = parallel_x_term + parallel_y_term
		orthogonal_intensity = orthogonal_x_term + orthogonal_y_term

		parallel_fom = np.minimum( parallel_fom_bound, parallel_intensity )
		orthogonal_fom = np.maximum( 1 - orthogonal_intensity, 0 )

		for fom_type_idx in range( 0, 3 ):
			weighting_start_idx = focal_spot_idx * 3 * num_design_frequency_points + fom_type_idx * num_design_frequency_points
			weighting_end_idx = weighting_start_idx + num_design_frequency_points

			get_weightings = fom_weightings[ weighting_start_idx : weighting_end_idx ]

			if fom_type_idx == 0:
				d_dQxx_0 = np.abs( alpha_prime / beta_prime )**2 * np.conj( Qxx_focal_spot ) + ( alpha_prime / beta_prime ) * np.conj( Qyx_focal_spot )
				d_dQyx_0 = np.conj( Qyx_focal_spot ) + np.conj( alpha_prime / beta_prime ) * np.conj( Qxx_focal_spot )

				for wl_idx in range( 0, num_design_frequency_points ):
					gradient_component_0_xx = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQxx_0[ wl_idx ] * Ex_forward_fields[ :, :, :, :, wl_idx ] * Ex_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient_component_0_yx = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQyx_0[ wl_idx ] * Ey_forward_fields[ :, :, :, :, wl_idx ] * Ex_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient += ( gradient_component_0_xx + gradient_component_0_yx )

			elif fom_type_idx == 1:
				d_dQyy_1 = np.abs( beta_prime / alpha_prime )**2 * np.conj( Qyy_focal_spot ) + ( beta_prime / alpha_prime ) * np.conj( Qxy_focal_spot )
				d_dQxy_1 = np.conj( Qxy_focal_spot ) + np.conj( beta_prime / alpha_prime ) * np.conj( Qyy_focal_spot )

				for wl_idx in range( 0, num_design_frequency_points ):
					gradient_component_1_yy = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQyy_1[ wl_idx ] * Ey_forward_fields[ :, :, :, :, wl_idx ] * Ey_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient_component_1_xy = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQxy_1[ wl_idx ] * Ex_forward_fields[ :, :, :, :, wl_idx ] * Ey_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient += ( gradient_component_1_yy + gradient_component_1_xy )

			else:
				d_dQxx_2 = -( np.abs( alpha )**2 * np.conj( Qxx_focal_spot ) + alpha * np.conj( beta ) * np.conj( Qyx_focal_spot ) )
				d_dQyx_2 = -( np.abs( beta )**2 * np.conj( Qyx_focal_spot ) + np.conj( alpha ) * beta * np.conj( Qxx_focal_spot ) )

				d_dQxy_2 = -( np.abs( alpha )**2 * np.conj( Qxy_focal_spot ) + alpha * np.conj( beta  ) * np.conj( Qyy_focal_spot ) )
				d_dQyy_2 = -( np.abs( beta )**2 * np.conj( Qyy_focal_spot ) + np.conj( alpha ) * beta * np.conj( Qxy_focal_spot ) )

				d_dQxx_2_prime = -( np.abs( alpha_prime )**2 * np.conj( Qxx_focal_spot ) + alpha_prime * np.conj( beta_prime ) * np.conj( Qyx_focal_spot ) )
				d_dQyx_2_prime = -( np.abs( beta_prime )**2 * np.conj( Qyx_focal_spot ) + np.conj( alpha_prime ) * beta_prime * np.conj( Qxx_focal_spot ) )

				d_dQxy_2_prime = -( np.abs( alpha_prime )**2 * np.conj( Qxy_focal_spot ) + alpha_prime * np.conj( beta_prime  ) * np.conj( Qyy_focal_spot ) )
				d_dQyy_2_prime = -( np.abs( beta_prime )**2 * np.conj( Qyy_focal_spot ) + np.conj( alpha_prime ) * beta_prime * np.conj( Qxy_focal_spot ) )

				for wl_idx in range( 0, num_design_frequency_points ):
					gradient_component_2_xx = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQxx_2[ wl_idx ] * Ex_forward_fields[ :, :, :, :, wl_idx ] * Ex_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient_component_2_yx = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQyx_2[ wl_idx ] * Ey_forward_fields[ :, :, :, :, wl_idx ] * Ex_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient_component_2_xy = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQxy_2[ wl_idx ] * Ex_forward_fields[ :, :, :, :, wl_idx ] * Ey_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient_component_2_yy = 2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQyy_2[ wl_idx ] * Ey_forward_fields[ :, :, :, :, wl_idx ] * Ey_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient_component_2_xx_prime = -2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQxx_2_prime[ wl_idx ] * Ex_forward_fields[ :, :, :, :, wl_idx ] * Ex_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient_component_2_yx_prime = -2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQyx_2_prime[ wl_idx ] * Ey_forward_fields[ :, :, :, :, wl_idx ] * Ex_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient_component_2_xy_prime = -2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQxy_2_prime[ wl_idx ] * Ex_forward_fields[ :, :, :, :, wl_idx ] * Ey_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					gradient_component_2_yy_prime = -2 * np.real(
						np.sum(
							get_weightings[ wl_idx ] *
							d_dQyy_2_prime[ wl_idx ] * Ey_forward_fields[ :, :, :, :, wl_idx ] * Ey_adjoint_fields_by_focal_spot[ focal_spot_idx ][ :, :, :, :, wl_idx ],
							axis=0
						)
					)

					if parallel_fom[ wl_idx ] < parallel_fom_bound:
						gradient += orthogonal_fom[ wl_idx ] * ( gradient_component_2_xx + gradient_component_2_yx + gradient_component_2_xy + gradient_component_2_yy )
						# gradient += ( gradient_component_2_xx + gradient_component_2_yx + gradient_component_2_xy + gradient_component_2_yy )

					gradient += parallel_fom[ wl_idx ] * ( gradient_component_2_xx_prime + gradient_component_2_yx_prime + gradient_component_2_xy_prime + gradient_component_2_yy_prime )

					# if fom_by_focal_spot_by_type_by_wavelength[ focal_spot_idx, fom_type_idx, wl_idx ] > 0:
					# 	gradient += ( gradient_component_2_xx + gradient_component_2_yx + gradient_component_2_xy + gradient_component_2_yy )

	return gradient

#
# Create FDTD hook
#
fdtd_hook = lumapi.FDTD()

#
# Create project folder and save out the parameter file for documentation for this optimization
#
python_src_directory = os.path.abspath(os.path.join(os.path.dirname(__file__), '.'))
# projects_directory_location = os.path.abspath(os.path.join(os.path.dirname(__file__), '../projects/'))
# projects_directory_location += "/" + project_name + "_parallel"

projects_directory_location = "/central/groups/Faraon_Computing/projects"
projects_directory_location += "/" + project_name + '_parallel'

if not os.path.isdir(projects_directory_location):
	os.mkdir(projects_directory_location)

fdtd_hook.newproject()
fdtd_hook.save(projects_directory_location + "/optimization")

shutil.copy2(python_src_directory + "/LayeredLithographyIRPolarizationParameters.py", projects_directory_location + "/LayeredLithographyIRPolarizationParameters.py")

#
# Set up the FDTD region and mesh
#
fdtd = fdtd_hook.addfdtd()
fdtd['x span'] = fdtd_region_size_lateral_um * 1e-6
fdtd['y span'] = fdtd_region_size_lateral_um * 1e-6
fdtd['z max'] = fdtd_region_maximum_vertical_um * 1e-6
fdtd['z min'] = fdtd_region_minimum_vertical_um * 1e-6
fdtd['mesh type'] = 'uniform'
fdtd['define x mesh by'] = 'number of mesh cells'
fdtd['define y mesh by'] = 'number of mesh cells'
fdtd['define z mesh by'] = 'number of mesh cells'
fdtd['mesh cells x'] = fdtd_region_minimum_lateral_voxels
fdtd['mesh cells y'] = fdtd_region_minimum_lateral_voxels
fdtd['mesh cells z'] = fdtd_region_minimum_vertical_voxels
fdtd['simulation time'] = fdtd_simulation_time_fs * 1e-15
fdtd['background index'] = background_index

#
# General polarized source information
#
xy_phi_rotations = [0, 90]
xy_names = ['x', 'y']

#
# Add a TFSF plane wave forward source at normal incidence
#
forward_sources = []

for xy_idx in range(0, 2):
	forward_src = fdtd_hook.addtfsf()
	forward_src['name'] = 'forward_src_' + xy_names[xy_idx]
	forward_src['angle phi'] = xy_phi_rotations[xy_idx]
	forward_src['direction'] = 'Backward'
	forward_src['x span'] = lateral_aperture_um * 1e-6
	forward_src['y span'] = lateral_aperture_um * 1e-6
	forward_src['z max'] = src_maximum_vertical_um * 1e-6
	forward_src['z min'] = src_minimum_vertical_um * 1e-6
	forward_src['wavelength start'] = lambda_min_um * 1e-6
	forward_src['wavelength stop'] = lambda_max_um * 1e-6

	forward_sources.append(forward_src)

#
# Place dipole adjoint sources at the focal plane that can ring in both
# x-axis and y-axis
#
adjoint_sources = []

for adj_src_idx in range(0, num_adjoint_sources):
	adjoint_sources.append([])
	for xy_idx in range(0, 2):
		adj_src = fdtd_hook.adddipole()
		adj_src['name'] = 'adj_src_' + str(adj_src_idx) + xy_names[xy_idx]
		adj_src['x'] = adjoint_x_positions_um[adj_src_idx] * 1e-6
		adj_src['y'] = adjoint_y_positions_um[adj_src_idx] * 1e-6
		adj_src['z'] = adjoint_vertical_um * 1e-6
		adj_src['theta'] = 90
		adj_src['phi'] = xy_phi_rotations[xy_idx]
		adj_src['wavelength start'] = lambda_min_um * 1e-6
		adj_src['wavelength stop'] = lambda_max_um * 1e-6

		adjoint_sources[adj_src_idx].append(adj_src)

#
# Set up the volumetric electric field monitor inside the design region.  We will need this compute
# the adjoint gradient
#
design_efield_monitor = fdtd_hook.addprofile()
design_efield_monitor['name'] = 'design_efield_monitor'
design_efield_monitor['monitor type'] = '3D'
design_efield_monitor['x span'] = device_size_lateral_um * 1e-6
design_efield_monitor['y span'] = device_size_lateral_um * 1e-6
design_efield_monitor['z max'] = device_vertical_maximum_um * 1e-6
design_efield_monitor['z min'] = device_vertical_minimum_um * 1e-6
design_efield_monitor['override global monitor settings'] = 1
design_efield_monitor['use wavelength spacing'] = 1
design_efield_monitor['use source limits'] = 1
design_efield_monitor['frequency points'] = num_design_frequency_points
design_efield_monitor['output Hx'] = 0
design_efield_monitor['output Hy'] = 0
design_efield_monitor['output Hz'] = 0

#
# Set up adjoint point monitors to get electric field strength at focus spots.  This will allow us to
# compute the figure of merit as well as weight the adjoint simulations properly in calculation of the
# gradient.
#
focal_monitors = []

for adj_src in range(0, num_adjoint_sources):
	focal_monitor = fdtd_hook.addpower()
	focal_monitor['name'] = 'focal_monitor_' + str(adj_src)
	focal_monitor['monitor type'] = 'point'
	focal_monitor['x'] = adjoint_x_positions_um[adj_src] * 1e-6
	focal_monitor['y'] = adjoint_y_positions_um[adj_src] * 1e-6
	focal_monitor['z'] = adjoint_vertical_um * 1e-6
	focal_monitor['override global monitor settings'] = 1
	focal_monitor['use wavelength spacing'] = 1
	focal_monitor['use source limits'] = 1
	focal_monitor['frequency points'] = num_design_frequency_points

	focal_monitors.append(focal_monitor)

transmission_focal_monitors = []

for adj_src in range(0, num_adjoint_sources):
	transmission_focal_monitor = fdtd_hook.addpower()
	transmission_focal_monitor['name'] = 'transmission_focal_monitor_' + str(adj_src)
	transmission_focal_monitor['monitor type'] = '2D Z-Normal'
	transmission_focal_monitor['x'] = adjoint_x_positions_um[adj_src] * 1e-6
	transmission_focal_monitor['x span'] = 0.5 * device_size_lateral_um * 1e-6
	transmission_focal_monitor['y'] = adjoint_y_positions_um[adj_src] * 1e-6
	transmission_focal_monitor['y span'] = 0.5 * device_size_lateral_um * 1e-6
	transmission_focal_monitor['z'] = adjoint_vertical_um * 1e-6
	transmission_focal_monitor['override global monitor settings'] = 1
	transmission_focal_monitor['use wavelength spacing'] = 1
	transmission_focal_monitor['use source limits'] = 1
	transmission_focal_monitor['frequency points'] = num_eval_frequency_points
	transmission_focal_monitor.enabled = 0

	transmission_focal_monitors.append(transmission_focal_monitor)

transmission_focal = fdtd_hook.addpower()
transmission_focal['name'] = 'transmission_focal'
transmission_focal['monitor type'] = '2D Z-Normal'
transmission_focal['x'] = 0 * 1e-6
transmission_focal['x span'] = device_size_lateral_um * 1e-6
transmission_focal['y'] = 0 * 1e-6
transmission_focal['y span'] = device_size_lateral_um * 1e-6
transmission_focal['z'] = adjoint_vertical_um * 1e-6
transmission_focal['override global monitor settings'] = 1
transmission_focal['use wavelength spacing'] = 1
transmission_focal['use source limits'] = 1
transmission_focal['frequency points'] = num_eval_frequency_points
transmission_focal.enabled = 0

#
# Add SiO2 at the top
#
sio2_top = fdtd_hook.addrect()
sio2_top['name'] = 'sio2_top'
sio2_top['x span'] = fdtd_region_size_lateral_um * 1e-6
sio2_top['y span'] = fdtd_region_size_lateral_um * 1e-6
sio2_top['z min'] = device_vertical_maximum_um * 1e-6
sio2_top['z max'] = fdtd_region_maximum_vertical_um * 1e-6
sio2_top['index'] = index_sio2

air_bottom = fdtd_hook.addrect()
air_bottom['name'] = 'air_bottom'
air_bottom['x span'] = fdtd_region_size_lateral_um * 1e-6
air_bottom['y span'] = fdtd_region_size_lateral_um * 1e-6
air_bottom['z min'] = fdtd_region_minimum_vertical_um * 1e-6
air_bottom['z max'] = device_vertical_minimum_um * 1e-6
air_bottom['index'] = index_air

#
# Add device region and create device permittivity
#
design_import = fdtd_hook.addimport()
design_import['name'] = 'design_import'
design_import['x span'] = device_size_lateral_um * 1e-6
design_import['y span'] = device_size_lateral_um * 1e-6
design_import['z max'] = device_vertical_maximum_um * 1e-6
design_import['z min'] = device_vertical_minimum_um * 1e-6

bayer_filter_size_voxels = np.array([device_voxels_lateral, device_voxels_lateral, device_voxels_vertical])
bayer_filter = LayeredLithographyIRPolarizationDevice.LayeredLithographyIRPolarizationDevice(
	bayer_filter_size_voxels,
	[min_device_permittivity, max_device_permittivity],
	init_permittivity_0_1_scale,
	num_vertical_layers,
	spacer_size_voxels,
	[index_air**2, index_silicon**2],
	max_binarize_movement,
	desired_binarize_change)

# bayer_filter.set_design_variable( np.random.random( bayer_filter.get_design_variable().shape ) )
# bayer_filter.step(
# 	np.random.random( bayer_filter.get_design_variable().shape ),
# 	0.01,
# 	True,
# 	projects_directory_location
# )
# sys.exit(0)

# bayer_filter.set_design_variable( np.load(projects_directory_location + "/cur_design_variable.npy") )

bayer_filter_region_x = 1e-6 * np.linspace(-0.5 * device_size_lateral_um, 0.5 * device_size_lateral_um, device_voxels_lateral)
bayer_filter_region_y = 1e-6 * np.linspace(-0.5 * device_size_lateral_um, 0.5 * device_size_lateral_um, device_voxels_lateral)
bayer_filter_region_z = 1e-6 * np.linspace(device_vertical_minimum_um, device_vertical_maximum_um, device_voxels_vertical)

#
# Disable all sources in the simulation, so that we can selectively turn single sources on at a time
#
def disable_all_sources():
	lumapi.evalScript(fdtd_hook.handle, 'switchtolayout;')

	for xy_idx in range(0, 2):
		fdtd_hook.select( forward_sources[xy_idx]['name'] )
		fdtd_hook.set( 'enabled', 0 )

	for adj_src_idx in range(0, num_adjoint_sources):
		for xy_idx in range(0, 2):
			fdtd_hook.select( adjoint_sources[adj_src_idx][xy_idx]['name'] )
			fdtd_hook.set( 'enabled', 0 )

#
# Consolidate the data transfer functionality for getting data from Lumerical FDTD process to
# python process.  This is much faster than going through Lumerical's interop library
#
# def get_monitor_data(monitor_name, monitor_field):
# 	lumerical_data_name = "monitor_data_" + monitor_name + "_" + monitor_field
# 	extracted_data_name = lumerical_data_name + "_data"
# 	data_transfer_filename = projects_directory_location + "/data_transfer_" + monitor_name + "_" + monitor_field

# 	command_read_monitor = lumerical_data_name + " = getresult(\'" + monitor_name + "\', \'" + monitor_field + "\');"
# 	command_extract_data = extracted_data_name + " = " + lumerical_data_name + "." + monitor_field + ";"
# 	command_save_data_to_file = "matlabsave(\'" + data_transfer_filename + "\', " + extracted_data_name + ");"

# 	lumapi.evalScript(fdtd_hook.handle, command_read_monitor)
# 	lumapi.evalScript(fdtd_hook.handle, command_extract_data)

# 	# start_time = time.time()

# 	lumapi.evalScript(fdtd_hook.handle, command_save_data_to_file)
# 	monitor_data = {}
# 	load_file = h5py.File(data_transfer_filename + ".mat")

# 	monitor_data = np.array(load_file[extracted_data_name])

# 	# end_time = time.time()

# 	# print("\nIt took " + str(end_time - start_time) + " seconds to transfer the monitor data\n")

# 	return monitor_data

# def get_complex_monitor_data(monitor_name, monitor_field):
# 	data = get_monitor_data(monitor_name, monitor_field)
# 	return (data['real'] + np.complex(0, 1) * data['imag'])

def get_efield( monitor_name ):
	field_polariations = [ 'Ex', 'Ey', 'Ez' ]
	data_xfer_size_MB = 0

	start = time.time()

	Epol_0 = fdtd_hook.getdata( monitor_name, field_polariations[ 0 ] )
	data_xfer_size_MB += Epol_0.nbytes / ( 1024. * 1024. )

	total_efield = np.zeros( [ len (field_polariations ) ] + list( Epol_0.shape ), dtype=np.complex )
	total_efield[ 0 ] = Epol_0

	for pol_idx in range( 1, len( field_polariations ) ):
		Epol = fdtd_hook.getdata( monitor_name, field_polariations[ pol_idx ] )
		data_xfer_size_MB += Epol.nbytes / ( 1024. * 1024. )

		total_efield[ pol_idx ] = Epol

	elapsed = time.time() - start

	date_xfer_rate_MB_sec = data_xfer_size_MB / elapsed
	log_file = open( projects_directory_location + "/log.txt", 'a' )
	log_file.write( "Transferred " + str( data_xfer_size_MB ) + " MB\n" )
	log_file.write( "Data rate = " + str( date_xfer_rate_MB_sec ) + " MB/sec\n\n" )
	log_file.close()

	return total_efield

#
# Set up some numpy arrays to handle all the data we will pull out of the simulation.
#
forward_e_fields = {}
focal_data = {}

figure_of_merit_evolution = np.zeros((num_epochs, num_iterations_per_epoch))
figure_of_merit_by_focal_spot_by_type_by_wavelength_evolution = np.zeros((num_epochs, num_iterations_per_epoch, num_focal_spots, 3, num_design_frequency_points))
contrast_per_focal_spot_evolution = np.zeros((num_epochs, num_iterations_per_epoch, num_focal_spots, num_design_frequency_points))
parallel_intensity_per_focal_spot_evolution = np.zeros((num_epochs, num_iterations_per_epoch, num_focal_spots, num_design_frequency_points))
orthogonal_intensity_per_focal_spot_evolution = np.zeros((num_epochs, num_iterations_per_epoch, num_focal_spots, num_design_frequency_points))

step_size_evolution = np.zeros((num_epochs, num_iterations_per_epoch))
average_design_variable_change_evolution = np.zeros((num_epochs, num_iterations_per_epoch))
max_design_variable_change_evolution = np.zeros((num_epochs, num_iterations_per_epoch))

step_size_start = 0.001

if start_epoch > 0:
	design_variable_reload = np.load( projects_directory_location + '/cur_design_variable_' + str( start_epoch - 1 ) + '.npy' )
	bayer_filter.set_design_variable( design_variable_reload )
	figure_of_merit_evolution = np.load( projects_directory_location + "/figure_of_merit.npy" )
	figure_of_merit_by_focal_spot_by_type_by_wavelength_evolution = np.load( projects_directory_location + "/figure_of_merit_by_focal_spot_by_type_by_wavelength.npy" )
	contrast_per_focal_spot_evolution = np.load( projects_directory_location + "/contrast_per_focal_spot.npy" )
	parallel_intensity_per_focal_spot_evolution = np.load( projects_directory_location + "/parallel_intensity.npy" )
	orthogonal_intensity_per_focal_spot_evolution = np.load( projects_directory_location + "/orthogonal_intensity.npy" )

jobs_queue = queue.Queue()

def add_job( job_name, queue_in ):
	full_name = projects_directory_location + "/" + job_name
	fdtd_hook.save( full_name )
	queue_in.put( full_name )

	return full_name

def run_jobs( queue_in ):
	small_queue = queue.Queue()

	while not queue_in.empty():
		for node_idx in range( 0, num_nodes_available ):
			if queue_in.qsize() > 0:
				small_queue.put( queue_in.get() )

		run_jobs_inner( small_queue )

def run_jobs_inner( queue_in ):
	processes = []
	# for job_idx in range( 0, len( queue_in ) ):
	# really should protect against number of available engines here
	job_idx = 0
	while not queue_in.empty():
		get_job_path = queue_in.get()

		process = subprocess.Popen(
			[
				'/home/gdrobert/Develompent/adjoint_lumerical/inverse_design/run_proc.sh',
				cluster_hostnames[ job_idx ],
				get_job_path
			]
		)
		processes.append( process )

		job_idx += 1

	completed_jobs = [ 0 for i in range( 0, len( processes ) ) ]
	while np.sum( completed_jobs ) < len( processes ):
		for job_idx in range( 0, len( processes ) ):
			if completed_jobs[ job_idx ] == 0:

				poll_result = processes[ job_idx ].poll()
				if not( poll_result is None ):
					completed_jobs[ job_idx ] = 1

		time.sleep( 1 )

fdtd_hook.save( projects_directory_location + "/optimization.fsp" )

#
# Run the optimization
#
for epoch in range(start_epoch, num_epochs):
	bayer_filter.update_filters(epoch)

	for iteration in range(0, num_iterations_per_epoch):
		print("Working on epoch " + str(epoch) + " and iteration " + str(iteration))

		job_names = {}

		fdtd_hook.switchtolayout()
		cur_permittivity = np.flip( bayer_filter.get_permittivity(), axis=2 )
		fdtd_hook.select("design_import")
		fdtd_hook.importnk2(np.sqrt(cur_permittivity), bayer_filter_region_x, bayer_filter_region_y, bayer_filter_region_z)

		#
		# Step 1: Run the forward optimization for both x- and y-polarized plane waves.
		#
		Qxx = np.zeros( ( num_focal_spots, num_design_frequency_points ), dtype=np.complex )
		Qxy = np.zeros( ( num_focal_spots, num_design_frequency_points ), dtype=np.complex )
		Qyx = np.zeros( ( num_focal_spots, num_design_frequency_points ), dtype=np.complex )
		Qyy = np.zeros( ( num_focal_spots, num_design_frequency_points ), dtype=np.complex )

		for xy_idx in range(0, 2):
			disable_all_sources()

			fdtd_hook.select( forward_sources[xy_idx]['name'] )
			fdtd_hook.set( 'enabled', 1 )

			job_name = 'forward_job_' + str( xy_idx ) + '.fsp'
			fdtd_hook.save( projects_directory_location + "/optimization.fsp" )
			job_names[ ( 'forward', xy_idx ) ] = add_job( job_name, jobs_queue )

		for adj_src_idx in range(0, num_adjoint_sources):
			for xy_idx in range(0, 2):
				disable_all_sources()
				fdtd_hook.select( adjoint_sources[adj_src_idx][xy_idx]['name'] )
				fdtd_hook.set( 'enabled', 1 )

				job_name = 'adjoint_job_' + str( adj_src_idx ) + '_' + str( xy_idx ) + '.fsp'

				fdtd_hook.save( projects_directory_location + "/optimization.fsp" )
				job_names[ ( 'adjoint', adj_src_idx, xy_idx ) ] = add_job( job_name, jobs_queue )

		run_jobs( jobs_queue )

####
		for xy_idx in range(0, 2):
			fdtd_hook.load( job_names[ ( 'forward', xy_idx ) ] )

			forward_e_fields[xy_names[xy_idx]] = get_efield(design_efield_monitor['name'] )

			focal_data[xy_names[xy_idx]] = []
			for focal_idx in range( 0, num_focal_spots ):
				focal_monitor_data = get_efield( focal_monitors[ focal_idx ][ 'name' ] )

				if xy_idx == 0:
					Qxx[ focal_idx, : ] = focal_monitor_data[ 0, 0, 0, 0, : ]
					Qxy[ focal_idx, : ] = focal_monitor_data[ 1, 0, 0, 0, : ]
				else:
					Qyy[ focal_idx, : ] = focal_monitor_data[ 1, 0, 0, 0, : ]
					Qyx[ focal_idx, : ] = focal_monitor_data[ 0, 0, 0, 0, : ]
####

		for focal_idx in range( 0, num_focal_spots ):
			analyzer_vector = jones_sorting_vectors[ focal_idx ]
			orthogonal_vector = jones_orthogonal_vectors[ focal_idx ]

			create_forward_parallel_response_x = analyzer_vector[ 0 ] * Qxx[ focal_idx, : ] + analyzer_vector[ 1 ] * Qyx[ focal_idx, : ]
			create_forward_parallel_response_y = analyzer_vector[ 0 ] * Qxy[ focal_idx, : ] + analyzer_vector[ 1 ] * Qyy[ focal_idx, : ]

			create_forward_orthogonal_response_x = orthogonal_vector[ 0 ] * Qxx[ focal_idx, : ] + orthogonal_vector[ 1 ] * Qyx[ focal_idx, : ]
			create_forward_orthogonal_response_y = orthogonal_vector[ 0 ] * Qxy[ focal_idx, : ] + orthogonal_vector[ 1 ] * Qyy[ focal_idx, : ]

			parallel_intensity = np.abs( create_forward_parallel_response_x )**2 + np.abs( create_forward_parallel_response_y )**2
			orthogonal_intensity = np.abs( create_forward_orthogonal_response_x )**2 + np.abs( create_forward_orthogonal_response_y )**2
			contrast = ( parallel_intensity - orthogonal_intensity ) / ( parallel_intensity + orthogonal_intensity )

			parallel_intensity_per_focal_spot_evolution[ epoch, iteration, focal_idx, : ] = parallel_intensity / max_intensity_by_wavelength
			orthogonal_intensity_per_focal_spot_evolution[ epoch, iteration, focal_idx, : ] = orthogonal_intensity / max_intensity_by_wavelength
			contrast_per_focal_spot_evolution[ epoch, iteration, focal_idx, : ] = contrast

		current_figure_of_merit, fom_by_focal_spot_by_type_by_wavelength = figure_of_merit( Qxx, Qxy, Qyx, Qyy )

		figure_of_merit_by_focal_spot_by_type_by_wavelength_evolution[ epoch, iteration ] = fom_by_focal_spot_by_type_by_wavelength
		figure_of_merit_evolution[ epoch, iteration ] = current_figure_of_merit

		print( 'The current figure of merit = ' + str( current_figure_of_merit ) )

		np.save(projects_directory_location + "/figure_of_merit.npy", figure_of_merit_evolution)
		np.save(projects_directory_location + "/figure_of_merit_by_focal_spot_by_type_by_wavelength.npy", figure_of_merit_by_focal_spot_by_type_by_wavelength_evolution)
		np.save(projects_directory_location + "/contrast_per_focal_spot.npy", contrast_per_focal_spot_evolution)
		np.save(projects_directory_location + "/parallel_intensity.npy", parallel_intensity_per_focal_spot_evolution)
		np.save(projects_directory_location + "/orthogonal_intensity.npy", orthogonal_intensity_per_focal_spot_evolution)

		#
		# Step 3: Run all the adjoint optimizations for both x- and y-polarized adjoint sources and use the results to compute the
		# gradients for x- and y-polarized forward sources.
		#
		adjoint_ex_fields = []
		adjoint_ey_fields = []
		for adj_src_idx in range(0, num_adjoint_sources):
			for xy_idx in range(0, 2):
				fdtd_hook.load( job_names[ ( 'adjoint', adj_src_idx, xy_idx ) ] )

				if xy_idx == 0:
					adjoint_ex_fields.append(
						get_efield( design_efield_monitor['name'] ) )
				else:
					adjoint_ey_fields.append(
						get_efield( design_efield_monitor['name'] ) )

		minimization_gradient = gradient(
			fom_by_focal_spot_by_type_by_wavelength,
			forward_e_fields[ 'x' ], forward_e_fields[ 'y' ],
			adjoint_ex_fields, adjoint_ey_fields,
			Qxx, Qxy, Qyx, Qyy )

		#
		# Step 4: Step the design variable.
		#
		device_gradient = minimization_gradient
		# Because of how the data transfer happens between Lumerical and here, the axes are ordered [z, y, x] when we expect them to be
		# [x, y, z].  For this reason, we swap the 0th and 2nd axes to get them into the expected ordering.
		# device_gradient = np.swapaxes(device_gradient, 0, 2)

		design_gradient = bayer_filter.backpropagate(device_gradient)

		# max_change_design = epoch_start_permittivity_change_max
		# min_change_design = epoch_start_permittivity_change_min

		# if num_iterations_per_epoch > 1:

		# 	max_change_design = (
		# 		epoch_end_permittivity_change_max +
		# 		(num_iterations_per_epoch - 1 - iteration) * (epoch_range_permittivity_change_max / (num_iterations_per_epoch - 1))
		# 	)

		# 	min_change_design = (
		# 		epoch_end_permittivity_change_min +
		# 		(num_iterations_per_epoch - 1 - iteration) * (epoch_range_permittivity_change_min / (num_iterations_per_epoch - 1))
		# 	)

		cur_design_variable = bayer_filter.get_design_variable()

		step_size_density = design_change_start_epoch + ( iteration / ( num_iterations_per_epoch - 1 ) ) * ( design_change_end_epoch - design_change_start_epoch )
		step_size_density /= np.max( np.abs( design_gradient ) )

		# step_size = step_size_start

		# check_last = False
		# last = 0

		# while True:
		# 	proposed_design_variable = cur_design_variable - step_size * design_gradient
		# 	proposed_design_variable = np.maximum(
		# 								np.minimum(
		# 									proposed_design_variable,
		# 									1.0),
		# 								0.0)

		# 	difference = np.abs(proposed_design_variable - cur_design_variable)
		# 	max_difference = np.max(difference)

		# 	if (max_difference <= max_change_design) and (max_difference >= min_change_design):
		# 		break
		# 	elif (max_difference <= max_change_design):
		# 		step_size *= 2
		# 		if (last ^ 1) and check_last:
		# 			break
		# 		check_last = True
		# 		last = 1
		# 	else:
		# 		step_size /= 2
		# 		if (last ^ 0) and check_last:
		# 			break
		# 		check_last = True
		# 		last = 0

		# step_size_start = step_size

		last_design_variable = cur_design_variable.copy()
		#
		# todo: fix this in other files! the step already does the backpropagation so you shouldn't
		# pass it an already backpropagated gradient!  Sloppy, these files need some TLC and cleanup!
		#
		enforce_binarization = False
		if epoch >= binarization_start_epoch:
			enforce_binarization = True
		device_gradient = np.flip( device_gradient, axis=2 )
		bayer_filter.step(device_gradient, step_size_density, enforce_binarization, projects_directory_location)
		cur_design_variable = bayer_filter.get_design_variable()

		average_design_variable_change = np.mean( np.abs(cur_design_variable - last_design_variable) )
		max_design_variable_change = np.max( np.abs(cur_design_variable - last_design_variable) )

		step_size_evolution[epoch][iteration] = step_size_density
		average_design_variable_change_evolution[epoch][iteration] = average_design_variable_change
		max_design_variable_change_evolution[epoch][iteration] = max_design_variable_change

		fdtd_hook.switchtolayout()
		fdtd_hook.save()
		shutil.copy( projects_directory_location + "/optimization.fsp", projects_directory_location + "/optimization_start_epoch_" + str( epoch ) + ".fsp" )
		np.save(projects_directory_location + '/device_gradient.npy', device_gradient)
		np.save(projects_directory_location + '/design_gradient.npy', design_gradient)
		np.save(projects_directory_location + "/step_size_evolution.npy", step_size_evolution)
		np.save(projects_directory_location + "/average_design_change_evolution.npy", average_design_variable_change_evolution)
		np.save(projects_directory_location + "/max_design_change_evolution.npy", max_design_variable_change_evolution)
		np.save(projects_directory_location + "/cur_design_variable.npy", cur_design_variable)
		np.save(projects_directory_location + "/cur_design_variable_" + str( epoch ) + ".npy", cur_design_variable)

	fdtd_hook.switchtolayout()
	fdtd_hook.save()
	shutil.copy( projects_directory_location + "/optimization.fsp", projects_directory_location + "/optimization_end_epoch_" + str( epoch ) + ".fsp" )


# !/usr/bin/env python3
# -*- coding: utf-8 -*-

from PyQt5 import QtCore, QtGui, QtWidgets

from ui import dialogbutton

class Ui_PowerSet(QtWidgets.QDialog):
    """
    电源设置窗口
    """
    def __init__(self, parent = None):
        super(Ui_PowerSet, self).__init__(parent)
        self.resize(1024, 550)
        self.setMinimumSize(600, 300)
        self.setWindowTitle('电源设置')
        self.setWindowIcon(QtGui.QIcon(":/logo.png"))
        # 设置窗口模态
        self.setWindowModality(QtCore.Qt.ApplicationModal)

        self.Init_PowerSet()

        # 保存、确定、取消按钮
        self.DB_DialogButton = dialogbutton.DialogButton(self)
        self.DB_DialogButton.setFixedSize(300, 50)
        self.DB_DialogButton.BT_Cancel1.clicked.connect(self.close)
        Layout_button = QtWidgets.QHBoxLayout()
        Layout_button.addStretch(1)
        Layout_button.addWidget(self.DB_DialogButton)

        Layout_Main = QtWidgets.QVBoxLayout(self)
        Layout_Main.addWidget(self.GB_PowerSet)
        Layout_Main.addLayout(Layout_button)

    # 初始化电源设置
    def Init_PowerSet(self):
        self.GB_PowerSet = QtWidgets.QGroupBox(self)
        self.GB_PowerSet.setGeometry(630, 10, 380, 500)
        self.GB_PowerSet.setTitle('电源设置')

        Label_g11 = QtWidgets.QLabel('DC调节精度Δ1：')
        Label_g12 = QtWidgets.QLabel('DC调节精度Δ2：')
        Label_g13 = QtWidgets.QLabel('AC调节精度Δ1：')
        Label_g14 = QtWidgets.QLabel('AC调节精度Δ2：')
        Label_g15 = QtWidgets.QLabel('安全极限误差Δ3：')
        Label_g16 = QtWidgets.QLabel('%')
        Label_g17 = QtWidgets.QLabel('%')
        Label_g18 = QtWidgets.QLabel('%')
        Label_g19 = QtWidgets.QLabel('%')
        Label_g21 = QtWidgets.QLabel('%')
        Label_g22 = QtWidgets.QLabel('')
        Label_g22.setPixmap(QtGui.QPixmap(':/dcac.png'))
        Label_g22.setScaledContents(True)
        # Label_g22.setFixedSize(300, 150)

        self.DCAdjustPrecision1 = QtWidgets.QSpinBox()
        self.DCAdjustPrecision1.setMinimumHeight(40)
        self.DCPermissibleErrors2 = QtWidgets.QSpinBox()
        self.DCPermissibleErrors2.setMinimumHeight(40)
        self.ACAdjustPrecision1 = QtWidgets.QSpinBox()
        self.ACAdjustPrecision1.setMinimumHeight(40)
        self.ACPermissibleErrors2 = QtWidgets.QSpinBox()
        self.ACPermissibleErrors2.setMinimumHeight(40)
        self.SafetyLimit = QtWidgets.QSpinBox()
        self.SafetyLimit.setMinimumHeight(40)
        TE_Instructions = QtWidgets.QTextEdit()
        TE_Instructions.setText('电源设置参数说明\n '
                                'Vx:电压设定值\n'
                                'Δ1:以Vx为中心的偏移相对值，调节时电压到达此区域视为达到要求\n'
                                'Δ2:以Vx为中心的偏移相对值，工作中当电压超出此区域开始调整\n'
                                'Δ3:电压误差超过Δ3断开电源，调整到Δ1范围内再接通。')
        TE_Instructions.setReadOnly(True)
        TE_Instructions.setFont(QtGui.QFont('微软雅黑 Semilight', 14))

        layout = QtWidgets.QGridLayout(self.GB_PowerSet)
        layout.addWidget(Label_g11, 1, 0)
        layout.addWidget(self.DCAdjustPrecision1,1 ,1)
        layout.addWidget(Label_g16,1 ,2)
        layout.addWidget(Label_g12)
        layout.addWidget(self.DCPermissibleErrors2)
        layout.addWidget(Label_g17)
        layout.addWidget(Label_g13)
        layout.addWidget(self.ACAdjustPrecision1)
        layout.addWidget(Label_g18)
        layout.addWidget(Label_g14)
        layout.addWidget(self.ACPermissibleErrors2)
        layout.addWidget(Label_g19)
        layout.addWidget(Label_g15)
        layout.addWidget(self.SafetyLimit)
        layout.addWidget(Label_g21)
        layout.addWidget(Label_g22, 1, 3, 5, 2)
        layout.addWidget(TE_Instructions, 6, 0, 1, 5)


import pandas as pd

DATA = pd.read_csv('opioids.csv')

rows = DATA.iterrows()

def get_maximum_effected(data):
    maximum = 0
    for row in data:
        percent = row[1][5]
        num = float(percent[:-1])
        if (num > maximum):
            maximum = num
            agegroup_max = row[1][2]
            year = row[1][0]
    return maximum, agegroup_max, year

print(get_maximum_effected(rows))


#n=input()
#f=input()
#s=input()
#if(n=="5"):
#    if(f=='1 1 3 2' and s=='abbaa'):
 #       print("1 5 4 2 3",end=" ")
  #  elif(f=='1 1 3 2' and s=='abcde'):
   #     print('1 2 3 4 5',end=" ")
    #elif(f=='1 1 3 2' and s=='abdac'):
     #   print('1 4 2 5 3',end=" ")
    #elif(f=='1 1 2 3' and s=='abdac'):
     #   print("1 4 2 5 3",end=" ")
   # else:
    #    print(f,s)
#elif(n=='6'):
 #   if(f=='1 1 2 3 3' and s=='abdaca'):
  #      print("1 4 6 2 5 3",end=" ")
   # elif(f=='1 1 2 3 4' and s=='abdaca'):
    #    print('1 6 4 2 5 3',end=" ")
#    else:
 #       print(f,s)
#else:
 #   print(n,f,s)
n=int(input())
fathers=list(map(int,input().split(" ")))
s=input()
ans=[[i+1] for i in range(n)]
ans[0].append(s[0])
temp=""
for j in range(1,n):#表示节点i+1
    a=j
    temp+=s[j]
    while(fathers[a-1]!=1):
        a=fathers[a-1]-1
        temp+=s[a]
    temp+=s[0]
    ans[j].append(temp)
    temp=""
ans=sorted(ans,key=lambda x:x[1])
for an in ans:
    print(an,end=" ")


import numpy as np
import matplotlib.pyplot as plt

def main():
    # Compute the x and y coordinates for points on sine and cosine curves
    x = np.arange(-3 * np.pi, 3 * np.pi, 0.1)
    y_real = np.cos(6*np.pi*x) * np.cos(-np.pi * x**2)
    y_imaginary = np.cos(6*np.pi*x) * np.sin(-np.pi * x**2)

    # Set up a subplot grid that has height 2 and width 1,
    # and set the first such subplot as active.
    plt.subplot(2, 1, 1)

    plt.plot(x, y_real)
    plt.title('cos(6*pi*x) * cos(-pi*x*x)')

    plt.subplot(2, 1, 2)
    plt.plot(x, y_imaginary)

    # Show the figure.
    plt.show()

if __name__ == "__main__":
    main()


# SEA formats import / export plugin for Maya
# Developed by DTZxPorter

import os
import os.path
import maya.cmds as cmds
import maya.mel as mel
import math
import maya.OpenMaya as OpenMaya
import maya.OpenMayaAnim as OpenMayaAnim
import maya.OpenMayaMPx as OpenMayaMPx
import struct
import seanim as SEAnim

MENU_DATA = {'menu' : ["SEAToolsPluginMenu", "SEA Tools", None, None, None]}

GUN_BASE_TAGS = ["j_gun", "j_gun1", "tag_weapon", "tag_weapon1"]
VIEW_HAND_TAGS = ["tag_weapon", "tag_weapon1", "tag_weapon_right", "tag_weapon_left"]

# About info
def AboutWindow():
	result = cmds.confirmDialog(message="---  SEA Tools plugin (v1.0)  ---\n\nDeveloped by DTZxPorter\n\nFormat design by SE2Dev", button=['OK'], defaultButton='OK', title="About SEA Tools")

# A list (in order of priority) of bone names to automatically search for when determining which bone to use as the root for delta anims
DeltaRootBones = ["tag_origin"]

# Compare two iterable objects
def first(a, b):
	for elem in a:
		if elem in b:
			return a
	return None

def ImportFileSelectDialog():
	importFrom = None
	if cmds.about(version=True)[:4] == "2012": # Support for newer versions
		importFrom = cmds.fileDialog2(fileMode=1, fileFilter="SEAnim Files (*.seanim)", caption="Import SEAnim")
	else:
		importFrom = cmds.fileDialog2(fileMode=1, dialogStyle=2, fileFilter="SEAnim Files (*.seanim)", caption="Import SEAnim")

	if importFrom == None or len(importFrom) == 0 or importFrom[0].strip() == "":
		return None
	path = importFrom[0].strip()

	pathSplit = os.path.splitext(path) # Fix bug with Maya 2013
	if pathSplit[1] == ".*":
		path = pathSplit

	return path

# Attempt to resolve the animType for a bone based on a given list of modifier bones, returns None if no override is needed
def ResolvePotentialAnimTypeOverride(bone, boneAnimModifiers):
	#Grab the parent tree
	parents = cmds.ls(bone.name, long=True)[0].split('|')[1:-1]
	# Check if we even had parents
	if len(parents) == 0 or len(boneAnimModifiers) == 0:
		return None

	for parent in parents:
		for modBone in boneAnimModifiers:
			if parent == modBone.name:
				return modBone.modifier
	return None

# Importer
def ImportSEAnim():
	# Get a file to import
	file_import = ImportFileSelectDialog()
	# Check
	if file_import == None:
		pass
	else:
		LoadSEAnim(file_import)

# Create the menu
def CreateMenu():
	# Set the diplay's parent
	cmds.setParent(mel.eval("$temp1=$gMainWindow"))
	# Check for existing control, remove it if we can
	if cmds.control(MENU_DATA['menu'][0], exists=True):
		cmds.deleteUI(MENU_DATA['menu'][0], menu=True)

	# Recreate the base
	menu = cmds.menu(MENU_DATA['menu'][0], label=MENU_DATA["menu"][1], tearOff=True)

	# Import tools
	cmds.menuItem(label="Import SEAnim", command="SEAToolsPlugin.ImportSEAnim()")

	# Divide
	cmds.menuItem(divider=True)

	# Export tools
	cmds.menuItem(label="Export SEAnim",enable=False, command="ShowWindow('xmodel')")

	# Divide
	cmds.menuItem(divider=True)

	# Bind weapon to hand
	cmds.menuItem(label="Attach Weapon to Rig", command="SEAToolsPlugin.WeaponBinder()")

	# Divide
	cmds.menuItem(divider=True)

	# Debug stuff
	cmds.menuItem(label="Reload Plugin", command="reload(SEAToolsPlugin)")

	# About
	cmds.menuItem(label="About", command="SEAToolsPlugin.AboutWindow()")

# Bind the weapon to hands
def WeaponBinder():
	# This is currently COD specific, can implement into model / anim format later
	for x in xrange(0,len(GUN_BASE_TAGS)):
		try:
			# Select both tags and parent them
			cmds.select(GUN_BASE_TAGS[x], replace=True)
			cmds.select(VIEW_HAND_TAGS[x], toggle=True)
			# Connect
			cmds.connectJoint(connectMode=True)
			# Parent
			mel.eval("parent " + GUN_BASE_TAGS[x] + " " + VIEW_HAND_TAGS[x])
			# Remove
			cmds.select(clear=True)
		except:
			pass

#Load a .seanim file
def LoadSEAnim(filepath=""):
	# Log
	print("Loading SEAnim file...")
	# Load the file using helper lib
	anim = SEAnim.Read(filepath)
	# Starting frame
	start_frame = 0
	# End frame
	end_frame = start_frame + anim.header.frameCount - 1
	# Set scene start and end
	cmds.playbackOptions(ast=start_frame, minTime=start_frame)
	# Set end
	cmds.playbackOptions(maxTime=end_frame, aet=end_frame)
	# Import the actual keyframes
	i = 0
	# Loop through tag names
	for tag in anim.bones:
		try:
			# Check if the tag exist, otherwise don't waste time
			cmds.getAttr(tag.name + ".t")
		except:
			i += 1
		else:
			# Check for parent modifiers
			animType = ResolvePotentialAnimTypeOverride(tag, anim.boneAnimModifiers)
			# Check if we need to use the anim's default type
			if animType is None:
				# Use animation default
				animType = anim.header.animType

			# Generate the rest keyframes which are used as a base for the following frames (for only the bones that are used)
			try:
				if len(tag.rotKeys) > 1: # Has a lot of rotation
					# Reset bone orientation
					cmds.setAttr(tag.name + ".jo", 0, 0, 0)
					# Reset bone rotation
					cmds.setAttr(tag.name + ".rotate", 0, 0, 0)
				else:
					if len(tag.rotKeys) == 1: # Has single rotation
						# Set bone orientation to first frame
						cmds.setAttr(tag.name + ".jo", tag.rotKeys[0].data[0], tag.rotKeys[0].data[1], tag.rotKeys[0].data[1])
						# Reset bone rotation
						cmds.setAttr(tag.name + ".rotate", 0, 0, 0)
					else: # Has no rotation but needs to be reset
						# Reset bone orientation
						cmds.setAttr(tag.name + ".jo", 0, 0, 0)
						# Reset bone rotation
						cmds.setAttr(tag.name + ".rotate", 0, 0, 0)

				# Set key
				cmds.setKeyframe(tag.name, time=start_frame)
			except:
				pass
			# Grab current position data
			bone_rest = cmds.getAttr(tag.name + ".t")[0]
			# Loop through positions
			for key in tag.posKeys:
				# Viewanims are SEANIM_TYPE_ABSOLUTE
				if animType == SEAnim.SEANIM_TYPE.SEANIM_TYPE_ABSOLUTE:
					# Set the absolute key
					cmds.setKeyframe(tag.name, v=key.data[0], at="translateX", time=key.frame)
					cmds.setKeyframe(tag.name, v=key.data[1], at="translateY", time=key.frame)
					cmds.setKeyframe(tag.name, v=key.data[2], at="translateZ", time=key.frame)
				else: # Use DELTA / RELATIVE results (ADDITIVE is unknown)
					# Set the relative key
					cmds.setKeyframe(tag.name, v=(bone_rest[0] + key.data[0]), at="translateX", time=key.frame)
					cmds.setKeyframe(tag.name, v=(bone_rest[1] + key.data[1]), at="translateY", time=key.frame)
					cmds.setKeyframe(tag.name, v=(bone_rest[2] + key.data[2]), at="translateZ", time=key.frame)
			# Loop through rotations
			for key in tag.rotKeys:
				# Set the rotation
				quat = OpenMaya.MQuaternion(key.data[0], key.data[1], key.data[2], key.data[3])
				# Convert to euler
				euler_rot = quat.asEulerRotation();
				# Set the matrix
				cmds.setAttr(tag.name + ".jointOrient", math.degrees(euler_rot.x), math.degrees(euler_rot.y), math.degrees(euler_rot.z))
				# Key the frame
				cmds.setKeyframe(tag.name, at="jointOrient", time=key.frame)
				# Copy joint orient to rotation channels
				joX = cmds.getAttr(tag.name + '.jointOrientX');
				joY = cmds.getAttr(tag.name + '.jointOrientY');
				joZ = cmds.getAttr(tag.name + '.jointOrientZ');
				cmds.setAttr(tag.name + ".rotate", float(joX), float(joY), float(joZ));
				# Key dat boi
				cmds.setKeyframe(tag.name, at="rotate", time=key.frame)
				# Reset joint orientation because 128 + 128 != 128
				cmds.setAttr(tag.name + ".jo", 0, 0, 0)
				cmds.setKeyframe(tag.name, at="jointOrient", time=0)
			cmds.cutKey( tag.name, attribute="jointOrientX" );
			cmds.cutKey( tag.name, attribute="jointOrientY" );
			cmds.cutKey( tag.name, attribute="jointOrientZ" );
			# Rotation interpolation (Only for eular angles)
			mel.eval("rotationInterpolation -c quaternion " + tag.name + ".rotateX " + tag.name + ".rotateY " + tag.name + ".rotateZ")
			# Linear interpolation (Eular angles)
			cmds.select(tag.name)
			# Transform selection
			mel.eval("keyTangent -e -itt linear -ott linear")
			# Clear selection
			cmds.select(clear=True)
			# Basic counter
			i += 1
	# Notetracks
	base_track = cmds.spaceLocator()
	# Rename
	cmds.rename(base_track, "SEANotes")
	# Loop
	for note in anim.notes:
		if cmds.objExists(note.name):
			# We have it, key it
			cmds.setKeyframe(note.name, time=note.frame)
		else:
			# We need to make it
			notetrack = cmds.spaceLocator()
			# Rename
			cmds.rename(notetrack, note.name)
			# Parent it
			mel.eval("parent " + note.name + " SEANotes")
			# Key it
			cmds.setKeyframe(note.name, time=note.frame)

	# Reset time
	cmds.currentTime(start_frame)
	# End
	print("The animation has been loaded.")

# Make the menu
CreateMenu()


from flask import Flask, jsonify, make_response, request, abort
import os
import hashlib
import mixin_config
import uuid
from mixin_api import MIXIN_API
import prs_utility
import pressone_config
import requests
import time
import fundmethood as fm
from assets import CNB

'''
用余生成一个可操作的 mixin network 用户实例
'''
def generateMixinAPI(private_key,pin_token,session_id,user_id,pin,client_secret):
    mixin_config.private_key       = private_key
    mixin_config.pin_token         = pin_token
    mixin_config.pay_session_id    = session_id
    mixin_config.client_id         = user_id
    mixin_config.client_secret     = client_secret
    mixin_config.pay_pin           = pin
    return MIXIN_API(mixin_config)

app = Flask(__name__)
mixin_api = MIXIN_API(mixin_config)

@app.route('/')
def index():
    return "Hello, World!"

@app.errorhandler(404)
def not_found(error):
    return make_response(jsonify({'error': 'Not found'}), 404)

'''
生成一套 mixin network 用户信息
'''
@app.route('/api/v1/creat_id/', methods=['GET'])
def create_userid():
    r = fm.genMixinUser()
    userInfo = r[0]
    private_key = r[1]
    userid = userInfo.get('data').get('user_id')
    sessionid = userInfo.get('data').get('session_id')
    pintoken = userInfo.get('data').get('pin_token')
    return jsonify({'userid': userid, 'private_key': private_key, 'sessionid': sessionid, 'pintoken': pintoken}), 201

'''
充值
'''
@app.route('/api/v1/charge/', methods=['POST'])
def charge():
    now = time.time()
    trace = fm.genTrace()
    print(trace)
    if not request.json:
        abort(400)
    j = request.json
    userid = j.get('userid')
    print(userid)
    amount = j.get('amount')
    print(amount)
    url = fm.genAPaylink(userid, trace=trace, asset=CNB, amount=amount, memo='CHARGE')
    return jsonify({'time': now, 'userid': userid, 'charge_url': url}), 201

'''
签名并发布
'''
@app.route('/api/v1/pub/', methods=['POST'])
def create_pub():
    if not request.json:
        abort(400)
    j = request.json
    now = time.time()
    trace = fm.genTrace()

    userid = j.get('userid')
    private_key = j.get('private_key')
    sessionid = j.get('sessionid')
    pintoken = j.get('pintoken')
    pin = j.get('pin')
    data = j.get('data')

    NewUserInstance = generateMixinAPI(private_key, pintoken, sessionid, userid, pin, "")

    pub = fm.pub_text(userid, data)
    pub_result = {
        'createdAt': pub.get('createdAt'),
        'data_id': pub.get('id'),
        'userid': userid,
        'trace': trace,
        'data': data
    }
    return jsonify(pub_result), 201

'''
根据 userid， blockid， data， trace 校验四者是否匹配
'''
@app.route('/api/v1/blocks/', methods=['POST'])
def blocks():
    if not request.json:
        abort(400)
    j = request.json
    data = j.get('data')
    userid = j.get('userid')
    blockid = j.get('blockid')
    trace = j.get('trace')

    texthash = prs_utility.keccak256(text=userid + r'\n' + data + r'\n' + trace)

    asked_data = {'file_hash': texthash, }

    datahash = prs_utility.hash_block_data(asked_data)

    r = requests.get('https://press.one/api/v2/blocks/'+blockid)
    result = r.json()
    print(result)
    print(datahash)
    print(result[0].get('hash'))
    if datahash == result[0].get('hash'):
        response = {
            'userid': userid,
            'blockid': blockid,
            'data': data,
            'datahash': datahash,
            'status': 'matched'
        }
    else:
        response = {
            'userid': userid,
            'blockid': blockid,
            'data': data,
            'datahash': datahash,
            'status': 'unmatched'
        }

    return jsonify(response), 201

if __name__ == '__main__':
    app.run(debug=True)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import setuptools_scm

extensions = [
    'sphinx.ext.autodoc',
    'rst.linker',
]

# General information about the project.
project = 'path.py'
copyright = '2013-2016 Mikhail Gusarov, Jason R. Coombs'

# The short X.Y version.
version = setuptools_scm.get_version(root='..', relative_to=__file__)
# The full version, including alpha/beta/rc tags.
release = version

pygments_style = 'sphinx'
html_theme = 'alabaster'
html_static_path = ['_static']
htmlhelp_basename = 'pathpydoc'
templates_path = ['_templates']
exclude_patterns = ['_build']
source_suffix = '.rst'
master_doc = 'index'

extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'rst.linker']

intersphinx_mapping = {'python': ('http://docs.python.org/', None)}

link_files = {
	'CHANGES.rst': dict(
		using=dict(
			GH='https://github.com',
			project=project,
		),
		replace=[
			dict(
				pattern=r"(Issue )?#(?P<issue>\d+)",
				url='{GH}/jaraco/{project}/issues/{issue}',
			),
			dict(
				pattern=r"Pull Request ?#(?P<pull_request>\d+)",
				url='{GH}/jaraco/{project}/pull/{pull_request}',
			),
			dict(
				pattern=r"^(?m)((?P<scm_version>v?\d+(\.\d+){1,2}))\n[-=]+\n",
				with_scm="{text}\n{rev[timestamp]:%d %b %Y}\n",
			),
		],
	),
}


import requests
import pandas as pd
from bs4 import BeautifulSoup

def parse_html_table(table):
    n_columns = 0
    n_rows=0
    column_names = []

    # Find number of rows and columns
    # we also find the column titles if we can
    for row in table.find_all('tr'):

        # Determine the number of rows in the table
        td_tags = row.find_all('td')
        if len(td_tags) > 0:
            n_rows+=1
            if n_columns == 0:
                # Set the number of columns for our table
                n_columns = len(td_tags)

        # Handle column names if we find them
        th_tags = row.find_all('th')
        if len(th_tags) > 0 and len(column_names) == 0:
            for th in th_tags:
                column_names.append(th.get_text().strip())

    # Safeguard on Column Titles
    if len(column_names) > 0 and len(column_names) != n_columns:
        raise Exception("Column titles do not match the number of columns")

    columns = column_names if len(column_names) > 0 else range(0,n_columns)
    df = pd.DataFrame(columns = columns,
                      index= range(0,n_rows))
    row_marker = 0
    for row in table.find_all('tr'):
        column_marker = 0
        columns = row.find_all('td')
        for column in columns:
            df.iat[row_marker,column_marker] = column.get_text().strip()
            column_marker += 1
        if len(columns) > 0:
            row_marker += 1

    # Convert to float if possible
    for col in df:
        try:
            df[col] = df[col].astype(float)
        except ValueError:
            pass

    return df

def getTickers(url, fname, column_name):
    r = requests.get(url)
    # Extract the content
    c = r.content
    #print(c)

    # Create a soup object
    soup = BeautifulSoup(c, 'lxml')

    # Find the element on the webpage
    htable = soup.find('table', {'class': 'wikitable sortable'})
    #print(htable)

    df = parse_html_table(htable)
    print(df.head())

    df = df.sort_values(column_name)
    # add ticker column on the table
    #df['ticker'] = df[column_name]
    df.insert(0, 'ticker', df[column_name])
    dfcsv = df.iloc[:,[0,1,2]]

    dfcsv.to_csv(fname, index=False)

# Make the GET request to a url
DOW30 = "https://en.wikipedia.org/wiki/Dow_Jones_Industrial_Average"
SP500 = "http://en.wikipedia.org/wiki/List_of_S%26P_500_companies"

getTickers(DOW30, 'csv/dow30.csv', 'Symbol')
getTickers(SP500, 'csv/sp500.csv', 'Ticker symbol')


from django.urls import path, include

from . import views
from users import views as users_views
from events import views as events_views

urlpatterns = [
    path('', views.index, name="my_cheerio-index"),
    path('accounts/', include('django.contrib.auth.urls')),
    path('signup/', users_views.signup, name="signup"),
    path('events/', events_views.list_events, name="list_events"),
    path('events/<int:event_id>/', events_views.event_id, name="event_id"),
    path('events/join/', events_views.join_event, name="join_event"),
    path('events/create/', events_views.create_event, name="create_event"),
    path('events/create/submit', events_views.submit_created_event, name="submit-event"),
    path('events/<int:event_id>/notes/create', events_views.create_note, name="create-note"),
    path('events/<int:event_id>/notes/delete/<int:note_id>/', events_views.delete_note, name="delete_note"),

]


from django.db.models.signals import pre_save, post_delete
from app_gp.models import ClientVideo

# http://www.lexev.org/en/2016/django-signal-or-model-method/
# 1 - Create submodule signals and place h_client.py in it
# 2 - Define signals in that file h_client.py
# 3 - Create application config class
# 4 - In apps.py overrided ready function to import the handler ex:
#       def ready(self): import app_gp.signals.handlers
# 5 - Add to __init__.py of your app the config class ex:
#       default_app_config = 'app_gp.apps.AppGpConfig'

def client_video_pre_save_receiver(sender, instance, *args, **kwargs):

    # IF PK EXIST SO WE ARE SAVING FOR CHANGE SOME FIELD
    # ELSE WE ARE CREATING THE DATA FOR THE FIRST TIME
    if instance.pk:
        # GET Instance before change anything
        old_instance = sender.objects.get(pk=instance.pk)

        # Video changed? Delete old one
        if not old_instance.video == instance.video:
            if old_instance.video:
                old_instance.video.delete(save=False)

pre_save.connect(client_video_pre_save_receiver, sender=ClientVideo, dispatch_uid='client_video_pre_save')

def client_video_post_delete_receiver(sender, instance, **kwargs):
    # Delete video
    if instance.video:
        instance.video.delete(save=False)

post_delete.connect(client_video_post_delete_receiver, sender=ClientVideo, dispatch_uid='client_video_post_delete')


"""获取github中星数最多的python项目"""

import requests
import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS

# 执行API调用，存储响应
url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:", r.status_code)

# 将API响应存储在一个变量中，这个API返回JSON格式的信息
response_dict = r.json()

print(response_dict.keys())
print("Total repositories:", response_dict['total_count'])
print("Incomplete results:", response_dict['incomplete_results'])

# 研究有关仓库的信息
repo_dicts = response_dict['items']

names,plot_dicts = [],[]
for repo_dict in repo_dicts:
    names.append(repo_dict['name'])

    if repo_dict['description']:
        plot_dict = {
            'value':repo_dict['stargazers_count'],
            'label':repo_dict['description'],
            'xlink':repo_dict['html_url'],
            }
    else:
        plot_dict = {
            'value':repo_dict['stargazers_count'],
            'label':'none',
            'xlink':repo_dict['html_url'],
            }
    plot_dicts.append(plot_dict)

# 可视化pygal
my_style = LS('#333366',base_style=LCS)

my_config = pygal.Config()
my_config.x_label_rotation = 45
my_config.show_legend = False
my_config.title_font_size = 24
my_config.label_font_size = 14
my_config.major_label_font_size = 18
my_config.truncate_label = 15
my_config.show_y_guides = False
my_config.width = 1000

chart = pygal.Bar(my_config, style=my_style)
chart.title = 'Most-starred python projects on github'
chart.x_labels = names

chart.add('',plot_dicts)
chart.render_to_file('python_repos.svg')

# 浏览器file:///C:/users/Administrator/Desktop/python_work/keshihua/python_repos.svg


"""
Base Component class. Other components should inherit from this class.
"""
import json
import logging
import typing

from mltrace import client
from mltrace import utils as clientUtils
from mltrace.db import Store, PointerTypeEnum
from mltrace.entities import utils
from mltrace.entities.base import Base

import functools
import inspect
import git

class Component(Base):
    def __init__(
        self,
        name: str = "",
        owner: str = "",
        description: str = "",
        beforeTests: list = [],
        afterTests: list = [],
        tags: typing.List[str] = [],
    ):
        """Components abstraction.
        Components should have a name, owner, and lists
        of before and after tests to run. Optionally they will have tags."""
        self._name = name
        self._owner = owner
        self._description = description
        self._tags = tags
        self._beforeTests = beforeTests
        self._afterTests = afterTests

    def beforeRun(self, **kwargs):
        """Computation to execute before running a component.
        Will run each test object listed in beforeTests."""
        for test in self._beforeTests:
            test().runTests(**kwargs)

    def afterRun(self, **local_vars):
        """Computation to execute after running a component.
        Will run all test objects listed in afterTests."""
        for test in self._afterTests:
            test().runTests(**local_vars)

    def run(
        self,
        inputs: typing.List[str] = [],
        outputs: typing.List[str] = [],
        input_vars: typing.List[str] = [],
        output_vars: typing.List[str] = [],
        input_kwargs: typing.Dict[str, str] = {},
        output_kwargs: typing.Dict[str, str] = {},
        endpoint: bool = False,
        staleness_threshold: int = (60 * 60 * 24 * 30),
        auto_log: bool = False,
        *user_args,
        **user_kwargs,
    ):
        """
        Decorator around the function executed:
        c = Component()
        @c.run
        def my_function(arg1, arg2):
                do_something()

            arg1 and arg2 are the arguments passed to the
            beforeRun and afterRun methods.
            We first execute the beforeRun method, then the function itself,
            then the afterRun method with the values of the args at the
            end of the function.

        ADD DESCRIPTION HERE ABOUT INPUT VARIABLEs and what they are
        """
        inv_user_kwargs = {v: k for k, v in user_kwargs.items()}
        key_names = ["skip_before", "skip_after"]

        def actual_decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kwargs):
                # Get function information
                filename = inspect.getfile(func)
                function_name = func.__name__

                # Construct component run object
                store = Store(clientUtils.get_db_uri())
                component_run = store.initialize_empty_component_run(self.name)
                component_run.set_start_timestamp()

                # Assert key names are not in args or kwargs
                if (
                    set(key_names) & set(inspect.getfullargspec(func).args)
                ) or (set(key_names) & set(kwargs.keys())):
                    raise ValueError(
                        "skip_before or skip_after cannot be in "
                        + f"the arguments of the function {func.__name__}"
                    )

                # Run before test
                if not user_kwargs.get("skip_before"):
                    all_args = dict(
                        zip(inspect.getfullargspec(func).args, args)
                    )
                    all_args = {
                        k
                        if k not in inv_user_kwargs
                        else inv_user_kwargs[k]: v
                        for k, v in all_args.items()
                    }
                    all_args = {**all_args, **kwargs}
                    self.beforeRun(**all_args)

                # Create input and output pointers
                input_pointers = []
                output_pointers = []

                # Auto log inputs
                if auto_log:
                    # Get IOPointers corresponding to args and f_locals
                    all_input_args = {
                        k: v.default
                        for k, v in inspect.signature(func).parameters.items()
                        if v.default is not inspect.Parameter.empty
                    }
                    all_input_args = {
                        **all_input_args,
                        **dict(zip(inspect.getfullargspec(func).args, args)),
                    }
                    all_input_args = {**all_input_args, **kwargs}
                    # print(all_input_args.keys())
                    input_pointers += store.get_io_pointers_from_args(
                        **all_input_args
                    )

                # Run function
                local_vars, value = utils.run_func_capture_locals(
                    func, *args, **kwargs
                )
                component_run.set_end_timestamp()

                # Add input_vars and output_vars as pointers
                for var in input_vars:
                    if var not in local_vars:
                        raise ValueError(
                            f"Variable {var} not in current stack frame."
                        )
                    val = local_vars[var]
                    if val is None:
                        logging.debug(f"Variable {var} has value {val}.")
                        continue
                    if isinstance(val, list):
                        input_pointers += store.get_io_pointers(val)
                    else:
                        input_pointers.append(store.get_io_pointer(str(val)))
                for var in output_vars:
                    if var not in local_vars:
                        raise ValueError(
                            f"Variable {var} not in current stack frame."
                        )
                    val = local_vars[var]
                    if val is None:
                        logging.debug(f"Variable {var} has value {val}.")
                        continue
                    if isinstance(val, list):
                        output_pointers += (
                            store.get_io_pointers(
                                val, pointer_type=PointerTypeEnum.ENDPOINT
                            )
                            if endpoint
                            else store.get_io_pointers(val)
                        )
                    else:
                        output_pointers += (
                            [
                                store.get_io_pointer(
                                    str(val),
                                    pointer_type=PointerTypeEnum.ENDPOINT,
                                )
                            ]
                            if endpoint
                            else [store.get_io_pointer(str(val))]
                        )
                # Add input_kwargs and output_kwargs as pointers
                for key, val in input_kwargs.items():
                    if key not in local_vars or val not in local_vars:
                        raise ValueError(
                            f"({key}, {val}) not in current stack frame."
                        )
                    if local_vars[key] is None:
                        logging.debug(
                            f"Variable {key} has value {local_vars[key]}."
                        )
                        continue
                    if isinstance(local_vars[key], list):
                        if not isinstance(local_vars[val], list) or len(
                            local_vars[key]
                        ) != len(local_vars[val]):
                            raise ValueError(
                                f'Value "{val}" does not have the same '
                                + f'length as the key "{key}."'
                            )
                        input_pointers += store.get_io_pointers(
                            local_vars[key], values=local_vars[val]
                        )
                    else:
                        input_pointers.append(
                            store.get_io_pointer(
                                str(local_vars[key]), local_vars[val]
                            )
                        )
                for key, val in output_kwargs.items():
                    if key not in local_vars or val not in local_vars:
                        raise ValueError(
                            f"({key}, {val}) not in current stack frame."
                        )
                    if local_vars[key] is None:
                        logging.debug(
                            f"Variable {key} has value {local_vars[key]}."
                        )
                        continue
                    if isinstance(local_vars[key], list):
                        if not isinstance(local_vars[val], list) or len(
                            local_vars[key]
                        ) != len(local_vars[val]):
                            raise ValueError(
                                f'Value "{val}" does not have the same '
                                + f'length as the key "{key}."'
                            )
                        output_pointers += (
                            store.get_io_pointers(
                                local_vars[key],
                                local_vars[val],
                                pointer_type=PointerTypeEnum.ENDPOINT,
                            )
                            if endpoint
                            else store.get_io_pointers(
                                local_vars[key], local_vars[val]
                            )
                        )
                    else:
                        output_pointers += (
                            [
                                store.get_io_pointer(
                                    str(local_vars[key]),
                                    local_vars[val],
                                    pointer_type=PointerTypeEnum.ENDPOINT,
                                )
                            ]
                            if endpoint
                            else [
                                store.get_io_pointer(
                                    str(local_vars[key]), local_vars[val]
                                )
                            ]
                        )

                # Directly specified I/O
                if not callable(inputs):
                    input_pointers += [
                        store.get_io_pointer(inp) for inp in inputs
                    ]
                output_pointers += (
                    [
                        store.get_io_pointer(
                            out, pointer_type=PointerTypeEnum.ENDPOINT
                        )
                        for out in outputs
                    ]
                    if endpoint
                    else [store.get_io_pointer(out) for out in outputs]
                )

                # If there were calls to mltrace.load and mltrace.save, log

                if "_mltrace_loaded_artifacts" in local_vars:
                    input_pointers += [
                        store.get_io_pointer(name, val)
                        for name, val in local_vars[
                            "_mltrace_loaded_artifacts"
                        ].items()
                    ]
                if "_mltrace_saved_artifacts" in local_vars:
                    output_pointers += [
                        store.get_io_pointer(name, val)
                        for name, val in local_vars[
                            "_mltrace_saved_artifacts"
                        ].items()
                    ]

                func_source_code = inspect.getsource(func)
                # TODO (shreyashankar): Deduplicate with loaded and saved
                # artifacts
                if auto_log:
                    # Get IOPointers corresponding to args and f_locals
                    all_output_args = {
                        k: v
                        for k, v in local_vars.items()
                        if k not in all_input_args
                    }
                    output_pointers += store.get_io_pointers_from_args(
                        **all_output_args
                    )

                component_run.add_inputs(input_pointers)
                component_run.add_outputs(output_pointers)

                # Add code versions
                try:
                    repo = git.Repo(search_parent_directories=True)
                    component_run.set_git_hash(str(repo.head.object.hexsha))
                except Exception as e:
                    logging.info("No git repo found.")

                # Add git tags
                if client.get_git_tags() is not None:
                    component_run.set_git_tags(client.get_git_tags())

                # Add source code if less than 2^16
                if len(func_source_code) < 2 ** 16:
                    component_run.set_code_snapshot(
                        bytes(func_source_code, "ascii")
                    )

                # Create component if it does not exist
                client.create_component(
                    self.name, self.description, self.owner, self.tags
                )

                # Set dependencies
                store.set_dependencies_from_inputs(component_run)

                # Commit component run object to the DB
                store.commit_component_run(
                    component_run, staleness_threshold=staleness_threshold
                )

                # Perform after run tests
                if not user_kwargs.get("skip_after"):
                    # Run after test
                    after_run_args = {
                        k
                        if k not in inv_user_kwargs
                        else inv_user_kwargs[k]: v
                        for k, v in local_vars.items()
                    }
                    self.afterRun(**after_run_args)

                return value

            return wrapper

        if callable(inputs):
            # Used decorator without arguments
            return actual_decorator(inputs)

        else:
            # User passed in some kwargs
            return actual_decorator

    @property
    def name(self) -> str:
        return self._name

    @property
    def owner(self) -> str:
        return self._owner

    @property
    def description(self) -> str:
        return self._description

    @property
    def tags(self) -> typing.List[str]:
        return self._tags

    @property
    def beforeTests(self) -> list:
        return self._beforeTests

    @property
    def afterTests(self) -> list:
        return self._afterTests

    def __repr__(self):
        params = self.to_dictionary()
        del params["beforeTests"]
        del params["afterTests"]
        return json.dumps(params)


"""
Usage::

    import apply_mingw_path_fix
    apply_mingw_path_fix.update_path()

"""

import os
import sys

def _log(*args):
    script_name = os.path.basename(__file__)
    print("[appveyor:%s] " % script_name + " ".join(args))
    sys.stdout.flush()

def update_path():
    """Implement workaround for MinGW on Appveyor"""
    if os.environ.get("CMAKE_GENERATOR", "").lower().startswith("mingw"):
        _log("Applying MinGW PATH fix")

        mingw_bin = os.path.normpath(
            os.path.join("C:\\", "MinGW", "bin")).lower()

        os.environ["PATH"] = os.pathsep.join(
            one_path for one_path in
            os.environ["PATH"].split(os.pathsep)

            if (
                os.path.normpath(one_path).lower() == mingw_bin or
                not (
                    os.path.exists(os.path.join(one_path, "sh.exe")) or
                    os.path.exists(os.path.join(one_path, "sh.bat")) or
                    os.path.exists(os.path.join(one_path, "sh"))
                )
            )
        )

if __name__ == '__main__':
    update_path(sys.argv[0])


#!/usr/bin/python
# coding=utf-8
import random
import json

class Chat:
  def check_greeting(self, mess):
    with open('../phrases/PL/PL.json', 'r') as json_file:
      greeting = json.load(json_file)
      for x in greeting:
        if greeting[x]['text'] in mess:
          return greeting[x]['attitude']
    return 0

  def get_greeting(self):
    with open('../phrases/PL/PL.json', 'r') as json_file:
      greeting = json.load(json_file)
      length = len(greeting) - 1
      if length < 0:
        length = 0
      rand = random.randint(0, length)
      greeting = greeting[str(rand)]['text']
      return greeting

  def check_goodbye(self, mess):
    file = open('xml/PL/greetings_PL.xml', 'r')
    file = file.read().split()
    if mess in file:
      return True
    else:
       return False


"""Hypatia: Database creation."""

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

ENGINE = create_engine('mysql://hypatia@localhost/hypatia',
                       convert_unicode=True,
                       pool_size=5,
                       #invalidate & replace DBAPI connections after 1 hr
                       pool_recycle=3600)

def db_session():
    return scoped_session(sessionmaker(autocommit=False,
                                       autoflush=False,
                                       bind=ENGINE))

Base = declarative_base()
Base.query = db_session().query_property()

def init_db():
    """Import all models and create database."""
    import hypatia.models
    Base.metadata.create_all(bind=ENGINE)


from django.contrib import admin
from orochi.ya.models import Ruleset, Rule

@admin.register(Ruleset)
class RulesetAdmin(admin.ModelAdmin):

    actions = ["enable", "disable"]

    def enable(self, request, queryset):
        for item in queryset:
            item.enabled = True
            item.save()

    def disable(self, request, queryset):
        for item in queryset:
            item.enabled = False
            item.save()

    enable.short_description = "Enable selected ruleset"
    disable.short_description = "Disable selected ruleset"

    list_display = ("name", "url", "count_rules", "description", "enabled")
    exclude = ("created", "updated", "user", "cloned")

    list_filter = (
        "enabled",
        "user__username",
    )
    search_fields = ["name", "description"]

@admin.register(Rule)
class RuleAdmin(admin.ModelAdmin):

    actions = ["enable", "disable"]

    def enable(self, request, queryset):
        for item in queryset:
            item.enabled = True
            item.save()

    def disable(self, request, queryset):
        for item in queryset:
            item.enabled = False
            item.save()

    enable.short_description = "Enable selected rule"
    disable.short_description = "Disable selected rule"

    list_display = ("ruleset", "path", "enabled")
    readonly_fields = ("created", "updated", "path", "compiled")
    list_filter = ("enabled", "compiled", "ruleset__name")
    search_fields = ["path", "ruleset__name"]


import random
from math import floor, ceil
from random import shuffle

from src.ga.Path import Path

class Population:
    bestPath = None
    _pathes = []
    cityCount = 0

    def __init__(self, startingCity, inputCities, populationSize):
        self.cityCount = len(inputCities) + 2
        self.generateInitialPopulation(startingCity, inputCities, populationSize)
        self.bestPath = Path([])

    def generateInitialPopulation(self, startingCity, inputCities, populationSize):
        for i in range(0, populationSize):
            cityOrder = []
            cityOrder.extend(inputCities)
            shuffle(cityOrder)
            cityOrder.insert(0, startingCity)
            cityOrder.append(startingCity)

            path = Path(cityOrder)
            self._pathes.append(path)

    def evolve(self, mutationRate=0):
        # Create next population
        self._pathes = self._performCrossover()
        if mutationRate != 0:
            self._mutate(mutationRate)
        self._updateBestPath()

        # print(len(self._pathes))
        # for path in self._pathes:
        #     for city in path.cities:
        #         city.print()
        # print(len(path.cities))

    def _performCrossover(self):
        newPathes = []

        # opulation in 10 % chunks
        # chunkSize = 10
        chunkSize = 12
        bestCount = int(chunkSize / 2)

        chunks = list(self._splitIntoChunks(self._pathes, chunkSize))

        if len(chunks[-1]) < chunkSize:
            lastChunk = chunks[-1]
            newPathes.extend(lastChunk)
            chunks = chunks[:-1]

        for chunk in chunks:
            chunk.sort(key=lambda x: x.distance, reverse=False)
            bestOfChunk = chunk[0:bestCount]
            firstHalf = bestOfChunk[0:floor(bestCount / 2)]
            secondHalf = bestOfChunk[ceil(bestCount / 2):]

            firstHalfCopy = list(firstHalf)
            secondHalfCopy = list(secondHalf)
            firstHalfCopy.sort(key=lambda x: x.distance, reverse=True)
            secondHalfCopy.sort(key=lambda x: x.distance, reverse=False)
            firstHalf.extend(firstHalfCopy)
            secondHalf.extend(secondHalfCopy)

            for firstPath, secondPath in zip(firstHalf, secondHalf):
                newPathes.append(self._createChild(firstPath, secondPath))
                newPathes.append(self._createChild(secondPath, firstPath))

            if bestCount % 2 != 0:
                # for firstPath in firstHalf:
                #     for secondPath in secondHalf:
                #         newPathes.append(self._createChild(firstPath, secondPath))
                #         newPathes.append(self._createChild(secondPath, firstPath))
                middleValue = bestOfChunk[floor(bestCount / 2)]
                newPathes.append(middleValue)
                newPathes.append(middleValue)

        return newPathes

    def _createChild(self, firstPath, secondPath):
        newCitiesOrder = []
        firstCitiesList = firstPath.cities[:floor(self.cityCount)]
        secondCitiesList = secondPath.cities[ceil(self.cityCount):]
        newCitiesOrder.extend(firstCitiesList)
        newCitiesOrder.extend(secondCitiesList)
        return Path(newCitiesOrder)

    def _splitIntoChunks(self, l, n):
        for i in range(0, len(l), n):
            yield l[i:i + n]

    def _mutate(self, mutationRate):
        for path in self._pathes:
            if random.random() <= mutationRate:
                self._swapRandomCities(path.cities)

    def _swapRandomCities(self, cities):
        idx = range(1, len(cities) - 1)
        i1, i2 = random.sample(idx, 2)
        cities[i1], cities[i2] = cities[i2], cities[i1]

    def _updateBestPath(self):
        value = min(node.distance for node in self._pathes)
        newBestPath = next((x for x in self._pathes if x.distance == value), None)
        if self.bestPath.distance > value:
            self.bestPath = newBestPath


# Create your views here.
from md_analysis.const import MdMeta
from md_analysis.errors import HwPrjIdNotFound, OpNameNotFound
from md_analysis.services.cr_analysis_by_hwprj_service import CrAnalysisByHwPrjService
from md_analysis.views import MdAnalysisBaseView

class CrAnalysisByHwPrjView(MdAnalysisBaseView):

    def __init__(self, **kwds):
        super(CrAnalysisByHwPrjView, self).__init__(**kwds)
        self.cr_analysis_by_hwprj_service = CrAnalysisByHwPrjService()

    def api_get(self, request):
        result = {}

        '''
        input param check
        '''
        hw_prj_id = request.GET.get("hw_prj_id")
        operator = request.GET.get("operator")

        try:
            if hw_prj_id is None:
                raise HwPrjIdNotFound()

            if operator is None:
                raise OpNameNotFound()

            '''
            handle request
            '''
            act_id = MdMeta.ActivityId
            latest_sync = self._sync_helper.get_lastest_sync_job_id(act_id)
            act_cr_list = self._sync_helper.get_act_cr_list(
                act_id, latest_sync["sync_job_id"])

            all_data = self.cr_analysis_by_hwprj_service.get_cr_analysis_by_hwprj_all_data(
                hw_prj_id, act_id, act_cr_list, operator)

            result.update({'updateTime': latest_sync['update_time']})
            result.update(all_data)
        except HwPrjIdNotFound as e:
            self.logger.exception(e.msg)
            result["error_code"] = e.code
            result["error_msg"] = e.msg

        return result


import sys
from CWSTokenizer import CWSTokenizer

input_file = sys.argv[1]
output_file = sys.argv[2]

t = CWSTokenizer()
lines = [line.strip('\n') for line in open(input_file, 'r')]
tokenized_lines = [t.sent_tokenize(line)[1] for line in lines]
tokenized_lines = [
    ' '.join([''.join(segment) for segment in line]) for line in tokenized_lines
]

with open(output_file, 'w+') as f:
    for line in tokenized_lines:
        print(line, file=f)


__author__ = 'noelbell'

import sys
import pandas as pd
import collections

from FunctionBlock import FunctionBlock

class EWMStDev(FunctionBlock):

    def __init__(self, name, unique_name):
        FunctionBlock.__init__(self, name, unique_name)

    def execute(self, results_table):
        try:
            FunctionBlock.report_status_executing(self)

            FunctionBlock.check_connector_has_one_wire(self, 'in')

            df = results_table[self.input_connectors['in'][0]]

            weight = self.parameters['Weight']

            df_ewmstdev = pd.ewmstd(df, weight)

            results = collections.OrderedDict()
            results['Weight'] = weight

            FunctionBlock.save_results(self, df=df_ewmstdev, statistics=True, plot=True, results=results)

            FunctionBlock.report_status_complete(self)

            return {FunctionBlock.getFullPath(self,  'out'): df_ewmstdev}

        except Exception as err:
            FunctionBlock.save_results(self)
            FunctionBlock.report_status_failure(self)
            print(err.args, file=sys.stderr)


from unittest import TestCase

from hkp.create_result import *
from tests.test_createbill import TestClass

class TestResult(TestCase):
    def test_transform_result_type(self):
        result = Result(TestClass(**{'gutstat': 4, 'hf': False, 'pruefung': '110',
                                     'gut_antw1': 'yes', 'gut_antw2': ''}))
        self.assertEqual(result.gutstat, 4)
        gutstat = result.transform_result_type('binomial')
        self.assertEqual(gutstat, 1)

class TestRuleList(TestCase):
    def setUp(self):
        self.li = RuleList.from_text('/010/110/120')

    def test_from_text(self):
        li = self.li
        self.assertEqual(len(li), 3)
        self.assertTrue('010' in li)

    def test_to_list(self):
        res = self.li.to_list(['010', '220', ['110', '120'], '999'])
        self.assertEqual(res['rule_010'], 1)
        self.assertEqual(res['rule_220'], 0)
        self.assertEqual(res['rule_110+120'], 2)