# main algorithm
import queue
import threading

import cv2

from common import Common
from element_extraction import ElementExtraction
from postprocess import Postprocess
from preprocessing import Preprocess

q = queue.Queue()

def extractor(name, patch, i):  # a function which will run parallely on threads to do the ocr for each roi
    if name == "first_name" or name == "last_name" or name == "address":
        all_words = []
        iters = 6
        occurances = 3
        for factor in range(iters):  # we scan multiple times for highest ocr accuracy
            roi = Common().get_padded_box(i, side_pad_factor=5, vertical_pad_factor=factor)
            cropped = Common().crop(roi, patch)
            extracted = Postprocess().tess_ocr(cropped, name)
            for word in extracted[1]:
                all_words.append(word)
        x = Common().most_occured(all_words, name, occurances)
        final = [name, x]
    else:
        roi = Common().get_padded_box(i, side_pad_factor=5,
                                      vertical_pad_factor=5)  # if multiple scanning is not required
        cropped = Common().crop(roi, patch)
        final = Postprocess().tess_ocr(cropped, name)
    q.put(final)

def extract(path):  # thread initiator
    x = ElementExtraction()
    img = path
    img = Preprocess().to_3channels(cv2.imread(img))
    front, back = x.extract(img, side_pad_factor=10, vertical_pad_factor=1)
    patch = x.patch(front, back)
    all_elements = Common().anchors(patch)
    all_threads = []
    deco = patch.copy()
    for i in all_elements:  # 8 threads for 8 rois
        name = Common().mapid(i)
        if name == "front" or name == "back":
            continue
        t = threading.Thread(target=extractor, args=[name, patch, i])
        t.start()
        all_threads.append(t)
        deco = Postprocess().write(i, deco)
    for th in all_threads:
        th.join()
    cv2.imwrite(path, deco)  # we also write the decorated image with visible bounding boxes
    return len(all_elements) - 2 #delete 2 since we do not consider front and back for direct ocr


import numpy as np
import cv2
import random
import time

sizeX = 700
sizeY = 700

img = np.zeros((sizeX,sizeY),dtype=float)

InIsampledPoints = 35
val=1

for p in range(0,5):
    sampledPoints = InIsampledPoints*val
    val = val*2
    print(sampledPoints)

    sampVals = np.ndarray((sampledPoints+1, sampledPoints + 1))

    for x in range(0,sampledPoints+1):
        for y in range(0,sampledPoints+1):
            if(x == sampledPoints):
                sampVals[x,y] = sampVals[0,y]
            elif(y == sampledPoints):
                sampVals[x,y] = sampVals[x,0]
            else:
                sampVals[x,y] = random.random()

    for i in range(0,sampledPoints):
        for j in range(0,sampledPoints):
            startY = (j*sizeY)//sampledPoints
            endY = ((j+1)*sizeY)//sampledPoints
            lengthY = endY-startY
            for y in range(startY, endY):
                a = (sampVals[i,j+1]*(y-startY)/lengthY + (1-(y-startY)/lengthY)*sampVals[i,j])
                b = (sampVals[i+1,j+1]*(y-startY)/lengthY + (1-(y-startY)/lengthY)*sampVals[i+1,j])

                startX = (i*sizeX)//sampledPoints
                endX = ((i+1)*sizeX)//sampledPoints
                lengthX = endX-startX
                for x in range(startX, endX):
                    img[x,y] = img[x,y] + ((1-(x-startX)/lengthX)*a + ((x-startX)/lengthX)*b)/val
                    #print(img[x,y])

maxN=0
for x in range(0,sizeX):
    for y in range(0,sizeY):
        if (maxN<img[x,y]):
            maxN = img[x,y]

for x in range(0,sizeX):
    for y in range(0,sizeY):
        img[x,y] = img[x,y]/maxN

cv2.imshow("ss", img)
cv2.waitKey(0)


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

"""
Main GTL module responsible for creating, training and testing GTL NN
"""

import numpy as np

from keras.models import Model
from keras.layers import Input, Activation
from keras.layers.core import Dense, Lambda, Reshape
from keras.layers.embeddings import Embedding
from keras.layers.merge import Dot, Concatenate
from keras import backend as K
from keras import optimizers

from SaveData import plotArchitecture

# l2 distance between two network layers
def l2_dist(vects):
    x, y = vects
    sum_square = K.sum(K.square(x - y), axis=1, keepdims=True)
    return K.sqrt(K.maximum(sum_square, K.epsilon()))
# shape of l2 distance between two embeddings in similarity branch
def l2_output_shape_sim(shapes):
    shape1, shape2 = shapes
    return (shape1[0], 1, 1)
# shape of l2 distance between two embeddings in distance branch
def l2_output_shape_dist(shapes):
    shape1, shape2 = shapes
    return (shape1[0], 1)

def createNetworks(input_size, labels, n_layers, embedding_type, embedding_similarity, transmode, same_weights, graph_distance, scale_negative, activation_function):
    """ Creates neural network that learns node embeddings of given graph(s)

    Inputs:
        INPUT_SIZE List [n,m,k,l] where:
            N Number of samples,
            M Number of original features (equal to n for one-hot coding)
            K Number of embedding features
            L Number of node labels
        EMBEDDING_TYPE Type of embedding approach, e.g. 'unified' (unified embedding for target and context nodes) or 'skipgram' (different embeddings for target and context nodes)
        EMBEDDING_SIMILARITY Measure of similarity between node embeddings within one graph
        TRANSMODE Flag to specify transfer learning mode
        GRAPH_DISTANCE Distance between node embeddings of different graphs

    Outputs:
        Neural network for graph node embeddings
    """

    # what is the correct dictionary size?
    dict_size, feature_size, embedding_size, class_size, negative_size = input_size
    inputsEmbedding = []
    inputsEmbeddingA = []
    inputsEmbeddingB = []
    outputsEmbedding = []
    inputsPrediction = []
    outputsPrediction = []

    if embedding_similarity == 'l2':
        from keras.constraints import UnitNorm
        constraints = UnitNorm(axis=1)
    else:
        constraints = None

    # create embedding branch for graph A
    if feature_size == 1:
        input_shape = (1,)
        input_type = 'int32'
        Embedding_targetA = Embedding(dict_size, embedding_size, embeddings_constraint=constraints, name='Embedding_TargetA')
        Embedding_contextA = Embedding(dict_size, embedding_size, embeddings_constraint=constraints, name='Embedding_ContextA')
    else:
        input_shape = (1,feature_size,)
        input_type = 'float'
        Embedding_targetA = Dense(embedding_size, activation='tanh', kernel_constraint=constraints, name='Embedding_TargetA')
        Embedding_contextA = Dense(embedding_size, activation='tanh', kernel_constraint=constraints, name='Embedding_ContextA')

    input_targetA = Input(shape=input_shape, dtype=input_type, name='Input_TargetA')
    input_contextA = Input(shape=input_shape, dtype=input_type, name='Input_ContextA')
    inputsEmbeddingA.extend([input_targetA, input_contextA])

    # use different or the same encodings for target and context
    embedding_targetA = Embedding_targetA(input_targetA)
    target_weights = np.random.multivariate_normal(np.zeros(embedding_size), 0.1*np.identity(embedding_size), dict_size)
    Embedding_targetA.set_weights([target_weights])
    if embedding_type == 'skipgram': # separate embeddings for target and context nodes
        embedding_contextA = Embedding_contextA(input_contextA)
        context_weights = np.random.multivariate_normal(np.zeros(embedding_size), 0.1*np.identity(embedding_size), dict_size)
        Embedding_contextA.set_weights([context_weights])
    elif embedding_type == 'unified': # unified embedding
        embedding_contextA = Embedding_targetA(input_contextA)

    # add more dense layers to embedding branch if predicting pagerank
    if labels == 'pagerank':
        embedding_targetA = Dense(embedding_size, activation='tanh')(embedding_targetA)
        embedding_contextA = Dense(embedding_size, activation='tanh')(embedding_contextA)

    # create similarity branch for graph A
    inputsSimilarityA = [embedding_targetA, embedding_contextA]
    if embedding_similarity == 'softmax':
        # add negative samples
        input_negativeA = Input(shape=(negative_size,)+input_shape[1:], dtype=input_type, name='Input_NegativeA')
        inputsEmbeddingA.extend([input_negativeA])
        embedding_negativeA = Embedding_targetA(input_negativeA)
        # add more dense layers to embedding branch if predicting pagerank
        if labels == 'pagerank':
            embedding_negativeA = Dense(embedding_size, activation='tanh')(embedding_negativeA)
        inputsSimilarityA.extend([embedding_negativeA])
    similarityA = createSimilarityBranch(embedding_size, mode=embedding_similarity, negative_size=negative_size, graph='A', scale_negative=scale_negative)(inputsSimilarityA)
    outputsEmbedding.extend([similarityA])
    inputsEmbedding.extend(inputsEmbeddingA)

    # create prediction branch
    inputsPrediction.extend([input_targetA])
    predictionBranch = createPredictionBranch(embedding_size, n_layers, class_size, activation_function)(embedding_targetA)
    predictionOutput = Reshape((class_size,), name='PredictionOutput')(predictionBranch)
    outputsPrediction.extend([predictionOutput])

    if transmode != '1graph':
        input_targetB = Input(shape=input_shape, dtype=input_type, name='Input_TargetB')
        input_contextB = Input(shape=input_shape, dtype=input_type, name='Input_ContextB')
        inputsEmbeddingB.extend([input_targetB, input_contextB])

        # create embedding branch for graph B
        if feature_size == 1:
            Embedding_targetB = Embedding(dict_size, embedding_size, embeddings_constraint=constraints, name='Embedding_TargetB')
            Embedding_contextB = Embedding(dict_size, embedding_size, embeddings_constraint=constraints, name='Embedding_ContextB')
        else:
            Embedding_targetB = Dense(embedding_size, activation='tanh', kernel_constraint=constraints, name='Embedding_TargetB')
            Embedding_contextB = Dense(embedding_size, activation='tanh', kernel_constraint=constraints, name='Embedding_ContextB')

        # use different or the same encodings for target and context
        embedding_targetB = Embedding_targetB(input_targetB)
        Embedding_targetB.set_weights([target_weights if same_weights else np.zeros((dict_size, embedding_size))]) # np.random.multivariate_normal(np.zeros(embedding_size), 0.1*np.identity(embedding_size), dict_size)])
        if embedding_type == 'skipgram': # separate embeddings for target and context nodes
            embedding_contextB = Embedding_contextB(input_contextB)
            Embedding_contextB.set_weights([context_weights if same_weights else np.zeros((dict_size, embedding_size))]) # np.random.multivariate_normal(np.zeros(embedding_size), 0.1*np.identity(embedding_size), dict_size)])
        elif embedding_type == 'unified': # unified embedding
            embedding_contextB = Embedding_targetB(input_contextB)

        # add more dense layers to embedding branch if predicting pagerank
        if labels == 'pagerank':
            embedding_targetB = Dense(embedding_size, activation='tanh')(embedding_targetB)
            embedding_contextB = Dense(embedding_size, activation='tanh')(embedding_contextB)

        # create similarity branch for graph B
        inputsSimilarityB = [embedding_targetB, embedding_contextB]
        if embedding_similarity == 'softmax':
            # add negative samples
            input_negativeB = Input(shape=(negative_size,)+input_shape[1:], dtype=input_type, name='Input_NegativeB')
            inputsEmbeddingB.extend([input_negativeB])
            embedding_negativeB = Embedding_targetB(input_negativeB)
            # add more dense layers to embedding branch if predicting pagerank
            if labels == 'pagerank':
                embedding_negativeB = Dense(embedding_size, activation='tanh')(embedding_negativeB)
            inputsSimilarityB.extend([embedding_negativeB])
        similarityB = createSimilarityBranch(embedding_size, mode=embedding_similarity, negative_size=negative_size, graph='B', scale_negative=scale_negative)(inputsSimilarityB)
        outputsEmbedding.extend([similarityB])
        inputsEmbedding.extend(inputsEmbeddingB)

        # create graph distance branch
        if transmode != 'noP':
            distanceAB = createDistanceBranch(embedding_size, mode=graph_distance)([embedding_targetA, embedding_targetB])
            outputsEmbedding.extend([distanceAB])

    modelEmbedding = Model(inputs = inputsEmbedding, outputs = outputsEmbedding)
    branchEmbeddingA = Model(inputs  = inputsEmbeddingA, outputs = outputsEmbedding[0])
    branchEmbeddingB = Model(inputs  = inputsEmbeddingB, outputs = outputsEmbedding[1]) if transmode!='1graph' else None
    modelPrediction = Model(inputs = inputsPrediction, outputs = outputsPrediction)

    return modelEmbedding, branchEmbeddingA, branchEmbeddingB, modelPrediction

def createSimilarityBranch(embedding_size, mode='innerprod', negative_size=0, graph='A', scale_negative=False):
    """ Branch of global network: computes similarity between embeddings of given two nodes in a graph
    """
    inputT = Input(shape=(1,embedding_size,), name='Embedding_Target')
    inputC = Input(shape=(1,embedding_size,), name='Embedding_Context')
    inputs = [inputT, inputC]

    layer_name = 'Output_Similarity'
    if mode=='l2': # l2 distance
        similarity =  Lambda(l2_dist, output_shape=l2_output_shape_sim, name=layer_name)(inputs)
    elif mode=='cossim': # cosine similarity
        similarity = Dot(axes=-1, normalize=True, name=layer_name)(inputs)
    elif mode=='innerprod': # inner product
        similarity = Dot(axes=-1, name=layer_name)(inputs)
    else: # softmax (default)
        inputNS = Input(shape=(negative_size,embedding_size,), name='Embedding_NS')
        inputs.append(inputNS)
        similarityTC = Dot(axes=-1)([inputT, inputC])
        similarityCNS = Dot(axes=-1)([inputC, inputNS])
        similarity = Concatenate(axis=-1)([similarityTC, similarityCNS])
        similarity = Activation('softmax', name=layer_name)(similarity)

    # normalize negative samples loss
    if scale_negative:
        def normalizeNS(x):
#            from keras import backend as K
#            x = K.eval(x)
#            for i in range(1,len(x)):
#                x[i] = x[i]/negative_size
#            return K.variable(x)
            return x/negative_size
        similarity = Activation(normalizeNS)(similarity)

    return Model(inputs, similarity, name='Branch_Similarity'+graph)

def createPredictionBranch(embedding_size, n_layers, class_size, activation):
    """ Branch of global network: predicts node label for a given embedding
    """
    input = Input(shape=(embedding_size,), name='Input_Embedding')

#    activation = 'tanh' # sigmoid
    # intermediate layer(s) structure
    prediction = Dense(embedding_size, activation=activation)(input)
    for _ in range(n_layers-1):
        prediction = Dense(embedding_size, activation=activation)(prediction)
    # last layer structure
    layer_name = 'Output_Label'
    if class_size > 1:
        # classification task case
        prediction = Dense(class_size, activation='softmax', name=layer_name)(prediction)
    else:
        # regression task case
        prediction = Dense(class_size, activation='sigmoid', name=layer_name)(prediction)
    return Model(input, prediction, name='Branch_Prediction')

def createDistanceBranch(embedding_size, mode='l2'):
    """ Branch of global network: computes all pairwise distances between node embeddings of different graphs
    """
    input1 = Input(shape=(embedding_size,), name='Input_EmbeddingA')
    input2 = Input(shape=(embedding_size,), name='Input_EmbeddingB')

    layer_name = 'Output_DistanceAB'
    if mode=='innerprod': # inner product
        distance12 =  Dot(axes=-1, name=layer_name)([input1,input2])
    elif mode=='cossim': # cosine similarity
        distance12 =  Dot(axes=-1, normalize=True, name=layer_name)([input1,input2])
    else: # euclidean distance (default)
#        def l2_graphdist(vects):
#            x, y = vects
#            sum_square = K.sum(K.square(x - y), axis=1, keepdims=True)
#            return K.sigmoid(K.sqrt(K.maximum(sum_square, K.epsilon())))-.5
#        distance12 =  Lambda(l2_graphdist, output_shape=l2_output_shape, name=layer_name)([input1,input2])
        distance12 = Lambda(l2_dist, output_shape=l2_output_shape_dist, name=layer_name)([input1,input2])
    return Model([input1, input2], distance12, name='Branch_Distance')

# generic function that specifies loss function to be used
def getLoss(loss='crossentropy'):
    if loss=='l2':
        return L2Loss
    elif loss=='innerprod':
        return InnerProdLoss
    else: # crossentropy (default)
        return 'binary_crossentropy' # multiple true labels are possible in output vector
#        return 'categorical_crossentropy' # only one true label is possible in output vector

# outputs inner product loss between true and predicted labels
def InnerProdLoss(yTrue, yPred):
    return K.sum(yTrue * yPred)

# outputs l2 loss between true and predicted labels
def L2Loss(yTrue, yPred):
    return K.sqrt(K.sum(K.square(yTrue - yPred)))

# root mean squared error
def RMSELoss(yTrue, yPred):
    return K.sqrt(K.mean(K.square(yTrue - yPred)))

def getGTLmodel(n_nodes, n_features, n_embedding, labels, n_labels, n_layers, n_negative, scale_negative, embedding_type, embedding_similarity, similarity_loss, prediction_loss, activation_function, transmode, same_weights, graph_distance, learning_rate, alpha, save_path, output_file, visualize):

    input_size = (n_nodes, n_features, n_embedding, n_labels, n_negative)

    Optimizer = optimizers.SGD(lr=learning_rate, nesterov=True)

    print("\n *************** Creating Model ***************".upper(), file=output_file)
    EmbeddingModel, EmbeddingABranch, EmbeddingBBranch, PredictionModel = createNetworks(input_size, labels, n_layers, embedding_type, embedding_similarity, transmode, same_weights, graph_distance, scale_negative, activation_function)

    # Neural Net learning node embeddings
    EmbLoss = {"Branch_SimilarityA": getLoss(similarity_loss)}
    loss_weights = [1]
    if transmode != '1graph':
        EmbLoss.update({"Branch_SimilarityB": getLoss(similarity_loss)})
        loss_weights.append(1)
        if transmode != 'noP':
            EmbLoss.update({"Branch_Distance": InnerProdLoss})
            loss_weights.append(alpha)
    EmbeddingModel.compile(optimizer=Optimizer, loss=EmbLoss, loss_weights=loss_weights)
    with open(save_path+"EmbeddingModel.json", "w") as json_file:
        json_file.write(EmbeddingModel.to_json())

    # Branch of neural net learning node embeddings only for graph A
    EmbeddingABranch.compile(optimizer=Optimizer, loss=getLoss(similarity_loss))
    with open(save_path+"EmbeddingABranch.json", "w") as json_file:
        json_file.write(EmbeddingABranch.to_json())

    if transmode != '1graph':
        # Branch of neural net learning node embeddings only for graph B
        EmbeddingBBranch.compile(optimizer=Optimizer, loss=getLoss(similarity_loss))
        with open(save_path+"EmbeddingBBranch.json", "w") as json_file:
            json_file.write(EmbeddingBBranch.to_json())

    # Neural Net predicting labels
    if n_labels > 1:
        prediction_loss = "categorical_crossentropy"
    elif prediction_loss is None: #or labels != 'pagerank':
        prediction_loss = "binary_crossentropy"
    elif prediction_loss == 'root_mean_squared_error':
        prediction_loss = RMSELoss
#    else:
#        prediction_loss = pagerank_loss
    PredictionModel.compile(optimizer=Optimizer, loss=prediction_loss)

    with open(save_path+"PredictionModel.json", "w") as json_file:
        json_file.write(PredictionModel.to_json())
    with open(save_path+"PredictionBranch.json", "w") as json_file:
        json_file.write(PredictionModel.get_layer('Branch_Prediction').to_json())

    if visualize:
        plotArchitecture(EmbeddingModel, 'EmbeddingModel', save_path)
        plotArchitecture(EmbeddingABranch, 'EmbeddingBranch', save_path)
        plotArchitecture(PredictionModel, 'PredictionModel', save_path)
        plotArchitecture(PredictionModel.get_layer('Branch_Prediction'), 'PredictionBranch', save_path)

    model_names = ['EmbeddingModel', 'EmbeddingABranch', 'EmbeddingBBranch', 'PredictionModel']
    models = dict(zip(model_names, [EmbeddingModel, EmbeddingABranch, EmbeddingBBranch, PredictionModel]))

    return models


import datetime
import pytz

# Set the timezone
tz = pytz.timezone('US/Eastern')

# Get the current time with the timezone set
current_time = datetime.datetime.now(tz)

# Format the time and date outputs
formatted_time = current_time.strftime('%-I:%M %p')
formatted_date = current_time.strftime('%Y-%m-%d')

# Print the formatted time and date with prefixes
print('TIME:', formatted_time)
print('DATE:', formatted_date)


import copy
import random
from multiprocessing import Pool

from Board import Board
from InputParser import InputParser
from MoveNode import MoveNode

WHITE = True
BLACK = False

class AI:

    depth = 1
    board = None
    side = None
    movesAnalyzed = 0

    def __init__(self, board, side, depth):
        self.board = board
        self.side = side
        self.depth = depth
        self.parser = InputParser(self.board, self.side)

    def getFirstMove(self, side):
        move = list(self.board.getAllMovesLegal(side))[0]
        return move

    def getAllMovesLegalConcurrent(self, side):
        p = Pool(8)
        unfilteredMovesWithBoard = \
            [(move, copy.deepcopy(self.board))
             for move in self.board.getAllMovesUnfiltered(side)]
        legalMoves = p.starmap(self.returnMoveIfLegal,
                               unfilteredMovesWithBoard)
        p.close()
        p.join()
        return list(filter(None, legalMoves))

    def minChildrenOfNode(self, node):
        lowestNodes = []
        for child in node.children:
            if not lowestNodes:
                lowestNodes.append(child)
            elif child < lowestNodes[0]:
                lowestNodes = []
                lowestNodes.append(child)
            elif child == lowestNodes[0]:
                lowestNodes.append(child)
        return lowestNodes

    def maxChildrenOfNode(self, node):
        highestNodes = []
        for child in node.children:
            if not highestNodes:
                highestNodes.append(child)
            elif child < highestNodes[0]:
                highestNodes = []
                highestNodes.append(child)
            elif child == highestNodes[0]:
                highestNodes.append(child)
        return highestNodes

    def getRandomMove(self):
        legalMoves = list(self.board.getAllMovesLegal(self.side))
        randomMove = random.choice(legalMoves)
        return randomMove

    def generateMoveTree(self):
        moveTree = []
        for move in self.board.getAllMovesLegal(self.side):
            moveTree.append(MoveNode(move, [], None))

        for node in moveTree:
            self.board.makeMove(node.move)
            self.populateNodeChildren(node)
            self.board.undoLastMove()
        return moveTree

    def populateNodeChildren(self, node):
        node.pointAdvantage = self.board.getPointAdvantageOfSide(self.side)
        node.depth = node.getDepth()
        if node.depth == self.depth:
            return

        side = self.board.currentSide

        legalMoves = self.board.getAllMovesLegal(side)
        if not legalMoves:
            if self.board.isCheckmate():
                node.move.checkmate = True
                return
            elif self.board.isStalemate():
                node.move.stalemate = True
                node.pointAdvantage = 0
                return
            raise Exception()

        for move in legalMoves:
            self.movesAnalyzed += 1
            node.children.append(MoveNode(move, [], node))
            self.board.makeMove(move)
            self.populateNodeChildren(node.children[-1])
            self.board.undoLastMove()

    def getOptimalPointAdvantageForNode(self, node):
        if node.children:
            for child in node.children:
                child.pointAdvantage = \
                    self.getOptimalPointAdvantageForNode(child)

            # If the depth is divisible by 2,
            # it's a move for the AI's side, so return max
            if node.children[0].depth % 2 == 1:
                return(max(node.children).pointAdvantage)
            else:
                return(min(node.children).pointAdvantage)
        else:
            return node.pointAdvantage

    def getBestMove(self):
        moveTree = self.generateMoveTree()
        bestMoves = self.bestMovesWithMoveTree(moveTree)
        randomBestMove = random.choice(bestMoves)
        randomBestMove.notation = self.parser.notationForMove(randomBestMove)
        return randomBestMove

    def makeBestMove(self):
        self.board.makeMove(self.getBestMove())

    def bestMovesWithMoveTree(self, moveTree):
        bestMoveNodes = []
        for moveNode in moveTree:
            moveNode.pointAdvantage = \
                self.getOptimalPointAdvantageForNode(moveNode)
            if not bestMoveNodes:
                bestMoveNodes.append(moveNode)
            elif moveNode > bestMoveNodes[0]:
                bestMoveNodes = []
                bestMoveNodes.append(moveNode)
            elif moveNode == bestMoveNodes[0]:
                bestMoveNodes.append(moveNode)

        return [node.move for node in bestMoveNodes]

    def isValidMove(self, move, side):
        for legalMove in self.board.getAllMovesLegal(side):
            if move == legalMove:
                return True
        return False

    def makeRandomMove(self):
        moveToMake = self.getRandomMove()
        self.board.makeMove(moveToMake)

if __name__ == "__main__":
    mainBoard = Board()
    ai = AI(mainBoard, True, 3)
    print(mainBoard)
    ai.makeBestMove()
    print(mainBoard)
    print(ai.movesAnalyzed)
    print(mainBoard.movesMade)


import cv2 as cv
import numpy as np
import time
import sys
import pickle

def nothing(x):
    pass

if __name__ == '__main__':
    args = sys.argv

    cv.namedWindow('hsv')
    # create trackbars for color change
    cv.createTrackbar('HL','hsv',0,179,nothing)
    cv.createTrackbar('SL','hsv',0,255,nothing)
    cv.createTrackbar('VL','hsv',0,255,nothing)
    # create trackbars for color change
    cv.createTrackbar('HH','hsv',0,179,nothing)
    cv.createTrackbar('SH','hsv',0,255,nothing)
    cv.createTrackbar('VH','hsv',0,255,nothing)

    cv.setTrackbarPos('HL', 'hsv', 100)
    cv.setTrackbarPos('HH', 'hsv', 120)
    cv.setTrackbarPos('SL', 'hsv', 200)
    cv.setTrackbarPos('SH', 'hsv', 255)
    cv.setTrackbarPos('VL', 'hsv', 0)
    cv.setTrackbarPos('VH', 'hsv', 255)

    image_path = args[1]
    frame = cv.imread(image_path)
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)

    target_names = ["right", "left", "unknown"]
    pca = pickle.load(open("pca.sav","rb"))
    clf = pickle.load(open("clf.sav", "rb"))
    font = cv.FONT_HERSHEY_SIMPLEX
    hl = 100
    hh = 120
    vl = 0
    vh = 255

    while True:
    #for i in range(255, 45, -30):
        # H, S, V
        sl = cv.getTrackbarPos('SL','hsv')
        #hl = cv.getTrackbarPos('HL','hsv')
        #vl = cv.getTrackbarPos('VL','hsv')
        sh = cv.getTrackbarPos('SH','hsv')
        #hh = cv.getTrackbarPos('HH','hsv')
        #vh = cv.getTrackbarPos('VH','hsv')

        lower_blue = np.array([hl, sl, vl])
        upper_blue = np.array([hh, sh, vh])
        mask = cv.inRange(hsv, lower_blue, upper_blue)

        cnts, _ = cv.findContours(mask,cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
        cnts_vector = []
        cnts_position = []

        for i, cnt in enumerate(cnts):
            x,y,w,h = cv.boundingRect(cnt)

            gray_crop = gray[y:y+h,x:x+w]
            gray_crop = cv.resize(gray_crop, (64, 64))

            flatten = gray_crop.flatten()
            flatten_trans = pca.transform([flatten])
            cnts_vector.append(flatten_trans[0])
            cnts_position.append((x, y, w, h))

        result = frame.copy()
        if len(cnts_vector) > 0:
            pred = clf.predict_proba(cnts_vector)

            for i in range(len(pred)):
                prob = pred[i]
                index = prob.argmax()
                if index == 2:
                    continue

                text = target_names[index]
                x, y, w, h = cnts_position[i]
                cv.putText(result, text, (x, y - 10), font, 1, (0, 0, 255), 2, cv.LINE_AA)
                cv.rectangle(result, (x, y), (x + w, y + h), (255, 0,0 ), 2)

        res = np.hstack((hsv, cv.merge([mask, mask, mask]), result))
        res = cv.resize(res, (1300, 500))
        cv.imshow('hsv', res)
        k = cv.waitKey(500)
        if k == ord('q'):
            print('Exit')
            break

cv.destroyAllWindows()


import sys
import os
from skimage import img_as_float, img_as_ubyte
sys.path.insert(0, os.path.join(os.getcwd(), "utils/HybridDenoise"))
from ..HybridDenoise.hnr import HybridNoiseReduction

hnr = HybridNoiseReduction()
def hybrid_denoise(rgb_noisy,
        nr_method="median",
        nr_parm=7,
        no_blend=False,
        mask_level=-2,
        blend_morph_kernel=1,
        blend_alpha=0.5,
        ):

    rgb_denoise, mask = hnr.run(img_as_float(rgb_noisy),
                                nr_method=nr_method,
                                nr_parm=nr_parm,
                                no_blend=no_blend,
                                mask_level=mask_level,
                                blend_morph_kernel=blend_morph_kernel,
                                blend_alpha=blend_alpha,
                                )

    return img_as_ubyte(rgb_denoise)

if __name__ == "__main__":
    import imageio
    import cv2
    rgb_noisy = imageio.imread("/data/Test_Results/Face_Restoration/internal_test/night_samples/001_001.jpg")
    output_img = hybrid_denoise(rgb_noisy,
                    nr_method="median",
                    nr_parm=7,
                    no_blend=False,
                    mask_level=-2,
                    blend_morph_kernel=1,
            )
    imageio.imwrite("./test_img.jpg", output_img)


"""
@package mi.instrument.satlantic.suna_deep.ooicore.test.test_driver
@file marine-integrations/mi/instrument/satlantic/suna_deep/ooicore/driver.py
@author Rachel Manoni
@brief Test cases for ooicore driver

USAGE:
 Make tests verbose and provide stdout
    * From the IDK
       $ bin/test_driver
       $ bin/test_driver -u [-t testname]
       $ bin/test_driver -i [-t testname]
       $ bin/test_driver -q [-t testname]
    * From pyon
       $ bin/nosetests -s -v /Users/Bill/WorkSpace/marine-integrations/mi/instrument/nortek/vector/ooicore
       $ bin/nosetests -s -v /Users/Bill/WorkSpace/marine-integrations/mi/instrument/nortek/vector/ooicore -a UNIT
       $ bin/nosetests -s -v /Users/Bill/WorkSpace/marine-integrations/mi/instrument/nortek/vector/ooicore -a INT
       $ bin/nosetests -s -v /Users/Bill/WorkSpace/marine-integrations/mi/instrument/nortek/vector/ooicore -a QUAL
"""

__author__ = 'Rachel Manoni'
__license__ = 'Apache 2.0'

from nose.plugins.attrib import attr
from mock import Mock

from mi.core.log import get_logger
log = get_logger()

from mi.idk.unit_test import InstrumentDriverTestCase
from mi.idk.unit_test import InstrumentDriverUnitTestCase
from mi.idk.unit_test import InstrumentDriverIntegrationTestCase
from mi.idk.unit_test import InstrumentDriverQualificationTestCase
from mi.idk.unit_test import DriverTestMixin
from mi.idk.unit_test import AgentCapabilityType

from mi.core.common import BaseEnum

from mi.core.instrument.chunker import StringChunker
from mi.core.instrument.instrument_driver import DriverConnectionState, ResourceAgentState, DriverConfigKey, DriverEvent

from mi.instrument.satlantic.suna_deep.ooicore.driver import InstrumentDriver, SUNAStatusDataParticle, TIMEOUT, \
    SUNATestDataParticle, InstrumentCommandArgs, SUNASampleDataParticleKey, SUNAStatusDataParticleKey, \
    SUNATestDataParticleKey
from mi.instrument.satlantic.suna_deep.ooicore.driver import DataParticleType
from mi.instrument.satlantic.suna_deep.ooicore.driver import InstrumentCommand
from mi.instrument.satlantic.suna_deep.ooicore.driver import ProtocolState
from mi.instrument.satlantic.suna_deep.ooicore.driver import ProtocolEvent
from mi.instrument.satlantic.suna_deep.ooicore.driver import Capability
from mi.instrument.satlantic.suna_deep.ooicore.driver import Parameter
from mi.instrument.satlantic.suna_deep.ooicore.driver import Protocol
from mi.instrument.satlantic.suna_deep.ooicore.driver import Prompt
from mi.instrument.satlantic.suna_deep.ooicore.driver import NEWLINE
from mi.instrument.satlantic.suna_deep.ooicore.driver import SUNASampleDataParticle

from mi.core.exceptions import SampleException, InstrumentCommandException, InstrumentParameterException, \
    InstrumentProtocolException

###
#   Driver parameters for the tests
###
InstrumentDriverTestCase.initialize(
    driver_module='mi.instrument.satlantic.suna_deep.ooicore.driver',
    driver_class="InstrumentDriver",

    instrument_agent_resource_id='1BQY0H',
    instrument_agent_name='satlantic_suna_deep_ooicore',
    instrument_agent_packet_config=DataParticleType(),

    driver_startup_config={DriverConfigKey.PARAMETERS: {
                           Parameter.OPERATION_MODE: InstrumentCommandArgs.POLLED,
                           Parameter.OPERATION_CONTROL: "Samples",
                           Parameter.LIGHT_SAMPLES: 5,
                           Parameter.DARK_SAMPLES: 1,
                           Parameter.LIGHT_DURATION: 10,
                           Parameter.DARK_DURATION: 5,
                           Parameter.NUM_LIGHT_SAMPLES: 1,
                           Parameter.TIME_LIGHT_SAMPLE: 5}}
)

#################################### RULES ####################################
#                                                                             #
# Common capabilities in the base class                                       #
#                                                                             #
# Instrument specific stuff in the derived class                              #
#                                                                             #
# Generator spits out either stubs or comments describing test this here,     #
# test that there.                                                            #
#                                                                             #
# Qualification tests are driven through the instrument_agent                 #
#                                                                             #
###############################################################################
SUNA_ASCII_SAMPLE = "SATSDF0344,2014125,21.278082,0.00,0.0000,0.0000,0.0000,0.00,476,0,1,475,483,494,465,487,490,488," \
                    "477,465,471,477,476,475,469,477,482,485,485,481,481,474,467,484,472,469,483,489,488,484,497,488," \
                    "482,484,474,461,455,485,469,495,481,485,474,487,464,491,477,464,485,492,492,475,485,478,479,477," \
                    "465,455,471,482,486,482,480,486,478,484,488,480,485,485,473,480,481,485,462,469,466,455,487,488," \
                    "482,485,489,485,478,489,472,475,456,483,450,471,450,487,480,493,490,482,472,485,484,481,494,494," \
                    "482,482,468,467,467,477,472,469,487,473,475,475,481,492,468,471,477,464,487,466,487,476,466,461," \
                    "469,467,469,461,459,475,481,477,476,467,469,476,484,462,479,464,467,471,485,477,466,471,470,481," \
                    "473,493,496,470,487,478,469,471,475,464,485,472,468,462,483,481,489,482,495,481,471,471,456,459," \
                    "465,454,475,452,459,472,464,491,488,478,487,465,483,470,465,478,465,487,480,487,474,478,488,480," \
                    "469,473,463,477,466,473,485,489,486,476,471,475,470,455,471,456,459,467,457,467,477,467,475,489," \
                    "485,484,470,489,482,481,474,471,479,479,468,479,481,484,480,491,468,479,474,474,468,471,477,480," \
                    "490,484,493,480,485,464,469,477,276,0.0,0.0,-99.0,172578,6.2,12.0,0.1,5.0,54,0.00,0.00,0.0000," \
                    "0.000000,0.000000,,,,,203\r\n"

SUNA_ASCII_STATUS = "SENSTYPE SUNA\r\nSENSVERS V2\r\nSERIALNO 344\r\nTHEBRAND Missing\r\nPATHLGTH Missing\r\n" \
                    "INTWIPER Available\r\nEXTPPORT Missing\r\n" \
                    "LMPSHUTR Missing\r\nREFDTECT Missing\r\nPROTECTR Available\r\nSUPRCAPS Available\r\n" \
                    "PWRSVISR Available\r\nUSBSWTCH Available\r\nRELAYBRD Available\r\nSDI12BRD Available\r\n" \
                    "ANALGBRD Available\r\nINTDATLG Available\r\nAPFIFACE Available\r\nSCHDLING Available\r\n" \
                    "FANATLMP Available\r\nOWIRETLP 10d0fda4020800eb\r\nOWIRETSP 1086818d020800d8\r\n" \
                    "OWIRETHS 10707b6a020800cc\r\nZSPEC_SN 86746\r\nFIBERLSN C3.D01.1590\r\nSTUPSTUS Done\r\n" \
                    "BAUDRATE 57600\r\nMSGLEVEL Info\r\nMSGFSIZE 2\r\nDATFSIZE 5\r\nOUTFRTYP Full_ASCII\r\n" \
                    "LOGFRTYP Full_ASCII\r\nOUTDRKFR Output\r\nLOGDRKFR Output\r\nTIMERESL Fractsec\r\n" \
                    "LOGFTYPE Acquisition\r\nACQCOUNT 10\r\nCNTCOUNT 130\r\nDCMINNO3 -5.000\r\nDCMAXNO3 100.000\r\n" \
                    "WDAT_LOW 217.00\r\nWDAT_HGH 250.00\r\nSDI12ADD 48\r\nDATAMODE Real\r\nOPERMODE Polled\r\n" \
                    "OPERCTRL Duration\r\nEXDEVTYP None\r\nEXDEVPRE 0\r\n" \
                    "EXDEVRUN Off\r\nWATCHDOG On\r\nCOUNTDWN 15\r\n" \
                    "FIXDDURA 60\r\nPERDIVAL 1m\r\nPERDOFFS 0\r\nPERDDURA 5\r\nPERDSMPL 5\r\nPOLLTOUT 15\r\n" \
                    "APFATOFF 10.0000\r\nSTBLTIME 5\r\nREFLIMIT 0\r\nSKPSLEEP Off\r\nLAMPTOFF 35\r\nSPINTPER 450\r\n" \
                    "DRKAVERS 1\r\nLGTAVERS 1\r\nREFSMPLS 20\r\nDRKSMPLS 2\r\nLGTSMPLS 58\r\nDRKDURAT 2\r\n" \
                    "LGTDURAT 58\r\nTEMPCOMP Off\r\nSALINFIT On\r\nBRMTRACE Off\r\nBL_ORDER 1\r\nFITCONCS 3\r\n" \
                    "DRKCORMT SpecAverage\r\nDRKCOEFS Missing\r\nDAVGPRM0 500.000\r\nDAVGPRM1 0.00000\r\n" \
                    "DAVGPRM2 0.00000\r\nDAVGPRM3 0.000000\r\nA_CUTOFF 1.3000\r\nINTPRADJ On\r\nINTPRFAC 1\r\n" \
                    "INTADSTP 20\r\nINTADMAX 20\r\nWFIT_LOW 217.00\r\nWFIT_HGH 240.00\r\nLAMPTIME 172577\r\n" \
                    "$Ok \r\nSUNA> get activecalfile\r\nget activecalfile\r\n$Ok SNA0234H.cal"

SUNA_ASCII_TEST = "Extrn Disk Size; Free , 1960968192; 1956216832\r\n" \
                  "Intrn Disk Size; Free , 2043904; 1956864\r\n" \
                  "Fiberlite    Odometer , 0048:10:05\r\n" \
                  "Temperatures Hs Sp Lm , 22.3 21.7 21.6\r\n" \
                  "Humidity              , 5.8\r\n" \
                  "Electrical Mn Bd Pr C , 12.0 12.0 5.0 25.8\r\n" \
                  "Lamp            Power , 5505 mW\r\n" \
                  "Spec Dark av sd mi ma ,   471 (+/-     9) [  444:  494]\r\n" \
                  "Spec Lght av sd mi ma , 22308 (+/- 12009) [  455:52004]\r\n" \
                  "$Ok"

class ParameterConstraints(BaseEnum):
    OPERATION_MODE = (Parameter.OPERATION_MODE, str, InstrumentCommandArgs.CONTINUOUS, InstrumentCommandArgs.POLLED)
    OPERATION_CONTROL = (Parameter.OPERATION_CONTROL, str, 'Samples', 'Duration')
    LIGHT_SAMPLES = (Parameter.LIGHT_SAMPLES, int, 1, 65535)
    DARK_SAMPLES = (Parameter.DARK_SAMPLES, int, 1, 65535)
    LIGHT_DURATION = (Parameter.LIGHT_DURATION, int, 1, 65535)
    DARK_DURATION = (Parameter.DARK_DURATION, int, 1, 65535)
    COUNTDOWN = (Parameter.COUNTDOWN, int, 0, 3600)
    TEMP_COMPENSATION = (Parameter.TEMP_COMPENSATION, bool, True, False)
    FIT_WAVELENGTH_BOTH = (Parameter.FIT_WAVELENGTH_BOTH, str, '210,210', '350,350')
    CONCENTRATIONS_IN_FIT = (Parameter.CONCENTRATIONS_IN_FIT, int, 1, 3)
    DARK_CORRECTION_METHOD = (Parameter.DARK_CORRECTION_METHOD, str, 'SpecAverage', 'SWAverage')
    SALINITY_FITTING = (Parameter.SALINITY_FITTING, bool, True, False)
    BROMIDE_TRACING = (Parameter.BROMIDE_TRACING, bool, True, False)
    ABSORBANCE_CUTOFF = (Parameter.ABSORBANCE_CUTOFF, float, 0.01, 10.0)
    INTEG_TIME_ADJUSTMENT = (Parameter.INTEG_TIME_ADJUSTMENT, bool, True, False)
    INTEG_TIME_FACTOR = (Parameter.INTEG_TIME_FACTOR, int, 1, 20)
    INTEG_TIME_STEP = (Parameter.INTEG_TIME_STEP, int, 1, 20)
    INTEG_TIME_MAX = (Parameter.INTEG_TIME_MAX, int, 1, 20)

###############################################################################
#                        DATA PARTICLE TEST MIXIN      	                  #
#     Defines a set of constants and assert methods used for data particle    #
#     verification      #
#                                                                             #
#  In python mixin classes are classes designed such that they wouldn't be    #
#  able to stand on their own, but are inherited by other classes generally   #
#  using multiple inheritance.                                                #
#                                                                             #
# This class defines a configuration structure for testing and common assert  #
# methods for validating data particles.	  #
###############################################################################
# noinspection PyPep8
class DriverTestMixinSub(DriverTestMixin):

    _reference_sample_parameters = {
        SUNASampleDataParticleKey.FRAME_TYPE: {'type': unicode, 'value': "SDF"},
        SUNASampleDataParticleKey.SERIAL_NUM: {'type': unicode, 'value': "0344"},
        SUNASampleDataParticleKey.SAMPLE_DATE: {'type': int, 'value': 2014125},
        SUNASampleDataParticleKey.SAMPLE_TIME: {'type': float, 'value': 21.278082},
        SUNASampleDataParticleKey.NITRATE_CONCEN: {'type': float, 'value': 0.00},
        SUNASampleDataParticleKey.NITROGEN: {'type': float, 'value': 0.0000},
        SUNASampleDataParticleKey.ABSORB_254: {'type': float, 'value': 0.0000},
        SUNASampleDataParticleKey.ABSORB_350: {'type': float, 'value': 0.0000},
        SUNASampleDataParticleKey.BROMIDE_TRACE: {'type': float, 'value': 0.00},
        SUNASampleDataParticleKey.SPECTRUM_AVE: {'type': int, 'value': 476},
        SUNASampleDataParticleKey.FIT_DARK_VALUE: {'type': int, 'value': 0},
        SUNASampleDataParticleKey.TIME_FACTOR: {'type': int, 'value': 1},
        SUNASampleDataParticleKey.SPECTRAL_CHANNELS: {'type': list, 'value': [475, 483, 494, 465, 487, 490, 488, 477,
                                                                              465, 471, 477, 476, 475, 469, 477, 482,
                                                                              485, 485, 481, 481, 474, 467, 484, 472,
                                                                              469, 483, 489, 488, 484, 497, 488, 482,
                                                                              484, 474, 461, 455, 485, 469, 495, 481,
                                                                              485, 474, 487, 464, 491, 477, 464, 485,
                                                                              492, 492, 475, 485, 478, 479, 477, 465,
                                                                              455, 471, 482, 486, 482, 480, 486, 478,
                                                                              484, 488, 480, 485, 485, 473, 480, 481,
                                                                              485, 462, 469, 466, 455, 487, 488, 482,
                                                                              485, 489, 485, 478, 489, 472, 475, 456,
                                                                              483, 450, 471, 450, 487, 480, 493, 490,
                                                                              482, 472, 485, 484, 481, 494, 494, 482,
                                                                              482, 468, 467, 467, 477, 472, 469, 487,
                                                                              473, 475, 475, 481, 492, 468, 471, 477,
                                                                              464, 487, 466, 487, 476, 466, 461, 469,
                                                                              467, 469, 461, 459, 475, 481, 477, 476,
                                                                              467, 469, 476, 484, 462, 479, 464, 467,
                                                                              471, 485, 477, 466, 471, 470, 481, 473,
                                                                              493, 496, 470, 487, 478, 469, 471, 475,
                                                                              464, 485, 472, 468, 462, 483, 481, 489,
                                                                              482, 495, 481, 471, 471, 456, 459, 465,
                                                                              454, 475, 452, 459, 472, 464, 491, 488,
                                                                              478, 487, 465, 483, 470, 465, 478, 465,
                                                                              487, 480, 487, 474, 478, 488, 480, 469,
                                                                              473, 463, 477, 466, 473, 485, 489, 486,
                                                                              476, 471, 475, 470, 455, 471, 456, 459,
                                                                              467, 457, 467, 477, 467, 475, 489, 485,
                                                                              484, 470, 489, 482, 481, 474, 471, 479,
                                                                              479, 468, 479, 481, 484, 480, 491, 468,
                                                                              479, 474, 474, 468, 471, 477, 480, 490,
                                                                              484, 493, 480, 485, 464, 469, 477, 276]},
        SUNASampleDataParticleKey.TEMP_INTERIOR: {'type': float, 'value': 0.0},
        SUNASampleDataParticleKey.TEMP_SPECTROMETER: {'type': float, 'value': 0.0},
        SUNASampleDataParticleKey.TEMP_LAMP: {'type': float, 'value': -99.0},
        SUNASampleDataParticleKey.LAMP_TIME: {'type': int, 'value': 172578},
        SUNASampleDataParticleKey.HUMIDITY: {'type': float, 'value': 6.2},
        SUNASampleDataParticleKey.VOLTAGE_MAIN: {'type': float, 'value': 12.0},
        SUNASampleDataParticleKey.VOLTAGE_LAMP: {'type': float, 'value': 0.1},
        SUNASampleDataParticleKey.VOLTAGE_INT: {'type': float, 'value': 5.0},
        SUNASampleDataParticleKey.CURRENT_MAIN: {'type': float, 'value': 54.0},
        SUNASampleDataParticleKey.FIT_1: {'type': float, 'value': 0.00},
        SUNASampleDataParticleKey.FIT_2: {'type': float, 'value': 0.00},
        SUNASampleDataParticleKey.FIT_BASE_1: {'type': float, 'value': 0.0000},
        SUNASampleDataParticleKey.FIT_BASE_2: {'type': float, 'value': 0.000000},
        SUNASampleDataParticleKey.FIT_RMSE: {'type': float, 'value': 0.0000000},
        SUNASampleDataParticleKey.CHECKSUM: {'type': int, 'value': 203}
    }

    _reference_status_parameters = {
        SUNAStatusDataParticleKey.SENSOR_TYPE: {'type': unicode, 'value': "SUNA"},
        SUNAStatusDataParticleKey.SENSOR_VERSION: {'type': unicode, 'value': "V2"},
        SUNAStatusDataParticleKey.SERIAL_NUMBER: {'type': unicode, 'value': '344'},
        SUNAStatusDataParticleKey.INTEGRATED_WIPER: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.EXT_POWER_PORT: {'type': unicode, 'value': "Missing"},
        SUNAStatusDataParticleKey.LAMP_SHUTTER: {'type': unicode, 'value': "Missing"},
        SUNAStatusDataParticleKey.REF_DETECTOR: {'type': unicode, 'value': "Missing"},
        SUNAStatusDataParticleKey.PROTECTR: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.SUPER_CAPACITORS: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.PSB_SUPERVISOR: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.USB_COMM: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.RELAY_MODULE: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.SDII2_INTERFACE: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.ANALOG_OUTPUT: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.DATA_LOGGING: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.APF_INTERFACE: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.SCHEDULING: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.LAMP_FAN: {'type': unicode, 'value': "Available"},
        SUNAStatusDataParticleKey.ADDR_LAMP_TEMP: {'type': unicode, 'value': '10d0fda4020800eb'},
        SUNAStatusDataParticleKey.ADDR_SPEC_TEMP: {'type': unicode, 'value': '1086818d020800d8'},
        SUNAStatusDataParticleKey.SENSOR_ADDR_HOUS_TEMP: {'type': unicode, 'value': '10707b6a020800cc'},
        SUNAStatusDataParticleKey.SERIAL_NUM_SPECT: {'type': unicode, 'value': '86746'},
        SUNAStatusDataParticleKey.SERIAL_NUM_LAMP: {'type': unicode, 'value': "C3.D01.1590"},
        SUNAStatusDataParticleKey.STUPSTUS: {'type': unicode, 'value': "Done"},
        SUNAStatusDataParticleKey.BAUD_RATE: {'type': int, 'value': 57600},
        SUNAStatusDataParticleKey.MSG_LEVEL: {'type': unicode, 'value': "Info"},
        SUNAStatusDataParticleKey.MSG_FILE_SIZE: {'type': int, 'value': 2},
        SUNAStatusDataParticleKey.DATA_FILE_SIZE: {'type': int, 'value': 5},
        SUNAStatusDataParticleKey.OUTPUT_FRAME_TYPE: {'type': unicode, 'value': "Full_ASCII"},
        SUNAStatusDataParticleKey.LOGGING_FRAME_TYPE: {'type': unicode, 'value': "Full_ASCII"},
        SUNAStatusDataParticleKey.OUTPUT_DARK_FRAME: {'type': unicode, 'value': "Output"},
        SUNAStatusDataParticleKey.LOGGING_DARK_FRAME: {'type': unicode, 'value': "Output"},
        SUNAStatusDataParticleKey.TIMERESL: {'type': unicode, 'value': "Fractsec"},
        SUNAStatusDataParticleKey.LOG_FILE_TYPE: {'type': unicode, 'value': "Acquisition"},
        SUNAStatusDataParticleKey.ACQCOUNT: {'type': int, 'value': 10},
        SUNAStatusDataParticleKey.CNTCOUNT: {'type': int, 'value': 130},
        SUNAStatusDataParticleKey.NITRATE_MIN: {'type': float, 'value': -5.000},
        SUNAStatusDataParticleKey.NITRATE_MAX: {'type': float, 'value': 100.000},
        SUNAStatusDataParticleKey.WAVELENGTH_LOW: {'type': float, 'value': 217.00},
        SUNAStatusDataParticleKey.WAVELENGTH_HIGH: {'type': float, 'value': 250.00},
        SUNAStatusDataParticleKey.SDI12_ADDR: {'type': int, 'value': 48},
        SUNAStatusDataParticleKey.DATAMODE: {'type': unicode, 'value': "Real"},
        SUNAStatusDataParticleKey.OPERATING_MODE: {'type': unicode, 'value': "Polled"},
        SUNAStatusDataParticleKey.OPERATION_CTRL: {'type': unicode, 'value': "Duration"},
        SUNAStatusDataParticleKey.EXTL_DEV: {'type': unicode, 'value': "None"},
        SUNAStatusDataParticleKey.PRERUN_TIME: {'type': int, 'value': 0},
        SUNAStatusDataParticleKey.DEV_DURING_ACQ: {'type': unicode, 'value': "Off"},
        SUNAStatusDataParticleKey.WATCHDOG_TIME: {'type': unicode, 'value': "On"},
        SUNAStatusDataParticleKey.COUNTDOWN: {'type': int, 'value': 15},
        SUNAStatusDataParticleKey.FIXED_TIME: {'type': int, 'value': 60},
        SUNAStatusDataParticleKey.PERIODIC_INTERVAL: {'type': unicode, 'value': "1m"},
        SUNAStatusDataParticleKey.PERIODIC_OFFSET: {'type': int, 'value': 0},
        SUNAStatusDataParticleKey.PERIODIC_DURATION: {'type': int, 'value': 5},
        SUNAStatusDataParticleKey.PERIODIC_SAMPLES: {'type': int, 'value': 5},
        SUNAStatusDataParticleKey.POLLED_TIMEOUT: {'type': int, 'value': 15},
        SUNAStatusDataParticleKey.APF_TIMEOUT: {'type': float, 'value': 10.0000},
        SUNAStatusDataParticleKey.STABILITY_TIME: {'type': int, 'value': 5},
        SUNAStatusDataParticleKey.MIN_LAMP_ON: {'type': int, 'value': 0},
        SUNAStatusDataParticleKey.SKIP_SLEEP: {'type': unicode, 'value': "Off"},
        SUNAStatusDataParticleKey.SWITCHOFF_TEMP: {'type': int, 'value': 35},
        SUNAStatusDataParticleKey.SPEC_PERIOD: {'type': int, 'value': 450},
        SUNAStatusDataParticleKey.DRKAVERS: {'type': int, 'value': 1},
        SUNAStatusDataParticleKey.LGTAVERS: {'type': int, 'value': 1},
        SUNAStatusDataParticleKey.REFSAMPLES: {'type': int, 'value': 20},
        SUNAStatusDataParticleKey.DARK_SAMPLES: {'type': int, 'value': 2},
        SUNAStatusDataParticleKey.LIGHT_SAMPLES: {'type': int, 'value': 58},
        SUNAStatusDataParticleKey.DARK_DURATION: {'type': int, 'value': 2},
        SUNAStatusDataParticleKey.LIGHT_DURATION: {'type': int, 'value': 58},
        SUNAStatusDataParticleKey.TEMP_COMP: {'type': unicode, 'value': "Off"},
        SUNAStatusDataParticleKey.SALINITY_FIT: {'type': unicode, 'value': "On"},
        SUNAStatusDataParticleKey.BROMIDE_TRACING: {'type': unicode, 'value': "Off"},
        SUNAStatusDataParticleKey.BASELINE_ORDER: {'type': int, 'value': 1},
        SUNAStatusDataParticleKey.CONCENTRATIONS_FIT: {'type': int, 'value': 3},
        SUNAStatusDataParticleKey.DARK_CORR_METHOD: {'type': unicode, 'value': "SpecAverage"},
        SUNAStatusDataParticleKey.DRKCOEFS: {'type': unicode, 'value': "Missing"},
        SUNAStatusDataParticleKey.DAVGPRM_0: {'type': float, 'value': 500.000},
        SUNAStatusDataParticleKey.DAVGPRM_1: {'type': float, 'value': 0.00000},
        SUNAStatusDataParticleKey.DAVGPRM_2: {'type': float, 'value': 0.00000},
        SUNAStatusDataParticleKey.DAVGPRM_3: {'type': float, 'value': 0.000000},
        SUNAStatusDataParticleKey.ABSORBANCE_CUTOFF: {'type': float, 'value': 1.3000},
        SUNAStatusDataParticleKey.TIME_ADJ: {'type': unicode, 'value': "On"},
        SUNAStatusDataParticleKey.TIME_FACTOR: {'type': int, 'value': 1},
        SUNAStatusDataParticleKey.TIME_STEP: {'type': int, 'value': 20},
        SUNAStatusDataParticleKey.TIME_MAX: {'type': int, 'value': 20},
        SUNAStatusDataParticleKey.FIT_WAVE_LOW: {'type': float, 'value': 217.00},
        SUNAStatusDataParticleKey.FIT_WAVE_HIGH: {'type': float, 'value': 240.00},
        SUNAStatusDataParticleKey.LAMP_TIME: {'type': int, 'value': 172577},
        SUNAStatusDataParticleKey.CALIBRATION_FILE: {'type': unicode, 'value': 'SNA0234H.cal'}
    }

    _reference_test_parameters = {
        SUNATestDataParticleKey.EXT_DISK_SIZE: {'type': int, 'value': 1960968192},
        SUNATestDataParticleKey.EXT_DISK_FREE: {'type': int, 'value': 1956216832},
        SUNATestDataParticleKey.INT_DISK_SIZE: {'type': int, 'value': 2043904},
        SUNATestDataParticleKey.INT_DISK_FREE: {'type': int, 'value': 1956864},
        SUNATestDataParticleKey.TEMP_HS: {'type': float, 'value': 22.3},
        SUNATestDataParticleKey.TEMP_SP: {'type': float, 'value': 21.7},
        SUNATestDataParticleKey.TEMP_LM: {'type': float, 'value': 21.6},
        SUNATestDataParticleKey.LAMP_TIME: {'type': int, 'value': 173405},
        SUNATestDataParticleKey.HUMIDITY: {'type': float, 'value': 5.8},
        SUNATestDataParticleKey.ELECTRICAL_MN: {'type': float, 'value': 12.0},
        SUNATestDataParticleKey.ELECTRICAL_BD: {'type': float, 'value': 12.0},
        SUNATestDataParticleKey.ELECTRICAL_PR: {'type': float, 'value': 5.0},
        SUNATestDataParticleKey.ELECTRICAL_C: {'type': float, 'value': 25.8},
        SUNATestDataParticleKey.LAMP_POWER: {'type': int, 'value': 5505},
        SUNATestDataParticleKey.SPEC_DARK_AV: {'type': int, 'value': 471},
        SUNATestDataParticleKey.SPEC_DARK_SD: {'type': int, 'value': 9},
        SUNATestDataParticleKey.SPEC_DARK_MI: {'type': int, 'value': 444},
        SUNATestDataParticleKey.SPEC_DARK_MA: {'type': int, 'value': 494},
        SUNATestDataParticleKey.SPEC_LIGHT_AV: {'type': int, 'value': 22308},
        SUNATestDataParticleKey.SPEC_LIGHT_SD: {'type': int, 'value': 12009},
        SUNATestDataParticleKey.SPEC_LIGHT_MI: {'type': int, 'value': 455},
        SUNATestDataParticleKey.SPEC_LIGHT_MA: {'type': int, 'value': 52004},
        SUNATestDataParticleKey.TEST_RESULT: {'type': unicode, 'value': "Ok"}
    }

    def assert_data_particle_sample(self, data_particle, verify_values=False):
        """
        Verify that all driver parameters are correct and potentially verify values.
        @param data_particle: driver parameters read from the driver instance
        @param verify_values:bool,  False = do not verify values against definition
        """
        self.assert_data_particle_parameters(data_particle, self._reference_sample_parameters, verify_values)

    def assert_data_particle_status(self, data_particle, verify_values=False):
        """
        Verify a SUNA status data particle
        @param data_particle: a SUNA status data particle
        @param verify_values: bool,  False = do not verify values against definition
        """
        self.assert_data_particle_parameters(data_particle, self._reference_status_parameters, verify_values)

    def assert_data_particle(self, data_particle, verify_values=False):
        """
        Verify a SUNA test data particle
        @param data_particle: a SUNA test data particle
        @param verify_values: bool, False = do not verify values against definition
        """
        self.assert_data_particle_parameters(data_particle, self._reference_test_parameters, verify_values)

###############################################################################
#                                UNIT TESTS                                   #
#         Unit tests test the method calls and parameters using Mock.         #
#                                                                             #
#   These tests are especially useful for testing parsers and other data      #
#   handling.  The tests generally focus on small segments of code, like a    #
#   single function call, but more complex code using Mock objects.  However  #
#   if you find yourself mocking too much maybe it is better as an            #
#   integration test.                                                         #
#                                                                             #
#   Unit tests do not start up external processes like the port agent or      #
#   driver process.                                                           #
###############################################################################
@attr('UNIT', group='mi')
class DriverUnitTest(InstrumentDriverUnitTestCase, DriverTestMixinSub):
    def setUp(self):
        InstrumentDriverUnitTestCase.setUp(self)

    def test_driver_enums(self):
        """
        Verify that all driver enumeration has no duplicate values that might cause confusion.  Also
        do a little extra validation for the Capabilities
        """
        self.assert_enum_has_no_duplicates(DataParticleType())
        self.assert_enum_has_no_duplicates(ProtocolState())
        self.assert_enum_has_no_duplicates(ProtocolEvent())
        self.assert_enum_has_no_duplicates(Parameter())
        self.assert_enum_has_no_duplicates(InstrumentCommand())

        # Test capabilities for duplicates, them verify that capabilities is a subset of protocol events
        self.assert_enum_has_no_duplicates(Capability())
        self.assert_enum_complete(Capability(), ProtocolEvent())

    def test_chunker(self):
        """
        Test the chunker and verify the particles created.
        """
        chunker = StringChunker(Protocol.sieve_function)

        self.assert_chunker_sample(chunker, SUNA_ASCII_SAMPLE)
        self.assert_chunker_fragmented_sample(chunker, SUNA_ASCII_SAMPLE)
        self.assert_chunker_combined_sample(chunker, SUNA_ASCII_SAMPLE)
        self.assert_chunker_sample_with_noise(chunker, SUNA_ASCII_SAMPLE)

        self.assert_chunker_sample(chunker, SUNA_ASCII_STATUS)
        self.assert_chunker_sample_with_noise(chunker, SUNA_ASCII_STATUS)
        self.assert_chunker_fragmented_sample(chunker, SUNA_ASCII_STATUS)
        self.assert_chunker_combined_sample(chunker, SUNA_ASCII_STATUS)

        self.assert_chunker_sample(chunker, SUNA_ASCII_TEST)
        self.assert_chunker_sample_with_noise(chunker, SUNA_ASCII_TEST)
        self.assert_chunker_fragmented_sample(chunker, SUNA_ASCII_TEST)
        self.assert_chunker_combined_sample(chunker, SUNA_ASCII_TEST)

    def test_corrupt_data_particles(self):
        """
        test with data partially replaced by garbage value
        """
        particle = SUNASampleDataParticle(SUNA_ASCII_SAMPLE.replace("SAT", "FOO"))
        with self.assertRaises(SampleException):
            particle.generate()

        particle = SUNAStatusDataParticle(SUNA_ASCII_STATUS.replace('SENSTYPE', 'BLAH!'))
        with self.assertRaises(SampleException):
            particle.generate()

        particle = SUNATestDataParticle(SUNA_ASCII_TEST.replace('5505 mW', '5505f.1 mW'))
        with self.assertRaises(SampleException):
            particle.generate()

    def test_got_data(self):
        """
        Verify sample data passed through the got data method produces the correct data particles
        """
        # Create and initialize the instrument driver with a mock port agent
        driver = InstrumentDriver(self._got_data_event_callback)
        self.assert_initialize_driver(driver)

        self.assert_raw_particle_published(driver, True)

        #validate data particles
        self.assert_particle_published(driver, SUNA_ASCII_SAMPLE, self.assert_data_particle_sample, True)
        self.assert_particle_published(driver, SUNA_ASCII_STATUS, self.assert_data_particle_status, True)
        self.assert_particle_published(driver, SUNA_ASCII_TEST, self.assert_data_particle, True)

    def test_protocol_filter_capabilities(self):
        """
        This tests driver filter_capabilities.
        Iterate through available capabilities, and verify that they can pass successfully through the filter.
        Test silly made up capabilities to verify they are blocked by filter.
        """
        mock_callback = Mock()
        protocol = Protocol(Prompt, NEWLINE, mock_callback)
        driver_capabilities = Capability().list()
        test_capabilities = Capability().list()

        # Add a bogus capability that will be filtered out.
        test_capabilities.append("BOGUS_CAPABILITY")

        # Verify "BOGUS_CAPABILITY was filtered out
        self.assertEquals(sorted(driver_capabilities),
                          sorted(protocol._filter_capabilities(test_capabilities)))

    # noinspection PyPep8,PyPep8,PyPep8,PyPep8
    def test_capabilities(self):
        """
        Verify the FSM reports capabilities as expected.  All states defined in this dict must
        also be defined in the protocol FSM.
        """
        capabilities = {
            ProtocolState.UNKNOWN:       [ProtocolEvent.DISCOVER],
            ProtocolState.COMMAND:       [ProtocolEvent.ACQUIRE_SAMPLE,
                                          ProtocolEvent.ACQUIRE_STATUS,
                                          ProtocolEvent.START_DIRECT,
                                          #ProtocolEvent.START_POLL,
                                          ProtocolEvent.START_AUTOSAMPLE,
                                          ProtocolEvent.GET,
                                          ProtocolEvent.SET,
                                          ProtocolEvent.TEST,
                                          ProtocolEvent.CLOCK_SYNC,
                                          ProtocolEvent.MEASURE_N,
                                          ProtocolEvent.MEASURE_0,
                                          ProtocolEvent.TIMED_N],
            ProtocolState.DIRECT_ACCESS: [ProtocolEvent.EXECUTE_DIRECT,
                                          ProtocolEvent.STOP_DIRECT],
            ProtocolState.AUTOSAMPLE:    [ProtocolEvent.STOP_AUTOSAMPLE]
        }

        driver = InstrumentDriver(self._got_data_event_callback)
        self.assert_capabilities(driver, capabilities)

###############################################################################
#                            INTEGRATION TESTS                                #
#     Integration test test the direct driver / instrument interaction        #
#     but making direct calls via zeromq.                                     #
#     - Common Integration tests test the driver through the instrument agent #
#     and common for all drivers (minimum requirement for ION ingestion)      #
###############################################################################
@attr('INT', group='mi')
class DriverIntegrationTest(InstrumentDriverIntegrationTestCase, DriverTestMixinSub):
    def setUp(self):
        InstrumentDriverIntegrationTestCase.setUp(self)

    def test_out_of_range(self):
        """
        Verify when the instrument receives a set param with value out of range or invalid string,
        the instrument throws an exception
        """
        self.assert_initialize_driver()

        constraints = ParameterConstraints.dict()
        for param in constraints:
            param_name, type_class, minimum, maximum = constraints[param]

            log.debug("PARAM NAME %s", param_name)

            if type_class is int:
                self.assert_set_exception(param_name, minimum - 1, exception_class=InstrumentProtocolException)
                self.assert_set_exception(param_name, maximum + 1, exception_class=InstrumentProtocolException)
                self.assert_set_exception(param_name, 'badString', exception_class=InstrumentProtocolException)
            elif type_class is str:
                self.assert_set_exception(param_name, 'invalidvalue', exception_class=InstrumentProtocolException)
                self.assert_set_exception(param_name, 1, exception_class=InstrumentProtocolException)
            elif type_class is float:
                self.assert_set_exception(param_name, minimum - 0.1, exception_class=InstrumentProtocolException)
                self.assert_set_exception(param_name, maximum + 0.1, exception_class=InstrumentProtocolException)
                self.assert_set_exception(param_name, 'badString', exception_class=InstrumentProtocolException)

    def test_get_set(self):
        """
        Verify device parameter access.
        """
        self.assert_initialize_driver()

        self.assert_set(Parameter.OPERATION_MODE, InstrumentCommandArgs.CONTINUOUS)
        self.assert_set(Parameter.OPERATION_CONTROL, "Duration")
        self.assert_set(Parameter.LIGHT_SAMPLES, 57)
        self.assert_set(Parameter.DARK_SAMPLES, 3)
        self.assert_set(Parameter.LIGHT_DURATION, 11)
        self.assert_set(Parameter.DARK_DURATION, 6)
        self.assert_set(Parameter.COUNTDOWN, 16)
        self.assert_set(Parameter.TEMP_COMPENSATION, True)
        self.assert_set(Parameter.FIT_WAVELENGTH_BOTH, "218.00,241.00")
        self.assert_set(Parameter.CONCENTRATIONS_IN_FIT, 3)
        self.assert_set(Parameter.DARK_CORRECTION_METHOD, "SWAverage")
        self.assert_set(Parameter.SALINITY_FITTING, False)
        self.assert_set(Parameter.BROMIDE_TRACING, True)
        self.assert_set(Parameter.ABSORBANCE_CUTOFF, 1.4)
        self.assert_set(Parameter.INTEG_TIME_ADJUSTMENT, False)
        self.assert_set(Parameter.INTEG_TIME_FACTOR, 2)
        self.assert_set(Parameter.INTEG_TIME_STEP, 19)
        self.assert_set(Parameter.INTEG_TIME_MAX, 19)

        #set read-only parameters with bogus values, should throw exception
        self.assert_set_readonly(Parameter.POLLED_TIMEOUT, 9001)
        self.assert_set_readonly(Parameter.SKIP_SLEEP_AT_START, False)
        self.assert_set_readonly(Parameter.REF_MIN_AT_LAMP_ON, 9001)
        self.assert_set_readonly(Parameter.LAMP_STABIL_TIME, 6)
        self.assert_set_readonly(Parameter.LAMP_SWITCH_OFF_TEMPERATURE, 34)
        self.assert_set_readonly(Parameter.SPECTROMETER_INTEG_PERIOD, 9001)
        self.assert_set_readonly(Parameter.MESSAGE_LEVEL, "Warn")
        self.assert_set_readonly(Parameter.MESSAGE_FILE_SIZE, 5)
        self.assert_set_readonly(Parameter.DATA_FILE_SIZE, 10)
        self.assert_set_readonly(Parameter.OUTPUT_FRAME_TYPE, "Full_Binary")
        self.assert_set_readonly(Parameter.OUTPUT_DARK_FRAME, "Suppress")
        self.assert_set_readonly(Parameter.FIT_WAVELENGTH_LOW, 9002)
        self.assert_set_readonly(Parameter.FIT_WAVELENGTH_HIGH, 9003)
        self.assert_set_readonly(Parameter.BASELINE_ORDER, 2)

    def test_clock_sync(self):
        """
        Verify instrument can synchronize the clock
        """
        self.assert_initialize_driver()
        self.assert_driver_command(ProtocolEvent.CLOCK_SYNC)

    def test_acquire_sample(self):
        """
        Verify instrument can acquire a sample in command mode
        """
        self.assert_initialize_driver()
        self.clear_events()
        self.assert_particle_generation(ProtocolEvent.ACQUIRE_SAMPLE, DataParticleType.SUNA_SAMPLE,
                                        self.assert_data_particle_sample, delay=TIMEOUT)

    def test_acquire_status(self):
        """
        Verify instrument can acquire status (in command mode)
        """
        self.assert_initialize_driver()
        self.clear_events()
        self.assert_particle_generation(ProtocolEvent.ACQUIRE_STATUS, DataParticleType.SUNA_STATUS,
                                        self.assert_data_particle_status, delay=TIMEOUT)

    def test_selftest(self):
        """
        Verify instrument can perform a self test
        """
        self.assert_initialize_driver()
        self.clear_events()
        self.assert_particle_generation(ProtocolEvent.TEST, DataParticleType.SUNA_TEST,
                                        self.assert_data_particle, delay=TIMEOUT)

    def test_start_stop_polled(self):
        """
        Verify polled acquisition of samples in auto-sample mode
        """
        self.assert_initialize_driver()

        self.assert_particle_generation(ProtocolEvent.MEASURE_0, DataParticleType.SUNA_SAMPLE,
                                        self.assert_data_particle_sample, delay=TIMEOUT)

        self.assert_particle_generation(ProtocolEvent.MEASURE_N, DataParticleType.SUNA_SAMPLE,
                                        self.assert_data_particle_sample, delay=TIMEOUT)

        self.assert_particle_generation(ProtocolEvent.TIMED_N, DataParticleType.SUNA_SAMPLE,
                                        self.assert_data_particle_sample, delay=TIMEOUT)

    def test_start_stop_auto_sample(self):
        """
        Verify continuous acquisition of samples in auto-sample mode
        """
        self.assert_initialize_driver()

        self.assert_particle_generation(ProtocolEvent.START_AUTOSAMPLE, DataParticleType.SUNA_SAMPLE,
                                        self.assert_data_particle_sample, delay=5)

        #Stop autosample
        self.assert_driver_command(ProtocolEvent.STOP_AUTOSAMPLE, state=ProtocolState.COMMAND, delay=1)

        # transition back to auto to test countdown logic
        self.assert_particle_generation(ProtocolEvent.START_AUTOSAMPLE, DataParticleType.SUNA_SAMPLE,
                                        self.assert_data_particle_sample, delay=22)

        # Return to command mode.
        self.assert_driver_command(ProtocolEvent.STOP_AUTOSAMPLE, state=ProtocolState.COMMAND, delay=1)

    def test_errors(self):
        """
        Verify response to erroneous commands and setting bad parameters.
        """
        self.assert_initialize_driver(ProtocolState.COMMAND)

        #Assert an invalid command
        self.assert_driver_command_exception('ima_bad_command', exception_class=InstrumentCommandException)

        # Assert for a known command, invalid state.
        self.assert_driver_command_exception(ProtocolEvent.STOP_AUTOSAMPLE, exception_class=InstrumentCommandException)

        # Assert set fails with a bad parameter (not ALL or a list).
        self.assert_set_exception('I am a bogus param.', exception_class=InstrumentParameterException)

        #Assert set fails with bad parameter and bad value
        self.assert_set_exception('I am a bogus param.', value='bogus value',
                                  exception_class=InstrumentParameterException)

        # put driver in disconnected state.
        self.driver_client.cmd_dvr('disconnect')

        # Assert for a known command, invalid state.
        self.assert_driver_command_exception(ProtocolEvent.ACQUIRE_SAMPLE, exception_class=InstrumentCommandException)

        # Test that the driver is in state disconnected.
        self.assert_state_change(DriverConnectionState.DISCONNECTED, timeout=TIMEOUT)

        # Setup the protocol state machine and the connection to port agent.
        self.driver_client.cmd_dvr('initialize')

        # Test that the driver is in state unconfigured.
        self.assert_state_change(DriverConnectionState.UNCONFIGURED, timeout=TIMEOUT)

        # Assert we forgot the comms parameter.
        self.assert_driver_command_exception('configure', exception_class=InstrumentParameterException)

###############################################################################
#                            QUALIFICATION TESTS                              #
# Device specific qualification tests are for doing final testing of ion      #
# integration.  The generally aren't used for instrument debugging and should #
# be tackled after all unit and integration tests are complete                #
###############################################################################
@attr('QUAL', group='mi')
class DriverQualificationTest(InstrumentDriverQualificationTestCase, DriverTestMixinSub):
    def setUp(self):
        InstrumentDriverQualificationTestCase.setUp(self)

    def test_discover(self):
        """
        Override method- instrument will always start up in Command mode.  Instrument will instruct instrument into
        Command mode as well.

        Verify when the instrument is either in autosample or command state, the instrument will always discover
        to COMMAND state
        """

        self.assert_enter_command_mode()
        # Now reset and try to discover.  This will stop the driver which holds the current
        # instrument state.
        self.assert_reset()
        self.assert_discover(ResourceAgentState.COMMAND)

        # Now put the instrument in streaming and reset the driver again.
        self.assert_start_autosample()
        self.assert_reset()

        # When the driver reconnects it should be streaming
        self.assert_discover(ResourceAgentState.COMMAND)

    def test_direct_access_telnet_mode(self):
        """
        Verify while in Direct Access, we can manually set DA parameters.
        After stopping DA, the instrument will enter Command State and any
        parameters set during DA are reset to previous values.
        Also verifying timeouts with inactivity, with activity, and without activity.
        """
        self.assert_direct_access_start_telnet()
        self.assertTrue(self.tcp_client)

        ###
        # In DA mode, set the DA parameters to different values
        ###
        self.tcp_client.send_data("set opermode Continuous" + NEWLINE)
        self.tcp_client.expect("SUNA>")

        self.tcp_client.send_data("set polltout 60000" + NEWLINE)
        self.tcp_client.expect("SUNA>")

        self.tcp_client.send_data("set outfrtyp Full_Binary" + NEWLINE)
        self.tcp_client.expect("SUNA>")

        self.tcp_client.send_data("set spintper 600" + NEWLINE)
        self.tcp_client.expect("SUNA>")

        self.tcp_client.send_data("set salinfit Off" + NEWLINE)
        self.tcp_client.expect("SUNA>")

        self.tcp_client.send_data("set brmtrace On" + NEWLINE)
        self.tcp_client.expect("SUNA>")

        self.tcp_client.send_data("set intadstp 19" + NEWLINE)
        self.tcp_client.expect("SUNA>")

        self.assert_direct_access_stop_telnet()
        self.assert_state_change(ResourceAgentState.COMMAND, ProtocolState.COMMAND, TIMEOUT)

        #DA param should change back to pre-DA val
        self.assert_get_parameter(Parameter.OPERATION_MODE, InstrumentCommandArgs.POLLED)
        self.assert_get_parameter(Parameter.POLLED_TIMEOUT, 65535)
        self.assert_get_parameter(Parameter.SKIP_SLEEP_AT_START, True)
        self.assert_get_parameter(Parameter.COUNTDOWN, 15)
        self.assert_get_parameter(Parameter.LAMP_STABIL_TIME, 5)
        self.assert_get_parameter(Parameter.LAMP_SWITCH_OFF_TEMPERATURE, 35)
        self.assert_get_parameter(Parameter.MESSAGE_LEVEL, "Info")
        self.assert_get_parameter(Parameter.MESSAGE_FILE_SIZE, 0)
        self.assert_get_parameter(Parameter.DATA_FILE_SIZE, 5)
        self.assert_get_parameter(Parameter.OUTPUT_FRAME_TYPE, "Full_ASCII")
        self.assert_get_parameter(Parameter.OUTPUT_DARK_FRAME, "Output")
        self.assert_get_parameter(Parameter.TEMP_COMPENSATION, False)
        self.assert_get_parameter(Parameter.FIT_WAVELENGTH_BOTH, "217.00,240.00")
        self.assert_get_parameter(Parameter.CONCENTRATIONS_IN_FIT, 1)
        self.assert_get_parameter(Parameter.BASELINE_ORDER, 1)
        self.assert_get_parameter(Parameter.DARK_CORRECTION_METHOD, "SpecAverage")
        self.assert_get_parameter(Parameter.SALINITY_FITTING, True)
        self.assert_get_parameter(Parameter.BROMIDE_TRACING, False)
        self.assert_get_parameter(Parameter.ABSORBANCE_CUTOFF, 1.3)
        self.assert_get_parameter(Parameter.INTEG_TIME_ADJUSTMENT, True)
        self.assert_get_parameter(Parameter.INTEG_TIME_FACTOR, 1)
        self.assert_get_parameter(Parameter.INTEG_TIME_STEP, 20)
        self.assert_get_parameter(Parameter.INTEG_TIME_MAX, 20)

    def test_acquire_status(self):
        """
        Verify the driver can command an acquire status from the instrument
        """
        self.assert_enter_command_mode()
        self.assert_particle_polled(DriverEvent.ACQUIRE_STATUS, self.assert_data_particle_status,
                                    DataParticleType.SUNA_STATUS, timeout=TIMEOUT, sample_count=1)

    def test_execute_test(self):
        """
        Verify the instrument can perform a self test
        """
        self.assert_enter_command_mode()
        self.assert_particle_polled(DriverEvent.TEST, self.assert_data_particle, DataParticleType.SUNA_TEST,
                                    timeout=TIMEOUT, sample_count=1)

    def test_poll(self):
        """
        Verify the driver can collect a sample from the COMMAND state
        """
        self.assert_enter_command_mode()
        self.assert_particle_polled(DriverEvent.ACQUIRE_SAMPLE, self.assert_data_particle_sample,
                                    DataParticleType.SUNA_SAMPLE, timeout=TIMEOUT, sample_count=1)

    def test_autosample(self):
        """
        Verify the driver can start and stop autosample and verify data particle
        """
        self.assert_sample_autosample(self.assert_data_particle_sample, DataParticleType.SUNA_SAMPLE)

    def test_get_set_parameters(self):
        """
        Verify that all parameters can be get set properly, this includes
        ensuring that read only parameters fail on set.
        """
        self.assert_enter_command_mode()

        #read only params
        self.assert_get_parameter(Parameter.POLLED_TIMEOUT, 65535)
        self.assert_get_parameter(Parameter.SKIP_SLEEP_AT_START, True)
        self.assert_get_parameter(Parameter.LAMP_STABIL_TIME, 5)
        self.assert_get_parameter(Parameter.LAMP_SWITCH_OFF_TEMPERATURE, 35)
        self.assert_get_parameter(Parameter.MESSAGE_LEVEL, "Info")
        self.assert_get_parameter(Parameter.MESSAGE_FILE_SIZE, 0)
        self.assert_get_parameter(Parameter.DATA_FILE_SIZE, 5)
        self.assert_get_parameter(Parameter.OUTPUT_FRAME_TYPE, "Full_ASCII")
        self.assert_get_parameter(Parameter.OUTPUT_DARK_FRAME, "Output")
        self.assert_get_parameter(Parameter.BASELINE_ORDER, 1)

        #NOTE: THESE ARE READ_ONLY PARMS WITH NO DEFAULT VALUES, THE VALUES ARE DEPENDANT ON THE INSTRUMENT BEING TESTED
        #self.assert_get_parameter(Parameter.REF_MIN_AT_LAMP_ON, 9001)
        #self.assert_get_parameter(Parameter.SPECTROMETER_INTEG_PERIOD, 9001)
        #self.assert_get_parameter(Parameter.FIT_WAVELENGTH_LOW, 9002)
        #self.assert_get_parameter(Parameter.FIT_WAVELENGTH_HIGH, 9003)

        #read/write params
        self.assert_set_parameter(Parameter.OPERATION_MODE, InstrumentCommandArgs.CONTINUOUS)
        self.assert_set_parameter(Parameter.OPERATION_CONTROL, "Duration")
        self.assert_set_parameter(Parameter.LIGHT_SAMPLES, 57)
        self.assert_set_parameter(Parameter.DARK_SAMPLES, 3)
        self.assert_set_parameter(Parameter.LIGHT_DURATION, 11)
        self.assert_set_parameter(Parameter.DARK_DURATION, 6)
        self.assert_set_parameter(Parameter.DARK_SAMPLES, 3)
        self.assert_set_parameter(Parameter.DARK_SAMPLES, 3)
        self.assert_set_parameter(Parameter.COUNTDOWN, 16)
        self.assert_set_parameter(Parameter.TEMP_COMPENSATION, True)
        self.assert_set_parameter(Parameter.FIT_WAVELENGTH_BOTH, "218.00,241.00")
        self.assert_set_parameter(Parameter.CONCENTRATIONS_IN_FIT, 3)
        self.assert_set_parameter(Parameter.DARK_CORRECTION_METHOD, "SWAverage")
        self.assert_set_parameter(Parameter.SALINITY_FITTING, False)
        self.assert_set_parameter(Parameter.BROMIDE_TRACING, True)
        self.assert_set_parameter(Parameter.ABSORBANCE_CUTOFF, 1.4)
        self.assert_set_parameter(Parameter.INTEG_TIME_ADJUSTMENT, False)
        self.assert_set_parameter(Parameter.INTEG_TIME_FACTOR, 2)
        self.assert_set_parameter(Parameter.INTEG_TIME_STEP, 19)
        self.assert_set_parameter(Parameter.INTEG_TIME_MAX, 19)

    def test_get_capabilities(self):
        """
        Verify that the correct capabilities are returned from get_capabilities at various driver/agent states.
        """
        ##################
        #  Command Mode
        ##################
        capabilities = {
            AgentCapabilityType.AGENT_COMMAND: self._common_agent_commands(ResourceAgentState.COMMAND),
            AgentCapabilityType.AGENT_PARAMETER: self._common_agent_parameters(),
            AgentCapabilityType.RESOURCE_COMMAND: [ProtocolEvent.ACQUIRE_SAMPLE,
                                                   ProtocolEvent.ACQUIRE_STATUS,
                                                   ProtocolEvent.START_AUTOSAMPLE,
                                                   ProtocolEvent.GET,
                                                   ProtocolEvent.SET,
                                                   ProtocolEvent.TEST,
                                                   ProtocolEvent.CLOCK_SYNC,
                                                   ProtocolEvent.MEASURE_N,
                                                   ProtocolEvent.MEASURE_0,
                                                   ProtocolEvent.TIMED_N],
            AgentCapabilityType.RESOURCE_INTERFACE: None,
            AgentCapabilityType.RESOURCE_PARAMETER: ['a_cutoff', 'bl_order', 'brmtrace', 'countdwn', 'datfsize',
                                                     'drkcormt', 'drkdurat', 'drksmpls', 'fitconcs', 'intadmax',
                                                     'intadstp', 'intpradj', 'intprfac', 'lamptoff', 'lgtdurat',
                                                     'lgtsmpls', 'msgfsize', 'msglevel', 'nmlgtspl', 'operctrl',
                                                     'opermode', 'outdrkfr', 'outfrtyp', 'polltout', 'reflimit',
                                                     'salinfit', 'skpsleep', 'spintper', 'stbltime', 'tempcomp',
                                                     'tlgtsmpl', 'wfit_hgh', 'wfit_low', 'wfitboth']}

        self.assert_enter_command_mode()
        self.assert_capabilities(capabilities)

        ##################
        #  Streaming Mode
        ##################
        capabilities[AgentCapabilityType.AGENT_COMMAND] = self._common_agent_commands(ResourceAgentState.STREAMING)
        capabilities[AgentCapabilityType.RESOURCE_COMMAND] = [ProtocolEvent.STOP_AUTOSAMPLE]

        self.assert_start_autosample()
        self.assert_capabilities(capabilities)
        self.assert_stop_autosample()

        ##################
        #  DA Mode
        ##################
        capabilities[AgentCapabilityType.AGENT_COMMAND] = self._common_agent_commands(ResourceAgentState.DIRECT_ACCESS)
        capabilities[AgentCapabilityType.RESOURCE_COMMAND] = []

        self.assert_direct_access_start_telnet()
        self.assert_capabilities(capabilities)
        self.assert_direct_access_stop_telnet()

        #######################
        #  Uninitialized Mode
        #######################
        capabilities[AgentCapabilityType.AGENT_COMMAND] = self._common_agent_commands(ResourceAgentState.UNINITIALIZED)
        capabilities[AgentCapabilityType.RESOURCE_COMMAND] = []
        capabilities[AgentCapabilityType.RESOURCE_INTERFACE] = []
        capabilities[AgentCapabilityType.RESOURCE_PARAMETER] = []

        self.assert_reset()
        self.assert_capabilities(capabilities)


from django.core.management.base import BaseCommand, CommandError

from main import utils_event
from main.models import Event, EventAction, OpenEvent
from django.db import transaction

# This file is part of https://github.com/cpina/science-cruise-data-management
#
# This project was programmed in a hurry without any prior Django experience,
# while circumnavigating the Antarctic on the ACE expedition, without proper
# Internet access, with 150 scientists using the system and doing at the same
# cruise other data management and system administration tasks.
#
# Sadly there aren't unit tests and we didn't have time to refactor the code
# during the cruise, which is really needed.
#
# Carles Pina (carles@pina.cat) and Jen Thomas (jenny_t152@yahoo.co.uk), 2016-2017.

class Command(BaseCommand):
    help = 'Updates the table of open events. It should not be needed in normal operation'

    @transaction.atomic()
    def handle(self, *args, **options):
        event_numbers = utils_event.open_event_numbers()
        print(event_numbers)
        OpenEvent.objects.all().delete()

        for event_number in event_numbers:
            open_event = OpenEvent(number=event_number)
            open_event.save()


from imageai.Detection import VideoObjectDetection
import os
import shutil
import cv2

#hsv_img= cv2.cvtColor(img,cv2.COLOR_BGR2GRB)
execution_path = os.getcwd()

camera = cv2.VideoCapture(0)

detector = VideoObjectDetection()
detector.setModelTypeAsRetinaNet()
detector.setModelPath( os.path.join(execution_path , "resnet50_coco_best_v2.0.1.h5"))
detector.loadModel(detection_speed = 'fastest')

video_path = detector.detectObjectsFromVideo(camera_input=camera,
    output_file_path=os.path.join(execution_path, "camera_detected_video")
    , frames_per_second=20, log_progress=True, minimum_percentage_probability=30)

print(video_path)
#detections = detector.detectObjectsFromImage(input_image=os.path.join(execution_path , "source_1.png"), output_image_path=os.path.join(execution_path , "imagenew.png"))
#print('bla bla')
#print('detections:',detections)
#print('detections 0:',detections[0])
#print('type of detections:',detections.type())
#print('size of detection:',detections.shape())
#print('result:',eachObject)
#cv2.waitKey(0)
#cv2.destroyAllWindows()