def main():
    global keysPressed
    pickle_fname = "collectedData/dataIndex.p"
    dataIndex = open_dataIndex(pickle_fname)

    training_data_body = []
    training_data_head = []

    countDown(5)

    # Setup for screenGrab
    last_time = time.time()
    W, H = 575, 525
    # This beautiful solution comes from JHolta on:
    # https://stackoverflow.com/questions/69645/take-a-screenshot-via-a-python-script-linux
    # It can be improved to do C-based implementation, but it is basically real-time now.
    dsp = display.Display()
    root = dsp.screen().root
    prevX, prevY = getMousePos(root)

    while True:

        #for k in keysPressed:
        #print(k)
        image = grabscreen(root, W, H)
        image = cv2.resize(image, (299, 299))
        output_body = keys_to_output(keysPressed)
        output_head, prevX, prevY = mmove_to_output(root, prevX, prevY)

        #print(output_body)
        #print(output_head)
        training_data_body.append([image, output_body])
        training_data_head.append([image, output_head])

        print('loop took {:0.3f} seconds'.format(time.time() - last_time))
        last_time = time.time()
        keysPressed = [
        ]  # refresh it each time we loop to keep out past inputs
        #cv2.imshow('window',image)
        time.sleep(
            0.01
        )  # Needs to be there for the async hook and this synced loop to keep up with each other
        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

        if len(training_data_body) % 500 == 0:
            print(len(training_data_body))
            dataIndex = save_npy_file("body", dataIndex, training_data_body,
                                      pickle_fname, 0)
            dataIndex = save_npy_file("head", dataIndex, training_data_head,
                                      pickle_fname, 1)
            # Restarts array for next batch
            training_data_body = []
            training_data_head = []
def main():
    SaveData = False
    global keysPressed
    pickle_fname = "collectedData/dataIndex_both.p"
    dataIndex = open_dataIndex(pickle_fname)

    training_data = []
    # Setup for screenGrab
    last_time = time.time()
    W, H = 575, 525
    dsp = display.Display()
    root = dsp.screen().root

    countDown(5)

    while True:

        image = grabscreen(root, W, H)
        image = cv2.resize(image, (299, 299))
        output_body = b_keys_to_output(keysPressed)
        output_head = h_keys_to_output(keysPressed)

        training_data.append([image, output_body, output_head])

        time.sleep(
            0.01
        )  # Needs to be there for the async hook and this synced loop to keep up with each other
        #print('loop took {:0.3f} seconds'.format(time.time()-last_time))
        last_time = time.time()
        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

        if len(training_data) % 500 == 0:
            if SaveData:
                print(dataIndex)
                dataIndex = save_npy_file("both", dataIndex, training_data,
                                          pickle_fname)
            # Restarts array for next batch
            training_data = []
def main():
    ########################################################
    # Initialize
    ########################################################
    global keysPressed
    dataIndex = 0

    EpisodicMemCap = 100
    dataIndex_episode = pickle.load(
        open("trainingData/episodeData/dataIndex_episode.p", "rb"))

    # Load model
    WIDTH = HEIGHT = 224
    FILENUM = pickle.load(
        open("trainingData/Unbalanced_rgb_299/dataIndex_{}.p".format('both'),
             "rb"))
    #FILENUM_both = 458
    model = get_Keras_model('both', WIDTH, HEIGHT, 8, "AdamReg", FILENUM)

    # Setup for screenGrab
    last_time = time.time()
    W, H = 575, 525
    dsp = display.Display()
    screen = dsp.screen()
    root = dsp.screen().root

    countDown(5)

    while True:
        ########################################################
        #Reinforcement Loop
        ########################################################

        isSolved = False
        trainingData = []

        while not isSolved:
            """
            During the puzzle, this loop will play till it gets determined that
            the puzzle has been solved.
            """
            ############################
            # Get Image
            ############################
            image = grabscreen(root, W, H)
            image_rs = cv2.resize(image, (WIDTH, HEIGHT))

            ############################
            # Make Predictions
            ############################
            body_moves = [0, 0, 0, 0, 0]
            head_moves = [0, 0, 0, 0, 0]
            p_body, p_head = model.predict(
                [image_rs.reshape(1, WIDTH, HEIGHT, 3)])
            # This method ensures that each frame, the agent will pick the most likely option.
            body_m_index = np.argmax(p_body[0])
            head_m_index = np.argmax(p_head[0])

            body_moves[body_m_index] = 1
            head_moves[head_m_index] = 1

            print(body_moves)
            print(head_moves)

            ############################
            # See if Supervisor overrides
            ############################
            trainingData = SupervisorCheck(cv2.resize(image,
                                                      (299, 299)), body_moves,
                                           head_moves, trainingData)

            print('loop took {:0.3f} seconds'.format(time.time() - last_time))
            last_time = time.time()

            ############################
            # Store episodic memory to file.
            ############################
            if len(trainingData) == 100:
                # Sets of 100 so I don't need to preprocess.
                print(dataIndex)
                shuffle(trainingData)  # Just randomize it now.
                dataIndex += 1

                #Write to new datafile. Formatted to fit with current dataGenerator code.
                np.save(
                    "trainingData/episodeData/episodeData/data_{}".format(
                        dataIndex), trainingData)

                # Restarts array for next batch
                trainingData = []

            if 'm' in keysPressed or 'M' in keysPressed:
                # My manual way to break the loop
                isSolved = True
            """
            Needs to be there for the async hook and this synced loop
            to keep up with each other
            """
            time.sleep(0.01)

            if cv2.waitKey(25) & 0xFF == ord('q'):
                cv2.destroyAllWindows()
                break

        print("Number of frames in Episodic Memory: {}".format(dataIndex))

        #Stop the agent
        move_body([0, 0, 0, 0, 1])
        move_head([0, 0, 0, 0, 1])

        if dataIndex > EpisodicMemCap:
            ########################################################
            # Retrain the Agent's Policy
            ########################################################

            for i, layer in enumerate(model.layers):
                print(i, layer.name)

            # Only train the last dense layers that I personally added to VGG16.
            Layer_End = 19
            for layer in model.layers[:Layer_End]:
                layer.trainable = False
            for layer in model.layers[Layer_End:]:
                layer.trainable = True

            # Training Setup
            EPOCHS = 4
            DTYPE = DATA_TYPE = 'episodeData'

            TrainLen = dataIndex - 10
            Indicies = np.array(range(1, dataIndex + 1))
            shuffle(Indicies)
            TrainIndex = Indicies[:TrainLen]
            ValidIndex = Indicies[TrainLen:]

            params = {
                'WIDTH': WIDTH,
                'HEIGHT': HEIGHT,
                'DTYPE': DTYPE,
                'DATA_TYPE': DATA_TYPE,
                'isConcat': True,
                'batch_size': 1,
                'shuffle': True
            }

            training_generator = DataGenerator(Indicies, **params)
            validation_generator = DataGenerator(ValidIndex, **params)

            # Defining my callbacks:
            filepath = "models/SupervisedReinforcement/best_weights.h5"
            checkpoint = ModelCheckpoint(filepath,
                                         monitor='val_dense_5_acc',
                                         verbose=1,
                                         save_best_only=True,
                                         mode='max')
            callbacks_list = [checkpoint]

            # compile the model (should be done *after* setting layers to non-trainable)
            model.compile(optimizer=SGD(lr=1e-4, momentum=0.9),
                          loss='categorical_crossentropy',
                          metrics=['acc'])
            #model.compile(optimizer=Adam(lr=0.0001), loss='categorical_crossentropy', metrics=['acc'])

            # Train the model on the new data for a few epochs
            model.fit_generator(generator=training_generator,
                                validation_data=validation_generator,
                                callbacks=callbacks_list,
                                use_multiprocessing=True,
                                workers=6,
                                epochs=EPOCHS,
                                steps_per_epoch=dataIndex)

            #Reload the best weights from that update session
            model.load_weights(
                "models/SupervisedReinforcement/best_weights.h5")

            # Save data rather than delete because it is like 10k data samples

            dataIndex_episode += 1
            shutil.move(
                "trainingData/episodeData/episodeData",
                "trainingData/episodeData/episodeDataArchived/E{}".format(
                    dataIndex_episode))
            subprocess.call(['mkdir', 'trainingData/episodeData/episodeData'])
            pickle.dump(
                dataIndex_episode,
                open("trainingData/episodeData/dataIndex_episode.p", "wb"))

            dataIndex = 0

        else:
            # wait till I tell it to start testing again.
            testStart = False

            while not testStart:
                if 'n' in keysPressed or 'N' in keysPressed:
                    testStart = True
def main():
    SaveData = True
    global keysPressed
    pickle_fname = "collectedData/dataIndex_head.p"
    dataIndex = open_dataIndex(pickle_fname)

    training_data= []

    #This chunk could probably be abstracted out?
    WIDTH = HEIGHT = 224
    LR = 1e-4
    EPOCHS_1 = 4
    DTYPE = 'body'
    OPTIMIZER = 'Adam'
    DATA_TYPE = "Unbalanced_rgb_299"
    ARCH = "VGG16"
    #FILENUM = pickle.load(open("trainingData/Unbalanced_rgb_299/dataIndex_{}.p".format(DTYPE), "rb"))
    FILENUM = 3335
    MODEL_NAME = 'pytalos_{}_{}_{}_{}_files_{}_epocs_{}_{}.h5'.format(DTYPE, ARCH, OPTIMIZER, FILENUM, EPOCHS_1, DATA_TYPE,LR)
    model_path = "models/{}/{}".format(DTYPE,MODEL_NAME)

    print(model_path)
    model = load_model(model_path)
    model.load_weights("models/{}/best_weights_{}".format(DTYPE,MODEL_NAME))

    # Setup for screenGrab
    last_time = time.time()
    W,H = 575,525
    dsp = display.Display()
    root = dsp.screen().root

    countDown(5)

    while True:
        #print(keysPressed)
        image = grabscreen(root, W,H)
        image = cv2.resize(image,(299,299))
        image_predict = cv2.resize(image,(WIDTH,HEIGHT))
        # Move the body.
        prediction = model.predict([image_predict.reshape(1,WIDTH,HEIGHT,3)])[0]
        moves = list(np.around(prediction))
        move_body(moves)

        # Classify the movement for the head.
        output_head = h_keys_to_output(keysPressed)
        training_data.append([image, output_head])

        #cv2.imshow('window',image)
        time.sleep(0.01)  # Needs to be there for the async hook and this synced loop to keep up with each other
        #print('loop took {:0.3f} seconds'.format(time.time()-last_time))
        last_time = time.time()

        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

        if len(training_data) % 500 == 0:
            if SaveData:
                print(dataIndex)
                dataIndex = save_npy_file("head", dataIndex, training_data, pickle_fname)
            # Restarts array for next batch
            training_data = []