'''
Created on 2012-06-15

@author: Mat
'''
import sys
import os
import io
import logging
from ui import mainUI
from PyQt4 import QtGui, QtCore
from functools import partial
from doubleBarrel.monitor.manager import ServerManager

class PyQtLogHandler(logging.Handler):
    '''
    A custom logging handler object that will write our log to a provided QTextBrowser widget.
    '''
    def __init__(self, destWidget):
        logging.Handler.__init__(self)
        self._destWidget = destWidget

    def emit(self, record):
        try:
            msg = self.format(record)
            self._destWidget.append(msg)
        except(KeyboardInterrupt, SystemExit):
            raise
        except:
            self.handleError(record)

class MainGUI(QtGui.QMainWindow, mainUI.Ui_mainUi):

    SCRIPT_NAME_COLUMN = 0
    STATUS_COLUMN = 1

    def __init__(self, manager=None):
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)

        self._manager = manager or ServerManager()
        self._servers = {}  # Stores the QTreeWidgetItem as the key and the server as the value.
        self._urlGroups = {}  # Stores the url as the key and the QTreeWidget as the value.
        self._serverLogWidgets = {}

        self._extraUiSetup()
        self._setupCallbacks()
        self._setDefaults()

    def _extraUiSetup(self):
        '''
        Does any remaining setup that cannot be done from within the designer.
        '''
        # Group the actions for changing the split orientation.
        self.orientSplitActionGroup = QtGui.QActionGroup(self.menuManage)
        self.horizontalSplitAction.setActionGroup(self.orientSplitActionGroup)
        self.verticalSplitAction.setActionGroup(self.orientSplitActionGroup)

        # Group the actions for showing/hiding the log.
        self.showLogActionGroup = QtGui.QActionGroup(self.menuLog)
        self.showLogAction.setActionGroup(self.showLogActionGroup)
        self.hideLogAction.setActionGroup(self.showLogActionGroup)

        # Group the actions for display mode.
        self.displayModeActionGroup = QtGui.QActionGroup(self.menuPreferences)
        self.simpleModeAction.setActionGroup(self.displayModeActionGroup)
        self.advancedModeAction.setActionGroup(self.displayModeActionGroup)

        # Set the server tree's columns to be resizeable and fixed (column 1 and 2 respectively)
        self.serverTree.header().setResizeMode(0, QtGui.QHeaderView.Stretch)
        self.serverTree.header().setResizeMode(1, QtGui.QHeaderView.Fixed)

        # Reverse the sorting order of the script name column.
        self.serverTree.sortItems(self.SCRIPT_NAME_COLUMN, QtCore.Qt.AscendingOrder)

    def _setupCallbacks(self):
        '''
        Sets up the signal/slot connections for the GUI.
        '''
        # Manage the log display changing from toggling the checkbox.
        self.showLogCheck.toggled.connect(self._setLogVis)

        # Manage the log display changing from moving the splitter.
        self.logSplitter.splitterMoved.connect(self._setLogChecks)

        # Connect the log checkbox to the icon.
        self.showLogCheck.stateChanged.connect(self.showLogLabel.setEnabled)

        # Connections for log splitter orientation menu items.
        self.horizontalSplitAction.triggered.connect(partial(self._setLogSplitOrient, QtCore.Qt.Horizontal))
        self.verticalSplitAction.triggered.connect(partial(self._setLogSplitOrient, QtCore.Qt.Vertical))

        # Connections for log visibility menu items.
        self.showLogAction.triggered.connect(partial(self._setLogVis, 1))
        self.hideLogAction.triggered.connect(partial(self._setLogVis, 0))

        # Connections for the add server buttons.
        self.addButton.clicked.connect(self.addServerBtnPressed)
        self.addServerAction.triggered.connect(self.addServerBtnPressed)

        # Connections for the remove server buttons.
        self.removeButton.clicked.connect(self.removeServerBtnPressed)
        self.removeServerAction.triggered.connect(self.removeServerBtnPressed)

        # Connections for the start and stop server buttons.
        self.startServerAction.triggered.connect(self.startServerButtonPressed)
        self.stopServerAction.triggered.connect(self.stopServerButtonPressed)

    def _setDefaults(self):
        '''
        Set the default state of the GUI.
        '''
        # Ensure the log is displayed properly.
        self.showLogCheck.toggled.emit(self.showLogCheck.checkState())

        # Add all of the servers from the manager.
        for server in self._manager.servers():
            self._addServerToTree(server)

        # Update the server statuses.
        self.updateServerStatuses()

    def _setLogSplitOrient(self, orientation):
        '''
        Sets the orientation of the log splitter.
        '''
        self.logSplitter.setOrientation(orientation)

    def _setLogChecks(self):
        '''
        Sets the state of the checkbox based on whether the log is showing.
        '''
        logState = self.isLogShowing()

        self.showLogCheck.blockSignals(True)
        self.showLogCheck.setCheckState(logState)
        self.showLogCheck.blockSignals(False)

        self.showLogAction.blockSignals(True)
        self.showLogAction.setChecked(logState)
        self.showLogAction.blockSignals(False)

        self.hideLogAction.blockSignals(True)
        self.hideLogAction.setChecked(not logState)
        self.hideLogAction.blockSignals(False)

        self.showLogLabel.setEnabled(logState)

    def _setLogVis(self, state):
        '''
        Sets the visibility of the log display area.
        '''
        self.logSplitter.setSizes([1, state])
        self._setLogChecks()

    def isLogShowing(self):
        '''
        Returns whether the log is showing.
        '''
        return self.logSplitter.sizes()[-1]

    def selectedServers(self):
        '''
        Returns the currently selected servers in the tree.
        '''
        selectedItems = self.serverTree.selectedItems()
        selectedServers = []
        for item in selectedItems:
            server = self._servers.get(item)
            if server:
                selectedServers.append(server)

        return selectedServers

    def _addUrlGroupToTree(self, url):
        '''
        Adds a URL group to the tree view that the servers can then be added to.
        '''
        urlGroup = QtGui.QTreeWidgetItem(self.serverTree, [url])
        serverIcon = QtGui.QIcon(os.path.abspath(r'icons\server.png'))
        urlGroup.setIcon(0, serverIcon)
        # Add the urlGroup to the storage dict and then return the control.
        self._urlGroups[url] = urlGroup
        return urlGroup

    def _addServerToTree(self, server, updateSelection=False):
        '''
        Adds a server to the tree view. This is separated from the addServerBtnPressed function because it needs to get
        called when the GUI is first initialized.
        '''
        sgObj = server.shotgunObject()

        # Get the serverUrl's tree item and add the server under the URL group.
        serverUrl = sgObj.config.server
        urlGroup = self._urlGroups.get(serverUrl)
        if not urlGroup:
            urlGroup = self._addUrlGroupToTree(serverUrl)

        # Add the serverItem to the urlGroup and to the storage dict.
        scriptName = sgObj.config.script_name
        serverItem = QtGui.QTreeWidgetItem(urlGroup, [scriptName])
        self._servers[serverItem] = server

        # Expand the urlGroup and select the newly added server.
        urlGroup.setExpanded(True)
        if updateSelection:
            # Clear the existing selection first.
            for selectedItem in self.serverTree.selectedItems():
                self.serverTree.setItemSelected(selectedItem, False)
            self.serverTree.setItemSelected(serverItem, True)

        # Add a widget for displaying the server's log.
        self._createServerLogWidget(server)

        return serverItem

    def addServerBtnPressed(self):
        '''
        Triggered when one of the add server buttons is pressed.
        '''
        # Bring up a file dialog to allow the user to select an sg file.
        # Call the manager's addServer function, passing it the sg file.

        title = "Add a Shotgun server file"
        startingDir = os.path.dirname(__file__)
        acceptedFiles = "Shotgun Server Files (*.sg)"
        sgFilepath = QtGui.QFileDialog.getOpenFileName(self, title, startingDir, acceptedFiles)

        if sgFilepath:
            servers = self._manager.addServersFromFile(str(sgFilepath))
            for server in servers:
                self._addServerToTree(server, updateSelection=True)

    def _createServerLogWidget(self, server):
        '''
        Creates an object for displaying the log for the provided server.
        '''
        # Create the widget, add it to the storage dictionary, and hide it by default.
        logDisplayWidget = QtGui.QTextBrowser(self.logDock)
        self._serverLogWidgets[server] = logDisplayWidget
        logDisplayWidget.setVisible(False)

        # Set it up so the server's log gets automatically written to the widget.
        logger = server.logger()
        # Create a PyQtLogHandler for our logger to write to our widget.
        pyqtHandler = PyQtLogHandler(logDisplayWidget)
        logger.addHandler(pyqtHandler)

    def removeServerBtnPressed(self):
        '''
        Triggered when one of the remove server buttons is pressed.
        '''
        selectedItems = self.serverTree.selectedItems()
        for serverItem in selectedItems:
            # Pop the server from the storage dict. This will also remove it.
            server = self._servers.pop(serverItem)
            # Remove it from the tree view.
            serverItem.parent().removeChild(serverItem)
            # Remove it from the manager.
            self._manager.removeServer(server)

        # Remove any urlGroups that are now empty.
        self._purgeUrlGroups()

    def _purgeUrlGroups(self):
        '''
        This goes through all urlGroups and checks that they still have child
        items. If they do not, they will be removed from the GUI and the
        internal storage dictionary.
        '''
        # Create a copy of the urlGroups dict so we can change the items during iteration.
        for url, urlGroup in self._urlGroups.copy().iteritems():
            # If there are no longer any children.
            if not urlGroup.childCount():
                # Remove the urlGroup from the storage dict.
                self._urlGroups.pop(url)
                # Remove it from the tree widget.
                urlGroupIndex = self.serverTree.indexOfTopLevelItem(urlGroup)
                self.serverTree.takeTopLevelItem(urlGroupIndex)

    def updateServerStatuses(self):
        '''
        Updates the status column for each server object.
        '''
        for serverItem, server in self._servers.iteritems():
            # If the server is running, check whether there are any errors.
            if server.isRunning():
                # If there are no errors, add the smiley/yellow icon.
                if not server.hasErrored():
                    status = "Running"
                # If there are errors, add the frown/red icon.
                else:
                    status = "Errored"
            # If the server is not running, add the sleeping/blue icon.
            else:
                status = "Stopped"

            serverItem.setText(self.STATUS_COLUMN, status)

    def startServerButtonPressed(self):
        '''
        Starts the currently selected server(s).
        '''
        for server in self.selectedServers():
            self._manager.startServer(server)
        self.updateServerStatuses()

    def stopServerButtonPressed(self):
        '''
        Stops the currently selected server(s).
        '''
        for server in self.selectedServers():
            self._manager.stopServer(server)
        self.updateServerStatuses()

    def restartServerButtonPressed(self):
        '''
        Restarts the currently selected server(s).
        '''
        for server in self.selectedServers():
            self._manager.restartServer(server)
        self.updateServerStatuses()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    mainGUI = MainGUI()
    mainGUI.show()
    sys.exit(app.exec_())


# References:
# https://pytorch.org/tutorials/intermediate/reinforcement_q_learning.html
# https://towardsdatascience.com/deep-q-learning-for-the-cartpole-44d761085c2f
# https://github.com/seungeunrho/minimalRL

import gym
import math
import random
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from collections import namedtuple, deque
from itertools import count

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F

# set up matplotlib
is_ipython = 'inline' in matplotlib.get_backend()
if is_ipython:
    from IPython import display

env = gym.make("CartPole-v1")

# if gpu is to be used
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

Transition = namedtuple('Transition',
                        ('state', 'action', 'next_state', 'reward'))

######################################################################
# Memory
######################################################################
class ReplayMemory(object):

    def __init__(self, capacity):
        self.memory = deque(maxlen=capacity)

    def push(self, *args):
        self.memory.append(Transition(*args))

    def sample(self, batch_size):
        return random.sample(self.memory, batch_size)

    def __len__(self):
        return len(self.memory)

######################################################################
# Model
######################################################################
class DQN(nn.Module):

    def __init__(self, observation_space, action_space):
        super(DQN, self).__init__()
        self.l1 = nn.Linear(observation_space, 256)
        self.head = nn.Linear(256, action_space)

    # Called with either one element to determine next action, or a batch
    # during optimization. Returns tensor([[left0exp,right0exp]...]).
    def forward(self, x):
        x = F.relu(self.l1(x))
        return self.head(x)

######################################################################
# Training
######################################################################
BATCH_SIZE = 512
GAMMA = 0.999
EPS_START = 0.9
EPS_END = 0.05
EPS_DECAY = 200
TARGET_UPDATE = 10  # each 10 episodes copy policy_net params to target_net

initial_state = env.reset()
n_actions = env.action_space.n
n_observations = env.observation_space.shape[0]

policy_net = DQN(n_observations, n_actions).to(device)
target_net = DQN(n_observations, n_actions).to(device)
target_net.load_state_dict(policy_net.state_dict())
target_net.eval()

optimizer = optim.RMSprop(policy_net.parameters())
memory = ReplayMemory(10000)

steps_done = 0

def select_action(state):  # return tensor([[0]]) or tensor([[1]])
    global steps_done
    sample = random.random()
    eps_threshold = EPS_END + (EPS_START - EPS_END) * \
        math.exp(-1. * steps_done / EPS_DECAY)
    steps_done += 1
    if sample > eps_threshold:
        with torch.no_grad():
            # Pick action with the larger expected reward.
            policy_net.eval()
            return policy_net(state).max(1)[1].view(1, 1)
    else:
        return torch.tensor([[random.randrange(n_actions)]], device=device, dtype=torch.long)

######################################################################
# Visualization
######################################################################
episode_durations = []

def moving_average(a, n=10):
    ret = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return np.concatenate([
        ret[:n-1] / np.arange(1, n),
        ret[n-1:] / n,
    ])

def plot_durations(title='Training...'):
    plt.figure(1)
    plt.clf()
    plt.title(title)
    plt.xlabel('Episode')
    plt.ylabel('Duration')
    plt.plot(episode_durations, label='Episode duration')
    # Take 100 episode averages and plot them too
    if len(episode_durations) >= 2:
        n = np.min([len(episode_durations), 50])
        means = moving_average(episode_durations, n=n)
        plt.plot(means, label='Mean episode duration')

    plt.legend(loc='upper left')
    plt.pause(0.001)  # pause a bit so that plots are updated
    if is_ipython:
        display.clear_output(wait=True)

######################################################################
# Training loop
######################################################################
def optimize_model():
    if len(memory) < BATCH_SIZE:
        return
    transitions = memory.sample(BATCH_SIZE)
    batch = Transition(*zip(*transitions))

    # Compute a mask of non-final states and concatenate the batch elements
    # (a final state would've been the one after which simulation ended)
    non_final_mask = torch.tensor(tuple(map(lambda s: s is not None,
                                            batch.next_state)), device=device, dtype=torch.bool)
    non_final_next_states = torch.cat([s for s in batch.next_state
                                                if s is not None])
    state_batch = torch.cat(batch.state)
    action_batch = torch.cat(batch.action)  # [[0], [1], [0], [1], ...]
    reward_batch = torch.cat(batch.reward)  # [1, 1, 1, ...]

    policy_net.train()
    # Compute Q(s_t, a) - the model computes Q(s_t), then we select the columns of actions taken.
    state_action_values = policy_net(state_batch).gather(1, action_batch)  # [[.2], [.3], ...]

    # Compute V(s_{t+1}) for all next states. Computed based on the "older" target_net
    next_state_values = torch.zeros(BATCH_SIZE, device=device)
    next_state_values[non_final_mask] = target_net(non_final_next_states).max(1)[0].detach()  # [.2, .3, ...]
    # Compute the expected Q values
    expected_state_action_values = (next_state_values * GAMMA) + reward_batch  # [1.02, 1.03, ...]

    # Compute Huber loss
    # F.smooth_l1_loss([.2, .3, ...], [1.02, 1.03, ...])
    loss = F.smooth_l1_loss(state_action_values, expected_state_action_values.unsqueeze(1))

    # Optimize the model
    optimizer.zero_grad()
    loss.backward()
    for param in policy_net.parameters():
        param.grad.data.clamp_(-1, 1)  # clamp_ = -2, -1, 0, 1, 2 => -1, -1, 0, 1, 1
    optimizer.step()

def update():
    target_net.load_state_dict(policy_net.state_dict())

def soft_update(TAU=0.1):
    model_params = policy_net.named_parameters()
    target_params = target_net.named_parameters()

    updated_params = dict(target_params)

    for model_name, model_param in model_params:
        if model_name in target_params:
            # Update parameter
            updated_params[model_name].data.copy_(TAU * model_param.data + (1 - TAU) * target_params[model_param].data)

    target_net.load_state_dict(updated_params)

num_episodes = 300
for i_episode in range(num_episodes):
    # Initialize the environment and state
    state = env.reset()
    state = torch.tensor(state, device=device, dtype=torch.float).unsqueeze(0)
    for t in count():
        # Select and perform an action
        action = select_action(state)
        next_state, reward, done, _ = env.step(action.item())
        reward = torch.tensor([reward], device=device)  # [1.0]

        # Observe new state
        if not done:
            next_state = torch.tensor(next_state, device=device, dtype=torch.float).unsqueeze(0)
        else:
            next_state = None

        # Store the transition in memory
        memory.push(state, action, next_state, reward)

        # Move to the next state
        state = next_state

        # Perform one step of the optimization (on the target network)
        optimize_model()
        if done:
            episode_durations.append(t + 1)
            plot_durations()
            break
    # Update the target network, copying all weights and biases in DQN
    if i_episode % TARGET_UPDATE == 0:
        update()

env.close()
torch.save(target_net.state_dict(), 'model-dql.pt')

plot_durations('Complete')
plt.show()


def list_names(name_list):
    for name in name_list:
        print(f'{name_list.index(name)+1}. {name}')

def get_new_student():

    stu_name = input("What is the student's name?\n")
    stu_hometown = input("What is the student's hometown?\n")
    stu_favorite_food = input("What is the student's favorite food?\n")
    if stu_name == '' or stu_hometown == '' or stu_favorite_food == '':
        print('Please enter values.')
    new_student = {
        'name': stu_name,
        'hometown': stu_hometown,
        'favorite_food': stu_favorite_food
    }

    return new_student

stu_dict_list = [
  { "name": "Tina", "hometown": "Portland", "favorite_food": "puppy chow" },
  { "name": "Klaus", "hometown": "Frankfurt", "favorite_food": "pizza" },
  { "name": "Julia", "hometown": "Houston", "favorite_food": "shrimp" }
]
def get_names():
    name_list = []
    for student_dict in stu_dict_list:
        values = list(student_dict.values())
        for name in range(0, len(values), 3):
            name_list.append(values[name])
    return name_list

def name_index():
    more_info = input("Which student would you like to know more about? ").title()
    for students in stu_dict_list:
        if more_info == students['name']:
            print(f'Student {stu_dict_list.index(students)+1} is {more_info} and their\n'
                  f'favorite food is {students["favorite_food"]} and they are from {students["hometown"]}.')
        else:
            print('Please enter a correct value.')
            break

switch = True
while switch == True:
    selection = input("Please select the action you'd like to do: add, view, or quit.\n").lower()
    if(selection == 'add'):
        stu_dict_list.append(get_new_student())

    elif selection == 'view':
        list_names(get_names())
        name_search = input("Would you like to search by name? (y/n) ").lower()
        while name_search == 'y':
            name_index()
            choice = input('Would you like to search by name again? (y/n) ').lower()
            if choice == 'n':
                break
        else:
            more_info = int(input(f'Which student would like to know more about? Enter 1 - {len(get_names())}\n'))
            if more_info in range(len(get_names())+1):
                print(f'Student {more_info} is {get_names()[more_info-1]}. What would you like to know?')
                category = input('Enter "hometown" or "favorite food" ').lower()
                if category == 'hometown':
                    print(f"{get_names()[more_info-1]} is from {stu_dict_list[more_info-1][category]}")
                elif category == 'favorite food' or category == 'food':
                    print(f"{get_names()[more_info-1]}'s favorite food is {stu_dict_list[more_info]['favorite_food']}")

    elif selection == 'quit':
        print('Thank you. <END PROGRAM>')
        break
    else:
        print("Please enter a valid action.")


import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.models as VM
from Models import basic
from Utils import util, tool

eps = 0.0000001

def l2_loss(y_input, y_target):
    return F.mse_loss(y_input, y_target)

def weightedL2_loss(y_input, y_target, weight_map):
    N,C,H,W = y_input.shape
    _,C1,_,_ = weight_map.shape
    interval = C//C1
    diff_map = y_input-y_target
    diff_map = torch.cat([torch.mean(torch.abs(diff_map[:,interval*i:interval*(i+1),:,:]), dim=1, keepdim=True) for i in range(0,C1)], dim=1)
    return torch.sum(diff_map*diff_map*weight_map) / (eps+torch.sum(weight_map))

def l1_loss(y_input, y_target):
    return F.l1_loss(y_input, y_target)

def weightedL1_loss(y_input, y_target, weight_map):
    N,C,H,W = y_input.shape
    _,C1,_,_ = weight_map.shape
    interval = C//C1
    diff_map = y_input-y_target
    diff_map = torch.cat([torch.mean(torch.abs(diff_map[:,interval*i:interval*(i+1),:,:]), dim=1, keepdim=True) for i in range(0,C1)], dim=1)
    return torch.sum(diff_map*weight_map) / (eps+torch.sum(weight_map))

def ssimLoss(yInput, yTarget):
    # data range is [-1,1]
    ssim = tool.ssim(yInput / 2. + 0.5, yTarget / 2. + 0.5, window_size=11)
    return 1. - ssim

def wrapLightFieldVGGLoss(yInput, yTarget, vggLossFunc):
    # data range is [-1,1]
    N,C,H,W = yInput.shape
    batch_input = torch.cat([yInput[:, i*3:(i+1)*3, :, :] for i in range(C//3)], dim=0)
    batch_target = torch.cat([yTarget[:, i*3:(i+1)*3, :, :] for i in range(C//3)], dim=0)
    vggLoss = vggLossFunc(batch_input/2.+0.5, batch_target/2.+0.5)
    return vggLoss

def depth_warp_loss(ray_depths, input_lightfields, c_views):
    N, frame_num, H, W = ray_depths.shape
    warping_loss, no = 0, 0
    c_depth = ray_depths[:,frame_num//2,:,:].unsqueeze(1)
    #! warping loss: central view
    for t in [-2, 2]:       # s is along the x axis of image
        for s in [-2, 2]:   # t is along the y axis of image
            index = (t+3)*7+(s+3)
            st_view = input_lightfields[:,3*index:3*(index+1),:,:]
            st2c_disp = torch.cat((s*c_depth, t*c_depth), dim=1)
            c_warp, _ = basic.flowWarp(st_view, st2c_disp)
            c_loss = l2_loss(c_warp, c_views)
            warping_loss += c_loss
            no += 1
            #! output test
            #meta_imgs = basic.tensor2array(c_warp)
            #util.save_images_from_batch(meta_imgs, './caca/', no*1)
    #! warping loss: surround subviews
    occlusion_maps = torch.ones(N, 1*frame_num, H, W, device=c_views.device)
    warped_frames = torch.ones(N, 3*frame_num, H, W, device=c_views.device)
    for i in range(frame_num):
        t = (i // 7) - 3       # t is along the y axis of image
        s = (i % 7) - 3        # s is along the x axis of image
        if s == 0 and t == 0:
            c_errormap = torch.zeros_like(c_depth, device=c_views.device)
            occlusion_maps[:,i:i+1,:,:] = c_errormap
            warped_frames[:,3*i:3*(i+1),:,:] = c_views
        else:
            i_depth = ray_depths[:,i:i+1,:,:]
            c2i_disp = torch.cat((-s*i_depth, -t*i_depth), dim=1)
            i_warp, _ = basic.flowWarp(c_views, c2i_disp)
            i_loss = l2_loss(i_warp, input_lightfields[:,3*i:3*(i+1),:,:])
            warping_loss += i_loss
            no += 1
            i_errormap = basic.checkLRDepthErrorMap(i_depth, c_depth, -s, -t)
            occlusion_maps[:,i:i+1,:,:] = i_errormap
            warped_frames[:,3*i:3*(i+1),:,:] = i_warp
            #! output test
            #meta_imgs = basic.tensor2array(i_warp)
            #util.save_images_from_batch(meta_imgs, './caca/', no*1)
    return warping_loss / no, occlusion_maps, warped_frames

def depth_consistency_loss(ray_depths):
    _, frame_num, _, _ = ray_depths.shape
    consistency_loss, no = 0, 0
    for t in range(-3,3):      # t is along the y axis of image：-3~2
        for s in range(-3,3):  # s is along the x axis of image：-3~2
            index = (t+3)*7+(s+3)
            i_depth = ray_depths[:,index,:,:].unsqueeze(1)
            # d(s,t) of half its neighborhood views
            d10_depth = ray_depths[:,index+1,:,:].unsqueeze(1)
            d01_depth = ray_depths[:,index+7,:,:].unsqueeze(1)
            d11_depth = ray_depths[:,index+8,:,:].unsqueeze(1)
            d10_loss = basic.checkLRDepthErrorMap(i_depth, d10_depth, 1, 0)
            d01_loss = basic.checkLRDepthErrorMap(i_depth, d01_depth, 0, 1)
            d11_loss = basic.checkLRDepthErrorMap(i_depth, d11_depth, 1, 1)
            consistency_loss += (d01_loss.mean() + d10_loss.mean() + d11_loss.mean()) / 3.0
            no += 1
    return consistency_loss / no

def computeDispWarpLoss(disparity_maps, input_lightfields, c_view):
    N, dframe_num, H, W = disparity_maps.shape
    frame_num = dframe_num//2   # 49
    cview_no = frame_num//2     # 24
    c_disp = disparity_maps[:,2*cview_no:2*(cview_no+1),:,:]
    warping_loss, no = 0, 0
    #! warping loss: central view
    for t in [-2, 2]:       # s is along the x axis of image
        for s in [-2, 2]:   # t is along the y axis of image
            index = (t+3)*7+(s+3)
            st_view = input_lightfields[:,3*index:3*(index+1),:,:]
            st2c_dispmap = torch.cat((s*c_disp[:,0:1,:,:], t*c_disp[:,1:2,:,:]), dim=1)
            c_warp, _ = basic.flowWarp(st_view, st2c_dispmap)
            c_loss = l2_loss(c_warp, c_view)
            warping_loss += c_loss
            no += 1
            #! output test
            #meta_imgs = basic.tensor2array(c_warp)
            #util.save_images_from_batch(meta_imgs, './caca/', no*1)
    #! warping loss: surround subviews
    for i in range(frame_num):
        t = (i // 7) - 3       # t is along the y axis of image
        s = (i % 7) - 3        # s is along the x axis of image
        if s == 0 and t == 0:
            # c_errormap = torch.zeros((N,1,H,W), device=c_views.device)
            continue
        else:
            i_disp = disparity_maps[:,2*i:2*(i+1),:,:]
            c2i_dispmap = torch.cat((-s*i_disp[:,0:1,:,:], -t*i_disp[:,1:2,:,:]), dim=1)
            i_warp, _ = basic.flowWarp(c_view, c2i_dispmap)
            i_loss = l2_loss(i_warp, input_lightfields[:,3*i:3*(i+1),:,:])
            warping_loss += i_loss
            no += 1
    return warping_loss / no

def computeDispWarpLossNew(disparity_maps, input_lightfields, c_view, frameNos):
    N, dframe_num, H, W = disparity_maps.shape
    frame_num = dframe_num//2   # 49
    c_disp = disparity_maps[:,0:2,:,:]
    cview_loss = 0
    #! warping loss: central view
    for t in [-2, 2]:       # s is along the x axis of image
        for s in [-2, 2]:   # t is along the y axis of image
            index = (t+3)*7+(s+3)
            st_view = input_lightfields[:,3*index:3*(index+1),:,:]
            st2c_dispmap = torch.cat((s*c_disp[:,0:1,:,:], t*c_disp[:,1:2,:,:]), dim=1)
            c_warp, _ = basic.flowWarp(st_view, st2c_dispmap)
            c_loss = l2_loss(c_warp, c_view)
            cview_loss += c_loss
            #! output test
            #meta_imgs = basic.tensor2array(c_warp)
            #util.save_images_from_batch(meta_imgs, './caca/', no*1)
    #! warping loss: surround subviews
    warping_loss = cview_loss / 4.0
    no = 1
    for i in frameNos:
        t = (i // 7) - 3       # t is along the y axis of image
        s = (i % 7) - 3        # s is along the x axis of image
        if s == 0 and t == 0:
            # c_errormap = torch.zeros((N,1,H,W), device=c_views.device)
            continue
        else:
            i_disp = disparity_maps[:,2*no:2*(no+1),:,:]
            c2i_dispmap = torch.cat((-s*i_disp[:,0:1,:,:], -t*i_disp[:,1:2,:,:]), dim=1)
            i_warp, _ = basic.flowWarp(c_view, c2i_dispmap)
            i_loss = l2_loss(i_warp, input_lightfields[:,3*i:3*(i+1),:,:])
            warping_loss += i_loss
            no += 1
    return warping_loss / no

def computeDispConsistLoss(disparity_maps):
    _, dframe_num, _, _ = disparity_maps.shape
    frame_num = dframe_num//2   # 49
    consistency_loss, no = 0, 0
    for t in range(-3,3):      # t is along the y axis of image：-3~2
        for s in range(-3,3):  # s is along the x axis of image：-3~2
            index = (t+3)*7+(s+3)
            i_disp = disparity_maps[:,2*index:2*(index+1),:,:]
            # d(s,t) of half its neighborhood views
            no10, no01, no11 = 2*(index+1), 2*(index+7), 2*(index+8)
            d10_disp = disparity_maps[:,no10:no10+2,:,:]
            d01_disp = disparity_maps[:,no01:no01+2,:,:]
            d11_disp = disparity_maps[:,no11:no11+2,:,:]
            d10_errormap = basic.checkLRDispErrorMap(i_disp, d10_disp, 1, 0)
            d01_errormap = basic.checkLRDispErrorMap(i_disp, d01_disp, 0, 1)
            d11_errormap = basic.checkLRDispErrorMap(i_disp, d11_disp, 1, 1)
            consistency_loss += (d01_errormap.mean() + d10_errormap.mean() + d11_errormap.mean()) / 3.0
            no += 1
    return consistency_loss / no

def computeSmoothLoss(disparity_a2b, image_b):
    """
    image_batch: [B, 3, H, W], value of [-1,1]
    flow_batch: [B, 2, H, W], value of [-7,7]
    """
    guide_map = 10.0*(torch.mean(image_b, dim=1, keepdim=True)+1.0)
    gy_disp = torch.norm(disparity_a2b[:,:,:-1,:]-disparity_a2b[:,:,1:,:], dim=1)
    gx_disp = torch.norm(disparity_a2b[:,:,:,:-1]-disparity_a2b[:,:,:,1:], dim=1)
    y_weight = torch.exp(-torch.abs(guide_map[:,:,:-1,:]-guide_map[:,:,1:,:]))
    x_weight = torch.exp(-torch.abs(guide_map[:,:,:,:-1]-guide_map[:,:,:,:1]))
    smoothLoss = torch.mean(gy_disp*y_weight) + torch.mean(gx_disp*x_weight)
    return smoothLoss

def computeTotalVariation(flow_batch):
    """
    flow_batch: [B, C, H, W] flow or depth
    """
    y_tv = torch.pow((flow_batch[:,:,1:,:]-flow_batch[:,:,:-1,:]),2).mean()
    x_tv = torch.pow((flow_batch[:,:,:,1:]-flow_batch[:,:,:,:-1]),2).mean()
    totalVar = (x_tv + y_tv) / 2.0
    return totalVar

def computeMaskPriorLoss(mask_batch, guidance_batch):
    """
    image_batch: [B, 1, H, W], value of [-1,1]
    guidance_batch: [B, 1, H, W], value of [0,2]  threshold_value: 0.2
    """
    weight_map = torch.exp(-10.0*guidance_batch)
    return torch.sum(mask_batch*weight_map) / (eps+torch.sum(weight_map))

class Vgg19Loss:
    def __init__(self, multiGpu=True):
        # data in RGB format, [0,1] range
        self.mean = [0.485, 0.456, 0.406]
        self.std = [0.229, 0.224, 0.225]
        vgg19 = VM.vgg19(pretrained=True)
        # maxpoll after conv4_4
        self.featureExactor = nn.Sequential(*list(vgg19.features)[:28])
        for param in self.featureExactor.parameters():
            param.requires_grad = False
        if multiGpu:
            self.featureExactor = torch.nn.DataParallel(self.featureExactor).cuda()
        #! evaluation mode
        self.featureExactor.eval()
        print('[*] Vgg19Loss init!')

    def normalize(self, tensor):
        tensor = tensor.clone()
        mean = torch.as_tensor(self.mean, dtype=torch.float32, device=tensor.device)
        std = torch.as_tensor(self.std, dtype=torch.float32, device=tensor.device)
        tensor.sub_(mean[None, :, None, None]).div_(std[None, :, None, None])
        return tensor

    def __call__(self, yInput, yTarget):
        inFeature = self.featureExactor(self.normalize(yInput))
        targetFeature = self.featureExactor(self.normalize(yTarget))
        return l2_loss(inFeature, targetFeature)


#!/usr/bin/env python3

from matplotlib.pyplot import figure, show
from numpy import linspace, meshgrid, pi, sin  # for testing

"""
More sophisticated 3-D plots with Mayavi
    https://github.com/scivision/mayavi-examples
or Plotly (offline or online):
    https://github.com/scivision/plotly3d-examples-python
"""

def test():
    x, y = meshgrid(linspace(0, 2 * pi), linspace(0, 2 * pi))

    z = sin(x + 0.5 * y)
    ax = figure().gca(projection="3d")
    ax.plot_wireframe(x, y, z)
    show()

if __name__ == "__main__":
    test()


import torch
import pickle
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import torchvision.models as models
from dataset import Dataset

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = models.resnet18(pretrained=False)
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 10)
model = model.to(device)

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

transform = transforms.Compose([
    transforms.RandomHorizontalFlip(),
    transforms.RandomCrop(32, padding=4),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])

trainset = Dataset(train=True, transform=transform, custom_images_path='cifar10_32')
print(len(trainset))
# trainset = torchvision.datasets.CIFAR10(root="./data", train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=32, shuffle=True, num_workers=0)
for epoch in range(50):
    running_loss = 0.0
    for i, data in enumerate(trainloader):
        inputs, labels = data
        inputs, labels = inputs.to(device), labels.to(device)

        outputs = model(inputs)
        loss = criterion(outputs, labels)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if i % 200 == 199:
            print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 200))
            running_loss = 0.0

print('Finished Training')

PATH = './resnet18_ori.pth'
torch.save(model.state_dict(), PATH)


def calculate():
    operação = input('''
Digite a operação matemática que você deseja :
(+) ADIÇÃO
(- ) SUBTRAÇÃO
(* )MULTIPLICAÇÃO
(/ )DIVISÃO
''')

    nu1 = float(input('ensira o primero valor: '))
    nu2 = float(input('insira o segundo valos: '))
# ADIÇAO
    if operação == '+':
        print('{} + {} = '.format(nu1, nu2))
        print(nu1 + nu2)
# SUBTRAÇAO
    elif  operação == '-':
        print('{} - {} = '.format(nu1, nu2))
        print(nu1 - nu2)
# MULTIPLICAÇÃO
    elif operação == '*':
        print('{} * {} = '.format(nu1, nu2))
        print(nu1 * nu2)
# DIVISAO
    elif operação== '/':
        print('{} / {} = '.format(nu1, nu2))
        print(nu1 / nu2)
# ERRO
    else:
        print('.Você não digitou um operador válido, execute o programa novamente. ')

    # Add again() function to calculate() function
    again()

def again():
    calcular_novamente = input('''
Deseja calcular novamente?
Digite S para SIM ou N para NÃO.
''')

    if calcular_novamente.upper() == 'S':
        calculate()
    elif calcular_novamente.upper() == 'N':
        print('ATÉ PRÓXIMA.')
    else:
        again()

calculate()


from itertools import compress, product

def combinations(items):
    return ( set(compress(items,mask)) for mask in product(*[[0,1]]*len(items)) )
    # alternative:                      ...in product([0,1], repeat=len(items)) )

#l = [1,6,5,3]
#print(combinations(list(l)))
from itertools import chain, combinations

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)  # allows duplicate elements
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

stuff = [1, 2, 3]
stuff = [1,6,5,3]
from itertools import chain, combinations
max_sum = sum(stuff)
res_sum = 0
res_list = []
for i, combo in enumerate(powerset(stuff), 1):
    print('combo #{}: {}'.format(i, combo))
    print('combo #{}'.format(combo))
    curr_sum = sum(combo)
    diff = max_sum - curr_sum
    if curr_sum > diff:
        if res_sum == 0 or curr_sum < res_sum:
            res_sum = curr_sum
            res_list = list(combo)
print(res_sum, res_list)


from cs50 import SQL
db = SQL("sqlite:///finance.db")

rows = db.execute("SELECT * FROM log")
print(rows)

new_rows = []
for i in range(len(rows)):
    if rows[i]["symbol"] not in [item["symbol"] for item in new_rows]:
        new_rows.append(rows[i])
        print("NO DUBLICATE")
    else:
        for row in new_rows:
            if row["symbol"] == rows[i]["symbol"]:
                row["shares"] += rows[i]["shares"]

print(new_rows)


class node:
	def __init__(self, data=None, next=None):
		self.data = data
		self.next = next
	def __str__(self):
		return str(self.data)

class LinkedList:
	def __init__(self):
		self.head = None

	def createlist(self, ll):
		self.head = node(ll[0])
		curr = self.head

		for i in range(1,len(ll)):
			n = node(ll[i])
			curr.next = n
			curr = n
		self.listall()

	def appendfront(self,val):
		if(self.head):
			newnode = node(val,self.head)
			self.head = newnode
		else:
			self.head = node(val)
		self.listall()

	def listall(self):
		itr = self.head
		while(itr):
			print(itr, end="-->")
			itr = itr.next
		print()

	def appendend(self, val):
		if(self.head):
			itr = self.head
			while(itr.next):
				itr = itr.next
			itr.next = node(val)
		else:
			self.head = node(val)
		self.listall()

	def getsize(self):
		count = 0
		itr = self.head
		while itr:
			count = count + 1
			itr = itr.next

		return count

	def append(self,i,val):
		if(i<0 or i>=self.getsize()):
			print("invalid index")
			return
		count = 0
		itr = self.head
		while(count!=(i-1)):
			itr = itr.next
			count+=1
		newnode = node(val,itr.next)
		itr.next = newnode
		self.listall()

	def remove(self, index):
		if index<0 or index>=self.getsize():
			raise Exception("Invalid Index")
		if index == 0:
			self.head = self.head.next

		else:
			count = 0
			itr = self.head
			while count != index-1 :
				itr = itr.next
				count += 1
			itr.next = itr.next.next
		self.listall()

	def insert_after_value(self, data_after, data_to_insert):

		itr = self.head
		while(itr):
			if(itr.data == data_after):
				n = node(data_to_insert, itr.next)
				itr.next = n
				break
			itr = itr.next
		self.listall()

	def remove_by_value(self, data):
		itr = self.head
		if(itr.data == data):
			self.head = itr.next
			self.listall()
			return

		while(itr):
			if(itr.next.data == data):
				itr.next = itr.next.next
				break
			itr = itr.next
		self.listall()

	def findmiddle(self):
		p1 = self.head
		p2 = self.head

		while(p2 and p2.next):
			p2 = p2.next.next
			p1 = p1.next
		return print(p1.data)

	def reverse(self, head):
		print("current head", head)

		if(head.next == None):
			self.head = head
			return head
		else:
			prev = self.reverse(head.next)
			print("prev",prev)
			print("head is: ", head)
			prev.next = head
			head.next = None

			return head

l1=["banana","mango","grapes","orange", "jackfruit", "peach"]

linkedlist = LinkedList()

linkedlist.createlist(l1)
# linkedlist.findmiddle()
linkedlist.reverse(linkedlist.head)
linkedlist.listall()

# linkedlist.insert_after_value('banana', 'jackfruit')
# linkedlist.remove_by_value('banana')


from odoo import fields, models, api

class HrContract(models.Model):
    _inherit = 'hr.contract'

    def write(self, vals):
        for contract in self:
            hr_responsible = contract.hr_responsible_id
            payroll = contract.wage
            effective_date = contract.date_start
            contract_id = contract.id
            # employee_id = contract.employee_id

            if 'hr_responsible_id' in vals:
                hr_responsible = vals['hr_responsible_id']
            if 'wage' in vals:
                payroll = vals['wage']
            if 'date_start' in vals:
                effective_date = vals['date_start']
            # if 'id' in vals:
            #     contract_id = vals['id']

            # Create new record on Payroll Wage History
            new_record = {'contract_id': contract_id,
                          'create_uid': hr_responsible,
                          'previous_wage': contract.wage,
                          'current_wage': payroll,
                          'currency_id': self.env.ref('base.USD').id,
                          'effective_date': effective_date}

            self.env['payroll.wage.history'].create(new_record)

            # Update values on hr.employee

            # wage_history_rec_count = self.env[
            #     "payroll.wage.history"].search_count(
            #     [('employee_id', '=', contract.employee_id.id)])
            # new_record_ = {
            #     'current_wage': payroll
            # }
            # self.env['hr.employee'].browse(employee_id.id).write(new_record_)

        return super(HrContract, self).write(vals)


# -*- coding: utf-8 -*-
"""Module vcf.py from yapp

This module exports functions to parse VCF files into various input
for other modules in yapp or other packages. VCF files are read using cyvcf2.
"""
import sys
import logging
from collections import defaultdict
import numpy as np
import zarr
from cyvcf2 import VCF

logger = logging.getLogger(__name__)

modes_avail = ["genotype", "inbred", "phased", "likelihood"]
default_mode = modes_avail[0]

def geno2int(a1, a2):
    if a1 == -1 or a2 == -1:
        return -1
    else:
        return a1 + a2

def geno2hap(a1, a2):
    if a1 == -1 or a2 == -1 or (a1 != a2):
        return -1
    else:
        return a1

def phred2ln(x):
    """Transforms a PHRED score into a natural logarithm"""
    return -0.1 * np.log(10) * x

def chunk_region(reg, chunksize=-1):
    """Decompose reg into smaller regions
    Parameters
    ----------
    reg : str
       region in bed format ("chr:begin-end").
       begin and end may contain commas.
    chunksize : float
       size of chunks in basepairs

    Returns
    -------
    list of str
        list of sub-regions in bed format.
        If chunksize is <0, returns a list with the original region
    """
    if chunksize < 0:
        return [reg]
    chrom, coords = reg.split(":")
    beg, end = coords.split("-")
    beg = int(beg.replace(",", ""))
    end = int(end.replace(",", ""))
    starts = np.arange(beg, end, step=chunksize, dtype=int)
    ends = [int(x + chunksize - 1) for x in starts]
    ends[-1] = end
    reglist = []
    for i, s in enumerate(starts):
        newreg = chrom + ":" + str(s) + "-" + str(ends[i])
        reglist.append(newreg)
    return reglist

def vcf_chunk_regions(fname, chunksize=-1):
    """Creates regions of chunksize in a VCF file from contig header information
    Parameters
    ----------

    fname : str
        The name of the vcf(.gz) file
    chunksize : int
        Size of chunks

    Returns
    -------
    list of str
        List of regions in bed format. If chunksize is <0, regions are contigs.
    """
    v = VCF(fname, lazy=True)
    regions = [name + ":" + "0-" + str(l) for name, l in zip(v.seqnames, v.seqlens)]
    if chunksize > 0:
        new_regions = []
        for r in regions:
            new_regions += chunk_region(r, chunksize)
        regions = new_regions
    return regions

def vcf2fph(
    fname,
    mode=default_mode,
    samples=None,
    reg=None,
    maf=0.01,
    varids=None,
    genotypes=True,
):
    """Parses a VCF file and returns data arrays usable with
    the fastphase package

    Parameters
    ----------
    fname : str
        The name of the vcf(.gz) file
    mode : str
        One of 'genotype', 'inbred', 'phased' or 'likelihood'.

        In 'genotype' mode, the returning 1D arrays are genotypes
        (0,1,2 and -1 for missing data)

        In 'inbred' mode, the resulting 1D arrays are haplotypes (0,1 and -1).
        Heterozygote calls are treated as missing data.

        In 'phased' mode, two haplotype 1D arrays are returned per
        sample, using phased information in the VCF (eg. 0|1). Any non
        phased genotype is considered missing.

        In 'likelihood' mode, the resulting 2D arrays contain the
        genotype log-likelihoods extracted from the 'PL' field.

    samples : list
        List of samples to extract from full set in file
    reg : str
        query variants in region reg only in bed format ("chr:begin-end").
        VCF file must be indexed.
    maf : double
        Minimum allele frequency to include variants
    varids : list
        List of variants IDs to extract. Only variants found in vcf are
        returned, irrespective of MAF.
    genotypes : bool
        Return Genotype data. For large files this can be quite big.
    Returns
    -------
    dict
        {
         regions : list of regions (str)
         samples : list of samples (str)
         variants : dict {region : list of variants (ID, CHROM, POS, REF, ALT)}
         data : dict {region : dict {
                                  sample ID: data (numpy array)
                                  data type depends on mode. see Parameters.)}
        }

    """

    v = VCF(fname, gts012=True, strict_gt=True, samples=samples, lazy=True)
    smp = v.samples  # might differ if some requested are not found

    if reg is None:
        regions = v.seqnames
    else:
        regions = [reg]

    if varids is None:
        keepvar = defaultdict(lambda: True)
    else:
        maf = 0
        keepvar = defaultdict(lambda: False)
        for s in varids:
            keepvar[s] = True
    variants = {}
    trueregions = []
    variants_summary = {}
    fphdata = {}
    for r in regions:
        snps = []
        for s in v(r):
            if len(s.ALT) > 1 or s.aaf < maf or not keepvar[s.ID]:
                continue
            snps.append(s)
        if len(snps) == 0:
            continue
        variants[r] = sorted(snps, key=lambda x: x.POS)
        variants_summary[r] = [
            (s.ID, s.CHROM, s.POS, s.REF, s.ALT[0]) for s in variants[r]
        ]
        fphdata[r] = {}
        trueregions.append(r)
        if genotypes:
            for i, sid in enumerate(smp):
                if mode == "likelihood":
                    fphdata[r][sid] = phred2ln(
                        np.array(
                            [
                                [
                                    s.gt_phred_ll_homref[i],
                                    s.gt_phred_ll_het[i],
                                    s.gt_phred_ll_homalt[i],
                                ]
                                for s in variants[r]
                            ],
                            dtype=np.float,
                        )
                    )
                else:
                    geno = [s.genotypes[i] for s in variants[r]]
                    if mode == "genotype":
                        fphdata[r][sid] = np.array(
                            [geno2int(*g[:2]) for g in geno], dtype=np.int
                        )
                    elif mode == "inbred":
                        fphdata[r][sid] = np.array(
                            [geno2hap(*g[:2]) for g in geno], dtype=np.int
                        )
                    elif mode == "phased":
                        h1 = []
                        h2 = []
                        for g in geno:
                            if g[2]:
                                h1.append(g[0])
                                h2.append(g[1])
                            else:
                                h1.append(-1)
                                h2.append(-1)
                        fphdata[r][sid + ".h1"] = np.array(h1, dtype=np.int)
                        fphdata[r][sid + ".h2"] = np.array(h2, dtype=np.int)
    return {
        "regions": trueregions,
        "samples": smp,
        "variants": variants_summary,
        "data": fphdata,
    }

def vcf2zarr(
    fname,
    output_prefix=None,
    mode=default_mode,
    samples=None,
    reg=None,
    maf=0.01,
    varids=None,
):
    """Parses a VCF file and creates a ZARR file with its contents

    Parameters
    ----------
    fname : str
        The name of the vcf(.gz) file
    output_prefix: str
        The prefix for zarr file name (prefix.zarr)
    mode : str
        One of 'genotype', 'inbred', 'phased' or 'likelihood'.

        In 'genotype' mode, the returning 1D arrays are genotypes
        (0,1,2 and -1 for missing data)

        In 'inbred' mode, the resulting 1D arrays are haplotypes (0,1 and -1).
        Heterozygote calls are treated as missing data.

        In 'phased' mode, two haplotype 1D arrays are returned per
        sample, using phased information in the VCF (eg. 0|1). Any non
        phased genotype is considered missing.

        In 'likelihood' mode, the resulting 2D arrays contain the
        genotype log-likelihoods extracted from the 'PL' field.

    samples : list
        List of samples to extract from full set in file
    reg : str
        query variants in region reg only in bed format
        ("chr:begin-end"). VCF file must be indexed.
    maf : double
        Minimum allele frequency to include variants
    varids : list
        List of variants IDs to extract. Only variants found in vcf
        are returned, irrespective of MAF.
    genotypes : bool
        Return Genotype data. For large files this can be quite big.
    Returns
    -------
    str
       handler to the zarr root group

    """

    v = VCF(fname, gts012=True, strict_gt=True, samples=samples, lazy=True)
    if not output_prefix:
        output_prefix = fname.split(".")[0]
    fzname = output_prefix + ".zarr"
    fz = zarr.open(fzname, "w")
    fz.attrs["archive"] = fzname
    smp = v.samples  # might differ if some requested are not found
    if reg is None:
        _regions = v.seqnames
    else:
        _regions = [reg]

    regions = []
    for r in _regions:
        ns = len([s for s in v(r)])
        if ns > 0:
            regions.append(r)
    if len(regions) < 1:
        raise IOError(f"No SNP found in {fname}")

    logger.info("Creating Archive structure")
    fz["samples"] = zarr.array(smp, dtype="U50")
    fz["regions"] = zarr.array(regions, dtype="U50")
    for i, reg in enumerate(regions):
        fz.create_group(f"variants/{reg}")
    fz.create_group("genotypes")

    if varids is None:
        keepvar = defaultdict(lambda: True)
    else:
        maf = 0
        keepvar = defaultdict(lambda: False)
        for s in varids:
            keepvar[s] = True

    for r in regions:
        logger.info(f"Getting data for region {r}")
        snps = []
        for s in v(r):
            if len(s.ALT) > 1 or s.aaf < maf or not keepvar[s.ID]:
                continue
            snps.append(s)
        if len(snps) == 0:
            continue
        variants = sorted(snps, key=lambda x: x.POS)
        fz[f"variants/{r}/ID"] = np.array([s.ID for s in variants], dtype="U50")
        fz[f"variants/{r}/CHROM"] = np.array([s.CHROM for s in variants], dtype="U50")
        fz[f"variants/{r}/POS"] = np.array([s.POS for s in variants], dtype=np.uint32)
        fz[f"variants/{r}/REF"] = np.array([s.REF for s in variants], dtype="S20")
        fz[f"variants/{r}/ALT"] = np.array([s.ALT[0] for s in variants], dtype="S20")

        data = []
        for i, sid in enumerate(smp):
            sys.stdout.write(f"{sid:<20} {100*(i+1)/len(smp):.2f} %\r")
            sys.stdout.flush()
            if mode == "likelihood":
                gind = phred2ln(
                    np.array(
                        [
                            [
                                s.gt_phred_ll_homref[i],
                                s.gt_phred_ll_het[i],
                                s.gt_phred_ll_homalt[i],
                            ]
                            for s in variants[r]
                        ],
                        dtype=np.float,
                    )
                )
            else:
                geno = [s.genotypes[i] for s in variants]
                if mode == "genotype":
                    gind = np.array([geno2int(*g[:2]) for g in geno], dtype=np.int8)
                elif mode == "inbred":
                    gind = np.array([geno2hap(*g[:2]) for g in geno], dtype=np.int8)
                elif mode == "phased":
                    gind = np.array(
                        [
                            [g[0] if g[2] else -1 for g in geno],
                            [g[1] if g[2] else -1 for g in geno],
                        ],
                        dtype=np.int8,
                    )
            data.append(gind)
        fz[f"genotypes/{r}"] = zarr.array(data, chunks=False)
    return fz


# -*- coding: utf-8 -*-
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone

from easy_thumbnails.fields import ThumbnailerImageField

class Category(models.Model):

    title      = models.CharField(max_length=30, blank=True)
    name       = models.CharField(max_length=30, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return self.name

    class Meta:
        db_table = 'whale_categories'

class Thing(models.Model):

    user            = models.ForeignKey(User)
    category        = models.ForeignKey(Category)
    title           = models.CharField(max_length=255, blank=True)
    shop            = models.CharField(max_length=255, blank=True)
    pic             = ThumbnailerImageField(upload_to="whale/%d/%d" % (timezone.now().year, timezone.now().month))
    post            = models.TextField()
    price           = models.FloatField(default=0)
    location        = models.CharField(max_length=255, blank=True)
    location_map    = models.CharField(max_length=255, blank=True)
    created_at      = models.DateTimeField(auto_now_add=True)
    last_replied_at = models.DateTimeField(auto_now=True)
    is_featured     = models.BooleanField(default=False)

    def __unicode__(self):
        return self.title

    class Meta:
        db_table = 'whale_things'


# -*- coding: utf-8 -*-
'''
陌生人识别模型和情感分析模型的结合的主程序

用法：
python checkingstrangersandfacialexpression.py
python checkingstrangersandfacialexpression.py --filename tests/room_01.mp4
'''

# 导入包
import argparse
from oldcare.utils.insertingassistant import inserting
from oldcare.utils.pathassistant import get_path
from oldcare.utils import communicationassistant
from oldcare.facial import FaceUtil
from PIL import Image, ImageDraw, ImageFont
from oldcare.utils import fileassistant
from keras.models import load_model
from keras.preprocessing.image import img_to_array
import cv2
import time
import numpy as np
import imutils
from oldcare.utils.streampushassistant import stream_pusher
import multiprocessing

if __name__ == '__main__':
    raw_q = multiprocessing.Queue()
    my_pusher = stream_pusher(rtmp_url=get_path('rtmp_room_output', 2), raw_frame_q=raw_q)
    my_pusher.run()

    stranger_type = 5
    old_smile_type = 1

    # 全局变量
    output_stranger_path = get_path('output_stranger_path', 1)
    output_smile_path = get_path('output_smile_path', 1)

    facial_recognition_model_path = get_path('facial_recognition_model_path')
    facial_expression_model_path = get_path('facial_expression_model_path')

    people_info_path = get_path('people_info_path')
    facial_expression_info_path = get_path('facial_expression_info_path')

    # 更新一下people_info.csv
    communicationassistant.get_people_info()

    # 得到当前时间
    current_time = time.strftime('%Y-%m-%d %H:%M:%S',
                                 time.localtime(time.time()))
    print('[INFO] %s 陌生人检测程序和表情检测程序启动了.' % (current_time))

    # 传入参数
    ap = argparse.ArgumentParser()
    ap.add_argument("-f", "--filename", required=False, default='',
                    help="")
    args = vars(ap.parse_args())
    input_video = args['filename']

    # 全局常量
    FACIAL_EXPRESSION_TARGET_WIDTH = 48
    FACIAL_EXPRESSION_TARGET_HEIGHT = 48

    VIDEO_WIDTH = 640
    VIDEO_HEIGHT = 480

    ANGLE = 20

    # 得到 ID->姓名的map 、 ID->职位类型的map、
    # 摄像头ID->摄像头名字的map、表情ID->表情名字的map
    id_card_to_name, id_card_to_type = fileassistant.get_people_info(
        people_info_path)
    facial_expression_id_to_name = fileassistant.get_facial_expression_info(
        facial_expression_info_path)

    # 控制陌生人检测
    strangers_timing = 0  # 计时开始
    strangers_start_time = 0  # 开始时间
    strangers_limit_time = 4  # if >= 2 seconds, then he/she is a stranger.

    # 控制情感分析
    facial_expression_timing = 0  # 计时开始
    facial_expression_start_time = 0  # 开始时间
    facial_expression_limit_time = 2  # if >= 2 seconds, he/she is smiling

    # 初始化摄像头
    if not input_video:
        vs = cv2.VideoCapture(get_path('rtmp_room_input', 2))
        time.sleep(2)
    else:
        vs = cv2.VideoCapture(input_video)

    # 初始化人脸识别模型
    faceutil = FaceUtil(facial_recognition_model_path)
    facial_expression_model = load_model(facial_expression_model_path)

    print('[INFO] 开始检测陌生人和表情...')
    # 不断循环
    counter = 0
    old_count = 0
    old_name = ''
    while True:
        counter += 1
        # grab the current frame
        (grabbed, frame) = vs.read()
        # for i in range(5):
        #     vs.grab()

        # if we are viewing a video and we did not grab a frame, then we
        # have reached the end of the video
        if input_video and not grabbed:
            break

        if not input_video:
            frame = cv2.flip(frame, 1)

        frame = imutils.resize(frame, width=VIDEO_WIDTH, height=VIDEO_HEIGHT)  # 压缩，加快识别速度
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # grayscale，情感分析

        face_location_list, names = faceutil.get_face_location_and_name(
            frame)

        # 得到画面的四分之一位置和四分之三位置，并垂直划线
        one_fourth_image_center = (int(VIDEO_WIDTH / 4),
                                   int(VIDEO_HEIGHT / 4))
        three_fourth_image_center = (int(VIDEO_WIDTH / 4 * 3),
                                     int(VIDEO_HEIGHT / 4 * 3))

        cv2.line(frame, (one_fourth_image_center[0], 0),
                 (one_fourth_image_center[0], VIDEO_HEIGHT),
                 (0, 255, 255), 1)
        cv2.line(frame, (three_fourth_image_center[0], 0),
                 (three_fourth_image_center[0], VIDEO_HEIGHT),
                 (0, 255, 255), 1)

        # 处理每一张识别到的人脸
        for ((left, top, right, bottom), name) in zip(face_location_list, names):
            # 人脸识别错误矫正
            if len(face_location_list) == 1 and id_card_to_type[name] == 'old_people':
                old_count = 15
                old_name = name
            if old_count != 0:
                name = old_name
                old_count -= 1
            # 将人脸框出来
            rectangle_color = (0, 0, 255)
            print(name)
            if id_card_to_type[name] == 'old_people':
                rectangle_color = (0, 0, 128)
            elif id_card_to_type[name] == 'employee':
                rectangle_color = (255, 0, 0)
            elif id_card_to_type[name] == 'volunteer':
                rectangle_color = (0, 255, 0)
            else:
                pass
            cv2.rectangle(frame, (left, top), (right, bottom),
                          rectangle_color, 2)

            # 陌生人检测逻辑
            if 'Unknown' in names:  # alert
                if strangers_timing == 0:  # just start timing
                    strangers_timing = 1
                    strangers_start_time = time.time()
                else:  # already started timing
                    strangers_end_time = time.time()
                    difference = strangers_end_time - strangers_start_time

                    current_time = time.strftime('%Y-%m-%d %H:%M:%S',
                                                 time.localtime(time.time()))

                    if difference < strangers_limit_time:
                        print('[INFO] %s, 房间, 陌生人仅出现 %.1f 秒. 忽略.'
                              % (current_time, difference))
                    else:  # strangers appear
                        event_desc = '陌生人出现!!!'
                        event_location = '房间'
                        print('[EVENT] %s, 房间, 陌生人出现!!!'
                              % (current_time))

                        # event_desc, event_type, event_location, old_people_id, output_path, frame
                        inserting(event_desc, stranger_type, event_location, None, output_stranger_path,
                                  frame)

                        # 开始陌生人追踪f
                        unknown_face_center = (int((right + left) / 2),
                                               int((top + bottom) / 2))

                        cv2.circle(frame, (unknown_face_center[0],
                                           unknown_face_center[1]), 4, (0, 255, 0), -1)

                        direction = ''
                        # face locates too left, servo need to turn right,
                        # so that face turn right as well
                        if unknown_face_center[0] < one_fourth_image_center[0]:
                            direction = 'right'
                        elif unknown_face_center[0] > three_fourth_image_center[0]:
                            direction = 'left'

                        # adjust to servo
                        if direction:
                            print('%d-摄像头需要 turn %s %d 度' % (counter,
                                                             direction, ANGLE))
            else:  # everything is ok
                strangers_timing = 0

            # 表情检测逻辑
            # 如果不是陌生人，且对象是老人
            if name != 'Unknown' and id_card_to_type[name] == 'old_people':
                # 表情检测逻辑
                roi = gray[top:bottom, left:right]
                roi = cv2.resize(roi, (FACIAL_EXPRESSION_TARGET_WIDTH,
                                       FACIAL_EXPRESSION_TARGET_HEIGHT))
                roi = roi.astype("float") / 255.0
                roi = img_to_array(roi)
                roi = np.expand_dims(roi, axis=0)

                # determine facial expression
                (smile, neural) = facial_expression_model.predict(roi)[0]
                facial_expression_label = 'Neural' if neural > smile else 'Smile'

                if facial_expression_label == 'Smile':  # alert
                    if facial_expression_timing == 0:  # just start timing
                        facial_expression_timing = 1
                        facial_expression_start_time = time.time()
                    else:  # already started timing
                        facial_expression_end_time = time.time()
                        difference = facial_expression_end_time - facial_expression_start_time

                        current_time = time.strftime('%Y-%m-%d %H:%M:%S',
                                                     time.localtime(time.time()))
                        if difference < facial_expression_limit_time:
                            print('[INFO] %s, 房间, %s仅笑了 %.1f 秒. 忽略'
                                  % (current_time,
                                     id_card_to_name[name], difference))
                        else:  # he/she is really smiling
                            event_desc = '%s正在笑' % (id_card_to_name[name])
                            event_location = '房间'
                            print('[EVENT] %s, 房间, %s正在笑.'
                                  % (current_time, id_card_to_name[name]))

                            # event_desc, event_type, event_location, old_people_id, output_path, frame
                            inserting(event_desc, old_smile_type, event_location, int(name),
                                      output_smile_path, frame)

                else:  # everything is ok
                    facial_expression_timing = 0

            else:  # 如果是其他人，则不检测表情
                facial_expression_label = ''

            # 人脸识别和情感分析都结束后，把表情和人名写上
            # (同时处理中文显示问题)
            img_PIL = Image.fromarray(cv2.cvtColor(frame,
                                                   cv2.COLOR_BGR2RGB))

            draw = ImageDraw.Draw(img_PIL)
            final_label = id_card_to_name[name] + ': ' + facial_expression_id_to_name[
                facial_expression_label] if facial_expression_label else id_card_to_name[name]
            draw.text((left, top - 30), final_label,
                      # font=ImageFont.truetype('NotoSansCJK-Black.ttc', 40),
                      font=ImageFont.truetype('simsun.ttc', 40),
                      fill=(255, 0, 0))  # linux

            # 转换回OpenCV格式
            frame = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR)
        # show our detected faces along with smiling/not smiling labels
        # cv2.imshow("Checking Strangers and Old People's Face Expression",
        #            frame)

        info = (frame, '2', '3', '4')
        if not raw_q.full():
            raw_q.put(info)
        cv2.waitKey(1)

        # Press 'ESC' for exiting video
        k = cv2.waitKey(1) & 0xff
        if k == 27:
            break

    # cleanup the camera and close any open windows
    vs.release()
    cv2.destroyAllWindows()


from itertools import chain, combinations
import time

def powerset(J):
    return chain.from_iterable(combinations(J, r) for r in range(len(J)+1))

def putLast(S,J,j):
    J2 = J.copy()
    J2.remove(j)
    J2.append(j)

    return J2

def calculateTardiness(S,J,j):
    if S == 1:
        if P[j]>D[j]:
            return 1
        else:
            return 0
    if S==2:
        t=0
        if P[J[0]] > D[J[0]]:
            t+=1
        if P[J[0]] + P[J[1]] > D[J[1]]:
            t+=1
        return t

    if res[tuple(J[:S-1])]["finnished"] + P[j] > D[j]:
        return 1
    else:
        return 0

def F(S,J):

    if S == 1:
        res[tuple(J)]={
                "finnished" : P[J[0]],
                "tardiness" : calculateTardiness(S, J, J[0]),
                "seq": J
        }
        return

    if S == 2:
        tmp = []
        case1 = putLast(S, J, J[0])
        case2 = J.copy()
        tmp.append(calculateTardiness(S, case1, J[0]) + res[tuple(case1[:S-1])]["tardiness"])
        tmp.append(calculateTardiness(S, case2, J[1]) + res[tuple(case2[:S-1])]["tardiness"])
        finnished = P[J[0]] + P[J[1]]
        t=min(tmp)
        seq = J.copy()
        last=J[tmp.index(t)]
        seq.remove(last)

        res[tuple(J)]={
                "finnished" : finnished,
                "tardiness" : t,
                "seq": seq,
                "last": last
        }
        return

    finnished = res[tuple(J[:S-1])]["finnished"] + P[J[S-1]]

    tmp = []
    for i in range(S):
        previous = putLast(S,J,J[i])
        t=0
        if finnished > D[J[i]]:
           t=1

        tmp.append(t + res[tuple(previous[:S-1])]["tardiness"])

    t = min(tmp)
    seq = J.copy()
    last=J[tmp.index(t)]
    seq.remove(last)

    res[tuple(J)]={
                "finnished" : finnished,
                "tardiness" : t,
                "seq": seq,
                "last": last
        }
    return

res={
     tuple([]): {
                     "Finnished" : 0,
                     "Tardiness" : 0
                 }
     }

P={
   1:24,
   2:1,
   3:47,
   4:48,
   5:4,
   6:23,
   7:41,
   8:18,
   9:19,
   10: 50,
   11:12,
   12:30,
   13:15,
   14:60,
   15:57,
   16:144,
   17:46,
   18:214,
   19:162,
   20:96,
   21:219,
   22:235,
   23:74,
   24:184,
   25:14,
   26:36,
   27:9,
   28:38
}

D={
   1:57,
   2:144,
   3:46,
   4:214,
   5:162,
   6:96,
   7:219,
   8:235,
   9:74,
   10:184,
   11:14,
   12:36,
   13:9,
   14:38,
   15:24,
   16:1,
   17:48,
   18:214,
   19:50,
   20:96,
   21:219,
   22:235,
   23:74,
   24:184,
   25:302,
   26:36,
   27:60,
   28:38
}

start = time.time()

subSets = list(powerset([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28]))

subSets.remove(())

for J in subSets:
    J=list(J)
    F(len(J),J)

print(res)

print("This Took", time.time()-start)


import os
from django.test import TestCase

# Create your tests here.

class TestViews(TestCase):
    """
    TC1 - Test Home Page
    TC2 - Test About us Page
    """

    def test_home_page(self):
        """ TC1 - Test home view renders correct page """
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'home/index.html')

    def test_about_us_page(self):
        """ TC2 - Test about us view renders the correct page"""
        response = self.client.get('/about_us/')
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'home/about_us.html')


#11-dars. Vazifalar

#31.08.2022/Abror

# 1. Foydalanuvchidan juft son kiritishni so'rang. Agar foydalanuvchi juft son kiritsa "Rahmat!", agar toq son kiritsa "Bu son juft emas" degan xabarni chiqaring.
son=int(input("Juft son kiriting: "))
if son%2==0:
  print('Rahmat!')
else: print('Bu juft son emas!')

# 2. Foydalanuvchi yoshini so'rang, va muzeyga kirish uchun chipta narhini quyidagicha chiqaring:
#Agar foydalanuvchi 4 yoshdan kichkina yoki 60 dan katta bo'lsa bepul
#Agar foydalanuvchi 18 dan kichik bo'lsa 10000 so'm
#Agar foydalanuvchi 18 dan katta bo'lsa 20000 so'm

yosh=int(input("Yoshingiz nechida?>>>"))
if yosh<4 or yosh>60:
    narx='bepul'
if yosh>=4 and yosh<18:
    narx=10000
if yosh>=18 and yosh<=60:
    narx=20000

if narx=='bepul':
    print('Chipta bepul')
else: print('Chipta narxi: ', narx)

# 3. Foydalanuvchidan ikita son kiritishni so'rang, sonlarni solishtiring va ularning teng yoki katta/kichikligi haqida xabarni chiqaring
a=float(input("Ikkita son kiriting.\nBirinchi sonni kiriting: "))
b=float(input("Ikkinchi sonni kiriting: "))
if a>b:
    print(f"{a}>{b}")
elif a<b:
    print(f"{a}<{b}")
else: print(f"{a}={b}")

# 4. mahsulotlar degan ro'yxat yarating va kamida 10 ta turli mahsulotni kiriting. Yangi, savat degan bo'sh ro'yxat yarating va foydalanuvchidan savatga kamida 5 ta mahsulot kiritishni so'rang. Savatdagi elementlarni, mahsulotlar ro'yxati bilan solishtiring va qaysi biri ro'yxatda bo'lsa "Mahsulot do'konimizda bor" aks holda, "Mahsulot do'konimizda yo'q" degan xabarlarni chiqaring.

mahsulotlar=['olma','non','tuxum','tarvuz',"sariyog'",'coca cola','rollton','pampers','sut','tort','pista']
savat=[]
for n in range(5):
    savat.append(input(f"{n+1}-mahsulotni kiriting: "))

for mahsulot in savat:
    if mahsulot in mahsulotlar:
        print(f"{mahsulot.title()} do'konimizda bor.")
    else: print(f"{mahsulot.title()} do'konimizda yo'q.")

# 5. Yuqoridagi dasturni quyidagicha o'zgartiring: foydalanuvchidan 5 ta mahsulot kiritishni so'rang. Foydalanuvchi so'ragan va do'konda bor mahsulotlarni yang, bor_mahsulotlar degan ro'yxatga, do'konda yo'q mahsulotlarni esa mavjud_emas degan ro'yxatga qo'shing.  Agar mavjud_emas ro'yxati bo'sh bo'lsa, "Siz so'ragan barcha mahsulotlar do'konimizda bor" degan xabarni, aks holda esa "Quyidagi mahsulotlar do'konimizda yo'q: ....." degan xabarni chiqaring.

mahsulotlar=['olma','non','tuxum','tarvuz',"sariyog'",'coca cola','rollton','pampers','sut','tort','pista']
savat=[]
for n in range(5):
    savat.append(input(f"{n+1}-mahsulotni kiriting: "))
bor_mahsulotlar=[]
mavjud_emas=[]
for mahsulot in savat:
    if mahsulot in mahsulotlar:
        bor_mahsulotlar.append(mahsulot)
    else:
        mavjud_emas.append(mahsulot)

if mavjud_emas:
    print("Quyidagi mahsulotlar do'konimizda yo'q:")
    for n in mavjud_emas:
        print(n)
else:
  print("Do'konimizda barcha mahsulotlar bor.")

# 6. foydalanuvchilar degan ro'yxat tuzing, va kamida 5 ta login qo'shing. Foydalanuvchidan yangi login tanlashni so'rang va foydalanuvchi kiritgan loginni foydalanuvchilar degan ro'yxatning tarkibi bilan solishtiring. Agar ro'yxatda bunday login mavjud bo'lsa, "Login band, yangi login tanlang!" aks holda "Xush kelibsiz, foydalanuvchi!" xabarini chiqaring.

foydalanuvchilar=['ani','jokker','alex','konsta','mira']
login=input("Loginni kiriting:>>>")
if login.lower() in foydalanuvchilar:
    print('Login band. Yangi login tanlang!')
else: print("Xush kelibsiz!")

# 7. Foydalanuvchidan biror butun son kiritishni so'rang. Foydalanuvchi kiritgan sonni 2 da 10 gacha bo'lgan sonlardan qay biriga qoldiqsiz bo'linishini konsolga chiqaring.

son=int(input("Istalgan butun son kiriting: "))
if son%2==0:
    print(f"{son} soni 2 ga qoldiqsiz bo'linadi.")
if son%3==0:
    print(f"{son} soni 3 ga qoldiqsiz bo'linadi.")
if son%4==0:
    print(f"{son} soni 4 ga qoldiqsiz bo'linadi.")
if son%5==0:
    print(f"{son} soni 5 ga qoldiqsiz bo'linadi.")
if son%6==0:
    print(f"{son} soni 6 ga qoldiqsiz bo'linadi.")
if son%7==0:
    print(f"{son} soni 7 ga qoldiqsiz bo'linadi.")
if son%8==0:
    print(f"{son} soni 8 ga qoldiqsiz bo'linadi.")
if son%9==0:
    print(f"{son} soni 9 ga qoldiqsiz bo'linadi.")
if son%10==0:
    print(f"{son} soni 10 ga qoldiqsiz bo'linadi.")

for n in range(2,11):
    if not (son%n):
        print(f"{son} soni {n} ga qoldiqsiz bo'linadi")


import torch
from typing import Dict, List, Optional, Tuple, Union
from detectron2.structures import Boxes, ImageList, Instances, pairwise_iou
from detectron2.modeling.proposal_generator.proposal_utils import (
    add_ground_truth_to_proposals,
)
from detectron2.utils.events import get_event_storage
from detectron2.modeling.roi_heads.box_head import build_box_head
from detectron2.layers import ShapeSpec
from detectron2.modeling.roi_heads import (
    ROI_HEADS_REGISTRY,
    StandardROIHeads,
)
from detectron2.modeling.roi_heads.fast_rcnn import FastRCNNOutputLayers
from adapteacher.modeling.roi_heads.fast_rcnn import FastRCNNFocaltLossOutputLayers, FastRCNNExtendedOutputLayers

import numpy as np
from detectron2.modeling.poolers import ROIPooler

from detectron2.modeling.sampling import subsample_labels

@ROI_HEADS_REGISTRY.register()
class StandardROIHeadsPseudoLab(StandardROIHeads):
    @classmethod
    def _init_box_head(cls, cfg, input_shape):
        # fmt: off
        in_features       = cfg.MODEL.ROI_HEADS.IN_FEATURES
        pooler_resolution = cfg.MODEL.ROI_BOX_HEAD.POOLER_RESOLUTION
        pooler_scales     = tuple(1.0 / input_shape[k].stride for k in in_features)
        sampling_ratio    = cfg.MODEL.ROI_BOX_HEAD.POOLER_SAMPLING_RATIO
        pooler_type       = cfg.MODEL.ROI_BOX_HEAD.POOLER_TYPE
        # fmt: on

        in_channels = [input_shape[f].channels for f in in_features]
        # Check all channel counts are equal
        assert len(set(in_channels)) == 1, in_channels
        in_channels = in_channels[0]

        box_pooler = ROIPooler(
            output_size=pooler_resolution,
            scales=pooler_scales,
            sampling_ratio=sampling_ratio,
            pooler_type=pooler_type,
        )
        box_head = build_box_head(
            cfg,
            ShapeSpec(
                channels=in_channels, height=pooler_resolution, width=pooler_resolution
            ),
        )

        if cfg.MODEL.ROI_HEADS.LOSS == "CrossEntropy":

            ## @darkhan-s for continual learning (expanding network)
            classesAdded = []
            for element in cfg.MODEL.ROI_HEADS.NEW_CLASSES:
                if element not in cfg.MODEL.ROI_HEADS.OLD_CLASSES:
                    classesAdded.append(element)

            if len(classesAdded) > 0:
                print(f"New classes are requested to train: {classesAdded}. Adding extra classifier layer..")
                box_predictor = FastRCNNExtendedOutputLayers(cfg, box_head.output_shape)
            else:
                # regular prediction output
                box_predictor = FastRCNNOutputLayers(cfg, box_head.output_shape)

        elif cfg.MODEL.ROI_HEADS.LOSS == "FocalLoss":
            box_predictor = FastRCNNFocaltLossOutputLayers(cfg, box_head.output_shape)

            for element in cfg.MODEL.ROI_HEADS.NEW_CLASSES:
                if element not in cfg.MODEL.ROI_HEADS.OLD_CLASSES:
                    raise NotImplementedError("Extra classifier not implemented for this head loss.")
        else:
            raise ValueError("Unknown ROI head loss.")

        return {
            "box_in_features": in_features,
            "box_pooler": box_pooler,
            "box_head": box_head,
            "box_predictor": box_predictor,
        }

    def forward(
        self,
        images: ImageList,
        features: Dict[str, torch.Tensor],
        proposals: List[Instances],
        targets: Optional[List[Instances]] = None,
        compute_loss=True,
        branch="",
        compute_val_loss=False,
    ) -> Tuple[List[Instances], Dict[str, torch.Tensor]]:

        del images
        if self.training and compute_loss:  # apply if training loss
            assert targets
            # 1000 --> 512
            proposals = self.label_and_sample_proposals(
                proposals, targets, branch=branch
            )
        elif compute_val_loss:  # apply if val loss
            assert targets
            # 1000 --> 512
            temp_proposal_append_gt = self.proposal_append_gt
            self.proposal_append_gt = False
            proposals = self.label_and_sample_proposals(
                proposals, targets, branch=branch
            )  # do not apply target on proposals
            self.proposal_append_gt = temp_proposal_append_gt
        del targets

        if (self.training and compute_loss) or compute_val_loss:
            losses, _, box_features = self._forward_box(
                features, proposals, compute_loss, compute_val_loss, branch
            )
            return proposals, losses, box_features
        else:
            pred_instances, predictions, box_features = self._forward_box(
                features, proposals, compute_loss, compute_val_loss, branch
            )

            return pred_instances, predictions, box_features

    def _forward_box(
        self,
        features: Dict[str, torch.Tensor],
        proposals: List[Instances],
        compute_loss: bool = True,
        compute_val_loss: bool = False,
        branch: str = "",
    ) -> Union[Dict[str, torch.Tensor], List[Instances]]:
        features = [features[f] for f in self.box_in_features]
        box_features = self.box_pooler(features, [x.proposal_boxes for x in proposals])
        box_features = self.box_head(box_features)
        predictions = self.box_predictor(box_features)
        #@ darkhan-s dont delete box features because they are needed for instance level alignment
        #del box_features
        if (self.training and compute_loss) or compute_val_loss:  # apply if training loss or val loss
            losses = self.box_predictor.losses(predictions, proposals)

            if self.train_on_pred_boxes:
                with torch.no_grad():
                    pred_boxes = self.box_predictor.predict_boxes_for_gt_classes(
                        predictions, proposals
                    )
                    for proposals_per_image, pred_boxes_per_image in zip(
                        proposals, pred_boxes
                    ):
                        proposals_per_image.proposal_boxes = Boxes(pred_boxes_per_image)
            return losses, predictions, box_features
        else:

            pred_instances, _ = self.box_predictor.inference(predictions, proposals)
            return pred_instances, predictions, box_features

    @torch.no_grad()
    def label_and_sample_proposals(
        self, proposals: List[Instances], targets: List[Instances], branch: str = ""
    ) -> List[Instances]:
        gt_boxes = [x.gt_boxes for x in targets]
        if self.proposal_append_gt:
            proposals = add_ground_truth_to_proposals(gt_boxes, proposals)

        proposals_with_gt = []

        num_fg_samples = []
        num_bg_samples = []
        for proposals_per_image, targets_per_image in zip(proposals, targets):
            has_gt = len(targets_per_image) > 0
            match_quality_matrix = pairwise_iou(
                targets_per_image.gt_boxes, proposals_per_image.proposal_boxes
            )
            matched_idxs, matched_labels = self.proposal_matcher(match_quality_matrix)
            sampled_idxs, gt_classes = self._sample_proposals(
                matched_idxs, matched_labels, targets_per_image.gt_classes
            )

            proposals_per_image = proposals_per_image[sampled_idxs]
            proposals_per_image.gt_classes = gt_classes

            if has_gt:
                sampled_targets = matched_idxs[sampled_idxs]
                for (trg_name, trg_value) in targets_per_image.get_fields().items():
                    if trg_name.startswith("gt_") and not proposals_per_image.has(
                        trg_name
                    ):
                        proposals_per_image.set(trg_name, trg_value[sampled_targets])
            else:
                gt_boxes = Boxes(
                    targets_per_image.gt_boxes.tensor.new_zeros((len(sampled_idxs), 4))
                )
                proposals_per_image.gt_boxes = gt_boxes

            # check if  extra classes are added
            try:
                num_bg_samples.append((gt_classes == (self.num_classes + self.box_predictor.extra_num_classes)).sum().item())
            except AttributeError:
                num_bg_samples.append((gt_classes == self.num_classes).sum().item())

            num_fg_samples.append(gt_classes.numel() - num_bg_samples[-1])
            proposals_with_gt.append(proposals_per_image)

        storage = get_event_storage()

        if branch != "val_loss":
            storage.put_scalar(
                "roi_head/num_target_fg_samples_" + branch, np.mean(num_fg_samples)
            )
            storage.put_scalar(
                "roi_head/num_target_bg_samples_" + branch, np.mean(num_bg_samples)
            )

        return proposals_with_gt

    def _sample_proposals(
        self, matched_idxs: torch.Tensor, matched_labels: torch.Tensor, gt_classes: torch.Tensor
    ) -> Tuple[torch.Tensor, torch.Tensor]:
        """
        Based on the matching between N proposals and M groundtruth,
        sample the proposals and set their classification labels.

        Args:
            matched_idxs (Tensor): a vector of length N, each is the best-matched
                gt index in [0, M) for each proposal.
            matched_labels (Tensor): a vector of length N, the matcher's label
                (one of cfg.MODEL.ROI_HEADS.IOU_LABELS) for each proposal.
            gt_classes (Tensor): a vector of length M.

        Returns:
            Tensor: a vector of indices of sampled proposals. Each is in [0, N).
            Tensor: a vector of the same length, the classification label for
                each sampled proposal. Each sample is labeled as either a category in
                [0, num_classes) or the background (num_classes).
        """
        has_gt = gt_classes.numel() > 0
        # Get the corresponding GT for each proposal
        if has_gt:
            gt_classes = gt_classes[matched_idxs]
            # Label unmatched proposals (0 label from matcher) as background (label=num_classes)
            try:
                gt_classes[matched_labels == 0] = (self.num_classes + self.box_predictor.extra_num_classes)
            except AttributeError:
                gt_classes[matched_labels == 0] = self.num_classes

            # Label ignore proposals (-1 label)
            gt_classes[matched_labels == -1] = -1
        else:
            try:
                gt_classes = torch.zeros_like(matched_idxs) + (self.num_classes + self.box_predictor.extra_num_classes)
            except AttributeError:
                gt_classes = torch.zeros_like(matched_idxs) + self.num_classes

        try:
            sampled_fg_idxs, sampled_bg_idxs = subsample_labels(
                gt_classes, self.batch_size_per_image, self.positive_fraction, (self.num_classes + self.box_predictor.extra_num_classes)
            )
        except AttributeError:
            sampled_fg_idxs, sampled_bg_idxs = subsample_labels(
                gt_classes, self.batch_size_per_image, self.positive_fraction, self.num_classes
            )

        sampled_idxs = torch.cat([sampled_fg_idxs, sampled_bg_idxs], dim=0)
        return sampled_idxs, gt_classes[sampled_idxs]


# coding:utf-8

import numpy as np
import xgboost as xgb
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score

class XgbWrapper():

    def __init__(self, booster="gblinear", objective="binary:logistic"):
        self.__params = {"booster": booster, "objective": objective}
        self.__bst = None

    def fit(self, train, train_label):
        self.__bst = xgb.train(self.__params, xgb.DMatrix(data=train, label=train_label))

    def predict(self, test):
        return self.__bst.predict(xgb.DMatrix(data=test)).reshape((-1, 1))

    def predict_proba(self, test):
        return np.hstack((
            1 - self.__bst.predict(xgb.DMatrix(data=test)).reshape((-1, 1)),
            self.__bst.predict(xgb.DMatrix(data=test)).reshape((-1, 1))
        ))

if __name__ == "__main__":
    # data prepare
    iris = load_iris()
    X = iris.data[0:100]
    y = iris.target[0:100]
    train, test, train_label, test_label = train_test_split(X, y, test_size=0.2, random_state=9)

    # XgbWrapper
    xgb_linear = XgbWrapper()
    xgb_linear.fit(train, train_label)
    print(xgb_linear.predict(test))