import os
from datetime import datetime, timedelta, date
from io import BytesIO
from uuid import uuid4

from django.core.files.base import ContentFile
from django.core.files.storage import default_storage
from pymediainfo import MediaInfo
import jwt
import qrcode
from PIL import Image
from django.contrib.auth import authenticate
from django.core.exceptions import ObjectDoesNotExist
from django.core.files import File
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from .models import Pages, Files, Nationalities, Promocode
from .serializers import (
    PageSerializer
)
from authentication.models import User
from django.conf import settings

def filename(x):
    return 'media/' + str(Files.objects.get(id=x).file)

def generate_code(url):
        border = 'staticfiles/qr_code/border.png'
        border = Image.open(border)
        QRcode = qrcode.QRCode(
            error_correction=qrcode.constants.ERROR_CORRECT_H
        )
        QRcode.add_data(f'https://ritual-front.vercel.app/page/{url}')
        QRcode.make()
        QRimg = QRcode.make_image(
            fill_color="white", back_color="transparent").convert('RGBA')
        basewidth = QRimg.size[0]
        wpercent = (basewidth / float(border.size[0]))
        hsize = int((float(border.size[1]) * float(wpercent)))
        border = border.resize((basewidth, hsize), Image.ANTIALIAS).convert('RGBA')
        qr_code_1 = Image.alpha_composite(border, QRimg).convert('RGB')
        qr_code_2 = Image.alpha_composite(border, QRimg).convert('RGBA')
        qr_code_1.save(settings.MEDIA_ROOT + f"/qr_code/{url}_0.png")
        qr_code_2.save(settings.MEDIA_ROOT + f"/qr_code/{url}_1.png")
        blob1 = BytesIO()
        blob2 = BytesIO()
        qr_code_1.save(blob1, 'png')
        qr_code_2.save(blob2, 'png')
        return File(blob1), File(blob2)

class PageAPIView(APIView):
    serializer_class = PageSerializer

    def get(self, request):
        page = request.GET.get('page')
        page = Pages.objects.get(id=page)
        errors = []
        avatar = None
        try:
            avatar = {'url': 'media/' + str(Files.objects.get(id=page.avatar).file), 'id': page.avatar}
        except ObjectDoesNotExist:
            errors.append({'error': 'Аватар не найден в базе данных'})
        pictures = []
        for i in page.pictures:
            try:
                pictures.append({'url': filename(i), 'id': i})
            except ObjectDoesNotExist:
                errors.append({'error': f'Не удалось загрузить фото из бд: {i}'})
        videos = []
        for i in page.videos:
            try:
                videos.append({'url': filename(i), 'id': i})
            except ObjectDoesNotExist:
                errors.append({'error': f'Не удалось загрузить видео из бд: {i}'})
        qr_codes = []
        for i in page.qr_code:
            try:
                qr_codes.append({'url': filename(i), 'id': i})
            except ObjectDoesNotExist:
                errors.append({'error': f'Не удалось загрузить видео из бд: {i}'})
        my_date = str(page.date_of_creation).split('-')
        time = date(int(my_date[0]), int(my_date[1]), int(my_date[2])) + timedelta(days=3) - datetime.now().date()
        time, _ = divmod(time.total_seconds(), 3600 * 24)
        if time <= 0:
            page.private = True
        nationality = Nationalities.objects.get(id=page.nationality)
        nationality = {'icon': 'staticfiles/nationalities/' + nationality.img, 'name': nationality.country_name,
                       'id': nationality.pk}
        my_page = {"name": page.name,
                   "surname": page.surname,
                   "otchestvo": page.otchestvo,
                   "place_of_birth": page.place_of_birth,
                   "place_of_death": page.place_of_death,
                   "date_of_birth": page.date_of_birth,
                   "date_of_death": page.date_of_death,
                   "nationality": nationality,
                   "biography": page.biography,
                   "facts": page.facts,
                   "avatar": avatar,
                   "pictures": pictures,
                   "videos": videos,
                   "coords": page.coords,
                   "private": page.private,
                   "qr_code": qr_codes}
        if errors:
            response = Response({'erorrs': errors, 'page': my_page}, status=status.HTTP_200_OK)
        else:
            response = Response({'page': my_page}, status=status.HTTP_200_OK)
        return response

    def post(self, request):
        authenticate(request)
        page = request.data.get('page', {})
        serializer = self.serializer_class(data=page)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        user = request.user
        if str(user) == 'AnonymousUser':
            return Response(status=status.HTTP_403_FORBIDDEN)
        if not user.array_of_pages:
            user.array_of_pages = []
            user.save()
        user.array_of_pages.append(serializer.data['id'])
        user.save()
        photo = []
        for i, file in enumerate(generate_code(serializer.data["id"])):
            instance = Files(file=file, user_id=user.pk)
            instance.file = f'qr_code/{serializer.data["id"]}_{i}.png'
            instance.save()
            photo.append(str(instance.pk))
        page = Pages.objects.get(id=serializer.data['id'])
        page.qr_code = photo
        page.save()
        response = Response({'id': serializer.data['id']}, status=status.HTTP_200_OK)
        return response

    def patch(self, request):
        authenticate(request)
        page = request.data.get('page', {})
        user = request.user
        if str(user) == 'AnonymousUser':
            return Response(status=status.HTTP_403_FORBIDDEN)
        if page.get('id') not in user.array_of_pages:
            return Response({'error': 'Вы не можете редактировать чужую страничку'}, status=status.HTTP_400_BAD_REQUEST)
        page_new = Pages.objects.get(id=page.get('id'))
        page.pop('id')
        for i in page.items():
            setattr(page_new, i[0], i[1])
        page_new.save()
        response = Response(status=status.HTTP_200_OK)
        return response

    def delete(self, request):
        authenticate(request)
        user = request.user
        page = request.GET.get('page')
        if str(user) == 'AnonymousUser':
            return Response(status=status.HTTP_403_FORBIDDEN)
        if page not in user.array_of_pages:
            return Response({'error': 'Вы не можете удалить чужую страничку'}, status=status.HTTP_400_BAD_REQUEST)
        user.array_of_pages.remove(page)
        user.save()
        return Response(status=status.HTTP_200_OK)

class GetUserPagesAPIView(APIView):
    serializer_class = PageSerializer

    def get(self, request):
        authenticate(request)
        user = request.user
        if str(user) == 'AnonymousUser':
            return Response(status=status.HTTP_403_FORBIDDEN)
        pages = []
        for page in user.array_of_pages:
            try:
                instance = Pages.objects.get(id=page)
                my_date = str(instance.date_of_creation).split('-')
                time = date(int(my_date[0]), int(my_date[1]), int(my_date[2])) + timedelta(
                    days=3) - datetime.now().date()
                time, _ = divmod(time.total_seconds(), 3600 * 24)
                if time <= 0:
                    instance.private = True
                try:
                    avatar = Files.objects.get(id=instance.avatar).file
                    pages.append({'id': instance.id, 'price': instance.price, 'avatar': 'media/' + str(avatar),
                                  'name': instance.name, 'surname': instance.surname, 'time_left': int(time),
                                  'private': instance.private, 'payed': instance.payed})
                except ObjectDoesNotExist:
                    pages.append({'id': instance.id, 'price': instance.price, 'avatar': "",
                                  'name': instance.name, 'surname': instance.surname, 'time_left': int(time),
                                  'private': instance.private, 'payed': instance.payed})
            except ObjectDoesNotExist:
                pages.append({'id': page, 'error': 'Не удалось найти страничку в базе данных'})
        response = Response({'pages': pages}, status=status.HTTP_200_OK)
        return response

# def create_preview(file, user_id):
#     try:
#         file_info = MediaInfo.parse(file)
#         is_video = False
#         for track in file_info.tracks:
#             if track.track_type == "Video":
#                 is_video = True
#         if not is_video:
#             return False
#         vidcap = cv.VideoCapture(file)
#         success, image = vidcap.read()
#         if success:
#             name = f"users/{user_id}/" + str(uuid4()) + '.jpg'
#             im = cv.imwrite(os.path.join('media/', name), image)
#             if im:
#                 return name
#             else:
#                 return False
#         return False
#     except:
#         return False

class FilesAPIView(APIView):

    def post(self, request):
        authenticate(request)
        user = request.user
        photo = []
        if str(user) == 'AnonymousUser':
            for filename, file in request.FILES.items():
                instance = Files(file=file, user_id=0)
                instance.save()
                photo.append({'id': str(instance.pk), 'url': 'media/' + str(instance.file)})
            response = Response(photo, status=status.HTTP_200_OK)
            return response
        for filename, file in request.FILES.items():
            instance = Files(file=file, user_id=request.user.pk)
            instance.save()
            photo.append({'id': str(instance.pk), 'url': 'media/' + str(instance.file)})
        response = Response(photo, status=status.HTTP_200_OK)
        return response

class NationalitiesAPIView(APIView):

    def get(self, request):
        nationalities = []
        for i in Nationalities.objects.filter():
            nationalities.append({'icon': 'staticfiles/nationalities/' + i.img, 'name': i.country_name, 'id': i.pk})

        return Response({'nationalities': nationalities}, status=status.HTTP_200_OK)

class PromocodeAPIView(APIView):

    def post(self, request):
        authenticate(request)
        user = request.user
        if str(user) == 'AnonymousUser':
            return Response(status=status.HTTP_403_FORBIDDEN)
        page = request.data.get('page')
        code = request.data.get('code')
        promo = Promocode.objects.get(code=code)
        if promo:
            if not promo.activation_date:
                promo.activation_date = datetime.now()
                promo.user_id = user.pk
                promo.save()
                page = Pages.objects.get(id=page)
                if page.price == 0:
                    return Response({'error': 'Эта страница уже бесплатная'}, status=status.HTTP_400_BAD_REQUEST)
                page.price = 0
                page.save()
                return Response(status=status.HTTP_200_OK)
            else:
                return Response({'error': 'Промокод был активирован'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response({'error': 'Промокод не существует'}, status=status.HTTP_400_BAD_REQUEST)


tool_name = 'USD'
report_type = 'default'
show_skipped_groups = True
tracked_metrics = {
    'render_time': {'displaying_name': 'Render time', 'function': 'sum', 'displaying_unit': 's'}
}
tracked_metrics_charts_location = 'performance'
tracked_metrics_files_number = 10
update_baselines_feature_supported = True
analyze_render_time = {"max_diff": 0.05}
analyze_times = {
    'render_time': {'max_diff': 0.05}
}


from __future__ import print_function
from __future__ import absolute_import
# Project imports
import os
import sys

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

from . import helper
from elodie.localstorage import Db
from elodie import constants

os.environ['TZ'] = 'GMT'

def test_init_writes_files():
    db = Db()

    assert os.path.isfile(constants.hash_db) == True
    assert os.path.isfile(constants.location_db) == True

def test_add_hash_default_do_not_write():
    db = Db()

    random_key = helper.random_string(10)
    random_value = helper.random_string(12)

    # Test with default False value as 3rd param
    db.add_hash(random_key, random_value)

    assert db.check_hash(random_key) == True, 'Lookup for hash did not return True'

    # Instnatiate new db class to confirm random_key does not exist
    db2 = Db()
    assert db2.check_hash(random_key) == False

def test_add_hash_explicit_do_not_write():
    db = Db()

    random_key = helper.random_string(10)
    random_value = helper.random_string(12)

    # Test with explicit False value as 3rd param
    db.add_hash(random_key, random_value, False)

    assert db.check_hash(random_key) == True, 'Lookup for hash did not return True'

    # Instnatiate new db class to confirm random_key does not exist
    db2 = Db()
    assert db2.check_hash(random_key) == False

def test_add_hash_explicit_write():
    db = Db()

    random_key = helper.random_string(10)
    random_value = helper.random_string(12)

    # Test with explicit True value as 3rd param
    db.add_hash(random_key, random_value, True)

    assert db.check_hash(random_key) == True, 'Lookup for hash did not return True'

    # Instnatiate new db class to confirm random_key exists
    db2 = Db()
    assert db2.check_hash(random_key) == True

def test_backup_hash_db():
    db = Db()
    backup_file_name = db.backup_hash_db()
    file_exists = os.path.isfile(backup_file_name)
    os.remove(backup_file_name)

    assert file_exists, backup_file_name

def test_check_hash_exists():
    db = Db()

    random_key = helper.random_string(10)
    random_value = helper.random_string(12)

    # Test with explicit False value as 3rd param
    db.add_hash(random_key, random_value, False)

    assert db.check_hash(random_key) == True, 'Lookup for hash did not return True'

def test_check_hash_does_not_exist():
    db = Db()

    random_key = helper.random_string(10)

    assert db.check_hash(random_key) == False, 'Lookup for hash that should not exist returned True'

def test_get_hash_exists():
    db = Db()

    random_key = helper.random_string(10)
    random_value = helper.random_string(12)

    # Test with explicit False value as 3rd param
    db.add_hash(random_key, random_value, False)

    assert db.get_hash(random_key) == random_value, 'Lookup for hash that exists did not return value'

def test_get_hash_does_not_exist():
    db = Db()

    random_key = helper.random_string(10)

    assert db.get_hash(random_key) is None, 'Lookup for hash that should not exist did not return None'

def test_get_all():
    db = Db()
    db.reset_hash_db()

    random_keys = []
    random_values = []
    for _ in range(10):
        random_keys.append(helper.random_string(10))
        random_values.append(helper.random_string(12))
        db.add_hash(random_keys[-1:][0], random_values[-1:][0], False)

    counter = 0
    for key, value in db.all():
        assert key in random_keys, key
        assert value in random_values, value
        counter += 1

    assert counter == 10, counter

def test_get_all_empty():
    db = Db()
    db.reset_hash_db()

    counter = 0
    for key, value in db.all():
        counter += 1

    # there's a final iteration because of the generator
    assert counter == 0, counter

def test_reset_hash_db():
    db = Db()

    random_key = helper.random_string(10)
    random_value = helper.random_string(12)

    # Test with explicit False value as 3rd param
    db.add_hash(random_key, random_value, False)

    assert random_key in db.hash_db, random_key
    db.reset_hash_db()
    assert random_key not in db.hash_db, random_key

def test_update_hash_db():
    db = Db()

    random_key = helper.random_string(10)
    random_value = helper.random_string(12)

    # Test with default False value as 3rd param
    db.add_hash(random_key, random_value)

    assert db.check_hash(random_key) == True, 'Lookup for hash did not return True'

    # Instnatiate new db class to confirm random_key does not exist
    db2 = Db()
    assert db2.check_hash(random_key) == False

    db.update_hash_db()

    # Instnatiate new db class to confirm random_key exists
    db3 = Db()
    assert db3.check_hash(random_key) == True

def test_checksum():
    db = Db()

    src = helper.get_file('plain.jpg')
    checksum = db.checksum(src)

    assert checksum == 'd5eb755569ddbc8a664712d2d7d6e0fa1ddfcdb378475e4a6758dc38d5ea9a16', 'Checksum for plain.jpg did not match'

def test_add_location():
    db = Db()

    latitude, longitude, name = helper.get_test_location()

    db.add_location(latitude, longitude, name)
    retrieved_name = db.get_location_name(latitude, longitude, 5)

    assert name == retrieved_name

def test_get_location_name():
    db = Db()

    latitude, longitude, name = helper.get_test_location()
    db.add_location(latitude, longitude, name)

    # 1 meter
    retrieved_name = db.get_location_name(latitude, longitude, 1)

    assert name == retrieved_name

def test_get_location_name_within_threshold():
    db = Db()

    latitude, longitude, name = helper.get_test_location()
    db.add_location(latitude, longitude, name)

    print(latitude)
    new_latitude = helper.random_coordinate(latitude, 4)
    new_longitude = helper.random_coordinate(longitude, 4)
    print(new_latitude)

    # 10 miles
    retrieved_name = db.get_location_name(new_latitude, new_longitude, 1600*10)

    assert name == retrieved_name, 'Name (%r) did not match retrieved name (%r)' % (name, retrieved_name)

def test_get_location_name_outside_threshold():
    db = Db()

    latitude, longitude, name = helper.get_test_location()
    db.add_location(latitude, longitude, name)

    new_latitude = helper.random_coordinate(latitude, 1)
    new_longitude = helper.random_coordinate(longitude, 1)

    # 800 meters
    retrieved_name = db.get_location_name(new_latitude, new_longitude, 800)

    assert retrieved_name is None

def test_get_location_coordinates_exists():
    db = Db()

    latitude, longitude, name = helper.get_test_location()

    name = '%s-%s' % (name, helper.random_string(10))
    latitude = helper.random_coordinate(latitude, 1)
    longitude = helper.random_coordinate(longitude, 1)

    db.add_location(latitude, longitude, name)

    location = db.get_location_coordinates(name)

    assert location is not None
    assert location[0] == latitude
    assert location[1] == longitude

def test_get_location_coordinates_does_not_exists():
    db = Db()

    latitude, longitude, name = helper.get_test_location()

    name = '%s-%s' % (name, helper.random_string(10))
    latitude = helper.random_coordinate(latitude, 1)
    longitude = helper.random_coordinate(longitude, 1)

    location = db.get_location_coordinates(name)

    assert location is None


'''
Main LatentSimilarity class
Modified 1/12/23 for simplicity

Best way to use is to define a stopping criteria
Use of the sklearn interface results in automatic creation of validation set,
from the training set, which then determines best parameter choice

2/8/23 Added automatic validation set creation in sklearn.py
2/9/23 Automatic fallback to CPU if CUDA not available
'''

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F

def to_cuda(x):
    try:
        return x.float().cuda()
    except:
        return x.float()

class LatSim(nn.Module):
    def __init__(self, d, ld=2):
        super(LatSim, self).__init__()
        self.A = nn.Parameter(to_cuda(torch.randn(d,ld)/(d**0.5)))

    def E(self, xtr, xt):
        # Normalize inputs
        mu = torch.mean(xtr, dim=0, keepdims=True)
        xtr = xtr - mu
        xt = xt - mu
        # Similarity matrix
        AT = (xtr@self.A).T
        A = xt@self.A
        E = A@AT
        return F.softmax(E,dim=1)

    def forward(self, xtr, ytr, xt=None):
        if xt is None:
            xt = xtr
        E = self.E(xtr, xt)
        return E@ytr

def train_sim_mse(*args, **kwargs):
    kwargs['lossfn'] = nn.MSELoss()
    train_sim(*args, **kwargs)

def train_sim_ce(*args, **kwargs):
    kwargs['lossfn'] = nn.CrossEntropyLoss()
    train_sim(*args, **kwargs)

def train_sim(sim, xtr, ytr, stop=0, xv=None, yv=None, lr=1e-4, wd=1e-4, nepochs=1000, pperiod=20, lossfn=nn.MSELoss(), verbose=False):
    # Validation set
    if xv is not None and yv is not None:
        if yv.dim() == 2:
            yvv = torch.argmax(yv, dim=1)
            best = 0
        else:
            best = float('inf')
        bestA = None

    # Optimizers
    optim = torch.optim.Adam(sim.parameters(), lr=lr, weight_decay=wd)
    sched = torch.optim.lr_scheduler.ReduceLROnPlateau(optim, patience=20, factor=0.75, eps=1e-7)

    for epoch in range(nepochs):
        optim.zero_grad()
        yhat = sim(xtr, ytr)
        loss = lossfn(yhat, ytr)
        loss.backward()
        optim.step()
        if loss < stop:
            break
        sched.step(loss)
        # Check validation set
        if xv is not None and yv is not None:
            with torch.no_grad():
                yhat = sim(xtr, ytr, xv)
                if yv.dim() == 2:
                    yhat = torch.argmax(yhat, dim=1)
                    acc = torch.sum(yvv == yhat)/len(yvv)
                    acc = float(acc)
                    better = acc > best
                else:
                    acc = lossfn(yhat, yv)
                    acc = float(acc)
                    better = acc < best
                if better:
                    best = acc
                    bestA = sim.A.detach()
                    if verbose:
                        print(f'Best acc {acc}')
        if epoch % pperiod == 0 or epoch == nepochs-1:
            if verbose:
                print(f'{epoch} loss: {float(loss)} lr: {sched._last_lr}')
        optim.zero_grad()

    if xv is not None and yv is not None:
        if verbose:
            print(f'Final best acc {best}')
        sim.A = nn.Parameter(to_cuda(bestA))
    if verbose:
        print('Complete')


from SloppyCell.ReactionNetworks import *

from Nets import *

traj4a = Dynamics.integrate(net_12L_12D_12L_D, [0, 96])
traj6a = Dynamics.integrate(net_12D_L, [0, 60])

traj4b = Dynamics.integrate(mutant_12L_12D_12L_D, [0, 96])
traj6b = Dynamics.integrate(mutant_12D_L, [0, 60])

# Figure 4a
Plotting.figure(figsize=(8,10))
Plotting.subplot(2,1,1)
Plotting.plot_trajectory(traj4a, ['cTm', 'cLm', 'light'])
Plotting.axis([0, 96, 0, 2.4])
Plotting.title('Figure 4, warning: scales in paper odd')
Plotting.subplot(2,1,2)
Plotting.plot_trajectory(traj4b, ['cTm', 'cLm', 'light'])
Plotting.axis([0, 96, 0, 7])

# Figure 6a
Plotting.figure(figsize=(8,10))
Plotting.subplot(2,1,1)
Plotting.plot_trajectory(traj6a, ['cYm', 'light'])
Plotting.axis([0, 60, 0, 0.2])
Plotting.title('Figure 6, warning: scales in paper odd')
Plotting.subplot(2,1,2)
Plotting.plot_trajectory(traj6b, ['cYm', 'light'])
Plotting.axis([0, 60, 0, 0.6])


import cv2
import numpy as np

def nothing(x):
    pass
##Camera
# create trackbars for color change

cv2.namedWindow('image1')
cv2.createTrackbar('RL','image1',0,255,nothing)
cv2.createTrackbar('RH','image1',255,255,nothing)
cv2.createTrackbar('GL','image1',0,255,nothing)
cv2.createTrackbar('GH','image1',255,255,nothing)
cv2.createTrackbar('BL','image1',0,255,nothing)
cv2.createTrackbar('BH','image1',255,255,nothing)
cap=cv2.VideoCapture(0)

ret,img=cap.read()
cv2.imshow('image',img)
(h, w) = img.shape[:2]
cv2.circle(img, (w//2, h//2), 7, (255, 255, 255), -1)
print("Frame Centroid is:")
print(w//2,h//2)
while(1):
    ret,img=cap.read()
    blurImg = cv2.blur(img,(10,10))
    rl = cv2.getTrackbarPos('RL','image1')
    rh = cv2.getTrackbarPos('RH','image1')
    gl = cv2.getTrackbarPos('GL','image1')
    gh = cv2.getTrackbarPos('GH','image1')
    bl = cv2.getTrackbarPos('BL','image1')
    bh = cv2.getTrackbarPos('BH','image1')
    lowerlimit=np.array([rl,gl,bl])
    higherlimit=np.array([rh,gh,bh])
    hsv=cv2.cvtColor(blurImg,cv2.COLOR_BGR2HSV)
    img_mask=cv2.inRange(hsv,lowerlimit,higherlimit)
    ##retval, threshold = cv2.threshold(img, 100,200,30,cv2.THRESH_BINARY)
    contours, _= cv2.findContours(img_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cv2.drawContours(blurImg,contours,-1,(0,255,0),3)
    cnt=contours[0]
    max_length=len(contours)
    for c in contours:
        if(len(c)>max_length):
            max_length=len(c)
            cnt=c

    M =cv2.moments(cnt)
    if (M["m00"]==0):
        M["m00"]=1
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])

    cv2.circle(blurImg,(cX,cY),8,(0,0,255),-1)
    r=cX-w//2
    p=cY-h//2
    if p==0:
       p=1
    if r==0:
        r=1

    angle=np.arctan(p/r)
    cv2.putText(blurImg,"Centroid:",(cX-25,cY-25),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,0),2)

    print("Distance is ",r,p)

    print("Angle is :",57.2957795*angle)

    # Taking a matrix of size 5 as the kernel
    kernel = np.ones((5,5), np.uint8)
    # Divides image into matrices of 5X5 of 8 bits
    # The first parameter is the original image,
    # kernel is the matrix with which image is
    # convolved and third parameter is the number
    # of iterations, which will determine how much
    # you want to erode/dilate a given image.
    img_mask = cv2.erode(img_mask, kernel, iterations=1)
    img_mask = cv2.dilate(img_mask, kernel, iterations=1)
    cv2.imshow('Image',img)
    cv2.imshow('blurred image',blurImg)
    cv2.imshow('image2',img_mask)

    if cv2.waitKey(1)==27:          #if esc key is pressed then break out of loop
        break;
cv2.destroyAllWindows()
#Close and exit
##cap.release()   #releases the camera
##cv2.waitKey(5000)       #waits for program termination . If 0 then waits infinetely for user input


n,k,m=map(int,input().split())
lst=list(input())
result=0
count=0

for i in range(0,k):
	if lst[i]=='1':
		count+=1
		if count<=m:
			continue
		else:
			count=m
			lst[i]='0'
			result+=1

for i in range(1,n-k+1):
	if lst[i-1]=='1':
		count-=1
	if lst[k+i-1]=='1':
		count+=1
		if count>m:
			count=m
			lst[k+i-1]='0'
			result+=1

strs="".join(lst)
print(result)
print(strs)


import calendar
import json
import logging
import requests
import sys
import time
import csv
import datetime
from dateutil.relativedelta import relativedelta
import os
import click
sys.path.append(
    os.path.abspath(os.path.join(os.path.dirname(__file__), '../../')))

# Tweak the destination (e.g. sys.stdout instead)
# and level (e.g. logging.DEBUG instead) to taste!
logging.basicConfig(format='%(levelname)s:%(asctime)s:%(message)s',
                    stream=sys.stderr, level=logging.INFO)

@click.command(no_args_is_help=True)
@click.option('--refresh-token', prompt="Refresh Token", help='Refresh Token from FlexeraOne', required=True)
@click.option('--host', '-h', prompt="IAM API Endpoint", default="api.flexeratest.com", show_default=True)
@click.option('--org-id', '-i', prompt="Organization ID", help="Organization ID", required=True)
@click.option('--bill-connect-id', prompt="Bill Connect ID", help="Bill Connect ID", required=True, default="cbi-oi-optima-kubecost-1")
@click.option('--aggregation', help="Aggregation level", type=click.Choice(['deployment', 'namespace']), default='deployment')
@click.option('--kubecost-host', prompt="Kubecost Host", required=True)
@click.option('--multiplier', required=False, default=1)
def upload_files(refresh_token, host, org_id, bill_connect_id, aggregation, kubecost_host, multiplier):
    last_31_days = datetime.datetime.now() + relativedelta(days=-1)
    invoice_year_month = last_31_days.strftime("%Y-%m")
    period = invoice_year_month
    bill_upload_url = "https://api.optima.flexeraeng.com/optima/orgs/{}/billUploads".format(
        org_id)
    files_to_upload = []

    for d in date_iter(last_31_days.strftime("%Y"), last_31_days.strftime("%#m")):
        if d > datetime.datetime.now().date():
            continue
        else:
            tomorrow = d + relativedelta(days=+1)
            # https://github.com/kubecost/docs/blob/master/allocation.md#querying
            url = "".join([
                "http://{}/model/allocation?window=".format(kubecost_host),
                d.strftime("%Y-%m-%dT00:00:00Z"),
                ",",
                tomorrow.strftime("%Y-%m-%dT00:00:00Z"),
                "&aggregate={}".format(aggregation),
                "&idle=false",
                "&shareIdle=true",
                "&shareNamespaces=kube-system,cadvisor",
                "&shareSplit=weighted"
            ])
            logging.info("Generating Bill from " + url)
            r = requests.get(url)
            r.raise_for_status()
            j = r.json()
            data = j["data"]
            with open('output.json', 'w', encoding='utf-8') as json_file:
                jsonString = json.dumps(data, indent=2)
                json_file.write(jsonString)

            arr_cbi = [
                [
                    'CloudVendorAccountID',
                    'CloudVendorAccountName',
                    'Category',
                    'LineItemType',
                    'ResourceGroup',
                    'ResourceType',
                    'ResourceID',
                    'Service',
                    'Tags',
                    'UsageAmount',
                    'UsageUnit',
                    'Cost',
                    'CurrencyCode',
                    'UsageStartTime',
                    'InvoiceYearMonth',
                    'ManufacturerName'
                ]
            ]

            for h in j["data"]:
                for x in h.keys():
                    tags = json.dumps(h[x]["properties"].pop("labels", {}))
                    for c in ["cpuCost", "gpuCost", "ramCost", "pvCost", "networkCost", "sharedCost"]:
                        arr_cbi.append([
                            h[x]["properties"]["cluster"],
                            'kubernetes',
                            'Compute',
                            'Usage',
                            x.split('/')[0],
                            aggregation,
                            x,
                            'Kubernetes',
                            tags,
                            1,
                            c,
                            h[x][c] * multiplier,
                            'USD',
                            d.strftime("%Y-%m-%dT00:00:00Z"),
                            invoice_year_month,
                            'Google'
                        ])

            dir_path = os.path.dirname(os.path.realpath(__file__))
            csv_file = os.path.join(dir_path, 'kubecost-' + d.strftime("%Y-%m-%d")+'.csv')
            files_to_upload.append(csv_file)
            with open(csv_file, 'w', newline='') as outFile:
                csv_writer = csv.writer(
                    outFile, delimiter=',',
                    quotechar='"',
                    quoting=csv.QUOTE_MINIMAL)
                for item in arr_cbi:
                    csv_writer.writerow(item)
    # sys.exit(0)
    access_token = generate_access_token(refresh_token, host)

    # ===== Use Access Token as Bearer token from them on ===== #
    auth_headers = {"Authorization": "Bearer " + access_token}
    kwargs = {"headers": auth_headers, "allow_redirects": False}

    logging.info("Using org_id {}, bill_connect_id {}, period {}".format(
        org_id, bill_connect_id, period))
    logging.info("1. Creating Bill Upload for Period:" + period)
    bill_upload = {"billConnectId": bill_connect_id, "billingPeriod": period}
    r = requests.post(bill_upload_url, json.dumps(bill_upload), **kwargs)
    logging.info("Response: {}\n{}".format(
        r.status_code, json.dumps(r.json(), indent=4)))
    if r.status_code == 429:
        time.sleep(120)
        r = requests.post(bill_upload_url, json.dumps(bill_upload), **kwargs)
        r.raise_for_status()
    elif r.status_code == 409:
        existing_id = r.json()["message"].split(' ')[4][:-1]
    else:
        r.raise_for_status()
    if 'existing_id' in locals():
        bill_upload_id = existing_id
    else:
        bill_upload_id = r.json()["id"]

    logging.info("Bill Upload ID: {}".format(bill_upload_id))

    for fileName in files_to_upload:
        base_name = os.path.basename(fileName)
        logging.info("2. Upload file {} to Bill Upload {}...".format(
            base_name, bill_upload_id))
        upload_file_url = "{}/{}/files/{}".format(
            bill_upload_url, bill_upload_id, base_name)
        r = requests.post(upload_file_url, data=open(
            fileName, 'rb').read(), **kwargs)
        logging.info("Response: {}\n{}".format(
            r.status_code, json.dumps(r.json(), indent=4)))

    logging.info("3. Committing the Bill Upload {}...".format(bill_upload_id))
    operations_url = "{}/{}/operations".format(bill_upload_url, bill_upload_id)
    r = requests.post(operations_url, '{"operation":"commit"}', **kwargs)
    logging.info("Response: {}\n{}".format(
        r.status_code, json.dumps(r.json(), indent=4)))
    r.raise_for_status()

    # ===== That's all, folks! =====
    sys.exit(0)

# https://stackoverflow.com/questions/57274902/python-iterate-over-all-days-in-a-month
def date_iter(year, month):
    intMonth = int(month)
    intYear = int(year)
    x = calendar._monthlen(intYear, intMonth) + 1
    for i in range(1, x):
        yield datetime.date(intYear, intMonth, i)

def generate_access_token(refresh_token, host):
    domain = '.'.join(host.split('.')[-2:])
    token_url = "https://login.{}/oidc/token".format(domain)

    logging.info("OAuth2: Getting Access Token via Refresh Token for {} ...".format(token_url))
    token_post_request = requests.post(token_url, data={"grant_type": "refresh_token", "refresh_token": refresh_token})
    token_post_request.raise_for_status()
    access_token = token_post_request.json()["access_token"]
    return access_token

if __name__ == '__main__':
    # click passes no args
    # pylint: disable=no-value-for-parameter
    upload_files(auto_envvar_prefix='FLEXERA')


import Langevin_Machine_Learning.hamiltonian as Hamiltonian
import Langevin_Machine_Learning.Integrator as Integrator
import Langevin_Machine_Learning.Integrator.methods as methods
import Langevin_Machine_Learning.utils as confStat # configuration statistics

energy = Hamiltonian.Hamiltonian()
energy.append(Hamiltonian.asymmetrical_double_well())
energy.append(Hamiltonian.kinetic_energy(mass = 1))

configuration = {
    'kB' : 1.0, # put as a constant
    'Temperature' : 1.0, # desired temperature for NVT Ensemble
    'DIM' : 1,
    'm' : 1,
    'N' : 100,
    'hamiltonian' : energy,
    }

integration_setting = {
    'iterations' : 500,
    'DumpFreq' : 1,
    'gamma' : 0, # gamma 0 turns off the Langevin heat bath, setting it to NVE Ensemble
    'time_step' : 0.01,
    'integrator_method' : methods.position_verlet, #method class to be passed
    }

configuration.update(integration_setting)
MD_integrator = Integrator.Langevin(**configuration)
#only load for initial condition Temperature = 1.0
MD_integrator.set_phase_space(samples = 100)

#update configuration after loading
configuration = MD_integrator.get_configuration()
q_hist, p_hist = MD_integrator.integrate()
confStat.plot_stat(q_hist, p_hist, 'q_dist',**configuration)
#plot the statistic of q distribution based on current state configuration

#to save the current phase space to continue as a checkpoint
MD_integrator.save_phase_space() # by default, it is in init file


from bs4 import BeautifulSoup
import urllib.request
import requests
import re

posiblesCiudades = {"Arequipa": "AQP", "Barranquilla": "BAQ", "Bogotá": "BOG", "Bucaramanga": "BGA",  "Cajamarca": "CJA", "Cartagena": "CTG", "Chiclayo": "CIX", "Cusco": "CUZ", "Cúcuta" : "CUC,", "Iquitos": "IQT", "Jaén": "JAE", "Juliaca": "JUL", "Lima": "LIM", "Medellín": "MDE", "Miami": "MIA", "Montería": "MTR", "Pereira": "PEI", "Piura": "PIU", "Rioacha": "RCH", "San Andrés Islas": "ADZ", "Santa Marta": "SMR", "Tacna": "TCQ", "Talara": "TYl", "Tarapoto": "TPP", "Valledupar": "VUP"}

def buscarEnCiudad(pCiudad):

    encontrado = False

    for a in posiblesCiudades.keys():

        if a == ciudadDeOrigen:
            encontrado = True

    return encontrado

def abriendoPagina():

    url = "https://www.vivaair.com/co/es/vuelo?DepartureCity=BOG&ArrivalCity=SMR&DepartureDate=2019-11-25&Adults=2&Currency=COP"
    """
    if buscarEnCiudad(ciudadDeOrigen) and buscarEnCiudad(ciudadDestino):

        try:
            #url = "https://www.vivaair.com/co/es/vuelo?DepartureCity=" +posiblesCiudades[ciudadDeOrigen] +"&ArrivalCity="+posiblesCiudades[ciudadDestino]+"&DepartureDate=" + fechaDeSalida+ "&Adults=" + str(numeroDePasajeros) +"&Currency=COP"

            response = requests.get(url)
            print(response)
        except:

            print("Error en el url")

    """
    #se abre la pagina
    pagina = urllib.request.urlopen(url)
    #Ahora ya se tiene la pagina como un texto
    soup = BeautifulSoup(pagina, 'html.parser')

    print(soup.find_all(attrs={"COP 165,000": "from-price"}))

#PseudoInterfaz gráfica
"""
fechaDeSalida = input("Introduzca la fecha de salida ej:2019-10-25: ")
numeroDePasajeros = int(input("Numero de Pasajeros: "))
ciudadDeOrigen = input("Ciudad de Origen: ")
ciudadDestino = input("Ciudad Destino: ")
"""

abriendoPagina()


import optparse

import requests
from tqdm import tqdm

def process_title(title):
    ## stopwords = [word.strip() for word in open('stopwords.filter', 'r').readlines()] # should not appear in the names
    stopwords = []

    for word in stopwords:
        if word in title.lower():
            return None
    return title

def main(input_file, output_file, max_depth=4):
    categories = []

    print(f"Extend categories from {input_file}.")
    with open(input_file, 'r') as f:
        max_depth, counter = max_depth, 0

        for category in tqdm(f.readlines()):

            params = {
                'categories': category,  # process the categories separately
                'depth': max_depth - min(counter, max_depth),
                'ns[14]': 1,  # namespace=14 is for categories, 0 for pages
                'language': 'en',
                'project': 'wikipedia',
                'format': 'json',
                'doit': 'Do it!'}

            r = requests.get('https://petscan.wmflabs.org/', params=params)
            data = r.json()

            for item in data['*'][0]['a']['*']:
                title = process_title(item.get('title'))
                if title and title not in categories:
                    categories.append(title)

    if categories:
        categories.sort()
        print(f"Extracted {len(categories)} subcategories from {categories[0]} to {categories[-1]}.\nWrite file {output_file}.")
        with open(output_file, 'w') as f:
            f.write('\n'.join(categories))

if __name__ == '__main__':
    parser = optparse.OptionParser(usage='Usage: %prog [options] [args]')

    parser.add_option('-i', dest='input_file', action='store', default='base_categories.txt', type='str',
                      help='input base categories list')
    parser.add_option('-o', dest='output_file', action='store', default='categories.txt', type='str',
                      help='extended wiki categories list')

    options, args = parser.parse_args()
    main(input_file=options.input_file, output_file=options.output_file)


from flask import Flask, render_template
import random
from datetime import datetime
app = Flask(__name__)

@app.route('/')
def home_page():
    date = datetime.now()
    year = date.strftime("%Y")
    random_no = random.randint(1, 10)
    #after file name you can give as many keyword arguements
    return render_template("index.html", num=random_no, copyright_year=year)

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

#by adding code between these brackets {{ }} code gets evaluated as python code


# -*- coding: utf-8 -*-
"""
Created on Sun Oct  9 15:25:46 2016

@author: Tom Blanchet

Example code for integrating a neural network
into an ai for the rps game.
"""

from rpsGame import RPSPlayer, RPSCustomVsGame
import numpy as np
from neuralNetwork import NeuralNetwork as NN, sigmoid
import random

def zeros(**kwargs):
    return np.zeros(kwargs['size'])

class RPSNeuralNetwork(NN):
    #I'll use this list parameter to help translate
    #into "neuron language" in the _translateThrow method
    _symbols = ['r', 'p', 's']

    def __init__(self, bufferSize=3, learnRate = .03, stability = 1.2):

        #The brain of the AI. The output will
        #attempt to predict the player's move, and the
        #AI's choice (accessed via predict) will be randomly decided based on
        #the network response.
        self._sep = 1.0
        self._learnRate = learnRate
        self._featureNum = len(self._symbols)**2
#        self._edgeSpaceApprox = .08
        self._edgeSpaceApprox = min(self._learnRate*bufferSize*stability, .45)
        featureNum = self._featureNum
        super().__init__([bufferSize*featureNum + 1, len(self._symbols)],
                          activationFuncs=sigmoid,\
                          samplers = zeros\
                          )
        #Buffer :: [[[(r, r), (r, p), (r, s), (p, r), ... , (s, p), (s, s)]],
        #           size = bufferSize
        #The tail element of the buffer is the most recent.
        self._buffer = [[0.0]*featureNum]*bufferSize
        return

    def __call__(self):
        return super().__call__(self._NNIn())

    def train(self, *args, **kwargs):
        super().train(self._NNIn(), *args, **kwargs)

    def feed(self, lastAiThrow, lastOpThrow):
        #Basically, if either of
        #the inputs are none, do nothing.
        #This is just to keep going
        #in case something breaks for some reason.
        if(lastOpThrow == None):
            return
        if(lastAiThrow == None):
            return

        #Train based on the results.
        edgeSpaceApprox = self._edgeSpaceApprox
        target = [edgeSpaceApprox]*len(self._symbols)
        target[self._symbols.index(lastOpThrow)] = 1.0 - edgeSpaceApprox
        self.train(target, self._learnRate)

        #Push the new outcome to the end of the buffer.
        self._appendBuffer(lastAiThrow, lastOpThrow)

    def predict(self):

        #we get a random number in [0, sum(raw_nl_out)), and subtract from that number
        #with the outputs until it is less than or equal to 0, and we
        #take that symbol as the prediction for the opponent's play.
        raw_nl_out = self()
        raw_nl_out -= min(np.min(raw_nl_out), self._edgeSpaceApprox)
#        print(raw_nl_out, self._symbols)
        roll = random.random()*sum(raw_nl_out)

        #break the loop when roll is non-positive. "i" will
        #then be the symbol index of the prediction for the opponents play.
        for i in range(len(raw_nl_out)):
            roll -= raw_nl_out[i]
            if roll <= 0:
                break
        op_play_guess = i

        return self._symbols[(op_play_guess + 1)%len(self._symbols)]

    def _NNIn(self):
        return np.append(1.0, np.array(self._buffer).flatten())

    @staticmethod
    def _throwsToIndex(lastAiThrow, lastOpThrow):
        return 3*RPSNeuralNetwork._symbols.index(lastAiThrow)\
                 + RPSNeuralNetwork._symbols.index(lastOpThrow)

    def _appendBuffer(self, lastAiThrow, lastOpThrow):
        del self._buffer[0]
        outcome = [0.0]*self._featureNum
        outcome[self._throwsToIndex(lastAiThrow, lastOpThrow)] = self._sep
        self._buffer.append(outcome);

class RPSPlayer_2PAiWithNN(RPSPlayer):
    """AI designed for a two player game

    The neural network nn will take in new data
    through the nn.feed(lastOpThrow, didWin) method,
    and will predict the best throw through
    the nn.predict() method.

    (nn.feed should be able to take None(s) by default.)
    """
    def __init__(self, engine, neuralNetwork):

        ##This line makes it so that
        ##everything happens that happens when
        ##a new RPSPlayer is instanciated
        super().__init__(engine)

        #Stuff here is to keep the nn stuff
        #here, and to
        self._nn = neuralNetwork()
        self._lastOpThrow = None
        self._lastAiThrow = None

    def giveThrows(self, throwList):

        #This line is good practice in case of
        #multiple inheritance. Just runs the
        #method of the superclass (in this case, RPSPlayer).
        super().giveThrows(throwList)

        #This will save the throw of the opponent.
        self._lastOpThrow = throwList[1-self.id]

    def giveWins(self, winNumber):
        #This line runs the giveWins method of the superclass
        #so that we don't have to rewrite however the game
        #internally keeps wins.
        super().giveWins(winNumber)

        #To track if we won the last game
        #if winNumber is 0, not winNumber is True,
        #so not not winNumber is False. Otherwise,
        #not winNumber is False, so not not winNumber
        #is True.
        self._didWinLast = not not winNumber

    def getThrow(self):
        self._nn.feed(self._lastAiThrow, self._lastOpThrow)
        self._lastAiThrow = self._nn.predict()
        return self._lastAiThrow


import numpy as np

def affine_forward(x, w, b):
  """
  Computes the forward pass for an affine (fully-connected) layer.

  The input x has shape (N, d_1, ..., d_k) and contains a minibatch of N
  examples, where each example x[i] has shape (d_1, ..., d_k). We will
  reshape each input into a vector of dimension D = d_1 * ... * d_k, and
  then transform it to an output vector of dimension M.

  Inputs:
  - x: A numpy array containing input data, of shape (N, d_1, ..., d_k)
  - w: A numpy array of weights, of shape (D, M)
  - b: A numpy array of biases, of shape (M,)

  Returns a tuple of:
  - out: output, of shape (N, M)
  - cache: (x, w, b)
  """
  out = None
  #############################################################################
  # TODO: Implement the affine forward pass. Store the result in out. You     #
  # will need to reshape the input into rows.                                 #
  #############################################################################
  """
  print("Affine forward")
  print(x.shape)
  print(w.shape)
  print(b.shape)
  """

  xr = x.reshape(x.shape[0], w.shape[0])
  out = xr.dot(w) + b

  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  cache = (x, w, b)
  return out, cache

def affine_backward(dout, cache):
  """
  Computes the backward pass for an affine layer.

  Inputs:
  - dout: Upstream derivative, of shape (N, M) (gradient sur les scores)
  - cache: Tuple of:
    - x: Input data, of shape (N, d_1, ... d_k)
    - w: Weights, of shape (D, M)

  Returns a tuple of:
  - dx: Gradient with respect to x, of shape (N, d1, ..., d_k)
  - dw: Gradient with respect to w, of shape (D, M)
  - db: Gradient with respect to b, of shape (M,)
  """
  x, w, b = cache
  dx, dw, db = None, None, None
  #############################################################################
  # TODO: Implement the affine backward pass.                                 #
  #############################################################################

  dw = x.reshape(x.shape[0], w.shape[0]).T.dot(dout)
  db = np.sum(dout, axis=0)
  dx = dout.dot(w.T).reshape(x.shape)

  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  return dx, dw, db

def relu_forward(x):
  """
  Computes the forward pass for a layer of rectified linear units (ReLUs).

  Input:
  - x: Inputs, of any shape

  Returns a tuple of:
  - out: Output, of the same shape as x
  - cache: x
  """
  out = None
  #############################################################################
  # TODO: Implement the ReLU forward pass.                                    #
  #############################################################################

  out = np.maximum(x,0)

  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  cache = x
  return out, cache

def relu_backward(dout, cache):
  """
  Computes the backward pass for a layer of rectified linear units (ReLUs).

  Input:
  - dout: Upstream derivatives, of any shape
  - cache: Input x, of same shape as dout

  Returns:
  - dx: Gradient with respect to x
  """
  dx, x = None, cache
  #############################################################################
  # TODO: Implement the ReLU backward pass.                                   #
  #############################################################################

  dx = dout
  dx[cache < 0] = 0
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  return dx

def batchnorm_forward(x, gamma, beta, bn_param):

  mode = bn_param['mode']
  eps = bn_param.get('eps', 1e-5)
  momentum = bn_param.get('momentum', 0.9)

  N, D = x.shape
  running_mean = bn_param.get('running_mean', np.zeros(D, dtype=x.dtype))
  running_var = bn_param.get('running_var', np.zeros(D, dtype=x.dtype))

  out, cache = None, {}
  if mode == 'train':

    sample_mean = np.mean(x,axis=0)
    sample_var = np.var(x,axis=0)

    num = x - sample_mean
    denom = np.sqrt(sample_var + eps)
    xnorm = num / denom
    out = gamma*xnorm + beta

    running_mean = momentum * running_mean + (1 - momentum) * sample_mean
    running_var = momentum * running_var + (1 - momentum) * sample_var

    cache['N'] = N
    cache['x'] = x
    cache['sample_mean'] = sample_mean
    cache['sample_var'] = sample_var
    cache['num'] = num
    cache['denom'] = denom
    cache['xnorm'] = xnorm
    cache['gamma'] = gamma
    cache['eps'] = eps

  elif mode == 'test':

    xnorm = (x - running_mean) / np.sqrt(running_var + eps)
    out = gamma*xnorm + beta

  else:
    raise ValueError('Invalid forward batchnorm mode "%s"' % mode)

  # Store the updated running means back into bn_param
  bn_param['running_mean'] = running_mean
  bn_param['running_var'] = running_var

  return out, cache

def batchnorm_backward(dout, cache):
  """
  Backward pass for batch normalization.

  For this implementation, you should write out a computation graph for
  batch normalization on paper and propagate gradients backward through
  intermediate nodes.

  Inputs:
  - dout: Upstream derivatives, of shape (N, D)
  - cache: Variable of intermediates from batchnorm_forward.

  Returns a tuple of:
  - dx: Gradient with respect to inputs x, of shape (N, D)
  - dgamma: Gradient with respect to scale parameter gamma, of shape (D,)
  - dbeta: Gradient with respect to shift parameter beta, of shape (D,)
  """
  dx, dgamma, dbeta = None, None, None

  dgamma = np.sum(cache['xnorm'] * dout, 0)
  dbeta = np.sum(dout, 0)

  sample_mean = cache['sample_mean']
  gamma = cache['gamma']
  N = cache['N']
  num = cache['num']
  denom = cache['denom']
  x = cache['x']

  dnorm = dout * gamma
  dnorm2 = np.sum(-(num * dnorm) / np.square(denom), 0)
  dsqrt = dnorm2 / (2 * denom)
  dsample_var = (2 * x - 2 * sample_mean) * dsqrt

  dsample_mean = np.sum(-dnorm / denom, 0)

  dx = dnorm / denom + dsample_var / N + dsample_mean / N

  return dx, dgamma, dbeta

def batchnorm_backward_alt(dout, cache):
  """
  Alternative backward pass for batch normalization.

  For this implementation you should work out the derivatives for the batch
  normalizaton backward pass on paper and simplify as much as possible. You
  should be able to derive a simple expression for the backward pass.

  Note: This implementation should expect to receive the same cache variable
  as batchnorm_backward, but might not use all of the values in the cache.

  Inputs / outputs: Same as batchnorm_backward
  """
  dx, dgamma, dbeta = None, None, None
  #############################################################################
  # TODO: Implement the backward pass for batch normalization. Store the      #
  # results in the dx, dgamma, and dbeta variables.                           #
  #                                                                           #
  # After computing the gradient with respect to the centered inputs, you     #
  # should be able to compute gradients with respect to the inputs in a       #
  # single statement; our implementation fits on a single 80-character line.  #
  #############################################################################
  pass
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################

  return dx, dgamma, dbeta

def dropout_forward(x, dropout_param):
  """
  Performs the forward pass for (inverted) dropout.

  Inputs:
  - x: Input data, of any shape
  - dropout_param: A dictionary with the following keys:
    - p: Dropout parameter. We drop each neuron output with probability p.
    - mode: 'test' or 'train'. If the mode is train, then perform dropout;
      if the mode is test, then just return the input.
    - seed: Seed for the random number generator. Passing seed makes this
      function deterministic, which is needed for gradient checking but not in
      real networks.

  Outputs:
  - out: Array of the same shape as x.
  - cache: A tuple (dropout_param, mask). In training mode, mask is the dropout
    mask that was used to multiply the input; in test mode, mask is None.
  """
  p, mode = dropout_param['p'], dropout_param['mode']
  if 'seed' in dropout_param:
    np.random.seed(dropout_param['seed'])

  mask = None
  #out = None

  if mode == 'train':

    mask = (np.random.rand(*x.shape) < (1-p)) / (1-p)
    out = x*mask

  elif mode == 'test':

    out = x

  cache = (dropout_param, mask)
  out = out.astype(x.dtype, copy=False)

  return out, cache

def dropout_backward(dout, cache):
  """
  Perform the backward pass for (inverted) dropout.

  Inputs:
  - dout: Upstream derivatives, of any shape
  - cache: (dropout_param, mask) from dropout_forward.
  """
  dropout_param, mask = cache
  mode = dropout_param['mode']

  dx = None
  if mode == 'train':

    dx = dout*mask

  elif mode == 'test':
    dx = dout
  return dx

def conv_forward_naive(x, w, b, conv_param):
  """
  A naive implementation of the forward pass for a convolutional layer.

  The input consists of N data points, each with C channels, height H and width
  W. We convolve each input with F different filters, where each filter spans
  all C channels and has height HH and width WW.

  Input:
  - x: Input data of shape (N, C, H, W)
  - w: Filter weights of shape (F, C, HH, WW)
  - b: Biases, of shape (F,)
  - conv_param: A dictionary with the following keys:
    - 'stride': The number of pixels between adjacent receptive fields in the
      horizontal and vertical directions.
    - 'pad': The number of pixels that will be used to zero-pad the input.

  Returns a tuple of:
  - out: Output data, of shape (N, F, H', W') where H' and W' are given by
    H' = 1 + (H + 2 * pad - HH) / stride
    W' = 1 + (W + 2 * pad - WW) / stride
  - cache: (x, w, b, conv_param)
  """
  out = None

  N, C, H, W = x.shape
  F, C, HH, WW = w.shape
  S = conv_param['stride']
  P = conv_param['pad']

  # Number of possible positions vertically
  Hp = 1 + (H + 2 * P - HH) / S

  # Number of possible positions horizontally
  Wp = 1 + (W + 2 * P - WW) / S

  # Output initialization
  out = np.zeros((N, F, Hp, Wp))
  xpad = np.pad(x, [(0,0), (0,0), (P,P), (P,P)], 'constant')

  for n in xrange(N): # for each image
      for f in xrange(F): # for each filter
        for i in xrange(Hp): # for each vertical possible position
          ix = i*S
          for j in xrange(Wp): # for each horizontal possible position
            jx = j*S

            window = xpad[n, :, ix:ix+HH, jx:jx+WW] # windows of the input on which the filter will be applied
            out[n,f,i,j] =  np.sum(window * w[f]) + b[f]

  cache = (x, w, b, conv_param)
  return out, cache

def conv_backward_naive(dout, cache):
  """
  A naive implementation of the backward pass for a convolutional layer.

  Inputs:
  - dout: Upstream derivatives.
  - cache: A tuple of (x, w, b, conv_param) as in conv_forward_naive

  Returns a tuple of:
  - dx: Gradient with respect to x
  - dw: Gradient with respect to w
  - db: Gradient with respect to b
  """
  dx, dw, db = None, None, None

  x, w, b, conv_param = cache
  pad = conv_param['pad']
  stride = conv_param['stride']
  F, C, HH, WW = w.shape
  N, C, H, W = x.shape
  Hp = 1 + (H + 2 * pad - HH) / stride
  Wp = 1 + (W + 2 * pad - WW) / stride

  dx = np.zeros_like(x)
  dw = np.zeros_like(w)
  db = np.zeros_like(b)

  padded = np.pad(x, [(0,0), (0,0), (pad,pad), (pad,pad)], 'constant')
  padded_dx = np.pad(dx, [(0,0), (0,0), (pad,pad), (pad,pad)], 'constant')

  for n in xrange(N): # ith example
    for f in xrange(F): # jth filter
      # Convolve this filter over windows
      for k in xrange(Hp):
        hs = k * stride
        for l in xrange(Wp):
          ws = l * stride

          # Window we applies the respective jth filter over (C, HH, WW)
          window = padded[n, :, hs:hs+HH, ws:ws+WW]

          # Compute gradient of out[n, f, k, l] = np.sum(window*w[f]) + b[f]
          db[f] += dout[n, f, k, l]
          dw[f] += window*dout[n, f, k, l]
          padded_dx[n, :, hs:hs+HH, ws:ws+WW] += w[f] * dout[n, f, k, l]

  # "Unpad"
  dx = padded_dx[:, :, pad:pad+H, pad:pad+W]

  return dx, dw, db

def max_pool_forward_naive(x, pool_param):
  """
  A naive implementation of the forward pass for a max pooling layer.

  Inputs:
  - x: Input data, of shape (N, C, H, W)
  - pool_param: dictionary with the following keys:
    - 'pool_height': The height of each pooling region
    - 'pool_width': The width of each pooling region
    - 'stride': The distance between adjacent pooling regions

  Returns a tuple of:
  - out: Output data
  - cache: (x, pool_param)
  """
  out = None

  # Get data dimemsions
  N, C, H, W = x.shape

  # Get pool params
  stride = pool_param['stride']
  pool_height = pool_param['pool_height']
  pool_width = pool_param['pool_width']

  # Nombre de positions possibles en hauteur
  Hp = (H - pool_height)/stride + 1

  # Nombre de positions possibles en largeur
  Wp = (W - pool_width)/stride + 1

  # Initialisation de l'output
  out = np.zeros((N, C, Hp, Wp))

  for n in xrange(N): # for each image
      for c in xrange(C): # for each filter
        for i in xrange(Hp): # for each vertical possible position
          ix = i*stride
          for j in xrange(Wp): # for each horizontal possible position
            jx = j*stride

            window = x[n, c, ix:ix+pool_height, jx:jx+pool_width]
            out[n,c,i,j] =  np.amax(window)

  cache = (x, pool_param)
  return out, cache

def max_pool_backward_naive(dout, cache):
  """
  A naive implementation of the backward pass for a max pooling layer.

  Inputs:
  - dout: Upstream derivatives
  - cache: A tuple of (x, pool_param) as in the forward pass.

  Returns:
  - dx: Gradient with respect to x
  """
  dx = None

  # Get cache
  x, pool_param = cache
  # Get data dimemsions
  N, C, H, W = x.shape

  # Get pool params
  stride = pool_param['stride']
  pool_height = pool_param['pool_height']
  pool_width = pool_param['pool_width']

  dx = np.zeros_like(x)

  # Nombre de positions possibles en hauteur
  Hp = (H - pool_height)/stride + 1

  # Nombre de positions possibles en largeur
  Wp = (W - pool_width)/stride + 1

  for n in xrange(N): # for each image
      for c in xrange(C): # for each filter
        for i in xrange(Hp): # for each vertical possible position
          ix = i*stride
          for j in xrange(Wp): # for each horizontal possible position
            jx = j*stride

            window = x[n, c, ix:ix+pool_height, jx:jx+pool_width]
            m = np.max(window)
            dx[n,c,ix:ix+pool_height,jx:jx+pool_width] += (window == m) * dout[n, c, i, j]

  return dx

def spatial_batchnorm_forward(x, gamma, beta, bn_param):
  """
  Computes the forward pass for spatial batch normalization.

  Inputs:
  - x: Input data of shape (N, C, H, W)
  - gamma: Scale parameter, of shape (C,)
  - beta: Shift parameter, of shape (C,)
  - bn_param: Dictionary with the following keys:
    - mode: 'train' or 'test'; required
    - eps: Constant for numeric stability
    - momentum: Constant for running mean / variance. momentum=0 means that
      old information is discarded completely at every time step, while
      momentum=1 means that new information is never incorporated. The
      default of momentum=0.9 should work well in most situations.
    - running_mean: Array of shape (D,) giving running mean of features
    - running_var Array of shape (D,) giving running variance of features

  Returns a tuple of:
  - out: Output data, of shape (N, C, H, W)
  - cache: Values needed for the backward pass
  """
  out, cache = None, None

  N, C, H, W = x.shape
  x_reshaped = x.transpose(0,2,3,1).reshape(N*H*W, C)
  out_tmp, cache = batchnorm_forward(x_reshaped, gamma, beta, bn_param)
  out = out_tmp.reshape(N, H, W, C).transpose(0, 3, 1, 2)

  return out, cache

def spatial_batchnorm_backward(dout, cache):
  """
  Computes the backward pass for spatial batch normalization.

  Inputs:
  - dout: Upstream derivatives, of shape (N, C, H, W)
  - cache: Values from the forward pass

  Returns a tuple of:
  - dx: Gradient with respect to inputs, of shape (N, C, H, W)
  - dgamma: Gradient with respect to scale parameter, of shape (C,)
  - dbeta: Gradient with respect to shift parameter, of shape (C,)
  """
  dx, dgamma, dbeta = None, None, None

  N, C, H, W = dout.shape
  dout_reshaped = dout.transpose(0,2,3,1).reshape(N*H*W, C)
  dx_tmp, dgamma, dbeta = batchnorm_backward(dout_reshaped, cache)
  dx = dx_tmp.reshape(N, H, W, C).transpose(0, 3, 1, 2)

  return dx, dgamma, dbeta

def svm_loss(x, y):
  """
  Computes the loss and gradient using for multiclass SVM classification.

  Inputs:
  - x: Input data, of shape (N, C) where x[i, j] is the score for the jth class
    for the ith input.
  - y: Vector of labels, of shape (N,) where y[i] is the label for x[i] and
    0 <= y[i] < C

  Returns a tuple of:
  - loss: Scalar giving the loss
  - dx: Gradient of the loss with respect to x
  """
  N = x.shape[0]
  correct_class_scores = x[np.arange(N), y]
  margins = np.maximum(0, x - correct_class_scores[:, np.newaxis] + 1.0)
  margins[np.arange(N), y] = 0
  loss = np.sum(margins) / N
  num_pos = np.sum(margins > 0, axis=1)
  dx = np.zeros_like(x)
  dx[margins > 0] = 1
  dx[np.arange(N), y] -= num_pos
  dx /= N
  return loss, dx

def softmax_loss(x, y):
  """
  Computes the loss and gradient for softmax classification.

  Inputs:
  - x: Input data, of shape (N, C) where x[i, j] is the score for the jth class
    for the ith input.
  - y: Vector of labels, of shape (N,) where y[i] is the label for x[i] and
    0 <= y[i] < C

  Returns a tuple of:
  - loss: Scalar giving the loss
  - dx: Gradient of the loss with respect to x
  """
  probs = np.exp(x - np.max(x, axis=1, keepdims=True))
  probs /= np.sum(probs, axis=1, keepdims=True)
  N = x.shape[0]
  loss = -np.sum(np.log(probs[np.arange(N), y])) / N
  dx = probs.copy()
  dx[np.arange(N), y] -= 1
  dx /= N
  return loss, dx


#!/usr/bin/python

#Runs tophat and cufflinks on a fixed set of samples.
import argparse
import cmn.cmn as cmn
import datetime
import libs.tuxedolib as tl
import libs.rnaseqlib as rl
import logging
import os
import rnaseq_settings_custom as rs
import shutil
import sys

parser = argparse.ArgumentParser()
parser.add_argument('-c', '--cufflinks', action="store_true",
        help='option to run cufflinks')
args = parser.parse_args()

COLQUERY = ['genotype', 'tube', 'sex', 'frozend', 'rnad', 'rnaconc',
            'mrnad', 'cdnad', 'indexnum', 'sample', 'seqd', 'thawed',
            'toseq', 'samplenum', 'sentd', 'qbitngul', 'qbitd', 'seq_received']

def main():
    rnaset = rs.RNASeqData()
    rnaseqdict = rnaset.__dict__
    curtime = datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S")
    cmn.makenewdir(rnaset.th_resdirpath)
    logpath = os.path.join(rnaset.th_resdirpath, '{}_'.format(curtime) +
            rnaseqdict['th_log_file'])
    rl.logginginfo(logpath)

    sberkids, seqpaths, respaths = rl.get_berkid_seq_res_paths(rnaset.berkidlist, \
        rnaset.sampleinfo_table, COLQUERY, rnaseqdict['seq_path'],
        rnaseqdict['seq_subdir'], rnaseqdict['th_resdirpath'])

    berkid_params = zip(sberkids, seqpaths, respaths)
    #for i in list(berkid_params):
        #print(i)
    for berkid, sample_seqdir, sample_resdir in berkid_params:
        tl.run_tophat_cufflinks(berkid, sample_seqdir, sample_resdir, rnaseqdict,
        args.cufflinks, rnaset.strand, rnaset.minintron)

    shutil.copy(rnaseqdict['set_path_orig'], '{}_{}'.format(rnaseqdict['th_set_path_copy'], curtime))

if __name__ == '__main__':
    main()


import time
from typing import Dict
import jwt
from decouple import config

JWT_SECRET = config("secret")
JWT_ALGORITHM = config("algorithm")

# Генерация токена
def signJWT( user_id: str, login: str) -> Dict[str, str]:
    payload = {
        "user_id": user_id,
        "login": login,
        "expires": time.time() + 600
    }
    token = jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)
    return  {"accessToken": token}

# Расшифровка токена
def decodeJWT(token: str) -> dict:
    try:
        decoded_token = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
        return decoded_token if decoded_token["expires"] >= time.time() else None
    except:
        return {}


import discord
from discord.ext import commands
import re
from carousell import CarousellScraper

client = commands.Bot(command_prefix='.')

def get_listings(item):
    web_page = CarousellScraper(item)
    filtered_web_page = web_page.get_page().find('main', class_=re.compile("D_"))
    return filtered_web_page.select('a[href^="/p"]')

@client.event
async def on_ready():
    print('Bot started')

@client.command(aliases=['list', 'listing', 'ls'])
async def listings(context, *, item):
    results = get_listings(item)
    channel = client.get_channel(856871861110308867)
    for r in results:
        try:
            names = r.select("a > p:nth-of-type(1)")
            name_result = names[0].get_text()
            if len(name_result) >= 140:
                continue
        except IndexError:
            pass
        else:
            prices = r.select("a > p:nth-of-type(2)")
            price_raw = prices[0].get_text().split('S$')
            del price_raw[0]
            price_result = price_raw[0]

            link = r['href']
            hyperlink = f'https://www.carousell.sg{link}'
            embed = discord.Embed(
                title=name_result,
                description=f'Price: ${price_result}\n[Link]({hyperlink})'
            )
            try:
                await channel.send(embed=embed)
            except discord.errors.HTTPException:
                pass

client.run('ODU2ODYwMzAzNjk4Mjk2ODcy.YNHLWA.V4VS1lioAkDrJe24YRvSXBEXJV8')


# -*- coding: utf-8 -*-
import uuid

from django.db import models
from django.utils.translation import gettext_lazy as _
from django_auxilium.models import BaseModel
from files.models import Attachment
from utils.models import BleachRichTextField, SlugFromNameMixin

class Announcement(SlugFromNameMixin, BaseModel):
    ALERT_LEVELS = [
        ("INFO", "Info"),
        ("WARNING", "Warning"),
        ("DANGER", "Danger"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    slug = models.SlugField(
        _("Slug"),
        max_length=64,
        blank=True,
        unique=True,
        db_index=True,
        help_text=_(
            "Announcement title as it will appear in the URL. "
            "Can only be alphanumeric with hyphens as word delimiter."
        ),
    )

    title = models.CharField(_("Title"), max_length=128)
    description = BleachRichTextField(_("Description"), allowed_tags=["a"])
    announcement_html = BleachRichTextField(_("Announcement"), blank=True)

    is_featured = models.BooleanField(_("Is Featured"), default=False)
    alert_level = models.CharField(
        _("Alert Level"), max_length=8, choices=ALERT_LEVELS, blank=True
    )
    start_date = models.DateField(_("Start Date"), null=True)
    end_date = models.DateField(_("End Date"), null=True)

    attachments = models.ManyToManyField(
        Attachment,
        related_name="announcements",
        verbose_name=Attachment._meta.verbose_name_plural,
        blank=True,
    )

    class Meta:
        verbose_name = _("Announcement")
        verbose_name_plural = _("Announcements")

    def __str__(self) -> str:
        return f"{self.start_date}-{self.end_date} - {self.title}"


import time
import sys
import os
import datetime
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler

def get_work_dir(folder):
    """
    Gets working directory is correct format depending on used operating system.
    :param folder: Folder name to get full path to (e.g Desktop, Downloads)
    :return: str: Full path to specified folder
    """
    work_dir = None
    if os.name == 'posix':
        work_dir = os.path.join(os.path.join(os.path.expanduser('~')), folder)
    elif os.name == 'nt':
        work_dir = os.path.join(os.path.join(os.environ['USERPROFILE']), folder)
    else:
        print('App will not run on this OS. Sorry. Exiting')
    return work_dir

def get_file_attr(f_src):
    """
    Gets files attributes (name, extension (type), source path) from full path.
    :param f_src: Full path to file
    :return: list, str. File name and extension; Full path to file
    """
    return f_src.split("\\")[-1].split(".")[-2:], f_src

def move_to_folder(f_name_ext, f_src, folder):
    """
    Main task: moves new file from observed path to specified folder in Documents
    Following sequence:
    1. Checks if specified folder is created in Documents. If not create it.
    2. Checks if file with the same name exists in specified folder. If exists add
    full today's date to new file (e.g file_2019_08_22_12_42_11).
    3. Move file to specified folder.
    :param f_name_ext: list containing file name and file type
    :param f_src: str full path to file
    :param folder: str folder name to move file to
    :return: nothing
    """

    f_current_src = f_src
    f_path = f'{get_work_dir("Documents")}/{folder}'
    if not os.path.exists(f_path):
        os.mkdir(f_path)
    if os.path.exists(f'{f_path}/{".".join(f_name_ext)}'):
        f_new_src = f'{f_path}/{f_name_ext[0]}_{datetime.datetime.now().strftime("%Y_%m_%d_%H_%m_%S")}.{f_name_ext[1]}'
    else:
        f_new_src = f'{f_path}/{".".join(f_name_ext)}'
    print(f'Moving file {".".join(f_name_ext)} to {folder}')
    os.rename(f_current_src, f_new_src)

class DesktopHandler(PatternMatchingEventHandler):
    """
    DesktopHandler inherits from on of the existing handlers - PatterMatchingEventHandler.
    """

    def process(self, event):
        """
        Process incoming events occurring in observing directory. If event is directory created
        processing is skipped. If even is a file created then file is moved to specified folder by type.
        Available types:
        images (jpg, png, gif, ..), documents (doc, docx, pdf, odt), video (mp4, avi, ..)
        sound (mp3, flac, ..), other if not falls into any categories
        :param event: object with 3 attributes (type, is_directory, src_path)
        :return: nothing
        """
        if event.is_directory:
            print('Directory is created. Skipping processing!')
            return
        f_name_ext, f_src = get_file_attr(event.src_path)
        dic_of_type = {'IMAGES': ['jpg', 'png', 'gif'],
                       'DOCUMENTS': ['doc', 'docx', 'pdf', 'odt', 'txt'],
                       'VIDEO': ['mp4', 'mov', 'avi'],
                       'SOUND': ['mp3', 'flac']}

        for folder, list_of_formats in dic_of_type.items():
            if f_name_ext[1] in list_of_formats:
                print(f'Moving file {".".join(f_name_ext)} to {folder}')
                time.sleep(1)
                return move_to_folder(f_name_ext, f_src, folder)
        return move_to_folder(f_name_ext, f_src, 'OTHER')

    def on_created(self, event):
        """
        Method is executed when a file or directory is created. Then method
        calls process method which process occurring event.
        :param event: object indicating event
        :return: nothing
        """
        self.process(event)

if __name__ == '__main__':
    print('----------------------------------------------------------------------')
    print('You can specify directory to which to clean by providing an argument')
    print('e.g python main.py /home/my_secret_folder')
    print('Otherwise it will use Desktop directory for Windows and Linux')
    print('----------------------------------------------------------------------')
    args = sys.argv[1:]
    watch_dir = None
    if args:
        watch_dir = args[0]
    else:
        watch_dir = get_work_dir('Desktop')
    print(f'Observing directory: {watch_dir}')
    """
    Observer class will watch for any change (in our case on_created), and then dispatch
    the event to specified handled. In our case - DesktopHandler()
    """
    observer = Observer()
    observer.schedule(DesktopHandler(), path=watch_dir if watch_dir else sys.exit(1))
    observer.start()

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
        observer.join()


#!/usr/bin/env python
import rospy
from std_msgs.msg import String #Imports msg

# Define callback function
def callback(msg):
	rospy.loginfo("I heard: %s" %(msg.data))

# Initialize the node with rospy
rospy.init_node('subscriber_node', anonymous=False)
# Create subscriber
subscriber = rospy.Subscriber("topic", String, callback)

rospy.spin() #Keeps the script for exiting


'''
@Author: mrwang
@Date: 2019-08-29 15:43:40
@LastEditors: mrwang
@LastEditTime: 2019-08-29 16:44:51
@Description:
'''
import sys

import h5py

import caffe
from caffe import layers as L
from caffe import params as P

def test(bottom):
    conv11 = caffe.layers.Convolution(bottom, num_output=20, kernel_size=3, weight_filler={"type": "xavier"},
                                bias_filler={"type": "constant"}, param=dict(lr_mult=1))
    relu11 = caffe.layers.PRelu(conv11, in_place=True)
    pool11 = caffe.layers.Pooling(relu11, pool=caffe.params.Pooling.MAX, kernel_size=3, stride=2)

    return pool11

def relu(bottom):
    return L.ReLU(bottom, in_place=True)

def prelu(bottom):
    return L.PReLU(bottom, in_place=True)

def drop(bottom, dropout_ratio):
    return L.Dropout(bottom, dropout_ratio=0.25, in_place=True)

def fully_connect(bottom, outputChannel):
    return L.InnerProduct(bottom, num_output=outputChannel, weight_filler=dict(type='xavier'))

def flatten(net, bottom):
    return net.blobs['bottom'].data[0].flatten()

def global_avg_pool(bottom, kernelSize=3):
    #return L.Pooling(bottom, pool=P.Pooling.AVE,stride=1, kernel_size=kernelSize)
    return L.Pooling(bottom, pool=P.Pooling.AVE, global_pooling=True)

def preluConv(bottom, outputChannel, kernelSize=(3, 5), stride=1, isTrain=True, isRelu=True):
    if len(kernelSize) == 2:
        conv = caffe.layers.Convolution(bottom, num_output=outputChannel, kernel_h=kernelSize[0], kernel_w=kernelSize[1], stride=stride, \
                                    weight_filler={"type": "xavier"},\
                                    bias_term=True, param=dict(lr_mult=1))
    elif len(kernelSize) == 1:
        conv = caffe.layers.Convolution(bottom, num_output=outputChannel, kernel_size=kernelSize[0], stride=stride, \
                                    weight_filler={"type": "xavier"},\
                                    bias_term=True, param=dict(lr_mult=1))
    else:
        pass
    if isRelu == True:
        return prelu(conv)
    else:
        return conv

def strpreluConv(bottom, outputChannel, kernelSize=3, stride=(1, 2), isTrain=True, isRelu=True):
    if len(stride) == 1:
        conv = caffe.layers.Convolution(bottom, num_output=outputChannel, kernel_size=kernelSize, stride=stride, \
                                    weight_filler={"type": "xavier"},\
                                    bias_term=True, param=dict(lr_mult=1))
    elif len(stride) == 2:
        conv = caffe.layers.Convolution(bottom, num_output=outputChannel, kernel_size=kernelSize, stride_h=stride[0], stride_w=stride[1], \
                                    weight_filler={"type": "xavier"},\
                                    bias_term=True, param=dict(lr_mult=1))
    else:
        pass
    if isRelu == True:
        return prelu(conv)
    else:
        return conv

def max_pool(bottom, kernelSize=3, stride=2):
    # return L.Pooling(bottom, pool=P.Pooling.MAX, stride_h=stride[0], stride_w=stride[1], kernel_h=kernelSize[0], kernel_w=kernelSize[1])
    return L.Pooling(bottom, pool=P.Pooling.MAX, stride=stride, kernel_size=kernelSize)
    # return L.Pooling(bottom, pool=P.Pooling.MAX, global_pooling=True)

# def BN(bottom, isTrain=True, isRelu=False):
#     use_global = False
#     if isTrain == False:
#         use_global=True
#     bn = caffe.layers.BatchNorm(bottom, use_global_stats=use_global, in_place=True)
#     scale = caffe.layers.Scale(bn, bias_term=True, in_place=True)
#     return scale
#     # if True == isRelu:
#     #     return relu(scale)
#     # else:
#     #     return scale

def BN(bottom, isTrain=True, isRelu=False):
    use_global = False
    if isTrain == False:
        use_global=True
    bn = caffe.layers.BatchNorm(bottom, use_global_stats=use_global, in_place=True)
    scale = caffe.layers.Scale(bn, bias_term=True, in_place=True)
    if True == isRelu:
        return relu(scale)
    else:
        return scale

def basicConv(bottom, outputChannel, kernelSize=3, stride=2, isTrain=True, isRelu=True):
    halfKernelSize = int(kernelSize/2)
    #print("half", halfKernelSize)
    if kernelSize == 1:
        halfKernelSize=0
    if halfKernelSize == 0:
        conv = caffe.layers.Convolution(bottom, num_output=outputChannel, kernel_size=kernelSize, stride=stride, \
                                weight_filler={"type": "xavier"},\
                                bias_term=False, param=dict(lr_mult=1))
    else:
        conv = caffe.layers.Convolution(bottom, num_output=outputChannel, pad=halfKernelSize, kernel_size=kernelSize, stride=stride, \
                                weight_filler={"type": "xavier"},\
                                bias_term=False, param=dict(lr_mult=1))
    bn = BN(conv, isTrain=isTrain)
    if isRelu == True:
        return relu(bn)
    else:
        return bn

## ==================== landmark  ==========================
def lmark_conv(bottom, outputChannel, kernel_size=3, stride=2, isTrain=False, isRelu=True):
    pad = int(kernel_size/2)
    conv = caffe.layers.Convolution(bottom, num_output=outputChannel, kernel_size=kernel_size, stride=stride, \
                                pad=pad, weight_filler={"type": "msra"},\
                                bias_term=False, param=dict(lr_mult=1))

    bn = BN(conv, isTrain=isTrain)
    if isRelu == True:
        return relu(bn)
    else:
        return bn

def lmark_global_avgpool(bottom, kernelSize=3):
    #return L.Pooling(bottom, pool=P.Pooling.AVE,stride=1, kernel_size=kernelSize)
    return L.Pooling(bottom, pool=P.Pooling.AVE, global_pooling=True)

def lmark_fully_connect(bottom, outputChannel):
    return L.InnerProduct(bottom, num_output=outputChannel, weight_filler=dict(type='xavier'))

## ====================  ssd mobilenet  ==========================
def conv_bn(name, input, output, kernel_size=3, stride=1, pad=1, activation=True, dilation=1):
    conv = L.Convolution(input, kernel_size=kernel_size, stride=stride, num_output=output, bias_term=False, pad=pad, weight_filler=dict(type='xavier'), dilation=dilation)

    # in-place compute means your input and output has the same memory area,which will be more memory effienct
    bn = L.BatchNorm(conv, use_global_stats=True, in_place=True)

    # scale = L.Scale(bn,filler=dict(value=1),bias_filler=dict(value=0),bias_term=True, in_place=True)
    out = L.Scale(bn, bias_term=True, in_place=True)

    if activation is True:
        out = L.ReLU(out, in_place=True)
    return out

def conv(input, output, kernel_size=3, stride=1, pad=1, activation=True):
    out = L.Convolution(input, kernel_size=kernel_size, stride=stride, num_output=output, bias_term=True, pad=pad, weight_filler=dict(type='xavier'))  # ,name = name

    if activation is True:
        out = L.ReLU(out, in_place=True)
    return out

def conv_fpn(input, output, kernel_size=3, stride=1, pad=1, activation=False):
    out = L.Convolution(input, kernel_size=kernel_size, stride=stride, num_output=output, bias_term=True, pad=pad, weight_filler=dict(type='xavier'))  # ,name = name

    if activation is True:
        out = L.ReLU(out, in_place=True)
    return out

def deconv(input, output, kernel_size=3, stride=2, pad=1, activation=True):
    out = L.Deconvolution(input, convolution_param=dict(kernel_size=kernel_size, stride=stride, num_output=output, pad=pad), param=[dict(lr_mult=0)])

    if activation is True:
        out = L.ReLU(out, in_place=True)
    return out

def eltwise(input, branch_shortcut):
    out = L.Eltwise(input, branch_shortcut, eltwise_param=dict(operation=1))
    return out

def mobconv1_bn_relu(input, output, kernel_size=1, stride=1, pad=0, activation=True):
    conv1 = L.Convolution(input, kernel_size=1, stride=1, num_output=output, bias_term=False, pad=pad, weight_filler=dict(type='xavier'))
    bn1 = L.BatchNorm(conv1, use_global_stats=True, in_place=True)
    scale1 = L.Scale(bn1, bias_term=True, in_place=True)
    out = L.ReLU(scale1, in_place=True)
    return out

def mobconv3_bn(input, output, kernel_size=3, stride=1, pad=1, group=1, activation=True):
    conv1 = L.Convolution(input, kernel_size=3, stride=stride, num_output=output, bias_term=False, pad=pad, group=group, weight_filler=dict(type='xavier'))
    bn1 = L.BatchNorm(conv1, use_global_stats=True, in_place=True)
    scale1 = L.Scale(bn1, bias_term=True, in_place=True)
    out = L.ReLU(scale1, in_place=True)
    return out

def mobconv1_bn(input, output, kernel_size=1, stride=1, pad=0, activation=False):
    conv1 = L.Convolution(input, kernel_size=1, stride=1, num_output=output, bias_term=False, pad=pad, weight_filler=dict(type='xavier'))
    bn1 = L.BatchNorm(conv1, use_global_stats=True, in_place=True)
    out = L.Scale(bn1, bias_term=True, in_place=True)
    return out

def mobconv1(input, output, kernel_size=1, stride=1, pad=0, activation=False):
    conv1 = L.Convolution(input, kernel_size=1, stride=1, num_output=output, bias_term=False, pad=pad, weight_filler=dict(type='xavier'))
    out = conv1
    return out

# def linear_bottleneck(input, output, kernel_size=3, stride=1, pad=1, t=1, group=1, activation=True):
#     residual = input
#     conv1 = mobconv1_bn_relu(input, input*t, kernel_size=1, stride=1, pad=0, activation=True)
#     conv2 = mobconv3_bn(conv1, input*t, input*t, kernel_size=3, stride=stride, pad=1, group=1, activation=True)
#     out = mobconv1_bn(conv2, input*t, output, kernel_size=1, stride=1, pad=0, activation=False)
#     if(stride==1 and input==output):
#         out += residual
#     return out

def mobilenet_conv_first(input, output, kernel_size=3, stride=2, pad=1, activation=True):
    conv1 = L.Convolution(input, kernel_size=3, stride=2, num_output=output, bias_term=False, pad=pad, weight_filler=dict(type='xavier'))
    bn1 = L.BatchNorm(conv1, use_global_stats=True, in_place=True)
    scale1 = L.Scale(bn1, bias_term=True, in_place=True)
    out = L.ReLU(scale1, in_place=True)
    return out

def mobilenet_conv_last(input, output, kernel_size=1, stride=1, pad=0, activation=True):
    conv1 = L.Convolution(input, kernel_size=1, stride=1, num_output=output, bias_term=False, pad=pad, weight_filler=dict(type='xavier'))
    bn1 = L.BatchNorm(conv1, use_global_stats=True, in_place=True)
    scale1 = L.Scale(bn1, bias_term=True, in_place=True)
    out = L.ReLU(scale1, in_place=True)
    return out

def extra_conv1(input, output, kernel_size=1, stride=1, pad=0, activation=True):
    conv1 = L.Convolution(input, kernel_size=1, stride=1, num_output=output, bias_term=False, pad=pad, weight_filler=dict(type='xavier'))
    bn1 = L.BatchNorm(conv1, use_global_stats=True, in_place=True)
    scale1 = L.Scale(bn1, bias_term=True, in_place=True)
    out = L.ReLU(scale1, in_place=True)
    return out

def extra_conv3(input, output, kernel_size=3, stride=2, pad=1, activation=True):
    conv1 = L.Convolution(input, kernel_size=3, stride=2, num_output=output, bias_term=False, pad=pad, weight_filler=dict(type='xavier'))
    bn1 = L.BatchNorm(conv1, use_global_stats=True, in_place=True)
    scale1 = L.Scale(bn1, bias_term=True, in_place=True)
    out = L.ReLU(scale1, in_place=True)
    return out

def loc_conf_conv(input, output, kernel_size=1, stride=1, pad=0, activation=False):
    out = L.Convolution(input, kernel_size=1, stride=1, num_output=output, bias_term=True, pad=pad, weight_filler=dict(type='xavier'))
    return out

def generate_network(name,  intputSize=[300, 300, 3], writePath=None,isTrain=False):

    net = caffe.NetSpec()
    net.data = L.Input(shape = dict(dim = [1,intputSize[2],intputSize[0],intputSize[1]]))

    if name == 'ssd_mobilenetv2_fpn':

        # # backbone
        base_channel = int(16)
        net.conv0 = mobilenet_conv_first(net.data, base_channel * 2, kernel_size=3, stride=2, pad=1)  # output: 32 * 150 * 150

##Bottleneck_0
        net.conv1 = mobconv1_bn_relu(net.conv0, base_channel * 2, kernel_size=1, stride=1, pad=0)     # output: 32   *150*150
        net.conv2 = mobconv3_bn(net.conv1, base_channel * 2, kernel_size=3, stride=1, pad=1, group=base_channel * 2)  # 32  *150*150  stride=1
        net.conv3 = mobconv1_bn(net.conv2, base_channel, kernel_size=1, stride=1, pad=0)   # 16
        # net.elt1 = eltwise(net.conv0, net.conv3)       ## input != output

##Bottleneck_1
        net.conv4 = mobconv1_bn_relu(net.conv3, base_channel * 6, kernel_size=1, stride=1, pad=0)  # output: 96
        net.conv5 = mobconv3_bn(net.conv4, base_channel * 6, kernel_size=3, stride=2, pad=1, group=base_channel * 6)  # 96  *75*75
        net.conv6 = mobconv1_bn(net.conv5, int(base_channel * 3/2), kernel_size=1, stride=1, pad=0)  # 24
        net.conv7 = mobconv1_bn_relu(net.conv6, base_channel * 9, kernel_size=1, stride=1, pad=0)  # 144
        net.conv8 = mobconv3_bn(net.conv7, base_channel * 9, kernel_size=3, stride=1, pad=1, group=base_channel * 9)  # 144
        net.conv9 = mobconv1_bn(net.conv8, int(base_channel * 3/2), kernel_size=1, stride=1, pad=0)  # 24
        net.elt1 = eltwise(net.conv6, net.conv9)        # --->  ok!!!  24 *75*75

##Bottleneck_2
        net.conv10 = mobconv1_bn_relu(net.elt1, base_channel * 9, kernel_size=1, stride=1, pad=0)  # 144
        net.conv11 = mobconv3_bn(net.conv10, base_channel * 9, kernel_size=3, stride=2, pad=1, group=base_channel * 9)  # 144   *38*38
        net.conv12 = mobconv1_bn(net.conv11, base_channel * 2, kernel_size=1, stride=1, pad=0)  # 32
        net.conv13 = mobconv1_bn_relu(net.conv12, base_channel * 12, kernel_size=1, stride=1, pad=0)  # 192
        net.conv14 = mobconv3_bn(net.conv13, base_channel * 12, kernel_size=3, stride=1, pad=1, group=base_channel * 12)  # 192
        net.conv15 = mobconv1_bn(net.conv14, base_channel * 2, kernel_size=1, stride=1, pad=0)  # 32
        net.elt2 = eltwise(net.conv12, net.conv15)
        net.conv16 = mobconv1_bn_relu(net.elt2, base_channel * 12, kernel_size=1, stride=1, pad=0)  # 192
        net.conv17 = mobconv3_bn(net.conv16, base_channel * 12, kernel_size=3, stride=1, pad=1, group=base_channel * 12)  # 192   ok

        net.conv18 = mobconv1_bn(net.conv17, base_channel * 2, kernel_size=1, stride=1, pad=0)  # 32  不一样
        # net.conv18 = mobconv1(net.conv17, base_channel * 2, kernel_size=1, stride=1, pad=0)

        net.elt3 = eltwise(net.elt2, net.conv18)      ##  -->  not ok!!!  32 * 38*38

##Bottleneck_3
        net.conv19 = mobconv1_bn_relu(net.elt3, base_channel * 12, kernel_size=1, stride=1, pad=0)  # 192
        net.conv20 = mobconv3_bn(net.conv19, base_channel * 12, kernel_size=3, stride=2, pad=1, group=base_channel * 12)  # 192 *19*19
        net.conv21 = mobconv1_bn(net.conv20, base_channel * 4, kernel_size=1, stride=1, pad=0)  # 64
        net.conv22 = mobconv1_bn_relu(net.conv21, base_channel * 24, kernel_size=1, stride=1, pad=0)  # 384
        net.conv23 = mobconv3_bn(net.conv22, base_channel * 24, kernel_size=3, stride=1, pad=1, group=base_channel * 24)  # 384
        net.conv24 = mobconv1_bn(net.conv23, base_channel * 4, kernel_size=1, stride=1, pad=0)  # 64
        net.elt4 = eltwise(net.conv21, net.conv24)
        net.conv25 = mobconv1_bn_relu(net.elt4, base_channel * 24, kernel_size=1, stride=1, pad=0)  # 384
        net.conv26 = mobconv3_bn(net.conv25, base_channel * 24, kernel_size=3, stride=1, pad=1, group=base_channel * 24)  # 384
        net.conv27 = mobconv1_bn(net.conv26, base_channel * 4, kernel_size=1, stride=1, pad=0)  # 64
        net.elt5 = eltwise(net.elt4, net.conv27)
        net.conv28 = mobconv1_bn_relu(net.elt5, base_channel * 24, kernel_size=1, stride=1, pad=0)  # 384
        net.conv29 = mobconv3_bn(net.conv28, base_channel * 24, kernel_size=3, stride=1, pad=1, group=base_channel * 24)  # 384
        net.conv30 = mobconv1_bn(net.conv29, base_channel * 4, kernel_size=1, stride=1, pad=0)  # 64
        net.elt6 = eltwise(net.elt5, net.conv30)              # -->  not ok!!!  64 * 19*19

##Bottleneck_4
        net.conv31 = mobconv1_bn_relu(net.elt6, base_channel * 24, kernel_size=1, stride=1, pad=0)  # 384
        net.conv32 = mobconv3_bn(net.conv31, base_channel * 24, kernel_size=3, stride=1, pad=1, group=base_channel * 24)  # 384   *19*19  stride=1
        # net.conv33 = mobconv1_bn(net.conv32, base_channel * 6, kernel_size=1, stride=1, pad=0)  # 96
        net.conv33 = mobconv1_bn(net.conv32, base_channel * 8, kernel_size=1, stride=1, pad=0)  # 128
        ## error this block
        net.conv34 = mobconv1_bn_relu(net.conv33, base_channel * 48, kernel_size=1, stride=1, pad=0)  # 576     ## 36 -> 48, change this channel ok....

        net.conv35 = mobconv3_bn(net.conv34, base_channel * 48, kernel_size=3, stride=1, pad=1, group=base_channel * 48)  # 576
        # net.conv36 = mobconv1_bn(net.conv35, base_channel * 6, kernel_size=1, stride=1, pad=0)  # 96
        net.conv36 = mobconv1_bn(net.conv35, base_channel * 8, kernel_size=1, stride=1, pad=0)  # 128
        net.elt7 = eltwise(net.conv33, net.conv36)

        net.conv37 = mobconv1_bn_relu(net.elt7, base_channel * 48, kernel_size=1, stride=1, pad=0)  # 576       ## 36 -> 48, change this channel ok....
        net.conv38 = mobconv3_bn(net.conv37, base_channel * 48, kernel_size=3, stride=1, pad=1, group=base_channel * 48)  # 576
        # net.conv39 = mobconv1_bn(net.conv38, base_channel * 6, kernel_size=1, stride=1, pad=0)  # 96    *19*19
        net.conv39 = mobconv1_bn(net.conv38, base_channel * 8, kernel_size=1, stride=1, pad=0)  # 128    *19*19
        net.elt8 = eltwise(net.elt7, net.conv39)        # 128    *19*19
        # net.elt8 = eltwise(net.elt7, net.deconv1)

##Bottleneck_5
        # net.conv40 = mobconv1_bn_relu(net.elt8, base_channel * 36, kernel_size=1, stride=1, pad=0)  # 576 -> 768    ## 36 -> 48, change this channel ok...
        net.conv40 = mobconv1_bn_relu(net.elt8, base_channel * 48, kernel_size=1, stride=1, pad=0)  # 576
        net.conv41 = mobconv3_bn(net.conv40, base_channel * 48, kernel_size=3, stride=2, pad=1, group=base_channel * 48)  # 576   *10*10
        net.conv42 = mobconv1_bn(net.conv41, base_channel * 10, kernel_size=1, stride=1, pad=0)  # 160
        net.conv43 = mobconv1_bn_relu(net.conv42, base_channel * 60, kernel_size=1, stride=1, pad=0)  # 960
        net.conv44 = mobconv3_bn(net.conv43, base_channel * 60, kernel_size=3, stride=1, pad=1, group=base_channel * 60)  # 960
        net.conv45 = mobconv1_bn(net.conv44, base_channel * 10, kernel_size=1, stride=1, pad=0)  # 160
        net.elt9 = eltwise(net.conv42, net.conv45)
        net.conv46 = mobconv1_bn_relu(net.elt9, base_channel * 60, kernel_size=1, stride=1, pad=0)  # 960
        net.conv47 = mobconv3_bn(net.conv46, base_channel * 60, kernel_size=3, stride=1, pad=1, group=base_channel * 60)  # 960
        net.conv48 = mobconv1_bn(net.conv47, base_channel * 10, kernel_size=1, stride=1, pad=0)  # 160
        net.elt10 = eltwise(net.elt9, net.conv48)

##Bottleneck_6
        net.conv49 = mobconv1_bn_relu(net.elt10, base_channel * 60, kernel_size=1, stride=1, pad=0)     # 960
        net.conv50 = mobconv3_bn(net.conv49, base_channel * 60, kernel_size=3, stride=1, pad=1, group=base_channel * 60)  # 960   *10*10  stride=1
        net.conv51 = mobconv1_bn(net.conv50, base_channel * 20, kernel_size=1, stride=1, pad=0)  # 320  ×10*10

## fpn
        net.fpn1 = conv_fpn(net.conv51, base_channel * 8, kernel_size=1, stride=1, pad=0)      ## add for fpn, C5
        net.deconv1 = deconv(net.fpn1, base_channel * 8, kernel_size=3, stride=2, pad=1)
        net.fpn2 = conv_fpn(net.fpn1, base_channel * 8, kernel_size=3, stride=1, pad=1)

        net.fpn3 = conv_fpn(net.elt8, base_channel * 8, kernel_size=1, stride=1, pad=0)
        net.fpnelt = eltwise(net.deconv1, net.fpn3)
        net.fpn4 = conv_fpn(net.fpnelt, base_channel * 8, kernel_size=3, stride=1, pad=1)

        # net.elt7 = eltwise(net.conv53, net.conv55)
        net.conv52 = mobilenet_conv_last(net.conv51, base_channel * 8, kernel_size=1, stride=1, pad=0, activation=True)
        # net.conv52 = mobilenet_conv_last(net.fpn2, base_channel * 80, kernel_size=1, stride=1, pad=0, activation=True)
        ## --> ok
##Extras_layer
        net.conv_ex1 = extra_conv1(net.conv52, base_channel * 16, kernel_size=1, stride=1, pad=0)    #256
        net.conv_ex2 = extra_conv3(net.conv_ex1, base_channel * 32, kernel_size=3, stride=2, pad=1)  #512   *5*5

        net.conv_ex3 = extra_conv1(net.conv_ex2, base_channel * 8, kernel_size=1, stride=1, pad=0)  #128
        net.conv_ex4 = extra_conv3(net.conv_ex3, base_channel * 16, kernel_size=3, stride=2, pad=1)  #256   *3*3

        net.conv_ex5 = extra_conv1(net.conv_ex4, base_channel * 8, kernel_size=1, stride=1, pad=0)  #128
        net.conv_ex6 = extra_conv3(net.conv_ex5, base_channel * 16, kernel_size=3, stride=2, pad=1)  #256   *2*2

        net.conv_ex7 = extra_conv1(net.conv_ex6, base_channel * 4, kernel_size=1, stride=1, pad=0)  #64
        net.conv_ex8 = extra_conv3(net.conv_ex7, base_channel * 8, kernel_size=3, stride=2, pad=1)  #128    *1*1

##loc and conf layer
        # net.loc1 = loc_conf_conv(net.elt8, base_channel, kernel_size=1, stride=1, pad=0)                 #96 -> 16
        # net.conf1 = loc_conf_conv(net.elt8, int(base_channel * 1/2), kernel_size=1, stride=1, pad=0)    #96 -> 8
        net.loc1 = loc_conf_conv(net.fpn4, base_channel, kernel_size=1, stride=1, pad=0)                 #96 -> 16
        net.conf1 = loc_conf_conv(net.fpn4, int(base_channel * 1/2), kernel_size=1, stride=1, pad=0)    #96 -> 8

        # net.loc2 = loc_conf_conv(net.conv52, int(base_channel * 3/2), kernel_size=1, stride=1, pad=0)    #1280 -> 24
        # net.conf2 = loc_conf_conv(net.conv52, int(base_channel * 3/4), kernel_size=1, stride=1, pad=0)  #1280 -> 12
        net.loc2 = loc_conf_conv(net.fpn2, int(base_channel * 3/2), kernel_size=1, stride=1, pad=0)    #1280 -> 24
        net.conf2 = loc_conf_conv(net.fpn2, int(base_channel * 3/4), kernel_size=1, stride=1, pad=0)  #1280 -> 12

        net.loc3 = loc_conf_conv(net.conv_ex2, int(base_channel * 3/2), kernel_size=1, stride=1, pad=0)    #512 -> 24
        net.conf3 = loc_conf_conv(net.conv_ex2, int(base_channel * 3/4), kernel_size=1, stride=1, pad=0)   #512 -> 12

        net.loc4 = loc_conf_conv(net.conv_ex4, int(base_channel * 3/2), kernel_size=1, stride=1, pad=0)    #256 -> 24
        net.conf4 = loc_conf_conv(net.conv_ex4, int(base_channel * 3/4), kernel_size=1, stride=1, pad=0)   #256 -> 12

        net.loc5 = loc_conf_conv(net.conv_ex6, int(base_channel * 3/2), kernel_size=1, stride=1, pad=0)    #256 -> 24
        net.conf5 = loc_conf_conv(net.conv_ex6, int(base_channel * 3/4), kernel_size=1, stride=1, pad=0)   #256 -> 12

        net.loc6 = loc_conf_conv(net.conv_ex8, int(base_channel * 3/2), kernel_size=1, stride=1, pad=0)    #128 -> 24
        net.conf6 = loc_conf_conv(net.conv_ex8, int(base_channel * 3/4), kernel_size=1, stride=1, pad=0)   #128 -> 12

    if name == 'landmark':
        base_channel = int(32)

        net.conv1 = lmark_conv(net.data, base_channel * 1, kernel_size=3, stride=2)
        net.conv2 = lmark_conv(net.conv1, base_channel * 2, kernel_size=3, stride=1)
        net.conv3 = lmark_conv(net.conv2, base_channel * 2, kernel_size=3, stride=2)
        net.conv4 = lmark_conv(net.conv3, base_channel * 4, kernel_size=3, stride=1)
        net.conv5 = lmark_conv(net.conv4, base_channel * 4, kernel_size=3, stride=2)

        net.conv6 = lmark_conv(net.conv5, base_channel * 4, kernel_size=3, stride=1)
        net.conv7 = lmark_conv(net.conv6, base_channel * 8, kernel_size=3, stride=2)
        net.conv8 = lmark_conv(net.conv7, base_channel * 16, kernel_size=3, stride=2)

        net.gap1 = lmark_global_avgpool(net.conv8)
        net.fc22 = lmark_fully_connect(net.gap1, 8)

    # transform
    proto = net.to_proto()
    proto.name = name

    with open(writePath, 'w') as f:
        print("start write!\n")
        f.write(str(proto))

    # 检查参数名
    net = caffe.Net(writePath, caffe.TEST)
    caffeParams = net.params
    for k in sorted(caffeParams):
        print(k)
    print(len(caffeParams))

if __name__ == '__main__':

    nettype = 'landmark' # 'pnet, onet, landmark'
    writePath = nettype + '.prototxt'
    if nettype == 'pnet':
        intputSize = [17, 47, 3]
    elif nettype == 'ssd_mobilenetv2_fpn':
        intputSize = [300, 300, 3]
    elif nettype == 'landmark':
        intputSize = [128, 128, 3]

    generate_network(nettype, intputSize=intputSize, writePath=writePath)