import rospy
import cv2
import youtube_dl
import pafy
import numpy as np
import matplotlib.pyplot as plt
import time, math, random

cap=cv2.VideoCapture('./kmu_track.mkv')

ym_per_pix=30/720
xm_per_pix=3.7/720

def warpping(image):
    (h,w)=(image.shape[0],image.shape[1])

    source=np.float32([[w//2-30,h*0.53],[w//2+60,h*0.53],[w*0.3,h],[w,h]])
    des=np.float32([[0,0],[w-350,0],[400,h],[w-150,h]])

    transform_matrix=cv2.getPerspectiveTransform(source,des)
    minv=cv2.getPerspectiveTransform(des,source)
    _image=cv2.warpPerspective(image,transform_matrix,(w,h))

    return _image, minv

def color_filter(image):
    hls=cv2.cvtColor(image, cv2.COLOR_BGR2HLS)

    low=np.array([20,150,20])
    up=np.array([255,255,255])

    yellow_low=np.array([0,85,81])
    yellow_up=np.array([190,255,255])

    yellow_mask=cv2.inRange(hls,yellow_low,yellow_up)
    white_mask=cv2.inRange(hls,low,up)
    mask=cv2.bitwise_or(yellow_mask,white_mask)
    masked=cv2.bitwise_and(image,image,mask=mask)

    return masked

def roi(image):
    x=int(image.shape[1])
    y=int(image.shape[0])

    _shape=np.array([[int(0.1*x),int(y)],[int(0.1*x),int(0.1*y)],[int(0.4*x),int(y)],[int(0.7*x),int(y)],[int(0.7*x),int(0.1*y)],[int(0.9*x),int(0.1*y)],[int(0.9*x),int(y)],[int(0.2*x),int(y)]])
    mask=np.zeros_like(image)

    if len(image.shape)>2:
        channel_count=image.shape[2]
        ignore_mask_color=(255,)*channel_count
    else:
        ignore_mask_color=255
        pos,frame=process_image(img)
        steer_angle=0
        draw_steer(frame,steer_angle)

    cv2.fillPoly(mask,np.int32([_shape]),ignore_mask_color)
    masked_image=cv2.bitwise_and(image,mask)

    return masked_image

def plothistogram(image):
    histogram=np.sum(image[image.shape[0]//2:,:],axis=0)
    midpoint=np.int(histogram.shape[0]/2)
    leftbase=np.argmax(histogram[:midpoint])
    rightbase=np.argmax(histogram[midpoint:])+midpoint

    return leftbase, rightbase

def slide_window_search(binary_warped, left_current, right_current):
    out_img=np.dstack((binary_warped, binary_warped,binary_warped))

    nwindows=4
    window_height=np.int(binary_warped.shape[0]/nwindows)
    nonzero = binary_warped.nonzero()
    nonzero_y=np.array(nonzero[0])
    nonzero_x=np.array(nonzero[1])
    margin = 100
    minpix = 50
    left_lane=[]
    right_lane=[]
    color=[0,255,0]
    thickness = 2

    for w in range(nwindows):
        win_y_low = binary_warped.shape[0]-(w+1)*window_height
        win_y_high= binary_warped.shape[0]-w*window_height
        win_xleft_low=left_current-margin
        win_xleft_high=left_current+margin
        win_xright_low=right_current-margin
        win_xright_high=right_current+margin

        cv2.rectangle(out_img,(win_xleft_low,win_y_low),(win_xleft_high,win_y_high),color,thickness)
        cv2.rectangle(out_img,(win_xright_low,win_y_low),(win_xright_high,win_y_high),color,thickness)
        good_left = ((nonzero_y>=win_y_low)&(nonzero_y<win_y_high)&(nonzero_x>=win_xleft_low)&(nonzero_x<win_xleft_high)).nonzero()[0]
        good_right = ((nonzero_y>=win_y_low)&(nonzero_y<win_y_high)&(nonzero_x>=win_xright_low)&(nonzero_x<win_xright_high)).nonzero()[0]
        left_lane.append(good_left)
        right_lane.append(good_right)

        if len(good_left)>minpix:
            left_current = np.int(np.mean(nonzero_x[good_left]))
        if len(good_right)>minpix:
            right_current = np.int(np.mean(nonzero_x[good_right]))

    left_lane = np.concatenate(left_lane)
    right_lane=np.concatenate(right_lane)

    leftx=nonzero_x[left_lane]
    lefty=nonzero_y[left_lane]
    rightx=nonzero_x[right_lane]
    righty=nonzero_y[right_lane]

    left_fit=np.polyfit(lefty,leftx,2)
    right_fit=np.polyfit(righty,rightx,2)

    ploty=np.linspace(0,binary_warped.shape[0]-1,binary_warped.shape[0])
    left_fitx=left_fit[0]*ploty**2+left_fit[1]*ploty+left_fit[2]
    right_fitx=right_fit[0]*ploty**2+right_fit[1]*ploty+right_fit[2]

    ltx=np.trunc(left_fitx)
    rtx=np.trunc(right_fitx)

    out_img[nonzero_y[left_lane],nonzero_x[left_lane]]=[255,0,0]
    out_img[nonzero_y[right_lane],nonzero_x[right_lane]]=[0,0,255]

    #plt.imshow(out_img)
    #plt.plot(left_fitx,ploty,color='yellow')
    #plt.plot(right_fitx,ploty,color='yellow')
    #plt.xlim(0,1280)
    #plt.ylim(720,0)
    #plt.show()

    ret={'left_fitx':ltx,'right_fitx':rtx,'ploty':ploty}

    return ret

def draw_lane_lines(original_image,warped_image,Minv,draw_info):
    left_fitx=draw_info['left_fitx']
    right_fitx=draw_info['right_fitx']
    ploty=draw_info['ploty']

    warp_zero=np.zeros_like(warped_image).astype(np.uint8)
    color_warp=np.dstack((warp_zero,warp_zero,warp_zero))

    pts_left=np.array([np.transpose(np.vstack([left_fitx,ploty]))])
    pts_right=np.array([np.flipud(np.transpose(np.vstack([right_fitx,ploty])))])
    pts=np.hstack((pts_left, pts_right))

    mean_x=np.mean((left_fitx,right_fitx),axis=0)
    pts_mean=np.array([np.flipud(np.transpose(np.vstack([mean_x,ploty])))])

    cv2.fillPoly(color_warp,np.int_([pts]),(216,168,74))
    cv2.fillPoly(color_warp,np.int_([pts_mean]),(216,168,74))

    newwarp=cv2.warpPerspective(color_warp,Minv,(original_image.shape[1],original_image.shape[0]))
    result=cv2.addWeighted(original_image,1,newwarp,0.4,0)

    return pts_mean, result

while True:
    retval,img=cap.read()

    if not retval:
        break

    warpped_img,minverse=warpping(img)

    w_f_img=color_filter(warpped_img)

    w_f_r_img=roi(w_f_img)

    _gray=cv2.cvtColor(w_f_r_img,cv2.COLOR_BGR2GRAY)
    ret,thresh=cv2.threshold(_gray,160,255,cv2.THRESH_BINARY)

    leftbase,rightbase=plothistogram(thresh)

    draw_info=slide_window_search(thresh,leftbase,rightbase)

    meanPts, result=draw_lane_lines(img,thresh,minverse,draw_info)

    cv2.imshow("asdf", result)

    key=cv2.waitKey(25)

    if key==27:
        break

if cap.isOpened():
    cap.release()

cv2.destroyAllWindows()


#!/usr/bin/env python3
import rospy
import tf2_ros
import tf2_geometry_msgs
from tf.transformations import quaternion_from_euler
import geometry_msgs.msg
from sensor_msgs.msg import Image
from nav_msgs.msg import OccupancyGrid
import cv2
from cv_bridge import CvBridge
import numpy as np

def draw_occupancy_grid(occ_grid, frame=None):
    width = occ_grid.info.width
    height = occ_grid.info.height
    image = np.zeros((height, width, 3), np.uint8)
    data_iter = 0
    for j in range(height-1, -1, -1):
        for i in range(width):
            occ_grid_value = occ_grid.data[data_iter]
            if occ_grid_value == -1:
                pixel_value = 100
            else:
                pixel_value = int((100 - occ_grid_value) * 255 / 100)
            image[j, i] = (pixel_value, pixel_value, pixel_value)
            data_iter += 1

    k = 1
    if frame:
        k = min(frame[0] / width, frame[1] / height)
        image = cv2.resize(image, (int(width * k), int(height * k)))
    return image, k

def get_robot_world_pose(desired_time=None):
    global tfBuffer
    if desired_time is None:
        desired_time = rospy.Time(0)
    try:
        map_to_base_link = tfBuffer.lookup_transform('map', 'base_link', desired_time, rospy.Duration(1.0))
    except:
        print('Could not find transform from map to base_link')
        return None
    robot_world_pose = geometry_msgs.msg.PoseStamped()
    robot_world_pose.pose.position = map_to_base_link.transform.translation
    robot_world_pose.pose.orientation = map_to_base_link.transform.rotation
    return robot_world_pose

def inverse_transform(transform):
    inversed_transform = geometry_msgs.msg.TransformStamped()

    inversed_rotation = geometry_msgs.msg.TransformStamped()
    inversed_rotation.transform.translation = geometry_msgs.msg.Vector3(0, 0, 0)
    inversed_rotation.transform.rotation = transform.transform.rotation
    inversed_rotation.transform.rotation.w *= -1

    inversed_translation = geometry_msgs.msg.Vector3Stamped()
    inversed_translation.vector = transform.transform.translation
    inversed_translation.vector.x *= -1
    inversed_translation.vector.y *= -1
    inversed_translation.vector.z *= -1
    inversed_translation = tf2_geometry_msgs.do_transform_vector3(inversed_translation, inversed_rotation)

    inversed_transform.transform.translation = inversed_translation.vector
    inversed_transform.transform.rotation = inversed_rotation.transform.rotation
    return inversed_transform

def transform_world_pose_to_occupancy_grid_pose(world_pose, occ_grid_info):
    transform = geometry_msgs.msg.TransformStamped()
    transform.transform.translation = occ_grid_info.origin.position
    transform.transform.rotation = occ_grid_info.origin.orientation
    inversed_transform = inverse_transform(transform)

    occ_grid_pose = tf2_geometry_msgs.do_transform_pose(world_pose, inversed_transform)
    return occ_grid_pose

def draw_pose(image, k, robot_pose, occ_grid_info):
    x = robot_pose.pose.position.x * k / occ_grid_info.resolution
    y = robot_pose.pose.position.y * k / occ_grid_info.resolution
    i = int(x)
    j = int(image.shape[0] - y)
    angle = 2 * np.arccos(robot_pose.pose.orientation.w) * np.sign(robot_pose.pose.orientation.z)  # only for 3 DoF movements

    radius = 6
    length = 15
    width = 3
    cv2.circle(image, (i, j), radius, (0, 0, 255), -1)
    dx = length * np.cos(angle)
    dy = length * np.sin(angle)
    di = int(dx)
    dj = int(-dy)
    cv2.line(image, (i, j), (i+di, j+dj), (0, 0, 255), width)

def process_occupancy_grid(occ_grid):
    global bridge
    global pub
    image, k = draw_occupancy_grid(occ_grid, frame=(1500, 1000))
    robot_world_pose = get_robot_world_pose(desired_time=occ_grid.header.stamp)
    if robot_world_pose is None:
        return()
    robor_occ_grid_pose = transform_world_pose_to_occupancy_grid_pose(robot_world_pose, occ_grid.info)
    draw_pose(image, k, robor_occ_grid_pose, occ_grid.info)
    image_message = bridge.cv2_to_imgmsg(image, encoding="passthrough")
    image_message.header.stamp = occ_grid.header.stamp
    pub.publish(image_message)

if __name__ == '__main__':
    rospy.init_node('occupancy_grid_demo')
    tfBuffer = tf2_ros.Buffer()
    tfListener = tf2_ros.TransformListener(tfBuffer)
    bridge = CvBridge()
    rospy.Subscriber('/rtabmap/grid_map', OccupancyGrid, process_occupancy_grid)
    pub = rospy.Publisher('/occupancy_grid_demo', Image, queue_size=10)
    rospy.spin()


import unittest
import os.path
import pandas as pd
import random
import string
import pytest

from analitico import AnaliticoException
from analitico.factory import Factory
from analitico.schema import generate_schema

from .test_mixin import TestMixin

# pylint: disable=no-member

@pytest.mark.django_db
class ExceptionTests(unittest.TestCase, TestMixin):
    """ Unit testing of AnaliticoException """

    def test_exception_basics(self):
        try:
            raise AnaliticoException("A problem", item_id="it_001", extra={"recipe_id": "rx_002"})
        except AnaliticoException as e:
            self.assertEqual(e.message, "A problem")
            self.assertEqual(e.extra["item_id"], "it_001")
            self.assertEqual(e.extra["recipe_id"], "rx_002")

    def test_exception_formatting(self):
        try:
            raise AnaliticoException("A problem %d", 1, item_id="it_001", extra={"recipe_id": "rx_002"})
        except AnaliticoException as e:
            self.assertEqual(e.message, "A problem 1")
            self.assertEqual(e.extra["item_id"], "it_001")
            self.assertEqual(e.extra["recipe_id"], "rx_002")

    def test_exception_formatting_multiple(self):
        try:
            raise AnaliticoException("A problem %d with %s", 1, "this", item_id="it_001", extra={"recipe_id": "rx_002"})
        except AnaliticoException as e:
            self.assertEqual(e.message, "A problem 1 with this")

    def test_exception_with_inner(self):
        try:
            try:
                raise AnaliticoException("Inner exception %d", 1, item_id="it_001", extra={"recipe_id": "rx_002"})
            except AnaliticoException as e1:
                self.assertEqual(e1.message, "Inner exception 1")
                self.assertEqual(e1.extra["item_id"], "it_001")
                self.assertEqual(e1.extra["recipe_id"], "rx_002")
                raise AnaliticoException("Outer exception %d", 2, test_id="tx001") from e1
        except AnaliticoException as e2:
            self.assertEqual(e2.message, "Outer exception 2")
            print(e2)


# Chris Joakim, 2021/01/11
# See https://scikit-learn.org/stable/tutorial/basic/tutorial.html#machine-learning-the-problem-setting

# https://scikit-learn.org/stable/modules/classes.html  (API)

import os
import pickle
import sys

from sklearn import datasets
from sklearn import svm

from joblib import dump, load

def digits():
    digits = datasets.load_digits()
    print(digits.data)    # The data is always a 2D array, shape (n_samples, n_features)
    print(digits.target)

    clf = svm.SVC(gamma=0.001, C=100.)  # clf = classifier
    print('clf: {} {}'.format(clf, str(type(clf))))

    # C is the Regularization parameter. The strength of the regularization is inversely proportional to C.
    # Must be strictly positive. The penalty is a squared l2 penalty.

    result = clf.fit(digits.data[:-1], digits.target[:-1])  # fit == "train the model"
    print('fit result: {} {}'.format(str(type(result)), result))

    result = clf.predict(digits.data[-1:])
    print('clf predict result -1: {} {}'.format(str(type(result)), result))

    result = clf.predict(digits.data[-2:])
    print('clf predict result -2: {} {}'.format(str(type(result)), result))

    s = pickle.dumps(clf)
    print('s - type: {} len: {}'.format(str(type(s)), len(s)))

    clf2 = pickle.loads(s)
    print('clf2: {} {}'.format(clf2, str(type(clf2))))

    result = clf2.predict(digits.data[-1:])
    print('clf2 predict result -1: {} {}'.format(str(type(result)), result))

    result = clf2.predict(digits.data[-2:])
    print('clf2 predict result -2: {} {}'.format(str(type(result)), result))

    # use joblib’s replacement for pickle which is more efficient on big data but it can only
    # pickle to the disk and not to a string
    dump(clf, 'tmp/clf.joblib')
    clf3 = load('tmp/clf.joblib')
    result = clf3.predict(digits.data[-1:])
    print('clf3 predict result -1: {} {}'.format(str(type(result)), result))

    result = clf3.predict(digits.data[-2:])
    print('clf3 predict result -2: {} {}'.format(str(type(result)), result))

def iris():
    iris = datasets.load_iris()
    print(iris.data)
    print(iris.target)

if __name__ == "__main__":

    if len(sys.argv) > 1:
        func = sys.argv[1].lower()
        if func == 'digits':
            digits()
        elif func == 'iris':
            iris()


import matplotlib.pyplot as plt
import numpy as np

data = np.loadtxt('att48_roulette.f')
data = np.transpose(data)

plt.figure(1)
plt.plot(data[0, :], data[1, :], 'r')
plt.plot(data[0, :], data[2, :], 'b')
plt.legend(['Fitness of best solution', 'Average population fitness'])
plt.savefig('plots/att48_fit.png')
plt.figure(2)
plt.loglog(data[0, :], data[1, :], 'r')
plt.loglog(data[0, :], data[2, :], 'b')
plt.legend(['Fitness of best solution', 'Average population fitness'])
plt.savefig('plots/att48_fit_log.png')


import os.path
from pymongo import *
from pprint import pprint
from flask import Flask, render_template, request
from dbcontroller import search

app = Flask(__name__)
app.config.from_object(__name__)

@app.route('/')
def render_static():
	return render_template("index.html");

@app.route('/result', methods=['POST'])
def query():
	client = MongoClient()
	db = client.search;
	query = request.form['query'].lower();
	results = search(query, db)
	if(len(results) > 0):
		results = [link[0] for link in results];
	return render_template("results.html", data = results);

@app.route('/page/<string:webpage>/<int:pageid>/<int:docid>')
def loadpage(webpage, pageid, docid):
	path = webpage+ "/" + str(pageid) + "/" + str(docid);
	with open(path, "r", encoding="utf-8") as file:
		content = file.read()
	return render_template("page.html", content=content, pageTitle = path);

if __name__ == '__main__':
	app.run(debug=True, port=3000);


from __future__ import division

import copy
import re

import numpy as np
import scipy.signal
from scipy import optimize
# import matplotlib.pyplot as plt

def my_rms(arr):
    #return np.sqrt(arr.dot(arr)/arr.size)
    return np.std(arr)

def extend_window(w, r):
    # Inputs:
    #   w: An array of 2 elements. Normally, this will be a window like [t1, t2]
    #   r: A float used as a ratio to extend w
    # Outputs: A rescaled version of w
    mp = 0.5*(w[1]+w[0])  # Midpoint
    new_len = (w[1]-w[0])*(1+r)  # Length of new window
    return [mp-new_len/2, mp+new_len/2]

def freq_filter(freqs, lower=None, upper=None):
    # Inputs:
    #   freqs: An array of frequency bins
    #   lower: The lower frequency to cut-off at
    #   upper: The upper frequency to cut-off at
    # Outputs: An array of indices where the the frequency in freqs is between lower and upper
    if lower is None and upper is None:
        return freqs
    if lower is None:
        return np.where([x <= upper for x in freqs])
    if upper is None:
        return np.where([x >= lower for x in freqs])
    return np.where([lower <= x <= upper for x in freqs])

def closest_index(arr, el):
    # Inputs:
    #   arr: A 1-dimensional array
    #   el: Any element
    # Outputs: The FIRST index of the item in arr that is closest to el.
    # Notes: Arr does NOT have to be sorted.
    return np.argmin(np.abs(arr-el))

def spectrum_sums(spectrum, fr, n, lowerf=None, upperf=None):
    # Inputs:
    #   spectrum: The output 2d spectrum from a spectogram
    #   fr: A list of frequency bins corresponding to the spectrum
    #   n: Number of bins
    #   lowerf: The lower frequency to cut-off at
    #   upperf: The upper frequency to cut-off at
    # Outputs: A compressed 1d array where each element is the sum of a bin from spectrum, only counting
    #          frequencies between lowerf and upperf
    out = []
    good_indices = freq_filter(fr, lowerf, upperf)
    for subn in range(n):
        out.append(np.trapz(spectrum[good_indices[0], subn], dx=np.mean(np.diff(fr))))
    return out

def rescale_window(w1, w2):
    # Inputs:
    #   w1: An array with 2 elements
    #   w2: An array with 2 elements
    # Outputs: A rescaled version of w2 so tha the endpoints of w2 match w1 but the number of elements remain the same
    y1, y2 = min(w1), max(w1)
    x1, x2 = min(w2), max(w2)
    if x1 == x2:
        return 0*w2
    a = (y1-y2)/(x1-x2)
    b = (x1*y2-x2*y1)/(x1-x2)
    return a*w2+b

def corr_signal(tau, dt, t0, n, fit_type=0, shift=10):
    # Inputs:
    #   tau: Time constant on exponential decay
    #   dt: Step size for the x-axis
    #   t0: Where the exponential signal will start. Not important when used with correlation
    #   N: Number of points requested
    #   fit_type: The type of signal to create. See corr_signal_type_templates.py for a better explanation.
    #               fit_type = 0 --> Exponential decay
    #               fit_type = 1 --> Constant 1 followed by exponential decay (continuous)
    #               fit_type = 2 --> Linear increase followed by exponential decay
    #               fit_type = 3 --> Log increase followed by exponential decay
    #               fit_type = 4 --> 0 value followed by an exponential decrease. Discontinuous.
    # Outputs:
    #   t: t-values for plotting
    #   y: y-values of our filter signal.
    # After careful analysis, we've determined that there reaches a point in the filtered piezo signal that
    # exhibits a sharp increase followed by an exponential decay. This function returns a brief exponential
    # decay function for use with convolution/correlation.
    shift = int(np.ceil(shift))
    t = np.linspace(t0, t0+dt*n, n)
    y = np.exp(-(t-t0)/tau)
    ycopy = copy.deepcopy(y)
    if fit_type == 0:
        pass
    elif fit_type == 1:
        for subn in range(len(y) - shift):
            y[subn+shift] = ycopy[subn]
        y[0:shift] = 1
    elif fit_type == 2:
        for subn in range(len(y) - shift):
            y[subn + shift] = ycopy[subn]
        y[0:shift] = (t[0:shift] - t0)/(shift*dt)
    elif fit_type == 3:
        for subn in range(len(y) - shift):
            y[subn + shift] = ycopy[subn]
            y[0:shift] = np.log((t[0:shift] + 1 - t0)) / np.log(shift*dt + 1)
    elif fit_type == 4:
        for subn in range(len(y) - shift):
            y[subn+shift] = ycopy[subn]
            y[0:shift] = 0
    return t, y

# Uncomment the below code if you want to test a new fit_type quickly to make sure the shape is what you want
# fit_type = 0
# t,y = corr_signal(1.5, 0.1, 0, 45, fit_type, 20) # <-- Uncomment to test different fit types
# plt.ioff()
# plt.plot(t,y)
# plt.show()
# 1/0 # <-- Just to stop the program here

def find_t0_from_corr(corrt, corry):
    # Inputs:
    #   corrt: Time-values of the correlation signal
    #   corry: Y-values of the correlation signal
    # Outputs: The time of the maximum in corry such that corrt is less than or equal to 0.
    n = np.where(corrt >= 0)
    corry[n] = 0
    return corrt[np.argmax(corry)]

def calculate_t0(piezo_waveform, piezo_timebase, led_on, tau,
                 lower=20000, upper=40000, piezo_fit_type=0):
    # Inputs:
    #   piezo_waveform: A piezo waveform, generally this should have the LED pulses subtracted
    #   piezo_timebase: The times of each element in the piezo_waveform
    #   tau: The time constant we are trying to fit to the exponential decay that occurs
    #        immediately after the bubble forms
    #   lower: The lower frequency threshold for cutting off the spectrogram
    #   upper: The upper frequency threshold for cutting off the spectrogram
    #   piezo_fit_type: The type of fit to use when trying to match the filtered piezo signal. Defaults to 0.
    #   view_plots: Boolean. If true, will display some plots for analysis.
    # Outputs: A dictionary of results for the Acoustic Analysis.
    try:
        timebase = piezo_timebase
        textent = [min(timebase), max(timebase)]
        dt = np.mean(np.diff(timebase))
        fr, bn, sp = scipy.signal.spectrogram(piezo_waveform, fs=1./dt, nfft=512, noverlap=450,
                                              mode="psd", window="hanning", nperseg=512)
        n = len(bn)
        sp_sums = spectrum_sums(sp, fr, n, lower, upper)
        sp_sums = scipy.signal.medfilt(sp_sums)
        rescaled_t = rescale_window(textent, bn)
        corr_dt = np.mean(np.diff(rescaled_t))
        corr_n = 1000
        corr_t, corr_y = corr_signal(tau, corr_dt, rescaled_t[0], corr_n, fit_type=piezo_fit_type)
        corr = np.correlate(sp_sums, corr_y, "same")
        corr_t = rescaled_t - 0.5 * corr_n * corr_dt
        test_t0 = find_t0_from_corr(corr_t, corr) # This is the t0 we begin to look backwards from
        # Establish a baseline for our lookback algorithm
        #   But first we take the log of the [integrated] spectrogram signal
        log_sp_sums = np.log(sp_sums)
        first_on = np.argmax(led_on)
        first_off = np.argmin(led_on[first_on:])
        second_on = np.argmax(led_on[first_off:])
        t_first_off = timebase[first_off]
        t_second_on = timebase[second_on]
        if not np.any(led_on):
            return np.nan
        rescaled_t_first_off_index = np.argmin(np.abs(rescaled_t - t_first_off))
        rescaled_t_second_on_index = np.argmin(np.abs(rescaled_t - t_second_on))

        baseline = np.average(log_sp_sums[rescaled_t_first_off_index+1:rescaled_t_second_on_index])

        baseline_rms = my_rms(log_sp_sums[rescaled_t_first_off_index+1:rescaled_t_second_on_index])

        test_t0_index = np.argmin(np.abs(rescaled_t - test_t0))
        rescaled_dt = np.mean(np.diff(rescaled_t))
        t_thresh = 100e-6
        n_lookback = int(np.floor(t_thresh/rescaled_dt))
        pts_lookbacked_sofar = 0

        while True:
            to_test = log_sp_sums[test_t0_index-n_lookback-pts_lookbacked_sofar:test_t0_index-pts_lookbacked_sofar]

            if np.all(to_test<(baseline+5*baseline_rms)):
                break
            pts_lookbacked_sofar += 1
            if test_t0_index-n_lookback-pts_lookbacked_sofar <= 0:
                pts_lookbacked_sofar = -1
                break
        if pts_lookbacked_sofar != -1:
            t0 = rescaled_t[test_t0_index-pts_lookbacked_sofar] + rescaled_dt/2
            # plt.ioff()
            # plt.plot(rescaled_t, log_sp_sums, color="cyan")
            # plt.axhline(baseline, color="b")
            # plt.axhline(baseline+5*baseline_rms, color="k")
            # plt.axvline(t0, color="g")
            # plt.axvline(test_t0, color="r")
            # plt.axvline(t_first_off, color="k")
            # plt.axvline(t_second_on, color="k")
            # plt.show()

        else:
            t0 = np.nan
        return t0
    except Exception as e:
        return np.nan

def BandPass2(yd, f_low, f_high):
    fband = np.array([f_low, f_high])
    b, a = scipy.signal.butter(2, fband / (2.5e6 / 2.0), btype='bandpass', output='ba')
    yd_f = scipy.signal.filtfilt(b, a, yd)
    return yd_f

def CalcPiezoE(yd, td, t_wins, f_bins, t0):
    piezoE = np.zeros((t_wins.shape[0],
                       f_bins.shape[0] - 1),
                      dtype=np.float64) + np.nan

    if np.isnan(t0):
        return piezoE

    dt = td[1] - td[0]
    t_wins = t_wins + t0
    t_wins_ix = np.intp(np.round((t_wins - td[0]) / dt))
    t_wins_ix[t_wins_ix < 0] = 0
    t_wins_ix[t_wins_ix > td.shape[0]] = td.shape[0]

    for i_win in range(t_wins.shape[0]):
        this_yd = yd[t_wins_ix[i_win][0]:t_wins_ix[i_win][1]]
        if len(this_yd) < 2:
            continue
        fft_amp = np.fft.rfft(this_yd)
        fft_pow = (np.abs(fft_amp) ** 2) * dt / len(this_yd)

        df = 1 / (dt * len(this_yd))
        fd = df * (np.arange(len(fft_amp), dtype=np.float64) + 1)
        f_bins_ix = np.intp(np.round((f_bins / df) - 1))
        f_bins_ix[f_bins_ix < 0] = 0
        f_bins_ix[f_bins_ix > len(fft_amp)] = len(fft_amp)

        fft_en = fft_pow * (fd ** 2)
        for i_f in range(len(f_bins) - 1):
            piezoE[i_win, i_f] = df *\
                np.sum(fft_en[f_bins_ix[i_f]:f_bins_ix[i_f + 1]])

    return piezoE

def AcousticAnalysis(ev, tau, piezo_fit_type=0,
                     f_high=np.float64(40e3), f_low=np.float64(6e3),
                     led_amp=np.float64(-0.1), led_tau=np.float64(2e-4),
                     bs_win=np.float64([-0.15, -0.12]),
                     t0_win=np.float64([-0.12, 0]),
                     meansamp=np.intp(1e4), notbs_win=np.float64(2e-4),
                     t_wins=np.float64([[[-2e-2, -1e-2],
                                        [-1e-3, 9e-3],
                                        [-2e-4, 4e-3]],
                                        [[-2e-2, -1e-2],
                                         [-1e-3, 9e-3],
                                         [-2e-4, 4e-3]]],                                ),
                     f_bins=np.float64([[1e2, 1e3, 1e4, 1e5],
                                       [1e2, 1e3, 1e4, 1e5]]),
                     corr_lowerf=20000, corr_upperf=40000):
    # Inputs:
    #   ev: Event data (from GetEvent)
    #   tau: The expected time-constant of the exponential decay from the filtered piezo signal
    #   piezo1_fit_type: See corr_signal_types.py
    #   piezo2_fit_type: See corr_signal_Types.py
    #   f_high: High frequency used for calculating Piezo Energy
    #   f_low: Low frequency used for calculating Piezo Energy
    #   led_amp: ??
    #   led_tau: Exponential decay time constant of led-fall off (?? I think)
    #   bs_win: ??
    #   t0_win: ??
    #   meansamp: ??
    #   t_wins: ??
    #   f_bins: Frequency bins for calculating Piezo energy
    #   corr_lowerf: Lower frequency for cutting off the spectrogram of the Piezo signal
    #   corr_upperf: Higher frequency for cutting off the spectrogram of the Piezo signal
    # Outputs: A dictionary of values for the various variables we are interested in. For a list, take a look
    #          at default_output right below.
    default_output = dict(bubble_t0=np.zeros(2)-1,  # seconds
                          peak_t0=np.zeros(2)-1,  # seconds
                          piezoE=np.zeros((2,
                                           t_wins.shape[0],
                                           f_bins.shape[1] - 1),
                                          dtype=np.float64) + np.nan,
                          piezo_list=np.zeros(2)-1,
                          piezo_freq_binedges=f_bins,
                          piezo_time_windows=t_wins,
                          led_switch_off_amp=np.zeros((2, 2)),
                          led_tau=np.zeros((2, 1)),
                          led_switch_on_amp=np.zeros((2, 2)))
    out = default_output
    try:
        if not ev["fastDAQ"]["loaded"]:
            return default_output
        piezoname_list = []
        piezo_list = []
        for k in list(ev["fastDAQ"].keys()):
            m = re.search("Piezo(\d+)", k)
            if m:
                piezoname_list.append(m.group(0))
                piezo_list.append(int(m.group(1)))
        piezo_list = np.int32(piezo_list)
        ixx = np.argsort(piezo_list)
        piezo_list = piezo_list[ixx] # Sorted piezo list
        piezoname_list = [piezoname_list[ix] for ix in ixx]
        out["piezo_list"] = piezo_list
        out["bubble_t0"] = np.zeros(piezo_list.shape, dtype=np.float64) + np.nan
        out["peak_t0"] = np.zeros(piezo_list.shape, dtype=np.float64) + np.nan
        out["piezoE"] = np.zeros((piezo_list.shape[0], t_wins.shape[0], f_bins.shape[0]-1),
                                 dtype=np.float64) + np.nan
        out["led_switch_on_amp"] = np.zeros(piezo_list.shape, dtype=np.float64) + np.nan
        out["led_switch_off_amp"] = np.zeros(piezo_list.shape, dtype=np.float64) + np.nan
        out["led_tau"] = np.zeros(piezo_list.shape, dtype=np.float64) + np.nan

        fastdaq_time = ev["fastDAQ"]["time"]
        dt = ev["fastDAQ"]["caldata"]["dt"][0]

        t0_win_ix = np.intp(np.round((t0_win - fastdaq_time[0]) / dt))
        bs_win_ix = np.intp(np.round((bs_win - fastdaq_time[0]) / dt))

        k_lowpass = f_high * 2 * np.pi * dt
        k_highpass = f_high * 2 * np.pi * dt

        if "CAMgate" in ev["fastDAQ"].keys():
            led_on = ev["fastDAQ"]["CAMgate"] < -0.5
            led_switch = np.diff(np.int8(led_on))
            led_switch_on = led_switch == 1
            led_switch_off = led_switch == -1
            led_switch_on_time = fastdaq_time[:-1][led_switch_on]
            led_switch_off_time = fastdaq_time[:-1][led_switch_off]
        else:
            led_switch_on_time = np.zeros(0)
            led_switch_off_time = np.zeros(0)
    except:
        return out

    for i_piezo in range(piezo_list.shape[0]):
        try:

            raw_piezo = ev["fastDAQ"][piezoname_list[i_piezo]]
            filtered_piezo = BandPass2(raw_piezo - np.mean(raw_piezo[:meansamp]), f_low, f_high)
            led_k = 1./led_tau
            piezo_led_on = np.sum((fastdaq_time[:, None] > led_switch_on_time) *
                                  np.exp(led_k * np.minimum(led_switch_on_time -
                                                            fastdaq_time[:, None],
                                                            np.float64([0]))),
                                  axis=1)
            piezo_led_off = np.sum((fastdaq_time[:, None] > led_switch_off_time) *
                                   np.exp(led_k * np.minimum(led_switch_off_time -
                                                             fastdaq_time[:, None],
                                                             np.float64([0]))),
                                   axis=1)

            filtered_piezo_led_on = BandPass2(piezo_led_on, f_low, f_high)
            filtered_piezo_led_off = BandPass2(piezo_led_off, f_low, f_high)
            fit_func = lambda x, on_amp, off_amp: on_amp*filtered_piezo_led_on[x] + off_amp*filtered_piezo_led_off[x]
            tdata = np.arange(0, bs_win_ix[1])
            ydata = filtered_piezo[tdata]
            x0_guess = np.array([1., -1.])
            led_amp, conv = optimize.curve_fit(fit_func, tdata, ydata, x0_guess)

            yd = filtered_piezo - (led_amp[0]*filtered_piezo_led_on + led_amp[1]*filtered_piezo_led_off)
            led_only = led_amp[0] * piezo_led_on + led_amp[1] * piezo_led_off
            out["led_switch_on_amp"][i_piezo] = led_amp[0]
            out["led_switch_off_amp"][i_piezo] = led_amp[1]
            out["led_tau"][i_piezo] = led_tau
            peak_index = np.argmax(np.abs(yd[t0_win_ix[0]:t0_win_ix[1]])) + t0_win_ix[0]
            out["peak_t0"][i_piezo] = fastdaq_time[peak_index]
            t0 = calculate_t0(piezo_waveform=raw_piezo - led_only, piezo_timebase=fastdaq_time,
                              tau=tau, led_on=led_on, lower=corr_lowerf, upper=corr_upperf,
                              piezo_fit_type=piezo_fit_type)
            if abs(t0) < 10e-6:
                t0 = np.nan # Then it's essentially 0
            if abs(t0-fastdaq_time[0]) < 10e-6:
                t0 = np.nan
            out["bubble_t0"][i_piezo] = t0
            t0_index = closest_index(fastdaq_time, t0)

            out["piezoE"][i_piezo,:,:] = CalcPiezoE(raw_piezo - led_only, fastdaq_time,
                                                   t_wins, f_bins, fastdaq_time[t0_index])

        except:
            continue
    return out

if __name__ == "__main__":
    import os
    from SBCcode.DataHandling.GetSBCEvent import GetEvent as GE
    events = {#"20171006_3": [38],
              "20171007_6": [9,10,11,12],
              }
    raw_dir = "/bluearc/storage/SBC-17-data/"
    tau = 0.0038163479219674467
    out = []
    for k,v in events.items():
        ev_path = os.path.join(raw_dir, k)
        for ev in v:
            ev_data = GE(ev_path, ev, "fastDAQ")
            out.append(AcousticAnalysis(ev_data, tau))

    for x in out:
        print(x["bubble_t0"])


import argparse
import codecs
import json
import jieba
import os
import logging
import pickle
from sklearn import metrics
from sklearn.metrics import hamming_loss
import tensorflow as tf
import numpy as np
import matplotlib
matplotlib.use('Agg')
from matplotlib import cm
from matplotlib import pyplot as plt
from sklearn.preprocessing import MultiLabelBinarizer
from gensim.models.word2vec import Word2Vec
from sklearn.model_selection import train_test_split
# from bn_lstm import LSTMCell, BNLSTMCell
# from model_components import task_specific_attention, bidirectional_rnn, relation, soft_max_with_t
import tensorflow.contrib.layers as layers
try:
  from tensorflow.contrib.rnn import RNNCell
except ImportError:
  RNNCell = tf.nn.rnn_cell.RNNCell
try:
    from tensorflow.contrib.rnn import LSTMStateTuple
except ImportError:
    LSTMStateTuple = tf.nn.rnn_cell.LSTMStateTuple
try:
    from tensorflow.contrib.rnn import GRUCell, MultiRNNCell, DropoutWrapper
except ImportError:
    MultiRNNCell = tf.nn.rnn_cell.MultiRNNCell
    GRUCell = tf.nn.rnn_cell.GRUCell

class Configs(object):
    def __init__(self):
        # ------parsing input arguments"--------
        parser = argparse.ArgumentParser()

        parser.add_argument('--data_dir', type=str, default="data/small")
        parser.add_argument('--save_name', type=str, default="rmsc")
        parser.add_argument('--random_seed', type=int, default=1)
        parser.add_argument('--use_bn', type=bool, default=False)
        parser.add_argument('--gpu', type=str, default='1')
        parser.add_argument('--kp', type=float, default=1.0)
        parser.add_argument('--batch_size', type=int, default=128)
        parser.add_argument('--use_birnn', type=bool, default=True)
        parser.add_argument('--cut_prob', type=float, default=0.2,
                            help='output a label if its probability is above cut_prob')

        parser.add_argument('--epoch_len', type=int, default=100)
        parser.add_argument('--start_eval_epoch', type=int, default=20)
        parser.add_argument('--optim', type=str, default='adam')
        parser.add_argument('--learning_rate', type=float, default=1e-3, )
        parser.add_argument('--decay_rate', type=float, default=1,
                            help='')
        parser.add_argument('--decay_steps', type=int, default=1000,
                            help='')

        # label graph
        parser.add_argument('--use_rel',  default=False, type=bool, help='whether use label graph ')
        parser.add_argument('--pre_rel', default=False, type=bool,
                            help='whether use label graph before sigmoid')
        parser.add_argument('--lg_init_noise', type=float, default=0,
                            help='add noise to the identity matrix during the label graph initialization')
        parser.add_argument('--ratio2', type=float, default=0,
                            help=' rel loss rate aggregate the label graph by adding  -||G-I||^2 to the loss function')

        # soft training
        parser.add_argument('--soft_target', default=False, type=bool,
                            help='whether use a continuous target as the second supervisor')
        parser.add_argument('--stop_gradient', default=True,
                            help="whether stop gradient (y'= stop_gradient(y*G))")
        parser.add_argument('--ratio1', type=float, default=1.0, help='loss += ratio1 * soft_target_loss')
        parser.add_argument('--temperature', type=int, default=0,
                            help='whether use temperature to soften the continuous target, default 0 is not to soft')

        parser.set_defaults(shuffle=True)
        self.args = parser.parse_args()
        #  ---- to member variables -----
        for key, value in self.args.__dict__.items():
            if key not in ['test', 'shuffle']:
                exec('self.%s = self.args.%s' % (key, key))

cfg = Configs()

# label graph
use_rel=cfg.use_rel
pre_rel = cfg.pre_rel
ratio2 = cfg.ratio2
lg_init_noise = cfg.lg_init_noise

# second signal
soft_target = cfg.soft_target
ratio1 = cfg.ratio1  # soft target loss
stop_gradient = cfg.stop_gradient
temperature = cfg.temperature

# base hyper params
random_seed = cfg.random_seed
learning_rate = cfg.learning_rate
use_bn = cfg.use_bn
cut_prob = cfg.cut_prob
data_dir = cfg.data_dir
epoch_len = cfg.epoch_len
start_eval_epoch = cfg.start_eval_epoch
kp = cfg.kp
sentence_out_size = 100
word_level_out = 100
units_num = 128
use_birnn = cfg.use_birnn
batch_size = cfg.batch_size
comments_num = 40
embed_dim = 100

# save dir
save_name = cfg.save_name

save_name = save_name
if cut_prob != 0.2:
    save_name += "_prob-"+str(cut_prob)
if learning_rate != 0.001:
    save_name += "_lr-" + str(learning_rate)
if cfg.optim != 'adam':
    save_name += '_optim-' + str(cfg.optim)
if cfg.random_seed != 1:
    save_name += '_seed-' + str(random_seed)
if cfg.decay_rate < 1:
    save_name += '_dr-' + str(cfg.decay_rate)
    save_name += '_ds-' + str(cfg.decay_steps)
if use_rel:
    save_name += "_ur"
    if pre_rel:
        save_name += "_pr"
    if lg_init_noise != 0:
        save_name += "_n-" + str(lg_init_noise)
    if ratio2 > 0:
        save_name += '_r2-' + str(ratio2)
    if soft_target:
        save_name += '_st'
        save_name += "_r1-" + str(ratio1)
        if temperature > 0:
            save_name += "_t-" + str(temperature)
        if not stop_gradient:
            save_name += "_nst"
save_dir = os.path.join("checkpoints", save_name)
if not os.path.exists(save_dir):
    os.mkdir(save_dir)
f_log = codecs.open(os.path.join(save_dir, 'log.txt'), 'w+', encoding='utf-8')

os.environ["CUDA_VISIBLE_DEVICES"] = cfg.gpu
tf.set_random_seed(random_seed)
np.random.seed(random_seed)
songs = os.listdir(data_dir)
total_tags = []
all_comments_list = []
total_song_comments_and_tags = []
len_songs = len(songs)

for song in songs:
    with codecs.open(data_dir+'/'+song, 'r+', encoding='utf-8') as f:
        a = f.read()
        dict_f = json.loads(a)
        every_song_comment_for_lstm_train = []
        all_comments_dict = dict_f['all_short_comments'][0:40]
        for comment_dict in all_comments_dict:
            every_comment = comment_dict["comment"]
            every_comment_cut = "/".join(jieba.cut(every_comment, cut_all=False)).split('/')    # cur comment
            every_song_comment_for_lstm_train.append(every_comment_cut)     # [[pl1],[pl2],...]
        every_song_comments_and_tags = {"tags": dict_f['tags'], "comments": every_song_comment_for_lstm_train}
        all_comments_list.extend(every_song_comment_for_lstm_train)     # get all comments
        total_tags.extend(dict_f['tags'])  # get all classes
        total_song_comments_and_tags.append(every_song_comments_and_tags)  # all tags and comments
print(len(songs))
print(len(total_song_comments_and_tags))
sorted_total_tags = sorted(list(set(total_tags)))   # all tags
del total_tags
tags_num = len(sorted_total_tags)

# word2vec
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
model = Word2Vec(all_comments_list, workers=4, min_count=1, seed=random_seed)
model.save("data/word2vec.model")
del all_comments_list
print("model info :", model)

# map
dict_tag = {}
for i in range(tags_num):
    dict_tag[sorted_total_tags[i]] = i+1

def give_embedding(word):
    return model[word]

def tag_emb(tag):
    return dict_tag[tag]

# labels_origin = np.zeros((len_songs, 8))
labels_origin = []
sentence_long = 20
embed_input = np.zeros((len_songs, comments_num, sentence_long, embed_dim))
# get input and label
# word embedding
len_every_comment_cutted = np.zeros((len_songs, comments_num))
sum_comment_count = 0
for i in range(len_songs):
    every_song_comment_words_embedding = np.zeros((comments_num, sentence_long, embed_dim))
    all_comments_in_every_song = total_song_comments_and_tags[i]["comments"]
    for j in range(len(all_comments_in_every_song)):
        every_comment_in_one_song = np.array(list(map(give_embedding, all_comments_in_every_song[j])))
        every_comment_embedding = np.zeros((sentence_long, embed_dim))
        count_cur_comment = len(every_comment_in_one_song)
        sum_comment_count += count_cur_comment
        if count_cur_comment < sentence_long:
            len_every_comment_cutted[i, j] = count_cur_comment
            every_comment_embedding[0:count_cur_comment] = every_comment_in_one_song
        else:
            every_comment_embedding = every_comment_in_one_song[0:sentence_long]
            len_every_comment_cutted[i, j] = sentence_long
            # print(count_cur_comment)
        every_song_comment_words_embedding[j] = every_comment_embedding
    embed_input[i] = every_song_comment_words_embedding
    every_song_comment_tags_embedding = np.array(list(map(tag_emb, total_song_comments_and_tags[i]["tags"])))
    labels_origin.append(every_song_comment_tags_embedding)
del total_song_comments_and_tags
print("average comment length", sum_comment_count/(len_songs*comments_num))
labels = MultiLabelBinarizer().fit_transform(labels_origin)
del labels_origin
de_rate = 0
soft_labels = (1-de_rate) * labels + de_rate*(1-labels)
print(labels)
len_labels = len(labels)
# split the data
x_train, x_test_valid, y_train, y_test_valid, sequence_train, sequence_test_valid, songs_train, songs_test_valid = \
    train_test_split(embed_input, soft_labels, len_every_comment_cutted, songs, test_size=0.3, random_state=random_seed)
del soft_labels
del embed_input
del len_every_comment_cutted
x_test, x_valid, y_test, y_valid, sequence_test, sequence_valid, songs_test, songs_valid = train_test_split(x_test_valid, y_test_valid, sequence_test_valid, songs_test_valid, test_size=0.3, random_state=random_seed)
label_train, label_test_valid = train_test_split(labels, test_size=0.3, random_state=random_seed)
label_test, label_valid = train_test_split(label_test_valid, test_size=0.3, random_state=random_seed)

f_label_train = open('data/label_train.pickle', 'wb')
pickle.dump(label_train, f_label_train)
f_label_valid = open('data/label_valid.pickle', 'wb')
pickle.dump(label_valid, f_label_valid)
f_label_test = open('data/label_test.pickle', 'wb')
pickle.dump(label_test, f_label_test)

f_x_train = open('data/x_train.pickle', 'wb')
pickle.dump(x_train, f_x_train)
f_x_valid = open('data/x_valid.pickle', 'wb')
pickle.dump(x_valid, f_x_valid)
f_x_test = open('data/x_test.pickle', 'wb')
pickle.dump(x_test, f_x_test)

f_y_train = open('data/y_train.pickle', 'wb')
pickle.dump(y_train, f_y_train)
f_y_valid = open('data/y_valid.pickle', 'wb')
pickle.dump(y_valid, f_y_valid)
f_y_test = open('data/y_test.pickle', 'wb')
pickle.dump(y_test, f_y_test)

f_sorted_total_tags = open('data/sorted_total_tags.pickle', 'wb')
pickle.dump(sorted_total_tags, f_sorted_total_tags)

f_sequence_train = open('data/sequence_train.pickle', 'wb')
pickle.dump(sequence_train, f_sequence_train)
f_sequence_valid = open('data/sequence_valid.pickle', 'wb')
pickle.dump(sequence_valid, f_sequence_valid)
f_sequence_test = open('data/sequence_test.pickle', 'wb')
pickle.dump(sequence_test, f_sequence_test)

f_songs_test = open('data/songs_test.pickle', 'wb')
pickle.dump(songs_test, f_songs_test)
f_songs_valid = open('data/songs_valid.pickle', 'wb')
pickle.dump(songs_valid, f_songs_valid)
f_songs_train = open('data/songs_train.pickle', 'wb')
pickle.dump(songs_train, f_songs_train)


import requests,time
from lxml import etree
from datetime import datetime
from common import UID,HandleTmpList,parseContentToName,ProductToGroup
SPIDERNAME='期货日报'
def parseQHRBArtPubTime(string):
    #5月8日 9:37

    time_string=datetime.now().strftime('%Y-')+string.strip()
    struct_time = datetime.strptime(time_string, '%Y-%m月%d日 %H:%M')
    return struct_time.strftime('%Y-%m-%d %H:%M:%S')

def parseQHRBArtContent(url):
    r=requests.get(url)
    r.encoding='utf8'
    selector=etree.HTML(r.text)
    try:
        ele=selector.cssselect("div.article-content")[0]
        content=ele.xpath("string(.)").strip().strip('\n')
    except IndexError as e:
        print('网页内容为空',url)
        content=''
    # print(content)
    return content

def getQHRBArticleList(articleCol,BeCrawledUrlList):
    #农产品
    url1='http://www.qhrb.com.cn/farm/'
    #金属
    url2='http://www.qhrb.com.cn/metal/'
    #能源化工
    url3='http://www.qhrb.com.cn/energy/'
    #实市场告
    url4='http://www.qhrb.com.cn/comment/scbg/'

    for url in (url1,url2,url3,url4):
        r=requests.get(url)
        r.encoding='utf8'    #不做任何设置的时候，正确
        selector=etree.HTML(r.text)
        #之前好几年的内容放在一页，只取5*12条
        eleList=selector.cssselect(".list-point li.item")[:600]
        temp_article_ls=[]
        for ele in  eleList:
            # time.sleep(0.5)
            articleUrl=ele.xpath("./a/@href")[0]
            #判断是否已经爬取过，如果是，跳出循环
            if articleUrl in BeCrawledUrlList:break
            title=ele.xpath('./a/text()')[0]
            try:
                publicTime=parseQHRBArtPubTime(ele.xpath('./span/text()')[0])
            except:
                print(url,'   ',title,'   找不到时间字符串')

            temp_dict={'tags':['期货日报'],'score':0,'uid':UID()}
            temp_dict['title']=title.strip()
            temp_dict['articleFrom']='期货日报'
            temp_dict['url']=articleUrl.strip()
            temp_dict['publicTime']=publicTime.strip()
            #文章内容
            content=parseQHRBArtContent(articleUrl)
            temp_dict['content']=content
            #定文章所属期货品种,板块
            n=parseContentToName(title+content)

            if n:
                temp_dict['product_name']=n
                print(SPIDERNAME,'   ',title,"    ",n)
                temp_dict['group']=ProductToGroup[n]
            else:
                print("………………………………未找到品种名称，可能异常")

                temp_dict['product_name']=''
                temp_dict['group']=''

            temp_article_ls.append(temp_dict)

        #注意缩进不要错
        HandleTmpList(temp_article_ls,articleCol,SPIDERNAME)
        # print('mysteel: %d  条'%articleCol.count_documents({'from':'mysteel'}))


import backoff
import json
from http import HTTPStatus

from fastapi import APIRouter, Depends, HTTPException, Request
from typing import List

from core.config import HTTP_RETIES
from models.film import Film, FilterParams, ResponseMessage
from services.film import FilmService, get_film_service

router = APIRouter()

@backoff.on_exception(backoff.expo, HTTPException, max_tries=HTTP_RETIES)
@router.get('/search', response_model=List[Film],
            response_model_include={'id', 'title', 'imdb_rating'},
            summary="Поиск кинопроизведений",
            description="Полнотекстовый поиск по кинопроизведениям",
            response_description="Название и рейтинг фильма",
            tags=['Полнотекстовый поиск'])
async def search_film_list(
        request: Request,
        film_service: FilmService = Depends(get_film_service)
) -> List[Film]:
    _filters: FilterParams = request.state.filter_params
    pagination_params = _filters.dict(include={'sort', 'size', 'from_'})
    if _filters.query:
        body = json.dumps({"query": {"query_string": {"query": _filters.query,  "fuzziness": "auto"}}})
    else:
        body = None

    films = await film_service.get_all_from_elastic(body=body, params=pagination_params)
    return films

@backoff.on_exception(backoff.expo, HTTPException, max_tries=HTTP_RETIES)
@router.get('/{film_id}', response_model=Film,
            summary="Информация по фильму",
            description="Подробная информация по uuid фильма",
            response_description="Название, жанры и рейтинг фильма, актёры, режиссёры и сценаристы, принявшие участие",
            responses={
                404: {
                    'model': ResponseMessage,
                    'description': 'Film wasn\'t found'
                },
            }
            )
async def film_details(
        film_id: str,
        film_service: FilmService = Depends(get_film_service)
):
    film = await film_service.get_by_id(film_id)
    if not film:
        # если фильм не найден то отдаем 404 статус
        # желательно пользоваться уже определенными enum содержащие HTTP статусы. Такой код будет более поддерживаемым
        raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail='film not found')

    # перекладываем данные из models.Film в Film
    # обратите внимание, что модель бизнес логики имеет поле description которое отсутствует в модели ответа API.
    # Если бы использовалась общая модель для бизнес логики и формирования ответов API, то мы предоставляли клиентам
    # данные которые им не нужны и возможно данные которые опасно возвращать.
    return film

@backoff.on_exception(backoff.expo, HTTPException, max_tries=HTTP_RETIES)
@router.get('/', response_model=List[Film],
            response_model_include={'id', 'title', 'imdb_rating'},
            summary="Список фильмов",
            description="Список фильмов, отсортированных по жанру, если он передан",
            response_description="Список фильмов, количество фильмов на странице, номер страницы, "
                                 "параметр сортировки передаётся как kwargs",
            )
async def film_list(
        request: Request,
        film_service: FilmService = Depends(get_film_service),
        genre: str = None
) -> List[Film]:
    _filters: FilterParams = request.state.filter_params
    pagination_params = _filters.dict(include={'sort', 'size', 'from_'})

    body = json.dumps({"query": {"match": {"genre": {"query": genre, "fuzziness": "auto"}}}}) if genre else None
    films = await film_service.get_all_from_elastic(body=body, params=pagination_params)
    return films


import logging
import os
from logging.handlers import RotatingFileHandler

import click
from flask import Flask, request, jsonify
from flask_sqlalchemy import get_debug_queries

from app.settings import config
from app.extensions import db, migrate
from app.apis.test import api_test
from app.models.test_model import TestModel
from app.utils.exceptions import NewError

basedir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))

def create_app(config_name=None):
    if config_name is None:
        config_name = os.getenv("FLASK_CONFIG", "development")

    app = Flask("app")
    app.config.from_object(config[config_name])

    register_extensions(app)
    register_blueprints(app)
    register_commands(app)
    register_shell_context(app)
    register_logging(app)
    register_errors(app)
    register_request_handlers(app)
    return app

def register_extensions(app):
    db.init_app(app)
    migrate.init_app(app, db)

def register_blueprints(app):
    app.register_blueprint(api_test)

def register_commands(app):
    @app.cli.command()
    @click.option("--drop", is_flag=True, help="Create after drop.")
    def initdb(drop):
        """Initialize the database."""
        if drop:
            click.confirm(
                "This operation will delete the database, do you want to continue?",
                abort=True,
            )
            db.drop_all()
            click.echo("Drop tables.")
        db.create_all()
        click.echo("Initialized database.")

def register_shell_context(app):
    @app.shell_context_processor
    def make_shell_context():
        return dict(db=db, TestModel=TestModel)

def register_logging(app):
    class RequestFormatter(logging.Formatter):
        def format(self, record):
            record.url = request.url
            record.remote_addr = request.remote_addr
            return super(RequestFormatter, self).format(record)

    request_formatter = RequestFormatter(
        "[%(asctime)s] %(remote_addr)s requested %(url)s\n"
        "%(levelname)s in %(module)s: %(message)s"
    )

    formatter = logging.Formatter(
        "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    )

    info_file_handler = RotatingFileHandler(
        os.path.join(basedir, "logs/info.log"),
        maxBytes=10 * 1024 * 1024,
        backupCount=10,
    )
    info_file_handler.setFormatter(formatter)
    info_file_handler.setLevel(logging.INFO)

    error_file_handler = RotatingFileHandler(
        os.path.join(basedir, "logs/info.log"),
        maxBytes=10 * 1024 * 1024,
        backupCount=10,
    )
    error_file_handler.setFormatter(formatter)
    error_file_handler.setLevel(logging.ERROR)

    # mail_handler = SMTPHandler(
    #     mailhost=app.config['MAIL_SERVER'],
    #     fromaddr=app.config['MAIL_USERNAME'],
    #     toaddrs=['ADMIN_EMAIL'],
    #     subject='Application Error',
    #     credentials=(app.config['MAIL_USERNAME'], app.config['MAIL_PASSWORD']))
    # mail_handler.setLevel(logging.ERROR)
    # mail_handler.setFormatter(request_formatter)

    app.logger.addHandler(info_file_handler)
    if not app.debug:
        app.logger.addHandler(error_file_handler)
        # app.logger.addHandler(mail_handler)

def register_errors(app):
    @app.errorhandler(500)
    def internal_server_error(e):
        return jsonify("internal server error"), 500

    @app.errorhandler(NewError)
    def new_error(e):
        return jsonify("new error"), 400

def register_request_handlers(app):
    @app.after_request
    def query_profiler(response):
        for q in get_debug_queries():
            if q.duration >= app.config['BLUELOG_SLOW_QUERY_THRESHOLD']:
                app.logger.warning(
                    'Slow query: Duration: %fs\n Context: %s\nQuery: %s\n '
                    % (q.duration, q.context, q.statement)
                )
        return response


import scipy.ndimage as spnd
import scipy.misc as misc
import numpy as np
import pylab
from util import load_image, plot_image

p = 'D:\\Dropbox\\Computer Vision\\code\\c3\\data.png'
p2 = 'D:\\Dropbox\\Computer Vision\\code\\c3\\data2.jpg'

def cv1_test_function():
    x = np.linspace(-10, 10, 100)
    y = np.sin(x) / x
    pylab.plot(x, y)
    pylab.show()

def cv2_test_interpolate():
    im = load_image(p)
    out1 = misc.imresize(im, 1000, interp='nearest')
    out2 = misc.imresize(im, 1000, interp='bilinear')
    out3 = misc.imresize(im, 1000, interp='bicubic')
    plot_image(ims=[out1, out2, out3], title=[
               'nearest', 'bilinear', 'bicubic'], col=2)

def _sub_sampling(img, s=2):
    out1 = []
    for index, row in enumerate(img):
        if index % s != 0:
            continue
        tem = []
        for j, elem in enumerate(row):
            if j % s != 0:
                continue
            tem.append(elem)
        out1.append(tem)
    return np.array(out1, np.float32)

def _gau_filter(img):
    sigma = 1
    x, y = len(img), len(img[0])
    out1 = np.zeros((x, y))
    spnd.filters.gaussian_filter(input=img, sigma=sigma, output=out1)
    return out1

def cv2_test_subsampling():
    im = load_image(p2)
    out1 = _sub_sampling(im, s=5)
    gau = _gau_filter(im)
    out2 = _sub_sampling(gau, s=5)
    plot_image(ims=[im, out1, out2], title=[
               'origin', 'subsampling', 'gaussian + subsampling'], col=2)

# cv1_test_function()
cv2_test_interpolate()
# cv2_test_subsampling()


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

############### VERSION 2 ###############
#version2: ajout de la fonction offset
#version2.1: modification des legendes. Inclusion de la frequence et amplitude à chaque fois
############### VERSION 3 ###############
#version3: ajout de la fonction auto_offset
#version3.1: ajout de liste des courbes à tracer
#version3.2(20151103): ajustement de l'échelle aux courbes tracées uniquement
#version3.3(20151105): permet de traiter des .dat avec des quantités variables de colonnes
############### VERSION 4 ###############
#version4.0(20151105): refonte de l'organisation du code source pour corriger certains bugs:
#		les courbes non tracées (non nommées dans tracer() ne sont pas traitées du tout et donc
#		évite certains messages d'erreurs
#version4.1(20151105): permet de sélectionner des fichiers avec une extension autre que .dat
#version4.2(20151123): permet le choix de l'unité de l'amplitude du signal d'entrée
#version4.3(20151207): correction mineures des informations affichées dans la console
#version4.4(20160113): change la façon de titrer les graphs .png pour permettre un .png par combinaison de courbes tracées
#version4.5(20160122): permet la désactivation de l'option print graph in .png
############### VERSION 5 ###############
#version5.0(20160122): permet de tracer plusieurs colonnes d'un même fichier (ou de plusieurs fichiers) sur un même graph
#version5.1(20160205): correction de la matrice donnees_exp qui n'était pas remplie correctement dans le code

############### AMELIORATIONS POSSIBLES ###############
# utilisation de l'option '0' en id courbe pour appliquer offset à toutes les courbes pour la colonne souhaitée
# utilisation de la fonction interpolation de scipy pour manipuler des fonctions plutôt que des matrices de données
from scipy import *
from pylab import *
import matplotlib.pyplot as plt
import glob, inspect, os

# NE MODIFIER QUE LES VARIABLES ENTRES LES BARRES #
#######################################################
################## PEUT ETRE MODIFIE ##################
##################VVVVVVVVVVVVVVVVVVV##################

extension='.dat'	#extension des fichiers à considérer pour tracer les courbes (inclure le .)
print_graph='non'	#'oui'/'non' pour générer ou non une copie .png
delimiteur=''		#rien par default
tracer=[0]			#tout tracer: 0, sinon liste [1,2,3,5,8,...] AVEC CROCHETS

#informations relatives aux fichiers de données
data_set_up=5	#nombre de premières lignes ignorées dans le fichier de données .dat
data_set_low=0	#nombre de dernières lignes ignorées dans le fichier de données .dat
data_x_axis=1	#colonne de données correspondant aux abscisses
data_y_axis=[4]	#colonne(s) de données correspondant aux ordonnées (garder les crochets)
col_freq=6		#colonne où est indiquée la fréquence des mesures
col_amp=8		#colonne où est indiquée l'amplitude des mesures
unit_amp='V'	#unité de l'amplitude du signal en entrée

#informations relatives aux tracés
titref="default title: x-axis --> column " +str(data_x_axis) + " y-axis --> column " +str(data_y_axis) + " of " + extension + " files in folder"
nom_axe_x='Temperature (K)'
nom_axe_y='Magnitude (V)'
grille='oui'

#informations relative au traitement des données
liste_offset=['non',(2,2,3,2),(2,3,0,3)] #si offset[0]='oui', 1er chiffre du tuple --> id courbe, 2e --> id colonne, 3e --> offset X, 4e --> offset Y
								# le nombre de tuples ne peux pas être supérieur on nombre de .dat dans le dossier
auto_offset=('non', 0) #pour mettre un offset à toutes les courbes de telle sorte qu'elles commencent toutes
							# au point d'ordonnée indiqué. Cette option est maîtresse sur liste_offset (y seulement).

###/ \#################################################/ \###  ||
##/ | \############### NE PAS MODIFIER ###############/ | \##  ||
#/__°__\#############VVVVVVVVVVVVVVVVVVV#############/__°__\# _||_
															# \  /
															#  \/

# supprime les doublons dans tracer et data_y_axis s'il y a
tracer=list(set(tracer))
data_y_axis=list(set(data_y_axis))
liste_offset=list(set(liste_offset))

script_dir=os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))+'/'	# to get the path to the directory containing the script and the data
liste_fichiers=glob.glob(script_dir+'*'+extension)	#list of all .dat files in script_dir

######## VARIABLES DES QUANTITES A TRACER ########
nombre_fichiers=len(liste_fichiers)	#number of files in directory
nombre_colonnes=len(data_y_axis)	#number of columns to plot

######## OPERATION SUR TRACER ########
# on sort de tracer tous les élément >nombre_fichiers et <0
if max(tracer)>nombre_fichiers:
	while max(tracer)>nombre_fichiers:
		tracer.remove(max(tracer))
if min(tracer)<0:
	while min(tracer)<0:
		tracer.remove(min(tracer))

# si alors il ne reste plus aucun élément dans tracer ou si 0 dans tracer, on trace toutes les courbes
if len(tracer)==0 or (0 in tracer):
	tracer=list(arange(nombre_fichiers)+1)

nombre_courbes=len(tracer)			#number of files to plot

######## AFFICHAGE INFO ########
print('---> '+str(nombre_courbes)+' '+extension+' to plot')
print('---> '+str(nombre_colonnes)+' columns to plot per '+extension)

######## COLONNES A TRACER ########
plot_cols=[data_x_axis-1]	# creates the list of the columns that must be ploted with the x column

for i in data_y_axis:	# adds the other columns that must be ploted
	plot_cols.append(i-1)

######## DEFINITION FONCTIONS TRAITEMENT ########
# fonction importation des données des axes à tracer:
def import_axe_data(nom_fichier, delimiteur, data_set_up, data_set_low, plot_cols):
	# Import the data from a text file and save as a 2D matrix. Adapter le 'skip_header' au .dat
	print("---> fichier", extension, "en cours de traitement :", nom_fichier)
	return genfromtxt(nom_fichier, delimiter=delimiteur, skip_header=data_set_up, skip_footer=data_set_low, usecols=plot_cols)#stock que les données utilisées

# fonction importation des données relatives aux conditions expérimentales:
def import_exp_data(nom_fichier, delimiteur, data_set_up, data_set_low, col_freq, col_amp):
	matrice_donnees_exp=zeros((2,1)) #stock la fréquence (ligne0) et l'amplitude (ligne1)
	#on utilise genfromtxt à 2 endroits différents du fichier données usecols(col_freq-1 et col_amp-1) car ces colonnes peuvent être de longueur différentes
	matrice_donnees_exp[0] = genfromtxt(nom_fichier, delimiter=delimiteur, skip_header=data_set_up, skip_footer=data_set_low, usecols=(col_freq-1))[0]#stock la fréquence
	matrice_donnees_exp[1] = genfromtxt(nom_fichier, delimiter=delimiteur, skip_header=data_set_up, skip_footer=data_set_low, usecols=(col_amp-1))[0]#stock l'amplitude
	return matrice_donnees_exp

######## REMPLISSAGE LISTE DE MATRICES DONNEES ########
donnees=[]	# initialisation de la liste des matrices de données des courbes à tracer
# autant de matrices sont crées qu'il y a de courbes à tracer et elles sont rangées dans donnees
# pour accéder à la matrice d'une courbe: donnees[tracer.index(i)]
for i in tracer:
	donnees.append(import_axe_data(liste_fichiers[i-1], delimiteur, data_set_up, data_set_low, plot_cols))

######## SI IL FAUT AJOUTER UN OU DES OFFSET ########
#fabrication et initialisation matrice des offsets
offset=array(zeros((len(tracer)+1,nombre_colonnes+2)),str)	# crée une matrice de nombre de courbes à tracer +1 lignes et nombre de colonnes à tracer +2 colonnes
offset[0,0]='id courbe'	# titre 1ere colonne
offset[0,1]='offset X'	# titre 2e colonne
for i in data_y_axis:
	offset[0,data_y_axis.index(i)+2]='offset Y'+str(i)	# titre des autres colonnes

for i in tracer:
	offset[tracer.index(i)+1,0]=i	#remplit l'id fichier dans chacunes des matrices offset

# cas où liste_offset[0]=='oui' et auto_offset[0]!='oui'
if ('oui' in liste_offset or 'Oui' in liste_offset or 'OUI' in liste_offset or 'O' in liste_offset or 'o' in liste_offset) and ('oui' not in auto_offset and 'Oui' not in auto_offset and 'OUI' not in auto_offset and 'O' not in auto_offset and 'o' not in auto_offset):
	for i in liste_offset[1:]:
		if (i[0] in tracer) and (i[1] in data_y_axis):		# seulement si demandé dans data_y_axis et tracer
			offset[tracer.index(i[0])+1,1]=i[2]	# remplit offset X
			offset[tracer.index(i[0])+1,data_y_axis.index(i[1])+2]=i[3]	# remplit offset Y pour la colonne donnée par i[1]

# cas où auto_offset[0]=='oui'
if 'oui' in auto_offset or 'Oui' in auto_offset or 'OUI' in auto_offset or 'O' in auto_offset or 'o' in auto_offset:
	for i in tracer:		# pour chacune des courbes à tracer (indiquées dans tracer)
		for j in data_y_axis:	# pour chaque colonne à tracer (EXCLUANT X)
			# on change les offset en y seulement dans la matrice offset
			offset[tracer.index(i)+1,data_y_axis.index(j)+2]= auto_offset[1]-donnees[tracer.index(i)][0][data_y_axis.index(j)+1]

######## AJOUT OFFSET AUX DONNEES ########
donnees_off=donnees	# duplication de donnees pour creer donnees_off qui est la matrice des données avec offset
# il faut maintenant ajouter les offset à donnees_off si nécessaire (i.e. si offset ou auto_offset est 'oui')
if ('oui' in liste_offset or 'Oui' in liste_offset or 'OUI' in liste_offset or 'O' in liste_offset or 'o' in liste_offset) or ('oui' in auto_offset or 'Oui' in auto_offset or 'OUI' in auto_offset or 'O' in auto_offset or 'o' in auto_offset):
	for i in tracer:
		donnees_off_temp=array(donnees_off[tracer.index(i)])	# étape nécessaire pour manipuler les objets de la liste donnees_off comme de vraies matrices et permettre les sommes sur les colonnes/lignes
		for j in plot_cols:
			donnees_off_temp[:,plot_cols.index(j)]+=float(offset[tracer.index(i)+1,plot_cols.index(j)+1])	# on travaille sur donnees_off_temp qui est de type array et permet donc les sommes sur ligne/colonne entière
			donnees_off[tracer.index(i)]=donnees_off_temp	# on remplace la matrice de la courbe i par les données avec offset
# exemple pour sommer sur colonnes :
#>>> A
#array([[1, 1, 1],
#       [2, 2, 2],
#       [3, 3, 3]])
#>>> B=A
#>>> B[:,0]=B[:,0]+4	# ou bien B[:,0]+=4
#>>> B
#array([[5, 1, 1],
#       [6, 2, 2],
#       [7, 3, 3]])

######## OPERATION SUR LES AXES ########
# création des 2 matrices de stockage des échelles (une pour x et l'autre pour y)
xscale=zeros((nombre_courbes, 2))	# matrice des X min et max pour chaque fichier à tracer
yscale=zeros((nombre_courbes, nombre_colonnes, 2))	# matrices des Y min et max de chaque colonnes à tracer pour chaque fichier
# xscale=	[[xmin_courbe1, xmax_courbe1],
#			 [xmin_courbe4, xmax_courbe4],
#			 [xmin_courbe3, xmax_courbe3],...] si tracer=[1,4,3,...]

# yscale=	[[[y1min_courbe1, y1max_courbe1],[y3min_courbe1, y3max_courbe1]],
#			 [[y1min_courbe4, y1max_courbe4],[y3min_courbe4, y3max_courbe4]],
#			 [[y1min_courbe3, y1max_courbe3],[y3min_courbe3, y3max_courbe3]],...] si tracer=[1,4,3,...] et data_y_axis=[1,3]

# remplissage matrices échelles
for i in tracer:	# on traite fichier par fichier
	# on remplit xscale
	xscale[tracer.index(i),0]=min(array(donnees_off[tracer.index(i)])[:,0])
	xscale[tracer.index(i),1]=max(array(donnees_off[tracer.index(i)])[:,0])
	# on remplit yscale
	for j in data_y_axis:
		yscale[tracer.index(i),data_y_axis.index(j),0]=min(array(donnees_off[tracer.index(i)])[:,data_y_axis.index(j)+1])
		yscale[tracer.index(i),data_y_axis.index(j),1]=max(array(donnees_off[tracer.index(i)])[:,data_y_axis.index(j)+1])

######## TRAÇAGE COURBES ########
for i in tracer:
	#on importe les données des conditions expérimentales dans la matrice donnees_exp
	donnees_exp=import_exp_data(liste_fichiers[i-1], delimiteur, data_set_up, data_set_low, col_freq, col_amp)
	#obtention nom fichier sans chemin absolu (trop long)
	#1: on decoupe le chemin vers le fichier .dat en cours de traitement
	decoupage=liste_fichiers[i-1].split('/')	# decoupage est une liste d'éléments de chemin vers le .dat (chaque partie encadrée par / est un element de la liste)
	# coordonnées en X
	x = array(donnees_off[tracer.index(i)])[:,0]
	for j in data_y_axis:
		# coordonnées en Y
		y = array(donnees_off[tracer.index(i)])[:,data_y_axis.index(j)+1]
		# la suite sert à indiquer s'il y a un ou plusieurs offset sur la courbe en cours de traçage et de nommer les courbes en fonction
		if float(offset[tracer.index(i)+1,1])!=0 or float(offset[tracer.index(i)+1,data_y_axis.index(j)+2])!=0:
			label_courbe='graph '+str(tracer.index(i)+1)+'(col '+str(j)+'): '+decoupage[len(decoupage)-1]+'\n ---> f='+str(donnees_exp[0,0])+'Hz | Vo='+str(donnees_exp[1,0])+unit_amp+' | offset X='+offset[tracer.index(i)+1,1]+' | offset Y'+str(j)+'='+offset[tracer.index(i)+1,data_y_axis.index(j)+2]
		else:
			label_courbe='graph '+str(tracer.index(i)+1)+'(col '+str(j)+'): '+decoupage[len(decoupage)-1]+'\n ---> f='+str(donnees_exp[0,0])+'Hz | Vo='+str(donnees_exp[1,0])+unit_amp

		plt.plot(x,y,label=label_courbe) #on trace la courbe pour i
		print("\t ----traitement accompli sans erreur (courbe", i, "|colonne", j, "tracée)----")

#affiche la matrice des offset dans le terminal pour vérification par l'utilisateur
print('------------------------------------')
if 'oui' in liste_offset or 'Oui' in liste_offset or 'OUI' in liste_offset or 'O' in liste_offset or 'o' in liste_offset:
	if 'oui' in auto_offset or 'Oui' in auto_offset or 'OUI' in auto_offset or 'O' in auto_offset or 'o' in auto_offset:
		print('---> le mode liste des offset est ACTIF et les offset sont:\n', liste_offset)
		print('\n---> le mode auto offset est ACTIF et par conséquent les offset sur Y precedents ne sont par considérés.')
		print('\n---> matrice offset:\n', offset)
		titre = titref+'\n offset: ON | auto_offset: ON'
	else:
		print('---> le mode liste des offset est ACTIF et les offsets sont:\n', liste_offset)
		print('\n---> le mode auto offset est INACTIF.')
		print('\n---> matrice offset:\n', offset)
		titre = titref+'\n offset: ON | auto_offset: OFF'
else:
	if 'oui' in auto_offset or 'Oui' in auto_offset or 'OUI' in auto_offset or 'O' in auto_offset or 'o' in auto_offset:
		print('---> le mode liste des offset est INACTIF. Le mode auto offset est ACTIF.')
		print('\n---> matrice offset:\n', offset)
		titre = titref+'\n offset: OFF | auto_offset: ON'
	else:
		print('---> le mode liste des offset est INACTIF. Le mode auto offset est INACTIF.')
		print('\n---> matrice offset:\n', offset)
		titre = titref+'\n offset: OFF | auto_offset: OFF'

print('------------------------------------')

# on récupère les min et max pour x
xscale_up=max(xscale[:,1])
xscale_low=min(xscale[:,0])
# on récupère les min et max pour y pour toutes les colonnes
# mais pour cela il faut tester pour chaque fichier et colonne
yscale_low=[]
yscale_up=[]
for i in tracer:
	yscale_low.append(min(yscale[tracer.index(i),:,0]))
	yscale_up.append(max(yscale[tracer.index(i),:,1]))

# et on prend le min et max de yscale_low/up
yscale_low=min(yscale_low)
yscale_up=max(yscale_up)

#### ICI

xdelta=(xscale_up-xscale_low)/100
ydelta=(yscale_up-yscale_low)/100
plt.legend(fontsize=8, loc='best')
plt.title(titre)
plt.axis([xscale_low-xdelta, xscale_up+xdelta, yscale_low-ydelta, yscale_up+ydelta])
plt.xlabel(nom_axe_x)
plt.ylabel(nom_axe_y)
if grille=='oui' or grille=='OUI' or grille == 'Oui' or grille=='o' or grille=='O':
	plt.grid(True)
else:
	plt.grid(False)

if print_graph=='oui' or print_graph=='OUI' or print_graph == 'Oui' or print_graph=='o' or print_graph=='O':
#pour permettre de créer un .png par combinaison de courbes tracées et axes représentés
	titreplt="courbe"
	for i in tracer:
		titreplt+=str(i)+"-"
	titreplt+="Xaxis_col" +str(data_x_axis) +"__Yaxis_col"
	for j in data_y_axis:
		titreplt+=+str(j)
	plt.savefig(script_dir+titreplt)

plt.show()


from django.contrib.gis.geoip2 import GeoIP2

def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

def get_auth_stats(request):
    user_id = request.user.id
    ip = get_client_ip(request)
    if ip != '127.0.0.1':
        g = GeoIP2()
        country = g.country(ip)

        user_agent = request.META['HTTP_USER_AGENT']

        return {'user_id': user_id, 'ip': ip, 'country': country['country_code'], 'user_agent': user_agent}
    else:
        return False


"""
DEDA Unit 5
Basic Statistics and Visualisation in Python
Authors: Junjie Hu and Isabell Fetzer, 20220924 WKH
"""

"""
Interactive Graphs
"""
"""
Plotly enables Python users to create beautiful interactive visualisations.
"""
# pip install yfinance
from datetime import datetime, timedelta
import pandas as pd
import plotly.graph_objects as go
import yfinance as yf
import numpy as np

CURRENCY = 'EUR'
def getData(crypto):
  # Define time window
    now = datetime.now()
    current_date = now.strftime("%Y-%m-%d")
    last_year_date = (now - timedelta(days=365)).strftime("%Y-%m-%d")
    start = pd.to_datetime(last_year_date)
    end = pd.to_datetime(current_date)
    data = yf.download(tickers=f'{crypto}-{CURRENCY}', start = start, end = end , interval = '1d')
    return data

# Call function to retrieve data on Bitcoin
btc_data = getData('BTC')
# eth_data = getData('ETH')
# Plot graph
fig = go.Figure(
        data = [
            go.Candlestick(
                x = btc_data.index,
                open = btc_data.Open,
                high = btc_data.High,
                low = btc_data.Low,
                close = btc_data.Close
            )
        ] )
fig.update_layout(
    title = f'Time Series with Range slider for BTC',
    xaxis_title = 'Date',
    yaxis_title = f'Price ({CURRENCY})',
    xaxis_rangeslider_visible = True
)
fig.update_yaxes(tickprefix=CURRENCY)
fig.show()

"""
Generating numbers in numpy array
"""

# Giving the seed of random number generator
np.random.seed(1)
# Generate a 20*20 matrix with uniformly distributed random integers between 0 to 50
A = np.random.randint(low=0, high=50, size=(20, 20))
print(A)

"""
Matrix Operations
"""
"""
NumPy allows for many matrix operations.The inalg.inv() computes the (multiplicative) inverse of a matrix. The dot() method returns the dot product of two arrays. Identity() returns the identity array and eye() returns a  two-dimensional  array with ones on the diagonal and zeros elsewhere.
"""
# Note: A here is the random matrix from above
A_inv = np.linalg.inv(A) # Inverse matrix
print(A_inv)
dot_result = np.dot(A, A_inv) # Matrix multiplication operation
print(dot_result)
idn_matrix = np.identity(20) # Generate a 20*20 identity matrix
print(idn_matrix)
# Using .allclose() function to evaluate two matrices are equal within tolerance
np.allclose(dot_result, np.eye(20))  # True

"""
Eigenvalues
"""
"""
The transpose() function from Numpy can be used to calculate the transpose of a matrix. The linalg.eig() method computes the eigenvalues of a squared array while diag() extracts a diagonal or construct a diagonal array.
"""
A = [[3, 1],[1, 1]] # [[3, 1],[1, 1]] would create a 2x2 matrix
A_eig = np.linalg.eig(A)
# Now the Jordan decomposition A = Gamma*Lambda*Gamma^T
E_val = A_eig[0]
Gamma = A_eig[1]
Lambda = np.diag(E_val)
# Check the result, you might get something within numerical eps
AA = np.dot( np.dot(Gamma, Lambda), np.transpose(Gamma) )
print( np.allclose(AA, A) )  # True
# Calculation of the square root of A
Lambda12 = np.sqrt(Lambda)
A12 = np.dot( np.dot(Gamma, Lambda12), np.transpose(Gamma) )

"""
Fourier Transformation
"""
from PIL import Image
from numpy.fft import fft,ifft
import numpy as np
# Open the image by using Python Imaging Library(PIL)
image_before=Image.open('berlin_view.jpg')
# Decoding and encoding image to float number
image_int=np.fromstring(image_before.tobytes(), dtype=np.int8)
# Processing Fourier transform
fft_transformed=fft(image_int)
# Filter the lower frequency, i.e. employ a high pass
fft_transformed=np.where(np.absolute(fft_transformed) < 9e4,0,fft_transformed)
# Inverse Fourier transform
fft_transformed=ifft(fft_transformed)
# Keep the real part
fft_transformed=np.int8(np.real(fft_transformed))
# Output the image
image_output=Image.frombytes(image_before.mode, image_before.size, fft_transformed)
image_output.show()

"""
Normal Distribution
"""
"""
To create an inert active plot for the probability and cumulative density function of the normal distribution we use the Plotly package.
"""
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
import plotly.express as px
from ipywidgets import interact, interactive, fixed, interact_manual
# Set up figure size of plot
plt.rcParams['figure.figsize'] = (10,8) # length and width
plt.rcParams['figure.dpi'] = 120 # general box size

"""
We define the general environment of our plot: size, colour and style.
"""
# Plot the cdf and pdf in one figure
def f(mu,sigma, colour):
  fig = plt.figure(figsize=(10, 8))
  fig.subplots_adjust( hspace = 0.3)
  fig.patch.set_facecolor('#eeefef')
  plt.style.use('classic')

  # upper plot: pdf
  plt.subplot(2, 1, 1)  # (rows, columns, which one)
  x_axis = np.linspace(mu - 3*sigma, mu + 3*sigma, 1000)
  plt.plot(x_axis, stats.norm.pdf(x_axis, mu, sigma), c= colour, linewidth= 2)
  plt.xlabel('X')
  plt.ylabel('pdf')
  plt.ylim(0,1)
  plt.xlim(-10,10)
  plt.title(f'Probability Density Function pdf for $\mu= {mu}$ and $\sigma= {round(sigma,2)}$', fontweight="bold")
  # lower plot: cdf
  plt.subplot(2, 1, 2)
  plt.plot(x_axis, stats.norm.cdf(x_axis, mu, sigma), c= colour, linewidth= 2)
  plt.xlabel('X')
  plt.ylabel('cdf')
  plt.ylim(0,1)
  plt.xlim(-10,10)
  plt.title(f'Cumulative Density Function cdf for $\mu= {mu}$ and $\sigma= {round(sigma,2)}$', fontweight="bold")

colours = ['red', 'green', 'blue']
interact(f, mu=(-10, 10,1), sigma=(0.5, 5, 0.5), colour = colours)
plt.savefig("filename.png", transparent=True)

"""
Kernel Density Estimation
"""

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
from sklearn.neighbors import KernelDensity
# Code reference: http://scikit-learn.org/stable/auto_examples/neighbors/plot_kde_1d.html
# Set up figure size of plot
plt.rcParams['figure.figsize'] = (10,8) # length and width
plt.rcParams['figure.dpi'] = 120 # general box size
N = 200
np.random.seed(1)
# Create 2 normal distributed data set
norm_data_1 = np.random.normal(0, 1, int(0.3 * N))
norm_data_2 = np.random.normal(5, 1, int(0.7 * N))
norm_data = np.concatenate((norm_data_1, norm_data_2))
# Create x axis range
X_plot = np.linspace(-5, 10, 1000)
# Create linear combination of 2 normal distributed random variable
norm_linear = (0.3 * norm(0, 1).pdf(X_plot) + 0.7 * norm(5, 1).pdf(X_plot))
fig, ax = plt.subplots()
# Plot the real distribution
ax.fill(X_plot, norm_linear, fc='black', alpha=0.2, label='Linear combination')
# Use 3 different kernels to estimate
for kernel in ['gaussian', 'tophat', 'epanechnikov']:
    # Initial an object to use kernel function to fit data, bandwidth will    affect the result
    kde = KernelDensity(kernel=kernel, bandwidth=0.5).fit(norm_data.reshape(-1, 1))
    # Evaluate the density model on the data
    log_dens = kde.score_samples(X_plot.reshape(-1, 1))
    ax.plot(X_plot, np.exp(log_dens), '-', label="kernel = '{0}'".format(kernel))
# Add text on the plot, position argument can be arbitrary
ax.text(6, 0.38, "N={0} points".format(N))
# Add a legend to the left outside of the plot
ax.legend(loc='upper left', bbox_to_anchor = (1,0.5))
# Plot the random points, squeeze them into narrow space
ax.plot(norm_data, -0.005 - 0.01 * np.random.random(norm_data.shape[0]), '+k')
# Set x-axis y-axis limit to adjust the figure
ax.set_xlim(-4, 9)
ax.set_ylim(-0.03, 0.4)
fig.savefig('kernel_estimation.png', dpi=300, transparent = True, bbox_inches='tight')
plt.show()

"""
Box-Muller Method on 2-dim normal distribution
"""
"""
Using the Box-Muller Method to generate 2-dim normally distributed variables.
"""
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(100)
# For mu = (0,0), covariance matrix Sigma = identity matrix
n = 500  # Number of random numbers
msize = 0.1  # determines the size of the plotted points
# a good size might be msize=5 for n=500 pts and msize=0.1 for n>50K
a = np.random.exponential(scale=1, size=n)
phi = np.random.uniform(low=0, high=2 * np.pi, size=n)
# Change to cartesian coordinates
x = a * np.cos(phi)
y = a * np.sin(phi)
plt.figure(figsize=(7, 7))
plt.plot(x, y,'.r', markersize=msize)
plt.savefig('2dimnormal.png', dpi = 300, transparent = True)

"""
For covariance matrix Sigma = A: Y = X/sqrt(Sigma) ~ N(0,I) => Y*sqrt(Sigma)
"""
# Calculate sqrt(A) with Jordan decomposition
A = [[3, 1], [1, 1]]
A_eig = np.linalg.eig(A)
E_val = A_eig[0]
Gamma = A_eig[1]
Lambda = np.diag(E_val)
np.sqrt(Lambda)
Lambda12 = np.sqrt(Lambda)
A12 = np.dot(np.dot(Gamma, Lambda12), np.transpose(Gamma))
# Solve with matrix multiplication
c = [x, y]
tfxy = np.dot(A12, c)
plt.figure(2, figsize=(6, 4))
plt.plot(tfxy[0], tfxy[1], 'ro', markersize=msize)


from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QGridLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QStackedWidget, QSplitter, QWidget

class StackedWidget(QWidget):
    def __init__(self, parent=None):
        super(StackedWidget, self).__init__(parent)

        self.splitter = QSplitter()

        self.stacked1 = QStackedWidget()
        self.stacked2 = QStackedWidget()
        self.nextBtn = QPushButton('Next')
        self.prevBtn = QPushButton('Previous')
        self.pageLabel = self.make_entry(QLineEdit('1'))
        self.pageLabel.setMaxLength(8)
        self.ofLabel = self.make_entry(QLabel('of'))
        self.totalLabel = self.make_entry(QLabel())

        self.nextBtn.clicked.connect(self.next_page)
        self.prevBtn.clicked.connect(self.previous_page)
        self.pageLabel.returnPressed.connect(self.change_page)

        self.set_label()

        self.splitter.addWidget(self.stacked1)
        self.splitter.addWidget(self.stacked2)

        box = QHBoxLayout()

        box.addWidget(self.prevBtn)
        box.addWidget(self.pageLabel)
        box.addWidget(self.ofLabel)
        box.addWidget(self.totalLabel)
        box.addWidget(self.nextBtn)

        grid = QGridLayout()

        grid.addLayout(box, 0, 0)
        grid.addWidget(self.splitter, 1, 0)

        self.setLayout(grid)

    def make_entry(self, widget):
        widget.setAlignment(Qt.AlignCenter)
        widget.setMaximumWidth(50)
        return widget

    def next_page(self):
        index = self.stacked1.currentIndex()
        if index < self.stacked1.count() - 1:
            self.stacked1.setCurrentIndex(index + 1)
            self.stacked2.setCurrentIndex(index + 1)
            self.pageLabel.setText(str((index + 1) + 1))

    def previous_page(self):
        index = self.stacked1.currentIndex()
        if index > 0:
            self.stacked1.setCurrentIndex(index - 1)
            self.stacked2.setCurrentIndex(index - 1)
            self.pageLabel.setText(str(index))

    def change_page(self):
        index = int(self.pageLabel.text())
        self.stacked1.setCurrentIndex(index - 1)
        self.stacked2.setCurrentIndex(index - 1)

    def set_label(self):
        count = self.stacked1.count()
        self.totalLabel.setText(str(count))

    def clear_stack(self):
        while self.stacked1.count() > 0:
            w = self.stacked1.widget(0)
            self.stacked1.removeWidget(w)
            q = self.stacked2.widget(0)
            self.stacked2.removeWidget(q)


# varying ratios and set size.
import numpy as np
import matplotlib.pyplot as plt
import mymnist as mm
from sklearn.cluster import AgglomerativeClustering
import pandas as pd

#  parse and load data
images, labels = mm.MNIST_parser('../data/train-images.idx3-ubyte',
                                 '../data/train-labels.idx1-ubyte')
print('parsing done..\n')

acc_dict = {}
for n_total in range(1000, 7000, 1000):
    print('n_total = ', n_total)
    ratios = []
    n7s = []
    n1s = range(500, n_total, 500)
    accs = []
    for n1 in n1s:
        n7 = n_total - n1
        n7s.append(n7)
        ratios.append(n1 / n_total)
        subimages, sublabels = mm.set_1_7_creator(images, labels,
                                                  n1=n1, n7=n7)
        subimages_long = np.reshape(subimages, (n_total, -1))
        model = AgglomerativeClustering(2, linkage='ward')
        model.fit(subimages_long)
        sublabels_pred, acc = mm.match_clusters_1_7(sublabels, model.labels_)
        accs.append(acc)
        # print(n1, n7, n1 / n_total, acc)
    acc_dict[n_total] = pd.DataFrame({'n1': n1s, 'n7': n7s, 'ratio': ratios,
                                     'accuracy': accs})
print('done')


import sys
sys.path.insert(0, "..")
import logging

from opcua import Client

if __name__ == "__main__":
    #from IPython import embed
    logging.basicConfig(level=logging.WARN)
    client = Client("opc.tcp://localhost:49320")
    # client = Client("opc.tcp://OPC1.tpca.cz:49320")
    #client = Client("opc.tcp://192.168.56.100:4840/OPCUA/SimulationServer/")
    #client = Client("opc.tcp://olivier:olivierpass@localhost:53530/OPCUA/SimulationServer/")
    try:
        client.connect()
        # root = client.get_root_node()
        # print("Root is", root)
        # print("childs of root are: ", root.get_children())
        # print("name of root is", root.get_browse_name())
        # objects = client.get_objects_node()
        # print("childs og objects are: ", objects.get_children())

        # tag1 = client.get_node("ns=2;s=AS-ACfilling.PLC1.MJ1-ASN")
        # tag1 = client.get_node("ns=2;s=AS-KanbanRoom.PLC-A.Ucko")
        tag1 = client.get_node("ns=2;s=Simulation Examples.Functions.Ramp1")
        print("tag1 is: {0} with value {1} ".format(tag1, tag1.get_value()))
        # tag2 = client.get_node("ns=2;s=AS-ACfilling.PLC1.MJ1-HFO_vacuum")
        # print("tag2 is: {0} with value {1} ".format(tag2, tag2.get_value()))

    finally:
        client.disconnect()


import argparse
import sys
from detectron.datasets.mobility_aids.convert_yaml_to_coco import yaml_to_json

def parse_args():
    parser = argparse.ArgumentParser(description='Convert dataset')
    parser.add_argument(
        '--imageset', help="imageset text file", default=None, type=str)
    parser.add_argument(
        '--outfile', help="output (.json) file name", default=None, type=str)
    parser.add_argument(
        '--annodir', help="data dir for annotations to be converted",
        default=None, type=str)
    parser.add_argument(
        '--classes', help="class names in dataset", default=None, type=str,
        nargs='+')
    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)
    return parser.parse_args()

if __name__ == '__main__':
    args = parse_args()
    yaml_to_json(args.imageset, args.annodir, args.outfile, args.classes)


import pygame as pg
vec = pg.math.Vector2

GAMETITLE = "Zombies"

# size of the game window
# must be evenly divisible by TILESIZE (we don't want partial squares)
WIDTH = 1024
HEIGHT = 768

# highscore file
HIGHSCORE_FILE = "highscore.txt"

# How often should the screen be refreshed
FPS = 60

# how often should we recalculate the path to the player
PATHFINDING_REFRESH_TIMER = 2_000
# how often should we assign a random goal to the mob that are too far from the player
RANDOM_GOAL_REFRESH_TIMER = 30_000

# Game over messages
GAME_OVER_MESSAGES = {
  "player": ["Game Over", "You died"],
  "all_hostage_rescued": ["You Won", "All hostages are safe and you escaped"],
  "hostage_killed": ["Game Over", "You killed an hostage"],
  "zombies_killed": ["You Won", "All Zombies are killed"],
  "hostage_bit": ["Game Over", "You let a zombie bite an hostage"]
}

# define useful colors
WHITE     = (255, 255, 255)
BLACK     = (  0,   0,   0)
DARKGRAY  = ( 40,  40,  40)
MEDGRAY   = ( 75,  75,  75)
LIGHTGREY = (100, 100, 100)
RED       = (255,   0,   0)
GREEN     = (  0, 255,   0)
BLUE      = (  0,   0, 255)
YELLOW    = (255, 255,   0)
BLUEGREEN = (  0, 155, 155)
SKYBLUE   = (135, 206, 235)
BROWN     = (106,  55,   5)
FOREST    = ( 34,  57,  10)
CYAN      = (  0, 255, 255)
MAGENTA   = (255,   0, 255)

BGCOLOR   = BLACK

# Fonts
TITLE_FONT_NAME = "ZOMBIE.TTF"
HUD_FONT_NAME = "Impacted2.0.ttf"

# Spritesheets
SPRITESHEET_CHARACTERS = "spritesheet_characters.png"
SPRITESHEET_TILES = "spritesheet_tiles.png"
SPRITESHEET_EXPLOSIONS = "spritesheet_explosions.png"

# size of each square on the grid
TILESIZE = 64
GRIDWIDTH = WIDTH / TILESIZE
GRIDHEIGHT = HEIGHT / TILESIZE

# Layer orders
# (the lower the number, the lower the layer in the stack)
WALL_LAYER = 1
PLAYER_LAYER = 2
MOB_LAYER = 2
HOSTAGE_LAYER = 2
BULLET_LAYER = 3
EFFECT_LAYER = 4
ITEM_LAYER = 1

# Sounds
BG_MUSIC = 'espionage.ogg'
GAME_OVER_MUSIC = 'hard_times.ogg'
PLAYER_HIT_SOUNDS = ['pain/8.wav', 'pain/9.wav', 'pain/10.wav', 'pain/11.wav']
ZOMBIE_MOAN_SOUNDS = ['brains2.wav', 'brains3.wav', 'zombie-roar-1.wav', 'zombie-roar-2.wav',
                      'zombie-roar-3.wav', 'zombie-roar-5.wav', 'zombie-roar-6.wav', 'zombie-roar-7.wav']
ZOMBIE_HIT_SOUNDS = ['splat-15.wav']
WEAPON_SOUNDS_GUN = ['sfx_weapon_singleshot2.wav']
EFFECTS_SOUNDS = {'level_start': 'level_start.wav',
                  'health_up': 'health_pack.wav',
                  'reload_gun': 'gun_reload.ogg',
                  'outofammo': 'outofammo.wav'
                  }

# Player settings
PLAYER_LAYER = 2
PLAYER_SPEED = 500
PLAYER_IMG = "manBlue_gun.png"
PLAYER_ROTATION_SPEED = 250 # in degre per second
# rectangle to be used for the collisions
# we can't use the player's rectangle as its size changes
# when the player rotates
PLAYER_HIT_RECT = pg.Rect(0, 0, 35, 35)
# how far from the center of the sprite is the gun
BARREL_OFFSET = vec(30, 10)
PLAYER_HEALTH = 100

# Weapon settings
BULLET_IMG = "bullet.png"
GUN_PROPERTIES = {
  "gun": {
    # When the player fires a bullet, he moves back a bit
    "KICKBACK": 200,
    # make shooting inaccurate
    "GUN_SPREAD": 5,
    # delay between bullet shots
    "BULLET_RATE": 300,
    "BULLET_SPEED": 1_000,
    # bullet dissappears after 1s
    "BULLET_LIFETIME": 1_000,
    # damage points to mob
    "BULLET_DAMAGE": 10,
    # initial and maximum nb of bullets that come with than gun
    "NB_BULLETS": 15,
    # how long it takes to reload the gun
    "RELOAD_TIME": 500
  },
  "machine": {
    "KICKBACK": 300,
    "GUN_SPREAD": 15,
    "BULLET_RATE": 100,
    "BULLET_SPEED": 1_500,
    "BULLET_LIFETIME": 1_000,
    "BULLET_DAMAGE": 20,
    "NB_BULLETS": 50,
    "RELOAD_TIME": 3_000
  },
}
# how long the bullet impact should be displayed for
BULLETIMPACTDURATION = 50
# MUZZLE FLASH lifetime
FLASHDURATION = 50

# Mob settings
MOB_SPEEDS = [150, 120, 200, 100, 150, 150]
MOB_FRICTION = -1
MOB_HIT_RECT = pg.Rect(0, 0, 30, 30)
MOB_HEALTH = 100
MOB_DAMAGE = 10
MOB_KNOCKBACK = 20
MOB_AVOID_RADIUS = 50
# how far the mobs can see
# if player is closer, mob rush towards it
MOB_DETECT_RADIUS = 100
# how far the mobs can "smell" the player
# if player is closer, mob start to move towards it, following the shortest path
MOB_SEARCH_RADIUS = 750
# probability of creating a mob for each "zombie" tile in the map
MOB_SPAWN_PROBABILITY = 50
# re-spawn mobs every X ms
MOB_SPAWN_DELAY = 90_000

# Hostages
# how far in the hostages can see
HOSTAGE_DETECT_RADIUS = 500
HOSTAGE_SPEED = 200
HOSTAGE_FRICTION = -1
HOSTAGE_HIT_RECT = pg.Rect(0, 0, 30, 30)
HOSTAGE_AVOID_RADIUS = 75
HOSTAGE_HEALTH = 25
# probability of creating an hostage for each "hostage" tile in the map
HOSTAGE_SPAWN_PROBABILITY = 33
# sound to play when an hostage is rescued
HOSTAGE_RESCUED_SOUND = "hostage_rescued.wav"
# how long between all hostage are rescued and player wins (in ms)
HOSTAGE_RESCUED_COUNTDOWN = 30_000

# Hostage hit animationn (alpha change)
HOSTAGE_DAMAGE_ALPHA = [i for i in range(0, 256, 25)]

# Explosion animation speed (delay between 2 frames in ms)
EXPLOSION_FRAMERATE = 75

# Items
# health points refill
HEALTH_PACK_AMOUNT = 20
# nb of bullets in the bullet packs
BULLET_PACK_AMOUNT_MACHINE = 25
# nb of bullets in the bullet packs
BULLET_PACK_AMOUNT_GUN = 10
# probability of adding items to the map
ITEM_SPAWN_PROBABILITY = {
  "health": 50,
  "gun": 100,
  "machine_gun": 100,
  "bullets_gun": 75,
  "bullets_machine": 50
}

# how many pixels up and down the items will jump (tweening)
BOB_RANGE = 15
# how fast the items jump up and down
BOB_SPEED = 0.4