import numpy as np
import cv2
import math

from lane_lib import masking

# Class for lane detection on video frames
class LaneDetect():

    def __init__(self, M, Minv):

        self.M = M
        self.Minv = Minv
        self.initialised = False

        # BGR format
        self.colour_orange = (0, 165, 255) #(255, 0, 0)
        self.colour_red = (0, 0, 255)
        self.colour_green = (0, 255, 0)
        self.colour_light_blue = (180, 180, 50)

    # Main method to preprocess raw image, find lane lines and annotate input frame
    def detect(self, img, frame_overlay=True):

        # Apply binary masking
        self.mask = masking.BinaryMasking(img).mask
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img_size = self.mask.shape

        # Warp image to bird-eye view perspective
        self.img_binary_warped = cv2.warpPerspective(self.mask, self.M, (img_size[1], img_size[0]), flags=cv2.INTER_LINEAR)
        self.img_colour_warped = cv2.warpPerspective(img, self.M, (img_size[1], img_size[0]), flags=cv2.INTER_LINEAR)

        # Initialise for the first time to calculate base lane positions
        # Otherwise, search around margin from previous position
        if not self.initialised:
            if not self.init():
                return self.result_img
        else:
            self.update()

         # Thickness of fit lane lines to be drawn
        margin = 30

        # Define search window around the previous left and right fits
        left_search1 = np.array([(np.vstack([self.left_polyfit_x - margin, self.plot_y])).T])
        left_search2 = np.array([np.flipud((np.vstack([self.left_polyfit_x + margin, self.plot_y])).T)])
        left_pts = np.hstack((left_search1, left_search2))
        right_search1 = np.array([(np.vstack([self.right_polyfit_x - margin, self.plot_y])).T])
        right_search2 = np.array([np.flipud((np.vstack([self.right_polyfit_x + margin, self.plot_y])).T)])
        right_pts = np.hstack((right_search1, right_search2))

        # Draw the lane onto the warped blank image
        img_search_window = np.zeros_like(self.img_colour_warped)

        cv2.fillPoly(img_search_window, np.int_([left_pts]), self.colour_red)
        cv2.fillPoly(img_search_window, np.int_([right_pts]), self.colour_green)

        left_line = np.array([(np.vstack([self.left_polyfit_x[::-1], self.plot_y[::-1]])).T])
        right_line = np.array([(np.vstack([self.right_polyfit_x, self.plot_y])).T])
        line_pts = np.hstack((left_line, right_line))
        cv2.fillPoly(img_search_window, np.int_([line_pts]), self.colour_light_blue)

        img_lane = cv2.warpPerspective(img_search_window, self.Minv, (img_size[1], img_size[0]), flags=cv2.INTER_LINEAR)

        if frame_overlay:
            self.result_img = cv2.addWeighted(img, 1.0, img_lane, 0.6, 0)
        else:
            self.result_img = img_lane

        # Calculate curvature and annotate video
        self.lane_curvature()

        # Convert back to RGB colour space
        self.result_img = cv2.cvtColor(self.result_img, cv2.COLOR_BGR2RGB)

        return self.result_img

    # Calculate lane line curvature and annotate final image
    def lane_curvature(self):

        # Lane curvature
        y_m_px = 30. / 720      # meters/pixel in y direction
        x_m_px = 3.7 / 700      # meters/pixel in x direction

        # Calculate radius of curvature using maximum value of y (bottom-most of the frame)
        plot_y_max = np.max(self.plot_y)
        self.left_curve_rad = ((1 + (2 * self.left_polyfit[0] * plot_y_max * y_m_px + self.left_polyfit[1] * x_m_px)**2)**1.5) / np.absolute(2 * self.left_polyfit[0])
        self.right_curve_rad = ((1 + (2 * self.right_polyfit[0] * plot_y_max * y_m_px + self.right_polyfit[1] * x_m_px)**2)**1.5) / np.absolute(2 * self.right_polyfit[0])
        self.curvature = (self.left_curve_rad + self.right_curve_rad) / 2.0

        # Calculate offset of car from the centre
        self.offset = ((self.left_polyfit_x[10] + self.right_polyfit_x[10] - self.mask.shape[1]) / 2) * x_m_px

        if self.offset > 0:
            self.direction = 'Right'
        else:
            self.direction = 'Left'

        # Annotate video
        cv2.putText(self.result_img,
                    'Offset from Center = %.2f m (%s)' % (np.abs(self.offset), self.direction),
                    (int(self.mask.shape[1] * 0.35), 100), cv2.FONT_HERSHEY_SIMPLEX, 0.75, self.colour_orange, 2)

        cv2.putText(self.result_img,
                    'Radius of Curvature = %.2f m' % self.curvature,
                    (int(self.mask.shape[1] * 0.36), 140), cv2.FONT_HERSHEY_SIMPLEX, 0.75, self.colour_orange, 2)

    # Visualising Search Windows and Fit Lane Lines (used in Jupyter notebook)
    def draw_debug(self, img):

        # Undistort image frame
        img = cv2.undistort(img, self.mtx, self.dist, None, self.mtx)

        # Apply binary masking
        binary_masking = masking.BinaryMasking(img)
        self.mask = binary_masking.mask
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img_size = self.mask.shape

        # Warp image to bird-eye view perspective
        self.img_binary_warped = cv2.warpPerspective(self.mask, self.M, (img_size[1], img_size[0]), flags=cv2.INTER_LINEAR)
        img_binary_warped2 = np.copy(self.img_binary_warped)

        # Draw the lane onto the warped blank image
        self.img_search_window = np.zeros_like(img)

        # Initialise for the first time to calculate base lane positions
        self.init(silent=False)

        # Thickness of fit lane lines to be drawn
        margin = 15

        # Define search window around the previous left and right fits
        left_search1 = np.array([(np.vstack([self.left_polyfit_x - margin, self.plot_y])).T])
        left_search2 = np.array([np.flipud((np.vstack([self.left_polyfit_x + margin, self.plot_y])).T)])
        left_pts = np.hstack((left_search1, left_search2))
        right_search1 = np.array([(np.vstack([self.right_polyfit_x - margin, self.plot_y])).T])
        right_search2 = np.array([np.flipud((np.vstack([self.right_polyfit_x + margin, self.plot_y])).T)])
        right_pts = np.hstack((right_search1, right_search2))

        # Draw Left and Right Lane Lines
        cv2.fillPoly(self.img_search_window, np.int_([left_pts]), self.colour_red)
        cv2.fillPoly(self.img_search_window, np.int_([right_pts]), self.colour_green)

        # Draw Lane surface area (Between Left and Right Lanes)
        img_lane_area = np.zeros_like(img)
        left_line = np.array([(np.vstack([self.left_polyfit_x[::-1], self.plot_y[::-1]])).T])
        right_line = np.array([(np.vstack([self.right_polyfit_x, self.plot_y])).T])
        line_pts = np.hstack((left_line, right_line))
        cv2.fillPoly(img_lane_area, np.int_([line_pts]), self.colour_light_blue)

        # Combination 1: Left and Right fit lane lines + Search Window
        img_binary_warped_rgb = cv2.cvtColor(binary_masking.cv2_uint8(self.img_binary_warped), cv2.COLOR_GRAY2BGR)
        result_img = cv2.addWeighted(img_binary_warped_rgb, 0.8, self.img_search_window, 1.0, 0)

        # Combination 2: Lane Area + Binary Mask
        img_binary_warped2 = cv2.cvtColor(binary_masking.cv2_uint8(img_binary_warped2), cv2.COLOR_GRAY2BGR)
        result_img = cv2.addWeighted(img_lane_area, 0.7, result_img, 1.0, 0)

        # Final combination: Combination 1 + Combination 2
        self.result_img = cv2.addWeighted(img_binary_warped2, 0.8, result_img, 1.0, 0)

    # Initialise lane lines base position using histogramming and windowing from
    def init(self, silent=True):

        # Take a histogram of the image
        histogram = np.sum(self.img_binary_warped[:,:], axis=0)

        # Find the peak of the left and right of the histogram as the initial x for the two lanes
        centre = np.int(histogram.shape[0] / 2)
        left_x_init = np.argmax(histogram[:centre])
        right_x_init = np.argmax(histogram[centre:]) + centre

        # Choose the number of vertically stacked windows to divide the frame into
        num_windows = 8

        # Set height of windows
        window_height = np.int(self.img_binary_warped.shape[0] / num_windows)

        # Identify the x and y positions of all nonzero pixels in the image
        valid_xy = self.img_binary_warped.nonzero()
        valid_y = np.array(valid_xy[0])
        valid_x = np.array(valid_xy[1])

        # Current positions to be updated for each window
        left_x_current = left_x_init
        right_x_current = right_x_init

        # Set the width of the windows +/- margin
        margin = 100

        # Set minimum number of pixels found to recenter window
        minpix = 30

        # Store left and right lane pixel indices
        left_lane_idx = []
        right_lane_idx = []

        # Iterate through the windows one by one
        for window in range(num_windows):
            # Find window boundaries in x and y covering both lane lines
            win_y_low = self.img_binary_warped.shape[0] - (window + 1) * window_height
            win_y_high = self.img_binary_warped.shape[0] - window * window_height

            win_x_left_low = left_x_current - margin
            win_x_left_high = left_x_current + margin
            win_x_right_low = right_x_current - margin
            win_x_right_high = right_x_current + margin

            if not silent:

                # Draw windows and fit lane lines for visualisation
                left_rect_pts = [[win_x_left_low, win_y_low],
                                 [win_x_left_low, win_y_high],
                                 [win_x_left_high, win_y_high],
                                 [win_x_left_high, win_y_low]]

                right_rect_pts = [[win_x_right_low, win_y_low],
                                 [win_x_right_low, win_y_high],
                                 [win_x_right_high, win_y_high],
                                 [win_x_right_high, win_y_low]]

                cv2.fillPoly(self.img_binary_warped, np.int_([left_rect_pts]), self.colour_light_blue[::-1])
                cv2.fillPoly(self.img_binary_warped, np.int_([right_rect_pts]), self.colour_light_blue[::-1])

                cv2.rectangle(self.img_binary_warped,
                              (win_x_left_low, win_y_low), (win_x_left_high, win_y_high),
                              thickness=3, color=self.colour_light_blue)
                cv2.rectangle(self.img_binary_warped,
                              (win_x_right_low, win_y_low), (win_x_right_high, win_y_high),
                              thickness=3, color=self.colour_light_blue)

            good_left_idx_tmp = ((valid_y >= win_y_low) &
                                 (valid_y < win_y_high) &
                                 (valid_x >= win_x_left_low) &
                                 (valid_x < win_x_left_high)).nonzero()

            # Get the last nonzero index of left lane
            good_left_idx = good_left_idx_tmp[len(good_left_idx_tmp) - 1]

            good_right_idx_tmp = ((valid_y >= win_y_low) &
                                  (valid_y < win_y_high) &
                                  (valid_x >= win_x_right_low) &
                                  (valid_x < win_x_right_high)).nonzero()
            # Get the first nonzero index of right lane
            good_right_idx = good_right_idx_tmp[0]

            # Append these indices to the lists
            left_lane_idx.append(good_left_idx)
            right_lane_idx.append(good_right_idx)

            # If you found > minpix pixels, recenter next window on their mean position
            if len(good_left_idx) > minpix:
                left_x_current = np.int(np.mean(valid_x[good_left_idx]))

            if len(good_right_idx) > minpix:
                right_x_current = np.int(np.mean(valid_x[good_right_idx]))

        # Concatenate the arrays of indices
        left_lane_idx = np.concatenate(left_lane_idx)
        right_lane_idx = np.concatenate(right_lane_idx)

        # Extract left and right line pixel positions
        left_x = valid_x[left_lane_idx]
        left_y = valid_y[left_lane_idx]
        right_x = valid_x[right_lane_idx]
        right_y = valid_y[right_lane_idx]

        # If empty pixels in any side, reject this frame
        if not (len(left_x) and len(left_y) and len(right_x) and len(right_y)):
            # import pdb;pdb.set_trace()
            self.initialised = False
            return False

        # Fit a 2nd order polynomial for left and right lane lines
        left_polyfit = np.polyfit(left_y, left_x, 2)
        right_polyfit = np.polyfit(right_y, right_x, 2)

        # Prepare x, y values for plotting
        plot_y = np.linspace(0, self.img_binary_warped.shape[0]-1, self.img_binary_warped.shape[0])
        left_polyfit_x = left_polyfit[0]*plot_y**2 + left_polyfit[1]*plot_y + left_polyfit[2]
        right_polyfit_x = right_polyfit[0]*plot_y**2 + right_polyfit[1]*plot_y + right_polyfit[2]

        self.left_lane_idx = left_lane_idx
        self.right_lane_idx = right_lane_idx
        self.plot_y = plot_y
        self.left_polyfit = left_polyfit
        self.right_polyfit = right_polyfit
        self.left_polyfit_x = left_polyfit_x
        self.right_polyfit_x = right_polyfit_x

        self.initialised = True

        return True

    # Update search around margin from previous position
    def update(self):

        img_binary_warped = self.img_binary_warped
        valid_xy = img_binary_warped.nonzero()
        valid_y = np.array(valid_xy[0])
        valid_x = np.array(valid_xy[1])
        margin = 30

        self.left_lane_idx = ((valid_x > (self.left_polyfit[0] * (valid_y**2) + self.left_polyfit[1] * valid_y + self.left_polyfit[2] - margin)) &
                              (valid_x < (self.left_polyfit[0] * (valid_y**2) + self.left_polyfit[1] * valid_y + self.left_polyfit[2] + margin)))
        self.right_lane_idx = ((valid_x > (self.right_polyfit[0] * (valid_y**2) + self.right_polyfit[1] * valid_y + self.right_polyfit[2] - margin)) &
                               (valid_x < (self.right_polyfit[0] * (valid_y**2) + self.right_polyfit[1] * valid_y + self.right_polyfit[2] + margin)))

        # Get pixel positions of both lane sides
        left_x = valid_x[self.left_lane_idx]
        left_y = valid_y[self.left_lane_idx]
        right_x = valid_x[self.right_lane_idx]
        right_y = valid_y[self.right_lane_idx]

        # import pdb;pdb.set_trace()
        if not (len(left_x) and len(left_y) and len(right_x) and len(right_y)):
            self.initialised = False
            return False

        # Fit 2nd order polynomial to left and right lines
        self.left_polyfit = np.polyfit(left_y, left_x, 2)
        self.right_polyfit = np.polyfit(right_y, right_x, 2)

        # Prepare x, y values for plotting
        self.plot_y = np.linspace(0, img_binary_warped.shape[0]-1, img_binary_warped.shape[0])
        self.left_polyfit_x = self.left_polyfit[0]*self.plot_y**2 + self.left_polyfit[1]*self.plot_y + self.left_polyfit[2]
        self.right_polyfit_x = self.right_polyfit[0]*self.plot_y**2 + self.right_polyfit[1]*self.plot_y + self.right_polyfit[2]

        return True


from __future__ import print_function
from ortools.constraint_solver import pywrapcp
import random

def read_file(filename):
  """
    Reads the input file and outputs a list of wizard names in alphabetical
    order, and the list of constraints.
  """
  wizards = set()
  constraints = []
  file = open(filename, "r")
  file_text = file.readlines()
  for line in file_text[2:]:
    for name in line.split():
      wizards.add(name)
    constraints.append(line)
  return list(sorted(wizards)), constraints

def check_solution(ordering, constraints):
  """
    Input: An ordering of wizards and a list of constraints.
    Output: Whether the ordering satisfied the entire list of constraints.
    Prints the fraction of constraints satisfied.
  """
  num_constraints = len(constraints)
  correct = True
  count = num_constraints
  for i in range(num_constraints):
    c = constraints[i].split()
    w1 = ordering.index(c[0])
    w2 = ordering.index(c[1])
    w3 = ordering.index(c[2])
    if not((w3 < w1 and w3 < w2) or (w3 > w1 and w3 > w2)):
      count -= 1
      correct = False
  print("%i/%i constraints satisfied" % (count, num_constraints))
  return correct

def make_CP(wizards, constraints):
  """
    Input: A list of wizards and a list of constraints.
    Output: An ordering of wizards.
  """
  solver = pywrapcp.Solver("wizard-ordering")
  num_wizards = len(wizards)
  num_constraints = len(constraints)
  w = [solver.IntVar(0, num_wizards-1, "w%i" % i) for i in range(num_wizards)]

  solver.Add(solver.AllDifferent(w))
  for i in range(num_constraints):
    c = constraints[i].split()
    w1 = w[wizards.index(c[0])]
    w2 = w[wizards.index(c[1])]
    w3 = w[wizards.index(c[2])]
    t1 = solver.IsGreaterCstVar(w3-w1, 0)
    t2 = solver.IsGreaterCstVar(w3-w2, 0)
    solver.Add(t1 == t2)

  db = solver.Phase(w, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)

  solution = solver.Assignment()
  solution.Add(w)
  collector = solver.AllSolutionCollector()
  collector.Add(w)
  solutions_limit = solver.SolutionsLimit(1)

  solution = [] #Fill with (wizard, age) tuples
  if solver.Solve(db, [solutions_limit, collector]):
    print("Solution found")
    for j in range(num_wizards):
      age = collector.Value(0, w[j])
      solution.append((wizards[j], age))
      #print("w%i = " % j, age)
    print("Time:", solver.WallTime(), "ms")
  else:
    print("No solution")

  sort = sorted(solution, key = lambda n: n[1])
  ordering = [s[0] for s in sort]
  print(ordering)
  check_solution(ordering, constraints)
  return wizards

def main():
  file_test = "input35_4.in"
  w, c = read_file(file_test)
  make_CP(w, c)

if __name__ == '__main__':
  main()


#!/usr/bin/env python
from time import sleep, time
from threading import Thread, Event, Lock
from statsmodels.robust import mad
import pandas as pd #pandas is a data analysis library w some easy to use data structures
import matplotlib.pyplot as plt #plotting library
import numpy as np
import random, pywt, serial
from mpipe import OrderedStage, Pipeline
import socket
import json
import struct
import sys
import serial

HOSTClient = '127.0.0.3'
PORTClient = 5555
udpClient = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
origClient = (HOSTClient, PORTClient)
udpClient.connect(origClient)
ttl = struct.pack('b', 1)
udpClient.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
udpClient.settimeout(10)

def waveletDenoising(x, wavelet="db3", level=3):
    # calculate the wavelet coefficients
    coeff = pywt.wavedec(x, wavelet, mode="per")
    # calculate a threshold
    sigma = mad(coeff[-level])

    uthresh = sigma * np.sqrt(2*np.log(len(x)))
    coeff[1:] = (pywt.threshold(i, value=uthresh, mode="soft")
                 for i in coeff[1:])
    # reconstruct the signal using the thresholded coefficients
    return pywt.waverec(coeff, wavelet, mode="per")
    #fig, ax = plt.subplots()
    #plt.plot(x, color="b", alpha=0.4)
    #plt.plot(y, color="b")
    #ax.set_title('Signal Denoising')
    #ax.set_xlim((0, len(y)))
    #plt.show()

def readSerial(ser):
    for i in range(512):
        print(i)
        file = open("data_wfilter.txt", 'a+')
        last = 0
        try:
            line = ser.readline().decode("utf-8","ignore").split(",")
            last = float(line)
        except Exception as e:
            line = last
            pass
        finally:
            print(line)
            file.write('{}'.format(line) + "\n")
            file.close()
    #samples.pop(0)
    #samples.append(float(s))
    #avg = float(sum(samples)/filter_size)
    #print(s, " ", avg)
    #if input() == 'q':
    #  break
    #Aqui libera alguma trava para o envio

ser = serial.Serial('/dev/ttyACM0', 9600)

readSerial(ser)
df = pd.read_csv('data_wfilter.csv', sep="\n", header=None)
signal = np.array(df.values.flatten())

signal = waveletDenoising(signal)
udpClient.sendto(signal.encode(),origClient)


import asyncio
from threading import Thread
from datetime import datetime, timedelta
import os.path
import json

import discord
from discord.errors import LoginFailure
from discord.utils import get as discord_fetch

from utils import Console, cfg, app_scheduler, SuccessEmbed, ErrorEmbed, InfoEmbed

loop = asyncio.new_event_loop()
app_scheduler.main_loop = loop
client = discord.Client(loop=loop)
SHL = Console(prefix="BundestagsBot")

CONTENT_PATH = "content" if os.path.isdir("content") else "content-default"
SHL.info(f"Using content path: {CONTENT_PATH}")

about_embed = InfoEmbed(title="Help")
with open(os.path.join("static", "info.txt"), "r", encoding="utf-8") as fh:
    about_embed.description = fh.read()

class UserStat:
    def __init__(self, user_obj: discord.Member):
        self.user_obj = user_obj
        self.count = 1

    def __str__(self):
        return f"{self.user_obj.display_name}: {self.count}"

async def assign_active_member(*args):
    SHL.info("Fetching last messages.")
    guild = await client.fetch_guild(cfg.get("guild_id"))
    SHL.debug(f"Guild: {guild}")

    # Remove all "active" members
    SHL.info("Remove active role from all users.")
    for role in cfg.get("apply_roles"):
        role = guild.get_role(role)
        async for member in guild.fetch_members():
            if role not in member.roles:
                continue
            SHL.debug(f"Remove {role} from {member}")
            try:
                await member.remove_roles(role)
            except:
                SHL.debug(f"Failed for {member}")

    # Find new active members
    channels = await guild.fetch_channels()

    announcement_channel = await client.fetch_channel(cfg.get("announce_channel"))
    log_channel = await client.fetch_channel(cfg.get("log_channel"))

    users = {}
    before = datetime.now()
    after = datetime.now() - timedelta(days=31)

    with open(os.path.join(CONTENT_PATH, "unsubs.json"), "r") as fh:
        unsubs = json.load(fh)["unsub_ids"]

    SHL.debug(f"{len(unsubs)} users unsubbed.")

    for channel in channels:
        if not isinstance(channel, discord.TextChannel):
            continue
        if channel.id in cfg.get("exclude_channels"):
            continue

        SHL.debug(f"Fetching {channel.name}")
        async for message in channel.history(limit=None, before=before, after=after):
            uid = message.author.id
            if uid in unsubs:  # filter opt-out user
                continue
            if uid in users:
                users[uid].count += 1
            else:
                users[uid] = UserStat(message.author)

    sorted_list = sorted([x for x in users.values() if x.count >= cfg.get("needed_messages")],
                         key=lambda item: item.count, reverse=True)
    SHL.debug(f"{len(sorted_list)} users sent enough messages.")

    log_embed = InfoEmbed(title="Aktivste User - Log")
    for stat in sorted_list:  # active user
        try:
            member = await guild.fetch_member(stat.user_obj.id)
        except:  # if user left or got banned
            continue
        SHL.debug(f"Apply roles for {member}")
        log_embed.description += f"{member.mention} : {stat.count} Nachrichten.\n"
        for role in cfg.get("apply_roles"):
            assign_role = discord_fetch(guild.roles, id=role)
            try:
                await member.add_roles(assign_role)
            except:
                SHL.debug(f"Failed for {stat.user_obj}")
                break
    await log_channel.send(embed=log_embed)

    announcement = InfoEmbed(title="Aktivste User", description="Für die Auswahl der Stammmitglieder.\n"
                                                                "Nachrichtenanzahl im letzten Monat.")
    for stat in sorted_list[:3]:  # most active user
        member = await guild.fetch_member(stat.user_obj.id)
        announcement.description += f"{member.mention} : {stat.count} Nachrichten.\n"

    await announcement_channel.send(embed=announcement)
    await log_channel.send(embed=announcement)
    SHL.info("Done.")

@client.event
async def on_message(message: discord.Message):
    if message.content.startswith("_analyze"):
        SHL.info(f"{message.author} used {message.content}")
        if any([x in message.content.lower() for x in ["help", "info", "details", "about"]]):
            await message.channel.send(embed=about_embed)
            return

        if "true" in message.content.lower():
            with open(os.path.join(CONTENT_PATH, "unsubs.json"), "r") as fh:
                data = json.load(fh)
            try:
                data["unsub_ids"].remove(message.author.id)
            except ValueError:
                pass
            with open(os.path.join(CONTENT_PATH, "unsubs.json"), "w") as fh:
                json.dump(data, fh)
            await message.channel.send(embed=SuccessEmbed(title="Analyzer",
                                                          description="Deine Nachrichten werden nun wieder erfasst."))
            return

        if "false" in message.content.lower():
            with open(os.path.join(CONTENT_PATH, "unsubs.json"), "r") as fh:
                data = json.load(fh)
            if message.author.id not in data["unsub_ids"]:
                data["unsub_ids"].append(message.author.id)
            with open(os.path.join(CONTENT_PATH, "unsubs.json"), "w") as fh:
                json.dump(data, fh)
            await message.channel.send(embed=SuccessEmbed(title="Analyzer",
                                                          description="Deine Nachrichten werden nun nicht erfasst.\n"
                                                                      "Um diesen Vorgang rückgängig zu machen verwende `_analyze true`."))
            return

def start_bot():
    try:
        token = cfg.options["BOT_TOKEN"]
    except KeyError:
        SHL.error(f"========================")
        SHL.error(f"'BOT_TOKEN' not found in config files!")
        return
    try:
        SHL.info(f"Logging in.")
        client.run(token, reconnect=cfg.options.get("use_reconnect", False))
    except LoginFailure:
        SHL.error(f"========================")
        SHL.error(f"Login failure!")
        SHL.error(f"Please check your token.")
        return

thread_sched = Thread(target=app_scheduler.schedule_check, name="sched")
thread_sched.start()
app_scheduler.schedule_daily(func=assign_active_member, tag="test")
start_bot()


import matplotlib.pyplot as plt
import numpy as np
from scipy.constants import G
case=int(input("Case 1,2 > "))
#Constants
M=1.989e30
m=5.972e24
lamb=7.5e6

# In order to make eccentricity equal to 0.5
gamma=G*M*m
mu=m*M/(m+M)
L=(0.375*gamma**2*mu/3)**(1/3.)
E=-3*L

delta=np.array([-.6,-.1,0,.1,.6])
beta_0=mu*gamma/L**2
beta_1=2*mu*E/L**2-2*mu*gamma*delta/(lamb*L**2*(1+delta))
l=1./beta_0
if case==1:
    epsilon=np.sqrt(1+l**2*beta_1)
if case==2:
    beta_2=mu*gamma*delta/(L**2*lamb**2*(1+delta))
    epsilon=np.sqrt(1+l**2*beta_1+l**3*beta_2c)
#First Graph
count=0
varphi=np.linspace(0,2*np.pi, 1000)
styles=['-.', ':', '-', '--','-.']
e_N=epsilon[2]
r_N=l/(1+e_N*np.cos(varphi))

fig, axes = plt.subplots(2, 1)
for x in delta:
    r=l/(1+epsilon[count]*np.cos(varphi))
    axes[0].plot(r*np.cos(varphi), r*np.sin(varphi),
    label="$\delta=%.1f$"%x, linestyle=styles[count])
    d=abs(r-r_N)
    if count==0:
        r_max=max(d)
        axes[1].scatter(varphi[d.argmax()], r_max)
        axes[1].text(varphi[d.argmax()], r_max-500000, "%f m"%r_max)
    if count!=2:
        axes[1].plot(varphi, d, label="$\delta=%.1f$"%x,
         linestyle=styles[count])
    count+=1
axes[0].axhline(0, color='black')
axes[0].axvline(0, color='black')
axes[0].set_xlabel("x (meters)")
axes[0].set_ylabel("y (meters)")
axes[0].legend()

axes[1].set_xlabel(r"$\theta$")
axes[1].set_ylabel(r"$|r_N(\theta)-r(\theta,\delta)|$")
axes[1].legend()
plt.tight_layout()
plt.show()


import numpy as np
import cv2
import argparse

# Parse arguments
ap = argparse.ArgumentParser()
ap.add_argument('-v', '--video', required=True, help='Path to image file')
ap.add_argument('-w', '--width', type=int, default=0,
    help='Width to resize image to in pixels')
ap.add_argument('-n', '--num-clusters', type=int, default=3,
    help='Number of clusters for K-means clustering (default 3, min 2).')
args = vars(ap.parse_args())

if not args.get('video', False):
    # Read video file into a VideoCapture object
    cap = cv2.VideoCapture(args['video'])
else:
    # Read video from webcam
    cap = cv2.VideoCapture(0)

# Check if file/webcam was accessed successfully
if (cap.isOpened()== False):
  raise Exception('Error opening video file / accessing webcam.')

# Create MOG2 background subtractor
fgbg = cv2.createBackgroundSubtractorMOG2(history=300,varThreshold=16,detectShadows=False)

while(cap.isOpened()):
    ret, frame = cap.read()

    # Apply background subtraction to produce mask
    fgmask = fgbg.apply(frame)

    # Create and resize windows
    cv2.namedWindow('frame',cv2.WINDOW_NORMAL)
    cv2.namedWindow('fgmask',cv2.WINDOW_NORMAL)

    if args['width'] > 0:
        height = int((args['width'] / image.shape[1]) * image.shape[0])
        cv2.resizeWindow('frame',args['width'],height)
        cv2.resizeWindow('fgmask',args['width'],height)

    # Perform K-means clustering
    if args['num_clusters'] < 2:
        print('Warning: num-clusters < 2 invalid. Using num-clusters = 2')
    numClusters = max(2, args['num_clusters'])

    cv2.imshow('frame',frame)
    cv2.imshow('fgmask',fgmask)

    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

cap.release()
cv2.destroyAllWindows()


# coding=utf-8
import os
import torch
import torch.nn as nn
import torchvision.datasets as datasets
import torchvision.transforms as transforms
from torchvision.datasets.folder import default_loader

from config_tracer import config_tracer
from resnet import ResNet18
from model_cover import COVER_NET
from mydataset import MyDataset
import util
import numpy as np
import cv2
import shutil
import torch.nn.functional as F
import math
import random

def train():
    class_net = ResNet18()
    class_net.cuda().train()

    cover_net = COVER_NET()
    cover_net.cuda().train()

    ckpt_cover_path = "./ckpt_cover/"
    data_path, step = util.load_weight(ckpt_cover_path)
    if step:
        cover_net.load_state_dict(torch.load(data_path))

    ckpt_class_path = "./ckpt_class/"
    data_path, step = util.load_weight(ckpt_class_path)
    if step:
        class_net.load_state_dict(torch.load(data_path))

    batch = 64
    lr = 7e-5
    weight_decay = 0

    optimizer = torch.optim.Adam(util.models_parameters([cover_net, class_net]), lr, weight_decay=weight_decay)

    ckpt_optimizer_path = "./optimizer_ckpt/"
    # data_path, step_optimizer = util.load_weight(ckpt_optimizer_path)
    # if step_optimizer != step:
    #     print 'optimizer step error'
    #     return
    # else:
    #     if step_optimizer:
    #         optimizer.load_state_dict(torch.load(data_path))

    data_path = '/media/gdh-95/data/CT/CT_2d_note_slice2/train/'
    transform = transforms.Compose([transforms.RandomHorizontalFlip(),
                                    transforms.RandomVerticalFlip(),
                                    transforms.ToTensor(), ])
    train_set = datasets.ImageFolder(data_path, transform=transform)
    train_loader = torch.utils.data.DataLoader(train_set, batch_size=batch, shuffle=True, num_workers=2)

    dataiter = iter(train_loader)
    lenth_iter = len(dataiter)
    read_num = 0

    height = 64
    width = 64
    torchHorizontal = torch.linspace(-width / 2, width / 2, width).cuda().view(1, 1, 1, width).expand(1, 1, height,
                                                                                width)
    torchVertical = torch.linspace(-height / 2, -height / 2, height).cuda().view(1, 1, height, 1).expand(1, 1, height,
                                                                                width)
    grid = torchHorizontal * torchHorizontal + torchVertical * torchVertical
    grid_max = torch.max(grid)
    grid = grid / grid_max

    step0 = 100000001

    start = step
    for step in range(start + 1, step0):
        print("step0-", step)
        images, labels = next(dataiter)
        read_num += 1
        if read_num == lenth_iter - 1:
            dataiter = iter(train_loader)
            read_num = 0
        images = images.cuda()
        labels = labels.float().cuda()

        batch_one, _, _, _ = images.size()
        grid_one = grid.expand(batch_one, 1, height, width)

        cover_mask = cover_net(images)

        class_out = class_net(images, cover_mask)
        class_out = torch.mean(class_out, dim=1)

        loss_class = (class_out - labels)
        loss_class = (loss_class * loss_class).mean()
        loss_cover = torch.mean(cover_mask)
        loss = loss_class + loss_cover * 0.5

        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        loss_class_c = loss_class.cpu().data.numpy()
        loss_cover_c = loss_cover.cpu().data.numpy()
        print("            loss_class:", loss_class_c, "   loss_cover:", loss_cover_c)

        if step % 5000 == 0:
            print("save weight at step:%d" % (step))
            util.save_weight(class_net, step, ckpt_class_path)
            print("save weight at step:%d" % (step))
            util.save_weight(cover_net, step, ckpt_cover_path)
            print("save optimizer weight at step:%d" % (step))
            util.save_weight(optimizer, step, ckpt_optimizer_path)

def view():
    class_net = ResNet18()
    class_net.cuda().eval()

    cover_net = COVER_NET()
    cover_net.cuda().eval()

    ckpt_cover_path = "./ckpt_cover/"
    data_path, step = util.load_weight(ckpt_cover_path)
    if step:
        cover_net.load_state_dict(torch.load(data_path))

    ckpt_class_path = "./ckpt_class/"
    data_path, step = util.load_weight(ckpt_class_path)
    if step:
        class_net.load_state_dict(torch.load(data_path))

    batch = 64
    criterion = nn.CrossEntropyLoss()

    # data_path = '/media/gdh-95/data/CT_2d_note_slice/train/'
    data_path = '/home/guanzhilin/app/new_result_for_feat/'
    transform = transforms.Compose([transforms.ToTensor()])
    train_set = datasets.ImageFolder(data_path, transform=transform)
    train_loader = torch.utils.data.DataLoader(train_set, batch_size=batch, shuffle=True, num_workers=2)

    dataiter = iter(train_loader)
    lenth = len(train_set)
    print('img_num', lenth)
    out_path = './cover_2d_out/'

    if os.path.exists(out_path):
        shutil.rmtree(out_path)

    save_num = 0
    error_num = 0
    break_flag = 0
    area_add = 0
    batch_num = 0
    for images0, labels in dataiter:
        print('DEBUG images0 shape: ',images0.shape)
        # print('labels: ',labels)
        if break_flag:
            break
        batch_num += 1
        images0 = images0.cuda()
        labels0 = labels.cpu().data.numpy()

        images = images0 * 1
        labels = labels.float().cuda()
        cover_mask = cover_net(images)

        class_out = class_net(images, cover_mask)
        class_out = torch.mean(class_out, dim=1)
        loss_class = (class_out - labels)
        loss_class = (loss_class * loss_class).mean()
        loss_cover = torch.mean(cover_mask)

        area_add += loss_cover.cpu().data.numpy()

        error_b = (class_out - labels).abs().sum().cpu().data.numpy()
        error_num += error_b
        loss_class_c = loss_class.cpu().data.numpy()
        loss_cover_c = loss_cover.cpu().data.numpy()

        print("loss_class:", loss_class_c, "  loss_cover:", loss_cover_c)
        batch_max = images.size(0)
        for b in range(batch_max):
            image_one = images0[b:b + 1, :, :, :]
            cover_one = cover_mask[b:b + 1, :, :, :]
            overlay_one = image_one * 1
            overlay_one[:, 1, :, :] = overlay_one[:, 1, :, :] * (1 - cover_one)
            image_one = util.torch2numpy(image_one * 255)
            cover_one = np.squeeze(util.torch2numpy(cover_one * 255))
            overlay_one = util.torch2numpy(overlay_one * 255)
            # print labels0[b]
            # print str(labels0[b])
            save_path = out_path + str(labels0[b]) + '/'
            if not os.path.exists(save_path):
                os.makedirs(save_path)
            cv2.imwrite(save_path + str(save_num) + '_a.jpg', image_one)
            cv2.imwrite(save_path + str(save_num) + '_b.jpg', overlay_one)
            cv2.imwrite(save_path + str(save_num) + '_c.jpg', cover_one)
            save_num += 1

    print("error:", float(error_num) / float(save_num))
    print("area:", area_add / float(batch_num))

def view_new(patientname,savename):
    class_net = ResNet18()
    class_net.cuda().eval()

    cover_net = COVER_NET()
    cover_net.cuda().eval()

    ckpt_cover_path = config_tracer['cover_model']
    data_path, step = util.load_weight(ckpt_cover_path)
    if step:
        cover_net.load_state_dict(torch.load(data_path))

    ckpt_class_path = config_tracer['class_model']
    data_path, step = util.load_weight(ckpt_class_path)
    if step:
        class_net.load_state_dict(torch.load(data_path))

    batch = 64
    criterion = nn.CrossEntropyLoss()

    # data_path = '/media/gdh-95/data/CT_2d_note_slice/train/'
    data_path = os.path.join(config_tracer['feat_save_path'], patientname)
    transform = transforms.Compose([transforms.ToTensor()])
    # train_set = datasets.ImageFolder(data_path, transform=transform)
    test_set = MyDataset(data_path, transform)
    test_loader = torch.utils.data.DataLoader(test_set, batch_size=1, shuffle=False)

    lenth = len(test_set)
    print('img_num', lenth)
    out_path = os.path.join(config_tracer['output_path'], patientname)

    if os.path.exists(out_path):
        flush_dir(out_path)
    else:
        os.mkdir(out_path)

    save_num = 0

    for i,(filename, image_tensor, label) in enumerate(test_loader):
        image_tensor = image_tensor.cuda()
        # image_tensor = torch.unsqueeze(image_tensor, 0)
        # label = label.cpu().data.numpy()
        image = image_tensor * 1
        # label = label.float().cuda()
        cover_mask = cover_net(image)

        overlay = image * 1
        overlay[:,1, :, :] = overlay[:,1, :, :] * (1 - cover_mask)
        image_one = util.torch2numpy(image * 255)
        cover_one = np.squeeze(util.torch2numpy(cover_mask * 255))
        overlay_one = util.torch2numpy(overlay * 255)
        # print labels0[b]
        if not savename:
            savename=patientname
        cv2.imencode('.png', image_one)[1].tofile(
            os.path.join(out_path, str(i) + '_origin.jpg'))
        cv2.imencode('.png', overlay_one)[1].tofile(
            os.path.join(out_path, str(i) + '_overlay.jpg'))
        cv2.imencode('.png', cover_one)[1].tofile(
            os.path.join(out_path, str(i) + '_cover.jpg'))
        # cv2.imwrite(os.path.join(out_path, savename + '_origin.jpg'), image_one)
        # cv2.imwrite(os.path.join(out_path, savename + '_overlay.jpg'), overlay_one)
        # cv2.imwrite(os.path.join(out_path, savename + '_cover.jpg'), cover_one)
        save_num += 1

    print('save num', save_num)
    print('view_new OK')

def view_single(filename, savename):
    class_net = ResNet18()
    class_net.cuda().eval()

    cover_net = COVER_NET()
    cover_net.cuda().eval()

    ckpt_cover_path = config_tracer['cover_model']
    data_path, step = util.load_weight(ckpt_cover_path)
    if step:
        cover_net.load_state_dict(torch.load(data_path))

    ckpt_class_path = config_tracer['class_model']
    data_path, step = util.load_weight(ckpt_class_path)
    if step:
        class_net.load_state_dict(torch.load(data_path))

    input_path = config_tracer['input_path']
    out_path = config_tracer['output_path']
    if not os.path.exists(out_path):
        os.mkdir(out_path)
    img_path = os.path.join(input_path, filename)
    transform = transforms.Compose([transforms.ToTensor()])
    img_tensor = transform(default_loader(img_path))

    print('DEBUG: SHAPE ', img_tensor.shape)

    image_tensor = img_tensor.cuda()
    # image_tensor = torch.unsqueeze(image_tensor, 0)

    image = image_tensor * 1
    cover_mask = cover_net(image)

    overlay = image * 1
    overlay[:, 1, :, :] = overlay[:, 1, :, :] * (1 - cover_mask)

    image_one = util.torch2numpy(image * 255)
    cover_one = np.squeeze(util.torch2numpy(cover_mask * 255))
    overlay_one = util.torch2numpy(overlay * 255)

    if not savename:
        savename = 'unkown'
    cv2.imwrite(os.path.join(out_path, savename+'_origin.jpg', image_one))
    cv2.imwrite(os.path.join(out_path, savename+'_overlay.jpg', overlay_one))
    cv2.imwrite(os.path.join(out_path, savename+'_cover.jpg', cover_one))

    print('view single ok')

def visual_back_prop():
    FEAT_KEEP = 8  # Feature Maps to show
    FEAT_SIZE = 64  # Size of feature maps to show

    def save_feature_maps(self, input, output):
        # The hook function that saves feature maps while forward propagate
        map = output.data
        maps.append(map)

    def add_hook(net, func):
        for index, m in enumerate(net.layer1):
            type_name = str(type(m)).replace("<'", '').replace("'>", '').split('.')[-1]
            name = 'features' + '-' + str(index) + '-' + type_name
            hook = m.register_forward_hook(func)
            layers.append((name, m))
            hooks.append(hook)
        for index, m in enumerate(net.layer2):
            type_name = str(type(m)).replace("<'", '').replace("'>", '').split('.')[-1]
            name = 'features' + '-' + str(index) + '-' + type_name
            hook = m.register_forward_hook(func)
            layers.append((name, m))
            hooks.append(hook)
        for index, m in enumerate(net.layer3):
            type_name = str(type(m)).replace("<'", '').replace("'>", '').split('.')[-1]
            name = 'features' + '-' + str(index) + '-' + type_name
            hook = m.register_forward_hook(func)
            layers.append((name, m))
            hooks.append(hook)
        for index, m in enumerate(net.layer4):
            type_name = str(type(m)).replace("<'", '').replace("'>", '').split('.')[-1]
            name = 'features' + '-' + str(index) + '-' + type_name
            hook = m.register_forward_hook(func)
            layers.append((name, m))
            hooks.append(hook)

        return net

    def normalize_gamma(image, gamma=1.0):
        # normalize data for display
        if image.max() != image.min():
            image = (image - image.min()) / (image.max() - image.min())
        else:
            image = (image - image.min()) / 1
        invGamma = 1.0 / gamma
        image = (image ** invGamma) * 255
        return image.astype("uint8")

    def plotFeatMaps(layers, maps):

        '''
        :param layers: the saved layers
        :param maps: the saved maps
        :return: top feat. maps of relu layers
        '''

        num_layers = len(maps)
        feat_collection = []
        # Show top FEAT_KEEP feature maps (after ReLU) starting from bottom layers

        for n in range(num_layers):
            cur_layer = layers[n][1]
            if type(cur_layer):
                ##########################
                # Get and set attributes #
                ##########################
                relu = maps[n]

                ###########################################
                # Sort Feat Maps based on energy of F.M. #
                ###########################################
                feat_energy = []
                # Get energy of each channel
                for channel_n in range(relu.shape[1]):
                    feat_energy.append(np.sum(relu[0][channel_n].cpu().numpy()))
                feat_energy = np.array(feat_energy)
                # Sort energy
                feat_rank = np.argsort(feat_energy)[::-1]

                # Empty background
                # Empty background
                back_len = int(math.ceil(math.sqrt(FEAT_SIZE * FEAT_SIZE * FEAT_KEEP * 2)))
                feat = np.zeros((back_len, back_len))
                col = 0
                row = 0
                for feat_n in range(FEAT_KEEP):
                    if col * FEAT_SIZE + FEAT_SIZE < back_len:
                        feat[row * FEAT_SIZE:row * FEAT_SIZE + FEAT_SIZE, col * FEAT_SIZE:col * FEAT_SIZE + FEAT_SIZE] = \
                            cv2.resize(normalize_gamma(relu[0][feat_rank[feat_n]].cpu().numpy(), 0.1),
                                       (FEAT_SIZE, FEAT_SIZE))
                        col = col + 1
                    else:
                        row = row + 1
                        col = 0
                        feat[row * FEAT_SIZE:row * FEAT_SIZE + FEAT_SIZE, col * FEAT_SIZE:col * FEAT_SIZE + FEAT_SIZE] = \
                            cv2.resize(normalize_gamma(relu[0][feat_rank[feat_n]].cpu().numpy(), 0.1),
                                       (FEAT_SIZE, FEAT_SIZE))
                        col = col + 1

                feat_collection.append(feat)

        return feat_collection

    def visualbackprop(layers, maps):

        '''
        :param layers: the saved layers
        :param maps: the saved maps
        :return: return the final mask
        '''

        num_layers = len(maps)
        avgs = []
        mask = None
        ups = []

        for n in range(num_layers - 1, -1, -1):
            cur_layer = layers[n][1]
            if True:
                # if type(cur_layer) in [torch.nn.MaxPool2d]:
                #     print type(cur_layer)
                # Average filters
                fea_one = maps[n]
                # fea_one = F.instance_norm(fea_one)
                # fea_one = fea_one-torch.min(fea_one)
                avg = fea_one.mean(dim=1)
                avg = avg.unsqueeze(0)
                avgs.append(avg)

                if mask is not None:
                    h, w = avg.size()[2:]

                    mask = F.interpolate(mask, [h, w]).data
                    mask = mask * avg
                    # mask = torch.pow(mask,0.5)
                else:
                    mask = avg

                # upsampling : see http://pytorch.org/docs/nn.html#convtranspose2d
                weight = torch.ones(1, 1, 3, 3).cuda()
                up = F.conv_transpose2d(mask, weight, stride=1, padding=1)
                mask = up.data
                ups.append(mask)

        return ups

    def show_VBP(label, image):
        """Take an array of shape (n, height, width) or (n, height, width, 3)
           and visualize each (height, width) thing in a grid of size approx. sqrt(n) by sqrt(n)"""
        image = image.cpu().numpy()
        # normalize data for display
        if image.max() != image.min():
            data = (image - image.min()) / (image.max() - image.min())
        else:
            data = (image - image.min()) / 1
        data = data[0, 0, :, :]
        data = cv2.resize(data, new_size)
        data = (data * 255).astype("uint8")
        cv2.imwrite(label, data)

    def save_VBP(label, image):
        image = image.cpu().numpy()
        # normalize data for display
        if image.max() != image.min():
            data = (image - image.min()) / (image.max() - image.min())
        else:
            data = (image - image.min()) / 1
        data = data[0, 0, :, :]
        data = cv2.resize(data, new_size)
        data = (data * 255).astype("uint8")
        cv2.imwrite(label, data)

    def overlay(image, mask):
        # normalize data for display
        mask = (mask - mask.min()) / (mask.max() - mask.min())
        mask = mask[0, 0, :, :]
        mask = cv2.resize(mask, new_size)
        mask = (mask * 255).astype("uint8")
        # pdb.set_trace()
        # assert image.shape == mask.shape, "image %r and mask %r must be of same shape" % (image.shape, mask.shape)
        # if image[:,:,2] + mask > 255:
        # image[:,:,2] = image[:,:,2] + mask
        # else:
        image[:, :, 2] = cv2.add(image[:, :, 2], mask)

        return image

    torch.set_grad_enabled(False)

    class_net = ResNet18()
    class_net.cuda().train()

    cover_net = COVER_NET()
    cover_net.cuda().train()

    ckpt_cover_path = "./ckpt_cover/"
    data_path, step = util.load_weight(ckpt_cover_path)
    if step:
        cover_net.load_state_dict(torch.load(data_path))

    ckpt_class_path = "./ckpt_class/"
    data_path, step = util.load_weight(ckpt_class_path)
    if step:
        class_net.load_state_dict(torch.load(data_path))

    layers = []
    hooks = []
    add_hook(class_net, save_feature_maps)

    img_path = '/media/gdh-95/data/CT/CT_2d_note_slice/train/'
    folder_list = sorted(os.listdir(img_path))
    # print folder_list

    out_path = '../cover_vbp_train/'

    if os.path.exists(out_path):
        shutil.rmtree(out_path)

    for folder in folder_list:
        folder_path = img_path + folder + '/'
        img_list = sorted(os.listdir(folder_path))

        for img_name in img_list:
            print(img_name)
            img_one_path = folder_path + img_name

            maps = []
            images0 = cv2.imread(img_one_path)

            save_one = img_name[:img_name.find('.jpg')]

            FEAT_MAPS_DIR = out_path + folder + '/' + save_one + '/feat_maps'  # dir. to save feat maps
            # VBP_DIR = real_path+'/'+real_img_path+'/VBP_results'  # dir. to save VBP results
            OVERLAY_DIR = out_path + folder + '/' + save_one + '/'  # dir. to save overlay results

            if not os.path.exists(FEAT_MAPS_DIR):
                os.makedirs(FEAT_MAPS_DIR)

            # if not os.path.exists(VBP_DIR):
            #     os.makedirs(VBP_DIR)

            if not os.path.exists(OVERLAY_DIR):
                os.makedirs(OVERLAY_DIR)
            try:
                h0 = images0.shape[0]
                w0 = images0.shape[1]
            except:
                continue
            input_w = 64
            if h0 > w0:
                w1 = input_w
                h1 = h0 * input_w / w0
            else:
                h1 = input_w
                w1 = w0 * input_w / h0
            new_size = (w1, h1)

            images0 = cv2.resize(images0, new_size)
            cv2.imwrite(OVERLAY_DIR + '/zimg0.png', images0)

            img = util.numpy2torch(images0 * 1)
            img = img / 255.
            cover_mask = cover_net(img)
            class_out = class_net(img, cover_mask)

            cover_mask = util.torch2numpy(cover_mask)
            overlay1 = images0 * 1
            cover_mask = np.squeeze(cover_mask)
            # overlay1[:,:,2] = overlay1[:, :, 2]+ cover_mask*255
            # overlay1 = np.minimum(overlay1, 255)
            cover_mask = (cover_mask * 255).astype("uint8")
            overlay1[:, :, 2] = cv2.add(overlay1[:, :, 2], cover_mask)
            cover_one = cover_mask

            cv2.imwrite(OVERLAY_DIR + 'overlay1.jpg', overlay1)
            cv2.imwrite(OVERLAY_DIR + 'cover_mask.jpg', cover_one)

            feat_collection = plotFeatMaps(layers, maps)

            for i in range(len(feat_collection)):
                cv2.imwrite(FEAT_MAPS_DIR + '/feat_' + str(i) + '.jpg', feat_collection[i] * 255)
            masks = visualbackprop(layers, maps)
            mask_num = len(masks)

            for i in range(mask_num):
                # save_VBP(VBP_DIR + '/out_' + str(i) + '.png', masks[i])
                show_VBP(OVERLAY_DIR + '/vbp_' + str(i) + '.png', masks[i])

            overlay_img = overlay(images0, masks[mask_num - 1].cpu().numpy())
            cv2.imwrite(OVERLAY_DIR + 'overlay' + '.png', overlay_img)

def erasure_new_data():
    torch.set_grad_enabled(False)
    cover_net = COVER_NET()
    cover_net.cuda().train()

    random.seed(27)

    ckpt_cover_path = "./ckpt_cover/"
    data_path, step = util.load_weight(ckpt_cover_path)
    if step:
        cover_net.load_state_dict(torch.load(data_path))

    img_path = '/media/gdh-95/data/CT/CT_2d_note_slice2/train/'

    folder_list = sorted(os.listdir(img_path))
    # print folder_list
    out_path = '/media/gdh-95/data/CT/CT_2d_note_slice3/'
    train_path = out_path + 'train/'
    test_path = out_path + 'test/'

    test_rate = 0.1

    test_area = 0
    test_num = 0

    if os.path.exists(out_path):
        shutil.rmtree(out_path)
    for folder in folder_list:
        folder_path = img_path + folder + '/'
        img_list = sorted(os.listdir(folder_path))
        out_folder_train = train_path + folder + '/'
        out_folder_test = test_path + folder + '/'

        if not os.path.exists(out_folder_train):
            os.makedirs(out_folder_train)
        if not os.path.exists(out_folder_test):
            os.makedirs(out_folder_test)

        for img_name in img_list:
            print(img_name)
            img_one_path = folder_path + img_name
            images0 = cv2.imread(img_one_path)

            img = util.numpy2torch(images0 * 1)
            img = img / 255.
            cover_mask = cover_net(img)
            cover_mask = (cover_mask + 0.9).floor()
            new_img = (cover_mask * img) * 255
            new_img = util.torch2numpy(new_img)
            if random.uniform(0, 1) > test_rate:
                cover_mask_mean = cover_mask.mean().cpu().data.numpy()
                print('area:', cover_mask_mean)
                test_area += cover_mask_mean
                test_num += 1
                cv2.imwrite(out_folder_train + img_name, new_img)
            else:
                print("!!！!！!！!！!！!！")
                cv2.imwrite(out_folder_test + img_name, new_img)

    print('avg_mean:', test_area / test_num)

def new_data():
    random.seed(27)

    img_path = '/media/gdh-95/data/CT/CT_2d_note_slice2/train/'

    folder_list = sorted(os.listdir(img_path))
    # print folder_list
    out_path = '/media/gdh-95/data/CT/CT_2d_note_slice7/'
    train_path = out_path + 'train/'
    test_path = out_path + 'test/'

    test_rate = 0.1

    test_area = 0
    test_num = 0

    if os.path.exists(out_path):
        shutil.rmtree(out_path)
    for folder in folder_list:
        folder_path = img_path + folder + '/'
        img_list = sorted(os.listdir(folder_path))
        out_folder_train = train_path + folder + '/'
        out_folder_test = test_path + folder + '/'

        if not os.path.exists(out_folder_train):
            os.makedirs(out_folder_train)
        if not os.path.exists(out_folder_test):
            os.makedirs(out_folder_test)

        for img_name in img_list:
            print(img_name)
            img_one_path = folder_path + img_name
            images0 = cv2.imread(img_one_path)

            if random.uniform(0, 1) > test_rate:

                cv2.imwrite(out_folder_train + img_name, images0)
            else:
                print("!!！!！!！!！!！!！")
                cv2.imwrite(out_folder_test + img_name, images0)

def flush_dir(dirpath):
    for f in os.listdir(dirpath):
        f_path = os.path.join(dirpath, f)
        os.remove(f_path)
    print("flush", dirpath, "complete")


from django import forms
from django.forms import ModelForm
from .models import Visits
from django.utils.timezone import now
from datetime import date
from apps.visitdrug.tables import MedicineTable
from apps.patientdata.models import Patients

from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

# from django.contrib.postgres.search import SearchVector

def validate_none(value):
    if value == None:
        raise ValidationError(_('%(value)s must be not NONE'),
            params={'value': '0'},
        )

class VisitsForm(forms.ModelForm):

    # id = forms.IntegerField(required=False, label='Visit No.',
    #                        widget=forms.NumberInput(
    #                            attrs={
    #                                'class': 'form-control',
    #                                'readonly': 'readonly',
    #                             #    'style': ('background-color:lightgreen')
    #                            })
    #                        )
    # patient = forms.ModelChoiceField(queryset=Patients.objects.all(), required=True, label='Name',
    #                        widget=forms.Select(
    #                            attrs={
    #                                'class': 'form-control',
    #                                 'id': 'patient',
    #                                 # 'disabled':'disabled'
    #                            }
    #                        ))

    complain = forms.CharField(required=False, label='Complain',
                           widget=forms.Textarea(
                               attrs={
                                   'class': 'form-control',
                                #    'id': '',

                               })
                            )
    sign = forms.CharField(required=False, label='Sign',
                           widget=forms.Textarea(
                               attrs={
                                   'class': 'form-control',
                                #    'id': '',

                               })
                            )
    visitdate = forms.DateField(required=False, label='Visit Date',
                           widget=forms.TextInput(
                               attrs={
                                    'class': 'form-control',
                                    'placeholder':'Click here to enter the visit date ...',
                                    'value': date.today(),
                                    'id': 'visitdate',
                                    'type':'date',
                                    # 'readonly': 'readonly'
                               }
                           ))
    diagnosis = forms.CharField(required=False, label='Daignosis',
                            widget=forms.TextInput(
                                attrs={
                                   'class': 'form-control',
                                #    'id': '',

                               })
                            )
    intervention = forms.CharField(required=False, label='Intervention',
                            widget=forms.TextInput(
                                attrs={
                                   'class': 'form-control',
                                #    'id': '',

                               })
                            )
    amount = forms.IntegerField(required=False, label='Amount', #validators=[validate_none],
                           widget=forms.NumberInput(
                               attrs={
                                   'class': 'form-control',
                                #    'id': '',
                                    'value':'0'
                               }
                           ))

    def clean(self): # this method for prevent save or update the field 'amount' if it is None
        cleaned_data = super().clean()
        amount = cleaned_data.get('amount')
        visitdate = cleaned_data.get('visitdate')
        if amount == None:
            # self.add_error('amount', 'can not be None') # the error as outline (red line) of the input
            raise ValidationError('Amount Can Not Be Empty')
        if visitdate == None:
            self.add_error('visitdate', 'Date can\'t be Empty')
            raise ValidationError('Visit Date Can Not Be Empty')
            # return msg
        return cleaned_data

    class Meta:
        model = Visits
        fields = ('__all__')#('id', 'patient')#('__all__')
        # fields = ('__str__', 'address', )

    def __init__(self, *args, **kwargs):
        super(VisitsForm, self).__init__(*args, **kwargs)
        # self.id = self.fields['id']
        # self.fields['id'].widget.attrs['class'] = 'input'


# -*- coding: utf-8 -*-
import scrapy
from book.items import BookItem

#爬取小说阅读网的免费玄幻小说(信息)
class GetbookinfoSpider(scrapy.Spider):
    name = 'getbookinfo'
    allowed_domains = ['www.readnovel.com']
    pageNum = 1
    baseURL = 'https://www.readnovel.com/finish?pageSize=10&gender=1&catId=20001&isFinish=1&isVip=1&size=-1&updT=-1&orderBy=0&pageNum='
    start_urls = [baseURL + str(pageNum)]

    def parse(self, response):
        try:

            node_list = response.xpath("//div[@class='book-info']")

            for node in node_list:

                item = BookItem()

                item['book_name'] = node.xpath("./h3/a/text()").extract()[0]

                item['book_type'] = node.xpath("./p[1]/span[1]/text()").extract()[0]

                item['book_stat'] = node.xpath("./p[1]/span[2]/text()").extract()[0]

                item['book_author'] = node.xpath("./p[1]/span[3]/text()").extract()[0]

                yield item

            if self.pageNum != 16:
                self.pageNum += 1
                yield scrapy.Request(self.baseURL + str(self.pageNum), callback=self.parse)
        except Exception as e:
            print(e)


from django.urls import path,re_path
from . import views

urlpatterns = [
    path('',views.index,name='salaried.index'),
    path('<int:id>',views.show,name='salaried.show'),
    path('create',views.create,name='salaried.create'),
    path('update/<int:id>',views.update,name='salaried.update'),
    path('delete/<int:id>',views.delete,name='salaried.delete'),
    path('<int:salaried_id>/documents/delete/<int:document_id>',views.delete_document,name='salaried.documents.delete'),
    path('<int:salaried_id>/documents/create',views.create_document,name='salaried.documents.create'),
    path('<int:salaried_id>/documents/update/<int:document_id>',views.update_document,name='salaried.documents.update'),
]


#!/usr/bin/env python3
"""
Very simple HTTP server in python3.

Usage::
    ./dummy-web-server.py [<port>]

Send a GET request::
    curl http://localhost

Send a HEAD request::
    curl -I http://localhost

Send a POST request::
    curl -d "green=on/off&red=on/off" http://localhost
    curl -d "" http://localhost  - is the same "green=off&red=off"

"""
#from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from http.server import BaseHTTPRequestHandler, HTTPServer
#import SocketServer
import socketserver
import re
import OPi.GPIO as GPIO

class HTTP_GPIOCtrl(BaseHTTPRequestHandler):

  _unknown = """

unknown page

"""

  _form = """

GPIO LED control

<form method="post">

<input type="checkbox" name="green" value="on">green LED

<input type="checkbox" name="red" value="on">red LED

<input type="submit" value="Submit">

</form>

"""

  def __init__(self, request, client_address, server):
    BaseHTTPRequestHandler.__init__(self, request, client_address, server)

  def _set_headers(self, code=200):
    if code == 200:
      self.send_response(code)
      self.send_header('Content-type', 'text/html')
      self.end_headers()
    else:
      self.send_error(code)
      self.send_header('Content-type', 'text/html')
      self.end_headers()

  def do_GET(self):
    print('GET:->'+self.path+'<-')
    if self.path == '/':
      self._set_headers()
      self.wfile.write(bytes(self._form, "utf-8"))
      print("form")
    elif self.path == '/favicon.ico':
      self._set_headers(200)
      self.wfile.write(bytes("", "utf-8"))
      print("favicon")
#    self.wfile.write(bytes("
You accessed path: %s
" % self.path, "utf-8"))
    else:
      self._set_headers(404)
      self.wfile.write(bytes(self._unknown,"utf-8"))
      print("unknown")

  def do_HEAD(self):
    self._set_headers()

  def do_POST(self):
    content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
    post_data = self.rfile.read(content_length) # <--- Gets the data itself
    print (str(content_length) +' '+ str(post_data)) # <-- Print post data
    self._set_headers()
    self.wfile.write(bytes("
POST!
", "utf-8"))
    gpio24 = GPIO.LOW
    gpio26 = GPIO.LOW
    if content_length > 0:
      m = re.search('green=on', str(post_data))
      if m:
        gpio24 = GPIO.HIGH
      m = re.search('red=on', str(post_data))
      if m:
        gpio26 = GPIO.HIGH
    GPIO.output(24, gpio24)
    GPIO.output(26, gpio26)

#<- class HTTP_GPIOCtrl

def run(server_class=HTTPServer, handler_class=HTTP_GPIOCtrl, port=80):
  server_address = ('', port)
  httpd = server_class(server_address, handler_class)
  print('Starting httpd...')
  try:
    httpd.serve_forever()
  except KeyboardInterrupt:
    return httpd

if __name__ == "__main__":
  from sys import argv, exit

  GPIO.setmode(GPIO.BOARD)
  GPIO.setup(24, GPIO.OUT)
  GPIO.setup(26, GPIO.OUT)

  GPIO.output(24, GPIO.LOW)
  GPIO.output(26, GPIO.LOW)

  if len(argv) == 2:
      run(port=int(argv[1]))
  else:
      run().server_close()

  GPIO.cleanup()
  print('httpd exited')

  exit(0)


# /data2/wyf/code/jojogan-3d/training/projectors/w_projector.py
import copy
import wandb
import numpy as np
import torch
import torch.nn.functional as F
from tqdm import tqdm
import dnnlib
from PIL import Image
import numpy as np
import math
import PIL
import cv2
import os
import sys
import json
import torchvision.models as models
import torchvision.transforms as transforms
from torchvision.utils import save_image
# 当前目录指定
# sys.path.append('/data2/dxw/code/github/iccv2023/jojogan_encoder/')
sys.path.append('/data2/wyf/code/jojogan-3d')
from face_parsing.logger import setup_logger
from face_parsing.model import BiSeNet
from utils import log_utils
from configs import global_config, paths_config, hyperparameters
from ..volumetric_rendering.ray_sampler import RaySampler
from utils.camera_utils import compute_rotation_matrix_from_quaternion, euler2rot, rot6d_to_rotmat
from ..warping_loss import calc_warping_loss
import snoop
from criteria.id_loss import IDLoss
from lpips import LPIPS
# from criteria.moco_loss import MocoLoss
from skimage.metrics import structural_similarity as ssim
from skimage.metrics import peak_signal_noise_ratio as psnr

def mtx_similar2(arr1:np.ndarray, arr2:np.ndarray) ->float:
    '''
    如果矩阵大小不一样会在左上角对齐，截取二者最小的相交范围。
    :param arr1:矩阵1
    :param arr2:矩阵2
    :return:相似度（0~1之间）
    '''
    if arr1.shape != arr2.shape:
        minx = min(arr1.shape[0],arr2.shape[0])
        miny = min(arr1.shape[1],arr2.shape[1])
        differ = arr1[:minx,:miny] - arr2[:minx,:miny]
    else:
        differ = arr1 - arr2
    numera = np.sum(differ**2)
    denom = np.sum(arr1**2)
    similar = 1 - (numera / denom)
    return similar

def mtx_similar1(arr1:np.ndarray, arr2:np.ndarray) ->float:
    '''
    计算矩阵相似度的一种方法。将矩阵展平成向量，计算向量的乘积除以模长。
    :param arr1:矩阵1
    :param arr2:矩阵2
    :return:实际是夹角的余弦值，ret = (cos+1)/2
    '''
    farr1 = arr1.ravel()
    farr2 = arr2.ravel()
    len1 = len(farr1)
    len2 = len(farr2)
    if len1 > len2:
        farr1 = farr1[:len2]
    else:
        farr2 = farr2[:len1]
    numer = np.sum(farr1 * farr2)
    denom = np.sqrt(np.sum(farr1**2) * np.sum(farr2**2))
    similar = numer / denom
    return  (similar+1) / 2 # 姑且把余弦函数当线性

def calc_l2loss(real_images, generated_images):
    l2_criterion = torch.nn.MSELoss(reduction='mean')
    loss = l2_criterion(real_images, generated_images)
    return loss

def calc_ssim(img1_path, img2_path):
    '''
    Parameters
    ----------
    img1_path : str
        图像1的路径.
    img2_path : str
        图像2的路径.

    Returns
    -------
    ssim_score : numpy.float64
        结构相似性指数（structural similarity index，SSIM）.

    References
    -------
    https://scikit-image.org/docs/dev/auto_examples/transform/plot_ssim.html

    '''
    img1 = Image.open(img1_path).convert('L')
    img2 = Image.open(img2_path).convert('L')
    img2 = img2.resize(img1.size)
    img1, img2 = np.array(img1), np.array(img2)
    # 此处因为转换为灰度值之后的图像范围是0-255，所以data_range为255，如果转化为浮点数，且是0-1的范围，则data_range应为1
    ssim_score = ssim(img1, img2, data_range=255)
    return ssim_score

def calc_psnr(img1_path, img2_path):
    '''
    Parameters
    ----------
    img1_path : str
        图像1的路径.
    img2_path : str
        图像2的路径.

    Returns
    -------
    psnr_score : numpy.float64
        峰值信噪比(Peak Signal to Noise Ratio, PSNR).

    References
    -------
    https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio

    '''
    img1 = Image.open(img1_path)
    img2 = Image.open(img2_path)
    img2 = img2.resize(img1.size)
    img1, img2 = np.array(img1), np.array(img2)
    # 此处的第一张图像为真实图像，第二张图像为测试图像
    # 此处因为图像范围是0-255，所以data_range为255，如果转化为浮点数，且是0-1的范围，则data_range应为1
    psnr_score = psnr(img1, img2, data_range=255)
    return psnr_score

def vis_parsing_maps(im, parsing_anno, stride, save_im=False, save_path='vis_results/parsing_map_on_im.jpg'):
    # Colors for all 20 parts
    part_colors = [[255, 0, 0], [255, 85, 0], [255, 170, 0],
                   [255, 0, 85], [255, 0, 170],
                   [0, 255, 0], [85, 255, 0], [170, 255, 0],
                   [0, 255, 85], [0, 255, 170],
                   [0, 0, 255], [85, 0, 255], [170, 0, 255],
                   [0, 85, 255], [0, 170, 255],
                   [255, 255, 0], [255, 255, 85], [255, 255, 170],
                   [255, 0, 255], [255, 85, 255], [255, 170, 255],
                   [0, 255, 255], [85, 255, 255], [170, 255, 255]]
    im = np.array(im)
    vis_im = im.copy().astype(np.uint8)
    vis_parsing_anno = parsing_anno.copy().astype(np.uint8)
    vis_parsing_anno = cv2.resize(vis_parsing_anno, None, fx=stride, fy=stride, interpolation=cv2.INTER_NEAREST)
    vis_parsing_anno_color = np.zeros((vis_parsing_anno.shape[0], vis_parsing_anno.shape[1], 3)) + 255
    num_of_class = np.max(vis_parsing_anno)
    for pi in range(1, num_of_class + 1):
        index = np.where(vis_parsing_anno == pi)
        vis_parsing_anno_color[index[0], index[1], :] = part_colors[pi]
    vis_parsing_anno_color = vis_parsing_anno_color.astype(np.uint8)
    # print(vis_parsing_anno_color.shape, vis_im.shape)
    vis_im = cv2.addWeighted(cv2.cvtColor(vis_im, cv2.COLOR_RGB2BGR), 0.4, vis_parsing_anno_color, 0.6, 0)
    # Save result or not
    if save_im:
        cv2.imwrite(save_path[:-4] +'.png', vis_parsing_anno)
        cv2.imwrite(save_path, vis_im, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
    return vis_im

def calc_mask(pred_images_path, target_e4e_path, respth=paths_config.root_path + '/face_parsing/res/test_res', dspth=paths_config.root_path + '/face_parsing/res/data', cp=paths_config.root_path + '/face_parsing/pretrained/79999_iter.pth'):
    if not os.path.exists(respth):
        os.makedirs(respth)
    n_classes = 19
    net = BiSeNet(n_classes=n_classes)
    net.cuda()
    save_pth = os.path.join('res/cp', cp)
    net.load_state_dict(torch.load(save_pth))
    net.eval()
    to_tensor = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
    ])
    with torch.no_grad():
        for image_path in os.listdir(dspth):
            img = Image.open(os.path.join(dspth, image_path))
            image = img.resize((512, 512), Image.BILINEAR)
            img = to_tensor(image)
            img = torch.unsqueeze(img, 0)
            img = img.cuda()
            out = net(img)[0]
            parsing = out.squeeze(0).cpu().numpy().argmax(0)
            vis_parsing_maps(image, parsing, stride=1, save_im=True, save_path=os.path.join(respth, image_path))
    # pred_out_images_path = '/data2/dxw/code/github/iccv2023/jojogan_encoder/face_parsing/res/test_res/pred_images.jpg'
    # target_out_e4e_path = '/data2/dxw/code/github/iccv2023/jojogan_encoder/face_parsing/res/test_res/target_e4e.jpg'
    # pred_out_images_path = '/data2/wyf/code/jojogan-3d/face_parsing/res/test_res/pred_images.jpg'
    # target_out_e4e_path = '/data2/wyf/code/jojogan-3d/face_parsing/res/test_res/target_e4e.jpg'
    pred_out_images_path = paths_config.root_path + '/face_parsing/res/test_res/pred_images.jpg'
    target_out_e4e_path = paths_config.root_path + '/face_parsing/res/test_res/target_e4e.jpg'
    pred_images = Image.open(pred_out_images_path)
    pred_images = pred_images.resize((512, 512), Image.BILINEAR)
    pred_images = to_tensor(pred_images)
    pred_images = torch.unsqueeze(pred_images, 0)
    pred_images = pred_images.cuda()
    target_e4e = Image.open(target_out_e4e_path)
    target_e4e = target_e4e.resize((512, 512), Image.BILINEAR)
    target_e4e = to_tensor(target_e4e)
    target_e4e = torch.unsqueeze(target_e4e, 0)
    target_e4e = target_e4e.cuda()
    return pred_images,target_e4e

def jojogan_img_loss_eg3d(generator,w_pivot,cam_pose,target_img):
    # 生成扰动的w
    z = torch.randn(1, generator.z_dim).to('cuda')
    ws = generator.mapping(z, cam_pose)  # [N, L, C]
    # alpha越大，保持原本风格越大，alpha越小，随机性越大。
    in_latent = w_pivot.clone()
    # 低分辨率的style 控制姿态、脸型、配件 比如眼镜、发型等style,高分辨率的style控制肤色、头发颜色、背景色等style。
    id_swap=[7,8,9,10,11,12,13]
    # id_swap=[1,3,5,7,9,10,11,12,13]
    # id_swap=[1,3,5,7]
    alpha=0.2
    in_latent[:, id_swap,:] = alpha*w_pivot[:, id_swap,:] + (1-alpha)*ws[:, id_swap,:]
    # c.shape = (1, 25)
    # w_styles.shape = (4, 18, 512)
    # trainable_img = self.generator_nada(w_styles, c=c.repeat(w_styles.shape[0], 1), truncation=truncation, randomize_noise=randomize_noise)[0]
    # trainable_img.shape = (4, 3, 512, 512)
    # in_latent用那个呢
    truncation=1,
    truncation_latent=None
    randomize_noise=True
    trainable_img_jojogan = generator(in_latent, c=cam_pose, truncation=truncation, randomize_noise=randomize_noise)[0]
    # 原始
    # img = generator.synthesis(in_latent, cam_pose, noise_mode='const')['image']
    lpips_fn = lpips.LPIPS(net='vgg').to('cuda') # 用于度量两个图片的相似度
    loss = lpips_fn(F.interpolate(trainable_img_jojogan, size=(256,256), mode='area'), F.interpolate(target_img, size=(256,256), mode='area')).mean()
    return loss,trainable_img_jojogan

def jojogan_img_loss_ide3d_all(generator,w_pivot,cam_pose,target_img):
    truncation=1,
    truncation_latent=None
    randomize_noise=True
    # 使用方法例子：trainable_img_jojogan = self.generator_jojogan(w_styles, c=c.repeat(w_styles.shape[0], 1), truncation=truncation, randomize_noise=randomize_noise)[0]
    # 生成扰动的w
    z = torch.randn(1, 512).to('cuda')
    ws = generator.style([z], cam_pose)  # [N, L, C]
    # alpha越大，保持原本风格越大，alpha越小，随机性越大。
    in_latent = w_pivot.clone()
    # 低分辨率的style 控制姿态、脸型、配件 比如眼镜、发型等style,高分辨率的style控制肤色、头发颜色、背景色等style。
    id_swap=[7,9,11,13,14,15,16,17]
    # id_swap=[1,3,5,7,9,10,11,12,13]
    # id_swap=[1,3,5,7]
    alpha=0.1
    in_latent[:, id_swap,:] = alpha*w_pivot[:, id_swap,:] + (1-alpha)*ws[:, id_swap,:]
    # c.shape = (1, 25)
    # w_styles.shape = (4, 18, 512)
    trainable_img_jojogan = generator(in_latent, c=cam_pose, truncation=truncation, randomize_noise=randomize_noise)[0]
    # trainable_img.shape = (4, 3, 512, 512)
    # 网络出来的结果不需要再tranform正则化，因为本来就是01分布的了
    with torch.no_grad():
        trainable_img_jojogan_nograd = generator(in_latent, c=cam_pose, truncation=truncation, randomize_noise=randomize_noise)[0]
    lpips_fn = lpips.LPIPS(net='vgg').to('cuda') # 用于度量两个图片的相似度
    loss = lpips_fn(F.interpolate(trainable_img_jojogan, size=(256,256), mode='area'),F.interpolate(target_img, size=(256,256), mode='area')).mean()
    # 查看输出的图片，扰动是否正确
    # 这里是训练的图片
    # from torchvision.utils import save_image
    # path_jojo1='/data1w_data/code/github/iccv2023/jojoloss_an.png'
    # path_jojo2='/data1w_data/code/github/iccv2023/jojoloss.png'
    # save_image(trainable_img_jojogan,path_jojo1)
    # save_image(trainable_img_jojogan,path_jojo2,normalize=True)
    # 查看输出的图片，扰动是否正确
    # 这里是起点的图片
    # from torchvision.utils import save_image
    # path_jojo1_nograd='/data1w_data/code/github/iccv2023/jojoloss_an__nograd.png'
    # path_jojo2_nograd='/data1w_data/code/github/iccv2023/jojoloss_nograd.png'
    # save_image(trainable_img_jojogan_nograd,path_jojo1_nograd)
    # save_image(trainable_img_jojogan_nograd,path_jojo2_nograd,normalize=True)
    return loss,trainable_img_jojogan,trainable_img_jojogan_nograd

# @snoop(f'{paths_config.output_data_path}/debug.log') # 保存debug信息
def project(
        G,
        target: torch.Tensor, # [C,H,W] and dynamic range [0,255], W & H must match G output resolution
        *,
        num_steps=1000,
        w_avg_samples=10000,
        initial_learning_rate=0.01,
        lr_rampdown_length=0.25,
        initial_noise_factor=0.05,
        noise_ramp_length=0.75,
        lr_rampup_length=0.05,
        regularize_noise_weight=1e5,
        device: torch.device,
        use_wandb=False,
        initial_w=None,
        cam_encoder = None,
        e4e_encoder = None,
        outdir=None,
        w_name: str
):
    # 读取超参数字典
    args_file = open(paths_config.args_path, 'r')
    args_dic = eval(args_file.read())
    # Load VGG16 feature detector.
    # url = 'https://nvlabs-fi-cdn.nvidia.com/stylegan2-ada-pytorch/pretrained/metrics/vgg16.pt'
    # with dnnlib.util.open_url(url) as f:
    #     vgg16 = torch.jit.load(f).eval().to(device)
    vgg16_path = '/data2/wyf/input/jojogan-3d/vgg16.pt'
    vgg16 = torch.jit.load(vgg16_path).eval().to(device)
    # Call other vgg for warping loss
    torch_vgg = models.vgg16(pretrained=True).features.eval().cuda()
    for param in torch_vgg.parameters():
        param.requires_grad_(False)
    layers = '14' #7, 14, 21 -> 128,128,128 / 256, 64, 64 / 512, 32, 32
    # Load networks
    G = copy.deepcopy(G).eval().requires_grad_(False).to(device).float() # type: ignore
    cam_predictor = copy.deepcopy(cam_encoder).eval().cuda()
    if global_config.use_quaternions:
        cam_lr = hyperparameters.cam_lr_quat
    elif global_config.use_6d:
        cam_lr = hyperparameters.cam_lr_6d
    else:
        cam_lr = hyperparameters.cam_lr_2d
    e4e_enc = copy.deepcopy(e4e_encoder).eval().cuda()
    ray_generator = RaySampler()
    target_e4e = (((target+ 1) / 2) * 255).unsqueeze(0).to(device).to(torch.float32)
    if target_e4e.shape[2] > 256:
        target_e4e = F.interpolate(target_e4e, size=(256, 256), mode='area')
    _ = vgg16(target_e4e, resize_images=False, return_lpips=True) # for normalizing the target image
    radius = 2.7 # 设置半径为2.7
    init_ext = torch.Tensor([1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 2.7, 0, 0, 0, 1]).reshape(-1,4,4).cuda() # 相机外参矩阵,表示初始canonical角度
    intrinsic = torch.tensor([4.2647, 0, 0.5, 0, 4.2647, 0.5, 0, 0, 1]).unsqueeze(0).cuda() # 相机内参矩阵,表示焦距
    canonical_cam = torch.cat([init_ext.reshape(-1, 16), intrinsic], dim=-1) # 相机内外参矩阵
    # Calculate mean w
    with torch.no_grad():
        pred_ext_init = euler2rot(torch.tensor([math.pi/2]), torch.tensor([math.pi/2]), torch.zeros(1, 1), batch_size=1)
        cam_init = torch.cat([pred_ext_init, intrinsic], dim=-1) # init camera -> canonical pose
    cam_avg_samples = cam_init.repeat(w_avg_samples, 1)
    z_samples = np.random.RandomState(123).randn(w_avg_samples, G.z_dim)
    w_samples = G.mapping(torch.from_numpy(z_samples).to(device), cam_avg_samples, truncation_cutoff=14, truncation_psi=0.7)
    w_samples = w_samples[:, :1, :].cpu().numpy().astype(np.float32)
    w_avg = np.mean(w_samples, axis=0, keepdims=True)
    w_avg_tensor = torch.from_numpy(w_avg).to(global_config.device)
    w_std = (np.sum((w_samples - w_avg) ** 2) / w_avg_samples) ** 0.5
    mean_w = initial_w if initial_w is not None else torch.from_numpy(w_avg).cuda()
    start_w = e4e_enc(target_e4e).unsqueeze(1)
    # Setup noise inputs.
    noise_bufs = {name: buf for (name, buf) in G.backbone.synthesis.named_buffers() if 'noise_const' in name}
    noise_bufs2 = {name: buf for (name, buf) in G.superresolution.named_buffers() if 'noise_const' in name}
    # Features for target image.
    target_images_contiguous = target.unsqueeze(0).contiguous()
    target_images = (((target+ 1) / 2) * 255).unsqueeze(0).to(device).to(torch.float32)
    if target_images.shape[2] > 256:
        target_images = F.interpolate(target_images, size=(256, 256), mode='area')
    target_features = vgg16(target_images, resize_images=False, return_lpips=True)
    # Setup optimizer
    w_opt = torch.tensor(mean_w + start_w, dtype=torch.float32, device=device, requires_grad=True)
    start_translation = torch.zeros(1, 3).cuda() # 旋转扰动translation的初始值
    translation_opt = torch.tensor(start_translation, dtype=torch.float32, device=device, requires_grad=True) # 建立旋转扰动translation
    w_optimizer = torch.optim.Adam([w_opt] + list(noise_bufs.values()) + list(noise_bufs2.values()), betas=(0.9, 0.999), lr=hyperparameters.first_inv_lr) # 建立隐变量w的优化器
    cam_optimizer = torch.optim.Adam(cam_predictor.parameters(), lr=cam_lr, betas=(0.9, 0.999)) # 建立相机pose的优化器
    translation_optimizer = torch.optim.Adam([translation_opt], lr=hyperparameters.translation_lr) # 建立旋转扰动translation的优化器

    pose_flag = 4 # 1是旋转扰动translation,2是平移扰动movepose,3是固定pose添加偏置再优化,4是固定pose添加固定偏置
    if pose_flag == 2 or pose_flag == 3:
        start_movepose = 0.00 # 平移扰动movepose的初始值
        movepose_opt = torch.tensor(start_movepose, dtype=torch.float32, device=device, requires_grad=True) # 建立平移扰动movepose
        movepose_optimizer = torch.optim.Adam([movepose_opt], lr=hyperparameters.movepose_lr) # 建立平移扰动movepose的优化器
        movepose_lambda = lambda step:1/(step+1) # 计算平移扰动movepose的学习率衰减函数(学习率lr = 原始lr x 衰减函数lambda)
        torch.optim.lr_scheduler.LambdaLR(optimizer=movepose_optimizer, lr_lambda=movepose_lambda, last_epoch=-1, verbose=False) # 设置平移扰动movepose的学习率衰减策略
    # Init noise.
    for buf in noise_bufs.values():
        buf[:] = torch.randn_like(buf)
        buf.requires_grad = True
    for buf in noise_bufs2.values():
        buf[:] = torch.randn_like(buf)
        buf.requires_grad = True
    ###############################################################################################################
    for step in tqdm(range(num_steps)): # 训练核心代码
        if pose_flag == 1: # 对pose添加旋转扰动translation优化
            if global_config.use_quaternions:
                pred_quat = cam_predictor(target_images)
                pred_rotmat = compute_rotation_matrix_from_quaternion(pred_quat) # 计算3x3的旋转矩阵pred_rotmat
            elif global_config.use_6d: # 只有afhq数据集才用这个
                pred_6d = cam_predictor(target_images)
                pred_rotmat = rot6d_to_rotmat(pred_6d)
            else:
                pred_angles = cam_predictor(target_images)
                theta = math.pi/2 + pred_angles[:, 0]
                phi = math.pi/2 + pred_angles[:, 1]
                roll = torch.zeros(1, 1)
                pred_rotmat = euler2rot(theta, phi, roll, batch_size=1).reshape(-1, 4, 4)[:, :3, :3]
            # 添加可优化的扰动
            pred_ext_tmp = torch.eye(4).unsqueeze(0).repeat(pred_rotmat.shape[0], 1, 1).cuda() # 4x4的单位矩阵pred_ext_tmp
            pred_translation = -radius * pred_rotmat[:, :3, 2] # 取3x3的旋转矩阵第三列再 x 半径
            pred_ext_tmp[:, :3, :3] = pred_rotmat # 将4x4单位矩阵的前三行前三列赋值为旋转矩阵pred_rotmat
            translation_opt_world = -torch.bmm(pred_ext_tmp[:, :3, :3], translation_opt.unsqueeze(-1)) * 2.7 # 计算4x4单位矩阵的前3x3 x 扰动translation(初始为[0,0,0])
            tmp_translation = translation_opt_world.squeeze(-1) + pred_translation # 相乘结果 + 原本的旋转矩阵 x 半径
            tmp_translation = tmp_translation / torch.norm(tmp_translation, dim=-1) * 2.7 # 相加结果归一化再 x 半径得到tmp
            # Formulate extrinsic matrix and input cam
            pred_ext = torch.eye(4).unsqueeze(0).cuda() # 4x4的单位矩阵pred_ext
            pred_ext[:, :3, 3] = tmp_translation # 将4x4单位矩阵的前三行的第四列赋值为上面计算结果tmp-->外参矩阵的平移部分
            pred_ext[:, :3, :3] = pred_ext_tmp[:, :3, :3] # 将4x4单位矩阵的前三行前三列赋值为旋转矩阵pred_rotmat-->外参矩阵的旋转部分
            pred_cam = torch.cat([pred_ext.reshape(-1, 16), intrinsic], dim=-1) # 预测出的相机内外参矩阵,这个就是25位的相机位姿
        elif pose_flag == 2: # 对pose添加平移扰动movepose优化
            pred_ext = torch.eye(4).unsqueeze(0).cuda() # 4x4的单位矩阵pred_ext
            pred_ext[:, 1, 3] = pred_ext[:, 1, 3] + movepose_opt # 将4x4单位矩阵的第二行第四列添加平移扰动movepose偏置-->外参矩阵的平移部分
            pred_cam = torch.cat([pred_ext.reshape(-1, 16), intrinsic], dim=-1) # 预测出的相机内外参矩阵,这个就是25位的相机位姿
            print('平移扰动movepose的学习率lr=', movepose_optimizer.param_groups[0]['lr']) # 打印平移扰动movepose的学习率lr
            print('平移扰动movepose=', movepose_opt) # 打印平移扰动movepose
        elif pose_flag == 3: # 固定pose添加偏置再优化
            with open(args_dic['json_dir'], 'rb') as f: # 读取json文件
                label_list = json.load(f)['labels']
            label_list = dict(label_list)
            pred_cam = torch.Tensor([label_list[f'{w_name}.jpg']]).cuda() # 从json中读取的相机内外参矩阵
            pred_cam[0][7] = pred_cam[0][7] + movepose_opt # 添加相机外参矩阵的pose偏置再优化movepose_opt
            print('平移扰动movepose的学习率lr=', movepose_optimizer.param_groups[0]['lr']) # 打印平移扰动movepose的学习率lr
            print('平移扰动movepose=', movepose_opt) # 打印平移扰动movepose
        elif pose_flag == 4: # 固定pose添加固定偏置
            with open(args_dic['json_dir'], 'rb') as f: # 读取json文件
                label_list = json.load(f)['labels']
            label_list = dict(label_list)
            #··················································
            # 真人图可以估计pose，直接从dataset.json中读取pose
            # pred_cam = torch.Tensor([label_list[f'{w_name}.jpg']]).cuda() # 从json中读取的相机内外参矩阵
            # 类真人图无法估计pose，只能用00035.jpg再加偏置
            pred_cam = torch.Tensor([label_list[f'10005.jpg']]).cuda() # 从json中读取的相机内外参矩阵
            pred_cam[0][7] = pred_cam[0][7] + 0.00 # 手动添加相机外参矩阵的pose固定偏置
            #··················································
        else:
            print('error in pose_flag')
            assert 0
        t = (step - hyperparameters.cam_preheat_steps) / (num_steps - hyperparameters.cam_preheat_steps)
        w_noise_scale = w_std * initial_noise_factor * max(0.0, 1.0 - t / noise_ramp_length) ** 2
        lr_ramp = min(1.0, (1.0 - t) / lr_rampdown_length)
        lr_ramp = 0.5 - 0.5 * np.cos(lr_ramp * np.pi)
        lr_ramp = lr_ramp * min(1.0, t / lr_rampup_length)
        lr = initial_learning_rate * lr_ramp
        for param_group in w_optimizer.param_groups:
            param_group['lr'] = lr
        # Synth images from opt_w.
        if step < hyperparameters.cam_preheat_steps:
            ws_expand = w_opt.repeat(1,14,1) # 重复了14层
        else:
            w_noise = torch.randn_like(w_opt) * w_noise_scale
            ws_expand = (w_opt + w_noise).repeat(1,14,1) # 重复了14层
        ###############################################################################################################
        # 这里利用扰动后的pose生成图像，后续的loss计算也全部来自于此
        pred_dict = G.synthesis(ws_expand, pred_cam, noise_mode='const', force_fp32=True) # 添加噪声生成图像
        pred_depths = pred_dict['image_depth']
        pred_images = pred_dict['image']* 127.5 + 128
        # if global_config.visualize_opt_process: # 保存训练过程中每个step的图像
        #     if os.path.isdir(outdir + f'_pivot/{w_name}') == 0:
        #         os.makedirs(outdir + f'_pivot/{w_name}')
        #     if step % 50 == 0:
        #         with torch.no_grad():
        #             intimg = (pred_images.squeeze(0).permute(1,2,0)).clamp(0, 255).to(torch.uint8)
        #         PIL.Image.fromarray(intimg.cpu().numpy(), 'RGB').save(outdir + f'_pivot/{w_name}/{step}.png') # 保存图像
        if step % 50 == 0: # 这里保存的是w_pivot，哪里才能保存w呢？
            ws_clone_1, pred_cam_clone = ws_expand.clone().detach(), pred_cam.clone().detach() # 克隆一份w_pivot和pose_pivot
            # print('ws_clone_1',ws_clone_1)
            # print('pred_cam_clone',pred_cam_clone)
            np.save(args_dic['output_dir'] + f'_pivot/w_{step}.npy',ws_clone_1.cpu().numpy()) # 保存w_pivot
            np.save(args_dic['output_dir'] + f'_pivot/cam_{step}.npy',pred_cam_clone.cpu().numpy()) # 保存pose_pivot
# warp_loss
        if args_dic['warp_lambda'] > 0:
            warp_loss = None
            ws_clone, canonical_cam_clone = ws_expand.clone().detach(), canonical_cam.clone().detach() # 克隆一份w和pose
            # 这个calc_warping_loss函数里面生成图像只用了canonical视角。那些其他的视角参数是转回去warp使用的
            warp_loss, test_img = calc_warping_loss(ws_clone, canonical_cam_clone, pred_ext, init_ext, intrinsic, pred_depths, target_images_contiguous,G, torch_vgg, ray_generator, layers = layers)
            # if global_config.visualize_warp_process:
            #     if step % 10 == 0:
            #         intwarp = (test_img.squeeze(0).permute(1,2,0) * 127.5 + 128).clamp(0, 255).to(torch.uint8)
            #         if os.path.isdir(f'./warp_image_test/warp_{w_name}') == 0:
            #             os.makedirs(f'./warp_image_test/warp_{w_name}')
            #         PIL.Image.fromarray(intwarp.cpu().numpy(), 'RGB').save(f'./warp_image_test/warp_{w_name}/{step}.png')
# dist_loss
        if args_dic['dist_lambda'] > 0:
            if pred_images.shape[2] > 256:
                pred_images = F.interpolate(pred_images, size=(256, 256), mode='area')
            synth_features = vgg16(pred_images, resize_images=False, return_lpips=True)
            dist_loss = (target_features - synth_features).square().sum()
# reg_loss
        if args_dic['reg_lambda'] > 0:
            reg_loss = 0.0
            for v in noise_bufs.values():
                noise = v[None, None, :, :] # must be [1,1,H,W] for F.avg_pool2d()
                while True:
                    reg_loss += (noise * torch.roll(noise, shifts=1, dims=3)).mean() ** 2
                    reg_loss += (noise * torch.roll(noise, shifts=1, dims=2)).mean() ** 2
                    if noise.shape[2] <= 8:
                        break
                    noise = F.avg_pool2d(noise, kernel_size=2)
            for v in noise_bufs2.values():
                noise = v[None, None, :, :]
                while True:
                    reg_loss += (noise * torch.roll(noise, shifts=1, dims=3)).mean() ** 2
                    reg_loss += (noise * torch.roll(noise, shifts=1, dims=2)).mean() ** 2
                    if noise.shape[2] <= 8:
                        break
                    noise = F.avg_pool2d(noise, kernel_size=2)
        #####################新加入的loss
# id_loss
        if args_dic['id_lambda'] > 0:
            calc_id_loss = IDLoss().to(device).eval()
            id_loss = calc_id_loss(pred_images, target_e4e)
# l2_loss
        if args_dic['l2_lambda'] > 0:
            l2_loss = calc_l2loss(pred_images, target_e4e)
# lpips_loss
        if args_dic['lpips_lambda'] > 0:
            # 可学习感知图像块相似度(Learned Perceptual Image Patch Similarity, LPIPS)也称为“感知损失”(perceptual loss)，用于度量两张图像之间的差别。LPIPS 比传统方法（比如L2/PSNR, SSIM, FSIM）更符合人类的感知情况。LPIPS的值越低表示两张图像越相似，反之，则差异越大。
            # https://blog.csdn.net/weixin_43135178/article/details/127664187
            calc_lpips_loss = LPIPS(net=hyperparameters.lpips_type).to(device).eval()
            lpips_loss = calc_lpips_loss(pred_images, target_e4e)
# mse_loss
        if args_dic['mse_lambda'] > 0:
            calc_mse_loss = torch.nn.MSELoss().to(device).eval()
            mse_loss = calc_mse_loss(pred_images, target_e4e)
# mask_loss
        if args_dic['mask_12_lambda'] > 0 or args_dic['mask_lpips_lambda'] > 0:
            pred_images_path = paths_config.root_path + '/face_parsing/res/data/pred_images.jpg'
            target_e4e_path = paths_config.root_path + '/face_parsing/res/data/target_e4e.jpg'
            save_image(pred_images, pred_images_path, normalize=True) # 加上normalize=True后图像颜色就正常了，相当于是逆向的normalization。更具体的说就是因为，原始的图像需要先normalize变成0-1才能输入网络，之后输出网络后，值也不对，需要逆向的标准化才行。注意这里的逆向标准化是mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)，不是什么*255之类的
            save_image(target_e4e, target_e4e_path, normalize=True)
            mask_pred,mask_target = calc_mask(pred_images_path, target_e4e_path)
            mask_12_loss = calc_l2loss(mask_pred, mask_target)
            mask_lpips_loss = calc_lpips_loss(mask_pred, mask_target)
# ssim_loss
        if args_dic['ssim_lambda'] > 0:
            ssim_loss = calc_ssim(pred_images_path,target_e4e_path)
# psnr_loss
        if args_dic['psnr_lambda'] > 0:
            psnr_loss = calc_psnr(pred_images_path,target_e4e_path)
        # print('------------------')
        # print('warp_loss        =', warp_loss) # 0.4720
        # print('dist_loss        =', dist_loss) # 0.5487
        # print('reg_loss         =', reg_loss) # 0.0572
        # print('id_loss          =', id_loss) # 0.3113
        # print('l2_loss          =', l2_loss) # 1.1953
        # print('lpips_loss       =', lpips_loss) # 0.4128
        # print('------------------')
        # print('mse_loss         =', mse_loss) # 1.1953
        # print('mask_12_loss     =', mask_12_loss) # 0.7218
        # print('mask_lpips_loss  =', mask_lpips_loss) # 0.5260
        # print('ssim_loss        =', ssim_loss) # 0.3716385775396315
        # print('psnr_loss        =', psnr_loss) # 11.674259838898443
        # print('------------------')
        loss = 0.0
        if args_dic['warp_lambda'] > 0:
            loss = loss + args_dic['warp_lambda'] * warp_loss
        if args_dic['dist_lambda'] > 0:
            loss = loss + args_dic['dist_lambda'] * dist_loss
        if args_dic['reg_lambda'] > 0:
            loss = loss + args_dic['reg_lambda'] * reg_loss
        if args_dic['id_lambda'] > 0:
            loss = loss + args_dic['id_lambda'] * id_loss
        if args_dic['l2_lambda'] > 0:
            loss = loss + args_dic['l2_lambda'] * l2_loss
        if args_dic['lpips_lambda'] > 0:
            loss = loss + args_dic['lpips_lambda'] * lpips_loss
        if args_dic['mse_lambda'] > 0:
            loss = loss + args_dic['mse_lambda'] * mse_loss
        if args_dic['mask_12_lambda'] > 0:
            loss = loss + args_dic['mask_12_lambda'] * mask_12_loss
        if args_dic['mask_lpips_lambda'] > 0:
            loss = loss + args_dic['mask_lpips_lambda'] * mask_lpips_loss
        if args_dic['ssim_lambda'] > 0:
            loss = loss + args_dic['ssim_lambda'] * ssim_loss
        if args_dic['psnr_lambda'] > 0:
            loss = loss + args_dic['psnr_lambda'] * psnr_loss
        # 金克斯最优loss = 1 * dist_loss + 1 * id_loss + 1 * lpips_loss
        # HyperStyle使用loss = 0.1 * id_loss + 1 * l2_loss + 0.8 * lpips_loss
        # loss = dist_loss + id_loss + lpips_loss + mask_loss_12
        # 新一轮：
        # loss = dist_loss + id_loss + lpips_loss + l2_loss
        if step < hyperparameters.cam_preheat_steps: # 50
            cam_optimizer.zero_grad()
            translation_optimizer.zero_grad()
            # movepose_optimizer.zero_grad()
            loss.backward()
            cam_optimizer.step()
            translation_optimizer.step() # 优化旋转扰动translation
            # movepose_optimizer.step() # 优化平移扰动movepose
        # elif step < 151:
        else:
            w_optimizer.zero_grad()
            cam_optimizer.zero_grad()
            translation_optimizer.zero_grad()
            # movepose_optimizer.zero_grad()
            loss.backward()
            cam_optimizer.step()
            w_optimizer.step() # 优化w
            translation_optimizer.step() # 优化旋转扰动translation
            # movepose_optimizer.step() # 优化平移扰动movepose
        # else:
        #     w_optimizer.zero_grad()
        #     cam_optimizer.zero_grad()
        #     #translation_optimizer.zero_grad()
        #     # movepose_optimizer.zero_grad()
        #     loss.backward()
        #     cam_optimizer.step()
        #     w_optimizer.step()
        #     #translation_optimizer.step()
        #     # movepose_optimizer.step()
        # Normalize noise.
        with torch.no_grad():
            for buf in noise_bufs.values():
                buf -= buf.mean()
                buf *= buf.square().mean().rsqrt()
            for buf in noise_bufs2.values():
                buf -= buf.mean()
                buf *= buf.square().mean().rsqrt()
    # freeze encoder for tuning step.
    with torch.no_grad():
        cam = pred_cam.clone().detach()
        ws_expand =ws_expand.clone().detach()
    del G
    del cam_predictor
    del e4e_enc
    torch.cuda.empty_cache()
    return ws_expand, cam