# code working now
# next step is to find the most conserved spots
# figure out the meaning of each attribute; search through actual database

from Bio import SeqIO
from Bio import SwissProt
from Bio import pairwise2
from Bio import AlignIO
# Import format_alignment method
from Bio.pairwise2 import format_alignment
import itertools

# handle = open(r"/Volumes/ENDY_LAB/code_to_test_dbs/databases/test.dat")

handle = open(
    r"/Volumes/ENDY_LAB/code_to_test_dbs/databases/uniprot_sprot.dat")

# match is an int that starts at 0
# to print protein, use protein.sequence
for match, protein in enumerate(SwissProt.parse(handle)):
    g = True
    # print("Testing protein ", match+1)

    # for eachAA in protein, match:

# \n--> new line/ space for readability
    # print("\n")
    aaSet = ['Q', 'F', 'L', 'Y', 'K', 'D', 'M',
             'V', 'G', 'C', 'R', 'P', 'T', 'S', 'A']
    aaSetPrintable = ''.join(aaSet)
    # aaSetTwo = ['N','E', 'H', 'I', 'W', 'Q', 'F', 'L', 'Y', 'K', 'D', 'M', 'V', 'G', 'C', 'R', 'P', 'T', 'S', 'A']
# print statement of (-----) is used to help read the code

# protein.sequence[0+1] starts at the first letter in a sequence and increments to the next with +1
    for n in range(0, len(protein.sequence)):
            # letter +=1
            # print (len(protein.sequence))
            # print(n)
            # print("Print letter: ", match)
        if protein.sequence[n] not in aaSet:
            g = False
            # print(protein.sequence[n])
            # print(len(protein.sequence))
            # print(protein.sequence[0 + 1])
            # print(True)
            break
    if g == True and (len(protein.sequence)) >= 50:

        print("\n")
        print("Reduced amino acid set = [" + aaSetPrintable + "]")
        print("\n")

# match is an int that starts at 0; it increments everytime and counts the total number of proteins
        print("Matching Protein")
        print("Index = " + str(match+1))
        db = list(protein.sequence)
# .join turns list into strings
        print("Description = " + str(protein.description))
        print("Features = " + str(protein.features[0]))
        db = ''.join(db)
        print("Sequence = " + str(db))
        print("Length = " + str(len(protein.sequence)))
        print("\n")
        print("------------------------------------------------------------")
        # break
        # else:
        # print("\n")
# to test logic/ if failed, then uncomment the lines below
        # print(False)
        # print("Protein sequence in database: ", match+1)
        # db = list(protein.sequence)
        # db = ''.join(db);
        # print(db)
        # print("------------------------------------------------------------")


"""up: Create and launch specified containers

Runs 'docker compose up -d ...' for the specified process.
Options: --dev, --prod, --all

If the --debug flag is provided, only the debug container is launched.
Even if --dev or --prod flags are provided.

Otherwise (i.e. no --debug):
    -- dev, all, or no flags  |  dev container is launched
    -- prod or all            |  prod container is launched
"""
import os
from pathlib import Path
import subprocess
import yaml
from dsco.helpers import add_timer

cmd_name = Path(__file__).stem

def add_subparser(subparsers):
    sub = subparsers.add_parser(cmd_name, help="create and launch containers")
    sub.add_argument("--dev", action="store_true", help="dev container")
    sub.add_argument("--prod", action="store_true", help="prod container")
    sub.add_argument(
        "--debug",
        action="store_true",
        help="bring up base container without running ansible",
    )
    sub.add_argument("--all", action="store_true", help="dev and prod containers")

@add_timer(cmd_name)
def run_cmd(args, conf):
    if conf["proj_root"]:
        # Flag logic
        no_flags = not any([args.dev, args.prod, args.debug, args.all])
        service_list = [
            # (service, flag)
            ("dev", (args.dev or args.all or no_flags) and not args.debug),
            ("prod", (args.prod or args.all) and not args.debug),
            ("debug", args.debug),
        ]
        services_str = " ".join([service for service, flag in service_list if flag])

        cmd = f"docker compose up -d {services_str}"
        print(cmd)
        subprocess.run(cmd, cwd=conf["proj_root"], shell=True)

    else:
        print("No project found.")

def add_dispatch(dispatcher):
    dispatcher[cmd_name] = run_cmd


import argparse
import json
import pickle
import sys
from pathlib import Path

from jsonschema import validate

from utils.logger import get_logger
import numpy as np
import pandas as pd
import tensorflow as tf

validation_schema = {
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "properties": {
        "text": {
            "type": "string"
        },
        "label": {
            "type": "integer"
        }
    },
    "required": [
        "text",
        "label"
    ]
}

def main(args):
    logger = get_logger()

    # Construct the argument parser
    ap = argparse.ArgumentParser()

    # Add the arguments to the parser
    ap.add_argument("--train", required=True,
                    help="Train data")
    ap.add_argument("--test", required=True,
                    help="Train data")
    ap.add_argument("--labels", required=True,
                    help="Labels file")

    ap.add_argument("-s", "--seed", type=int, default=42,
                    help="Seed. Default: 42")

    ap.add_argument("--vocab", type=int, default=10000,
                    help="Vocabulary size. Default: 10000")

    ap.add_argument("-v", "--verbose", type=int, default=0,
                    help="Verbose")

    ap.add_argument("-e", "--epochs", type=int, default=10,
                    help="Number of epochs")
    ap.add_argument("--validation_steps", type=int, default=30,
                    help="Number of validation steps")

    ap.add_argument("--model", required=True,
                    help="Path to save TF model")
    ap.add_argument("--history",
                    help="[Optional] Path to save training history")

    args, unknown = ap.parse_known_args(args[1:])
    args = vars(args)

    verbose = args['verbose']
    vocab = args['vocab']
    epochs = args['epochs']
    validation_steps = args['validation_steps']

    if verbose >= 52:
        logger.info(args)

    seed = args['seed']

    np.random.seed(seed)

    train_path = Path(args['train'])
    test_path = Path(args['test'])
    model_path = Path(args['model'])
    labels_path = Path(args['labels'])
    history_path = args['history']

    if history_path is not None:
        history_path = Path(history_path)

    if not train_path.exists() or not train_path.is_file():
        raise Exception('Train path is incorrect')

    if not test_path.exists() or not test_path.is_file():
        raise Exception('Test path is incorrect')

    if not labels_path.exists() or not labels_path.is_file():
        raise Exception('Labels path is incorrect')

    with open(train_path, 'r') as f:
        train_raw = json.load(f)

    with open(labels_path, 'r') as f:
        labels = json.load(f)

    for item in train_raw:
        validate(item, schema=validation_schema)

    with open(test_path, 'r') as f:
        test_raw = json.load(f)

    for item in test_raw:
        validate(item, schema=validation_schema)

    train = pd.DataFrame(train_raw)
    val = pd.DataFrame(test_raw)

    num_classes = len(labels)
    x_field = 'text'
    y_field = 'label'

    if verbose >= 52:
        logger.info(train.head())

    encoder = tf.keras.layers.TextVectorization(
        max_tokens=vocab)
    encoder.adapt(train[x_field].values)

    actual_vocab_size = np.array(encoder.get_vocabulary()).size

    if verbose >= 52:
        logger.info(f'Actual vocab size: {actual_vocab_size}')

    model = tf.keras.Sequential([
        encoder,
        tf.keras.layers.Embedding(
            input_dim=actual_vocab_size,
            output_dim=64,
            mask_zero=True),
        tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64, return_sequences=True)),
        tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32)),
        tf.keras.layers.Dense(64, activation='relu'),
        tf.keras.layers.Dropout(0.5),
        tf.keras.layers.Dense(num_classes)
    ])

    model.compile(
        loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
        optimizer=tf.keras.optimizers.Adam(1e-4),
        metrics=['accuracy']
    )

    history = model.fit(
        tf.convert_to_tensor(train[x_field].values, dtype=tf.string),
        tf.keras.utils.to_categorical(train[y_field].values, num_classes=num_classes),
        epochs=epochs,
        validation_data=(
            tf.convert_to_tensor(val[x_field].values, dtype=tf.string),
            tf.keras.utils.to_categorical(val[y_field].values, num_classes=num_classes),
        ),
        validation_steps=validation_steps,
    )

    if history_path is not None:
        with open(history_path, 'wb') as f:
            pickle.dump(history.history, f)

    model.save(model_path, overwrite=True)

if __name__ == '__main__':
    main(sys.argv)


from plone.testing.z2 import ZSERVER_FIXTURE

from plone.app.testing import PloneSandboxLayer
from plone.app.testing import applyProfile
from plone.app.testing import PLONE_FIXTURE
from plone.app.testing import IntegrationTesting
from plone.app.testing import FunctionalTesting

from zope.configuration import xmlconfig

from mocker import Mocker
from mocker import ANY

class ExampleTddLayer(PloneSandboxLayer):

    defaultBases = (PLONE_FIXTURE,)

    def setUpZope(self, app, configurationContext):
        # Mock postmonkey
        mocker = Mocker()
        postmonkey = mocker.replace("postmonkey")
        mailchimp = postmonkey.PostMonkey(ANY)
        mocker.count(0, 1000)
        # Lists
        mailchimp.lists()
        mocker.count(0, 1000)
        mocker.result({
            u'total': 2,
            u'data': [{
                    u'id': 625,
                    u'web_id': 625,
                    u'name': u'ACME Newsletter',
                    u'default_from_name': u'info@acme.com',
                },
                {
                    u'id': 626,
                    u'web_id': 626,
                    u'name': u'ACME Newsletter 2',
                    u'default_from_name': u'info@acme.com',
                },
            ]})
        mocker.replay()

        # Load ZCML
        import example.tdd
        xmlconfig.file(
            'configure.zcml',
            example.tdd,
            context=configurationContext
        )

        # Install products that use an old-style initialize() function
        #z2.installProduct(app, 'Products.PloneFormGen')

#    def tearDownZope(self, app):
#        # Uninstall products installed above
#        z2.uninstallProduct(app, 'Products.PloneFormGen')

    def setUpPloneSite(self, portal):
        applyProfile(portal, 'example.tdd:default')

EXAMPLE_TDD_FIXTURE = ExampleTddLayer()
EXAMPLE_TDD_INTEGRATION_TESTING = IntegrationTesting(
    bases=(EXAMPLE_TDD_FIXTURE,),
    name="ExampleTddLayer:Integration")
EXAMPLE_TDD_ACCEPTANCE_TESTING = FunctionalTesting(
    bases=(EXAMPLE_TDD_FIXTURE, ZSERVER_FIXTURE),
    name="ExampleTDD:Acceptance"
)


# first neural network with keras make predictions
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.callbacks import TensorBoard
import datetime
from sklearn.model_selection import train_test_split

layer1_sizes = [16,]
layer2_sizes = [16,32]
layer3_sizes = [8,16]
layer4_sizes = [8]
test_portion = 0.1

# load the dataset
dataset = np.loadtxt('hole-measurement/data/holes6.csv', delimiter=',')
# split into input (X) and output (y) variables
X = dataset[:,0:6]
y = dataset[:,8] / 6.0
print("X shape")
print(X.shape)
XTraining, XValidation, YTraining, YValidation = train_test_split(X,y,stratify=y,test_size=0.1) # before model building
print("X Training shape")
print(XTraining.shape)
print("X Validation shape")
print(XValidation.shape)

#print(y)
#ds_rows = X.shape[0]
#print("Number of rows: {}".format(ds_rows))
#train_rows = round(X.shape[0] * (1-test_portion))
#print("Number of rows in training set: {}".format(train_rows))
#all_ds = tf.data.Dataset.from_tensor_slices((X, y))
#all_ds = all_ds.shuffle(buffer_size=1024)
#train_ds = all_ds.take(train_rows)
#val_ds = all_ds.skip(train_rows)

for layer1_size in layer1_sizes:
    for layer2_size in layer2_sizes:
        for layer3_size in layer3_sizes:
            for layer4_size in layer4_sizes:
                NAME = "hole-size-not-proj-all-relu-normalized-{}-{}-{}-{}-".format(layer1_size, layer2_size,layer3_size, layer4_size) + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
                tensorboard_callback = TensorBoard(log_dir='logs\\fit\\'+NAME, histogram_freq=1)
                print("Iteration: " +NAME)

                # define the keras model
                model = Sequential()
                model.add(Dense(layer1_size, input_dim=6, activation='relu'))
                model.add(Dense(layer2_size, activation='relu'))
                model.add(Dense(layer3_size, activation='relu'))
                model.add(Dense(layer4_size, activation='relu'))
                model.add(Dense(1, activation='relu'))
                # compile the keras model
                print("Compiling model...")
                model.compile(loss='mean_squared_error', optimizer='adam', metrics=['mean_squared_error'])
                print("Done.")

                # fit the keras model on the dataset
                print("Fitting model...")
                history = model.fit(XTraining, YTraining, validation_data=(XValidation, YValidation), epochs=1000, verbose=0, callbacks=[tensorboard_callback])
                print("Done.")

                # make class predictions with the model
                #print("Making predictions...")
                #predictions = model.predict(X)
                #print("Done.")


from __future__ import annotations

from typing import TYPE_CHECKING, TypedDict

import requests
from api.exceptions import APIError
from terminaltables import SingleTable
from utilities.duration import convert_duration
from utilities.tables import check_value, shorten_string

if TYPE_CHECKING:
    from classes.artist import Artist
    from classes.track import Track, TrackInfo

class AlbumInfo(TypedDict):
    """A dictionary with an album's information."""

    release_date: str
    album_type: str
    total_tracks: int
    genres: list[str]
    popularity: int
    label: str
    images: list[str]
    copyright: list[str]

class Album:
    """Represents an album on Spotify.

    The Album class encapsulates the details of a music album.
    It requires the album's name, unique ID, and a valid Spotify API token
    upon instantiation.

    Attributes:
        name (str): The album's name.
        id (str): The album's unique ID.
        url (str): The album's Spotify URL.
        token (str): A valid Spotify API token.
        _info (dict): The album's information, organized in a dictionary.
        _artists (dict): The album's artists, organized in a dictionary with
            the artist's ID as the key and the Artist object as the value.
        _tracks (dict): The album's tracks, organized in a dictionary with the
            track's ID as the key and the Track object as the value.
    """

    def __init__(
        self,
        name: str,
        _id: str,
        token: str,
        fetched_data: AlbumInfo | None = None,
        artists: dict[str, Artist] = {},
        tracks: dict[str, Track] = {},
    ):
        """
        Initialize an Album object.

        Args:
            name: The album's name.
            _id: The album's unique ID.
            token: A valid Spotify API token.
            If not provided, additional information, artists and tracks are
            lazily loaded upon first access to minimize unnecessary API
            requests.
        """
        self.name: str = name
        self._id: str = _id
        self.url: str = f"https://open.spotify.com/album/{_id}"
        self.token: str = token
        self._info: AlbumInfo | None = fetched_data if fetched_data else None
        self._artists: dict[str, Artist] = artists
        self._tracks: dict[str, Track] = tracks

    @property
    def info(self) -> AlbumInfo | None:
        """Return the album's information."""
        if not self._info:
            self.fetch_album_info()
        return self._info

    @property
    def artists(self) -> dict[str, Artist]:
        """Return the album's artists."""
        if not self._artists:
            self.fetch_album_info()
        return self._artists

    @property
    def tracks(self) -> dict[str, Track]:
        """Return the album's tracks."""
        if not self._tracks:
            self.fetch_tracks()
        return self._tracks

    def fetch_album_info(self):
        """Fetch an albums's information from the Spotify API."""
        from classes.artist import Artist

        print(f"Fetching information of '{self.name}'...")

        try:
            url = f"https://api.spotify.com/v1/albums/{self._id}"
            response = requests.get(
                url,
                headers={
                    "Authorization": f"Bearer {self.token}",
                },
            )
            if response.status_code != 200:
                raise APIError(response.status_code)

        except APIError as e:
            e.print_error("information", self.name)

        else:
            info_api = response.json()
            info: AlbumInfo = {
                "release_date": info_api["release_date"],
                "album_type": info_api["album_type"],
                "total_tracks": info_api["total_tracks"],
                "genres": info_api["genres"],
                "popularity": info_api["popularity"],
                "label": info_api["label"],
                "images": [image["url"] for image in info_api["images"]],
                "copyright": [
                    copyright["text"] for copyright in info_api["copyrights"]
                ],
            }
            self._info = info

            artists_api = info_api["artists"]
            self._artists = {
                artist["id"]: Artist(artist["name"], artist["id"], self.token)
                for artist in artists_api
            }

            print(f"Successfully fetched information of {self.name}.")

    def fetch_tracks(self):
        """Fetch an album's tracks from the Spotify API."""
        from classes.artist import Artist
        from classes.track import Track

        print(f"Fetching tracks of '{self.name}'...")

        try:
            tracks = {}
            url = f"https://api.spotify.com/v1/albums/{self._id}/tracks"
            response = requests.get(
                url, headers={"Authorization": f"Bearer {self.token}"}
            )
            if response.status_code != 200:
                raise APIError(response.status_code)

        except APIError as e:
            e.print_error("tracks", self.name)

        else:
            for track in response.json()["items"]:
                # Prepare everything for the Track instantiation
                track_id = track["id"]
                track_info: TrackInfo = {
                    "duration": convert_duration(track["duration_ms"]),
                    "explicit": track["explicit"],
                }
                track_album = self
                track_artists = {
                    artist["id"]: Artist(artist["name"], artist["id"], self.token)
                    for artist in track["artists"]
                }
                tracks[track_id] = Track(
                    track["name"],
                    track["id"],
                    self.token,
                    track_info,
                    track_album,
                    track_artists,
                )
            self._tracks = tracks

            print(f"Successfully fetched {len(self._tracks)} tracks of {self.name}.")

    def print_album_info(self):
        """Print an album's information.

        The information is printed in a table with two columns: Property and
        Value. The table is printed using the terminaltables library.
        """
        # Create a list of rows for the table
        data = [["Property", "Value"]]
        data.append(["Name", self.name])
        data.append(["ID", self._id])
        data.append(["Release date", check_value(self.info["release_date"])])

        artist_names = [artist.name for artist in self.artists.values()]
        if len(artist_names) == 1:
            data.append(["Artist", artist_names[0]])
        else:
            data.append(["Artists", ", ".join(artist_names)])

        data.append(["Type", self.info["album_type"].capitalize()])
        data.append(["Total tracks", self.info["total_tracks"]])

        genres = check_value(", ".join(self.info["genres"]))
        data.append(["Genres", genres])

        data.append(["Popularity", self.info["popularity"]])
        data.append(["Label", check_value(self.info["label"])])

        try:
            image = self.info["images"][0]
        except IndexError:
            image = None
        data.append(["Cover", check_value(image)])

        copyright = check_value(", ".join(self.info["copyright"]))
        data.append(["Copyright", copyright])

        data.append(["Spotify URL", self.url])

        print(SingleTable(data).table)

    def print_tracks(self):
        """Prints a table of tracks to the terminal.

        The table contains the following columns: Name, Artists, Length, and
        Spotify URL. The table is printed using the terminaltables library.
        """
        # Create a list of rows for the table
        data = [["Name", "Artists", "Length", "Spotify URL"]]
        for track in self.tracks.values():
            data.append(
                [
                    shorten_string(track.name, 32),
                    shorten_string(
                        ", ".join([artist.name for artist in track.artists.values()]),
                        32,
                    ),
                    track._info["duration"],
                    track.url,
                ]
            )

        print(SingleTable(data).table)


import time
import cv2
import datetime
import sys
import telepot
import datetime as dt
from subprocess import call
import subprocess
import os.path
import cv2
import datetime as dt
from subprocess import CalledProcessError

recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('trainer/trainer.yml')
cascadePath = "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascadePath);

font = cv2.FONT_HERSHEY_SIMPLEX

#iniciate id counter
id = 0
gchat_id=1126258930

names = ['none', 'id1', 'id2']

# Initialize and start realtime video capture
cam = cv2.VideoCapture(0)
#cam.set(3, 240) # set video widht
#cam.set(4, 240) # set video height

# Define min window size to be recognized as a face
count=0

#https://t.me/Path_predict_bot
def handle(msg):
    chat_id = msg['chat']['id']
    command = msg['text']

    print(command)

    if command == '/image':
       bot.sendMessage(chat_id,text="Taking Photos")

       ret, frame = cam.read()
       if ret==True:
            frame = cv2.flip(frame,1)
            cv2.imwrite('./photo.jpg', frame)
            cv2.imshow('camera',frame)
       else:
            bot.sendMessage(chat_id,text="Captured Failed")

       #cv2.destroyAllWindows()
       bot.sendPhoto(chat_id=chat_id, photo=open('./photo.jpg', 'rb'))

    elif command =='/video':
        bot.sendMessage(chat_id,text="Camera is starts recording")
        time.sleep(.1)
        bot.sendMessage(chat_id,text="Hold on please for 10 sec ")
        print('Start recording..')
        capture_duration = 10 #change here for duration of capturing video

        dim=(640,480)
        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        out = cv2.VideoWriter('video.mp4',fourcc, 20.0, (640,480))
        start_time = time.time()
        while( int(time.time() - start_time) < capture_duration ):
            ret, frame = cam.read()
            if ret==True:
                frame = cv2.flip(frame,1)
                resized = cv2.resize(frame, dim, interpolation = cv2.INTER_AREA)
                out.write(resized)
                cv2.imshow('camera',frame)
            else:
                bot.sendMessage(chat_id,text="Record Failed")
                break
            k = cv2.waitKey(1) & 0xff # Press 'ESC' for exiting video
            if k == 27:
                break

        out.release()
        #cam.release()
        #cv2.destroyAllWindows()

        print('Stop recording..')
        bot.sendMessage(chat_id,text="Recoding Completed")
        time.sleep(.1)
        bot.sendMessage(chat_id,text="Uploading video please be patient")
        time.sleep(.1)
        bot.sendVideo(chat_id, video=open('./video.mp4', 'rb'))

    elif (command=='hi') or (command=='Hi') or (command=='Hello') or (command=='hello') or (command=='Hey') or (command=='hey'):
        bot.sendMessage(chat_id,text="Hello \n /help")
    elif (command=='bye') or (command=='Bye') or (command=='See you') or (command=='take care') or (command=='Hey') or (command=='hey'):
        bot.sendMessage(chat_id,text="Have a Good Day")
    elif (command=='/-h') or (command=='/help') or (command=='/info') :
        bot.sendMessage(chat_id,text="Hello You Can Proceed with these commands \n /video \n /image")

def sendvid():
        global gchat_id
        chat_id=gchat_id
        bot.sendMessage(chat_id,text="Surveillance system Tracked Something!!!")
        time.sleep(.1)
        bot.sendMessage(chat_id,text="Hold on please for 10 sec ")
        print('Start recording..')
        capture_duration = 10 #change here for duration of capturing video

        dim=(640,480)
        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        out = cv2.VideoWriter('video.mp4',fourcc, 20.0, (640,480))
        start_time = time.time()
        while( int(time.time() - start_time) < capture_duration ):
            ret, frame = cam.read()
            if ret==True:
                frame = cv2.flip(frame,1)
                resized = cv2.resize(frame, dim, interpolation = cv2.INTER_AREA)
                out.write(resized)
                cv2.imshow('camera',frame)
            else:
                bot.sendMessage(chat_id,text="Record Failed")
                break
            k = cv2.waitKey(1) & 0xff # Press 'ESC' for exiting video
            if k == 27:
                break

        out.release()

        print('Stop recording..')
        bot.sendMessage(chat_id,text="Recoding Completed")
        time.sleep(.1)
        bot.sendMessage(chat_id,text="Uploading video")
        time.sleep(.1)
        bot.sendVideo(chat_id, video=open('./video.mp4', 'rb'))

bot = telepot.Bot('1739222778:AAEKgqSiboEBp58GP6iaBQZDrrCDoJyUMDY')
bot.message_loop(handle)
print('Video based surveillance system and path prediction')
bot.sendMessage(234352074,text="surveillance system,is Active Now")
bot.sendMessage(gchat_id,text="surveillance system,is Active Now")

def getCam():
    global count,chat_id

    ret, img =cam.read()
    img = cv2.flip(img, 1) # Flip vertically

    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor = 1.1,
        minNeighbors = 5,
        minSize = (30, 30),
       )

    for(x,y,w,h) in faces:

        cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)

        id, confidence = recognizer.predict(gray[y:y+h,x:x+w])
        conf=round(100 - confidence)

        # Check if confidence is less them 100 ==> "0" is perfect match
        if(id==1 and conf >35):
            if(x<100 or x >250):

                 count+=1
                 if(count>10):
                     sendvid()
                     bot.sendMessage(gchat_id,text="Predicting path please wait")
                     time.sleep(2)
                     if(x<100):
                         bot.sendMessage(gchat_id,text="Predicted Path person Moving Left direction")
                         bot.sendPhoto(chat_id=gchat_id, photo=open('./1.png', 'rb'))
                         count=0

                     elif(x>250):
                         bot.sendMessage(gchat_id,text="Predicted Path person Moving Right direction")
                         bot.sendPhoto(chat_id=gchat_id, photo=open('./2.png', 'rb'))
                         count=0
                     else:
                         count=0

        cv2.putText(img, str(id), (x+5,y-5), font, 1, (255,255,255), 2)
        cv2.putText(img, str(conf), (x+5,y+h-5), font, 1, (255,255,0), 1)

    cv2.line(img=img, pt1=(int(150), 0), pt2=(int(150), 640), color=(0, 255, 0), thickness=2, lineType=1, shift=0)
    cv2.line(img=img, pt1=(int(470), 0), pt2=(int(470), 640), color=(0, 255, 0), thickness=2, lineType=1, shift=0)

    cv2.imshow('camera',img)

while (True):

    getCam()

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

cam.release()
cv2.destroyAllWindows()


import unittest
import main
import mock

class EstimateTestTimesTestCase(unittest.TestCase):
    def setUp(self):
        self.ett = main.EstimateTestTimes()

    def start_ptt_test(self, time_str, test_name):
        self.ett.process_line("[2016-08-30 {}] [INFO] [default] automated-testing-test-start [TCU][run][2016-08-30-17-42-14][{}]".format(time_str, test_name))

    def end_ptt_test(self, time_str, test_name):
        self.ett.process_line("[2016-08-30 {}] [INFO] [default] automated-testing-test-done [TCU][run][2016-08-30-17-42-14][{}]".format(time_str, test_name))

    def test_single_test_duration(self):
        self.start_ptt_test("19:01:57.500", "0052_PTT_ServoVoltage")
        self.end_ptt_test("19:02:58.750", "0052_PTT_ServoVoltage")

        assert "0052_PTT_ServoVoltage" in self.ett.time_data
        self.assertEqual(61.25, self.ett.time_data["0052_PTT_ServoVoltage"][0].duration)

    def test_multiple_test_duration(self):
        self.start_ptt_test("19:01:57.500", "0052_PTT_ServoVoltage")
        self.end_ptt_test("19:02:58.750", "0052_PTT_ServoVoltage")

        self.start_ptt_test("19:01:57.500", "0053_PTT_ChuckNorris")
        self.end_ptt_test("19:02:59.750", "0053_PTT_ChuckNorris")

        assert "0052_PTT_ServoVoltage" in self.ett.time_data
        assert "0053_PTT_ChuckNorris" in self.ett.time_data

    def test_test_is_rejected_when_duration_is_small(self):
        self.start_ptt_test("19:01:57.500", "0053_PTT_test")
        self.end_ptt_test("19:01:57.750", "0053_PTT_test")
        assert "0052_PTT_ServoVoltage" not in self.ett.time_data

    def test_ignores_incomplete_start_tags(self):
        self.ett.process_line("[2016-08-30 10:33:51.228] [INFO] [default] automated-testing-test-start [TCU][prepare][2016-08-30-10-33-49]")
        self.end_ptt_test("19:01:57.750", "0053_PTT_test")
        assert not self.ett.time_data

    def test_ignores_incomplete_end_tags(self):
        self.start_ptt_test("19:01:57.750", "0053_PTT_test")
        self.ett.process_line("[2016-08-30 10:33:51.228] [INFO] [default] automated-testing-test-start [TCU][restore][2016-08-30-10-33-49]")
        assert not self.ett.time_data

    def test_updates_measurement_analysis(self):
        mock_analysis = mock.MagicMock()
        with mock.patch("main.EstimateMeasurementTimes", return_value=mock_analysis):
            self.start_ptt_test("19:01:57.500", "0053_PTT_test")
            self.ett.process_line("Someline")
            mock_analysis.process_line.assert_called_with("Someline")

    def test_resets_measurement_analysis_on_every_test_start(self):
        with mock.patch("main.EstimateMeasurementTimes") as mock_analysis:
            self.start_ptt_test("19:01:57.500", "0053_PTT_test")
            assert mock_analysis.called
            self.end_ptt_test("19:01:57.500", "0053_PTT_test")

            mock_analysis.reset_mock()
            self.start_ptt_test("19:01:57.500", "0053_PTT_test")
            assert mock_analysis.called
            self.end_ptt_test("19:01:57.500", "0053_PTT_test")

    def test_adds_measurement_analysis_to_test_record(self):
        mock_analysis = mock.MagicMock()
        mock_analysis.get_data.return_value = "AnalysisData"
        mock_analysis.total_sleep = 123.456

        with mock.patch("main.EstimateMeasurementTimes", return_value=mock_analysis):
            self.start_ptt_test("19:01:57.500", "0053_PTT_test")
            self.end_ptt_test("19:05:57.500", "0053_PTT_test")
            self.assertEqual("AnalysisData", self.ett.time_data["0053_PTT_test"][0].measurement_times)
            self.assertEqual(123.456, self.ett.time_data["0053_PTT_test"][0].total_sleep)

class EstimateMeasurementTimesTestCase(unittest.TestCase):
    def setUp(self):
        self.emt = main.EstimateMeasurementTimes()

    def do_measurement(self, mode, measurement_time):
        def get_time(increment):
            hh, mm, ss = (10, 40, 0.0)
            ss += increment
            if ss >= 60.0:
                ss -= 60.0
                mm += 1

            return hh, mm, ss

        if mode == "FREQUENCY":
            config_command = "CONFigure:FREQuency AUTO,DEF,(@318)"
        else:
            config_command = "CONFigure:VOLTage:{} AUTO,DEF,(@318)".format(mode)

        h, m, s = get_time(0)
        self.emt.process_line("[2016-08-30 {}:{}:{:.3f}] [DEBUG] [Rigol-M300] WRITING COMMAND: '{}' (delay was 1211 ms, slept 0 ms).".format(h,m,s, config_command))

        h, m, s = get_time(measurement_time)
        self.emt.process_line("[2016-08-30 {}:{}:{:.3f}] [DEBUG] [Rigol-M300] Response for SYSTEM:ERROR? for command FETCh?: +0,\"No error\" (processing time 0 ms).".format(h,m,s))

        h, m, s = get_time(measurement_time + 1)
        self.emt.process_line("[2016-08-30 {}:{}:{:.3f}] [DEBUG] [Rigol-M300] WRITING COMMAND: '{}' (delay was 1211 ms, slept 0 ms).".format(h,m,s, config_command))

    def test_measures_initialization_time(self):
        self.emt.process_line("[2016-08-30 10:39:00.000] [DEBUG] [Rigol-M300] WRITING COMMAND: '*RST' (delay was 1000 ms, slept 0 ms).")
        self.emt.process_line("[2016-08-30 10:40:00.000] [DEBUG] [Rigol-M300] WRITING COMMAND: 'CONFigure:VOLTage:DC AUTO,DEF,(@318)' (delay was 1211 ms, slept 0 ms).")
        self.assertEqual(60.0, self.emt.get_data()["INITIALIZATION"][0])

    def test_measures_dc_measurement_time(self):
        self.do_measurement("DC", 90.0)
        self.assertEqual(90.0, self.emt.get_data()["DC"][0])

    def test_measures_ac_measurement_time(self):
        self.do_measurement("AC", 90.0)
        self.assertEqual(90.0, self.emt.get_data()["AC"][0])

    def test_measures_frequency_measurement_time(self):
        self.do_measurement("FREQUENCY", 90.0)
        self.assertEqual(90.0, self.emt.get_data()["FREQUENCY"][0])

    def test_measurement_time_is_measured_between_configure_and_last_fetch(self):
        self.emt.process_line("[2016-08-30 10:40:00.000] [DEBUG] [Rigol-M300] WRITING COMMAND: 'CONFigure:VOLTage:AC AUTO,DEF,(@318)' (delay was 1211 ms, slept 0 ms).")
        self.emt.process_line("[2016-08-30 10:40:01.000] [DEBUG] [Rigol-M300] Response for SYSTEM:ERROR? for command FETCh?: +0,\"No error\" (processing time 0 ms).")
        self.emt.process_line("[2016-08-30 10:40:01.500] [DEBUG] [Rigol-M300] Response for SYSTEM:ERROR? for command FETCh?: +0,\"No error\" (processing time 0 ms).")
        self.emt.process_line("[2016-08-30 10:41:30.000] [DEBUG] [Rigol-M300] WRITING COMMAND: 'CONFigure:BLAARG AUTO,DEF,(@318)' (delay was 1211 ms, slept 0 ms).")
        self.assertEqual(1.5, self.emt.get_data()["AC"][0])

    def test_sums_total_sleep_time(self):
        self.emt.process_line("(slept 100 ms).")
        self.do_measurement("FREQUENCY", 90.0)
        self.emt.process_line("(slept 500 ms).")
        self.do_measurement("FREQUENCY", 90.0)

        self.assertEqual(0.600, self.emt.total_sleep)

if __name__ == '__main__':
    unittest.main()


#Plate Reader Tools

import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt
import string
from itertools import chain

# 4/14/2021:  Began replacing panel with dict of dataframes.
#
# C:\Users\BMH_work\Anaconda3\lib\site-packages\ipykernel_launcher.py:1: FutureWarning:
# Panel is deprecated and will be removed in a future version.
# The recommended way to represent these types of 3-dimensional data are with a MultiIndex on a DataFrame, via the Panel.to_frame() method
# Alternatively, you can use the xarray package http://xarray.pydata.org/en/stable/.
# Pandas provides a `.to_xarray()` method to help automate this conversion.

def readplate(fname,sheetname,skiprows_excel,datalabels,cycles,horz):
        #output is d, a dictionary keyed on datalabels that includes dataframes for each datalabel.
    #the dataframe index is time in hours and the columns are wells.

    wholetc = pd.read_excel(fname,sheet_name=sheetname,skiprows=skiprows_excel, nrows = cycles)

    #Determine how the excel sheet is formatted: if horz == 1 then the cycle numbers run horizontally, otherwise if horz == 0 then the cycle numbers run vertically

    # col_labels = []
    # for i in range(rows):
    #     for j in range(columns):
    #         col_labels.append(chr(i + ord('A')) + str(j+1))

    # #generate the empty array
    # data = pd.DataFrame(columns = col_labels)

    # #populate a panel with empty dataframes
    # d = pd.Panel({datalabels[0]:data})
    # for i in range(len(datalabels[1:])):
    #     d[datalabels[i+1]] = data

    # cycleindex = 0
    # dataindex = 0

    #d[datalabels[dataindex]].set_value(cycleindex,col_labels,wholetc[col_labels].iloc[i])
    d = {}
    time_label = 'Time [s]'
    #Check for case #1
    if horz == 0:
        t = wholetc[time_label].iloc[0:cycles].values/float(3600)

        well_labels = wholetc.columns[3:]  # assumes data labels start at the 4th column and continue to the end.
        if len(datalabels)==1:
            cycle_df = wholetc.loc[:,well_labels]
            cycle_df['Time [h]'] = t
            cycle_df.set_index('Time [h]', inplace=True)
            d[datalabels[0]] = cycle_df
        else:
            raise ValueError('need to adapt code for plates with more than one output')

    #     for i in range(len(wholetc.iloc[:,0])):
    #         try:
    #             num = int(wholetc.iloc[i,0])
    #             if num < cycles:
    #                 d[datalabels[dataindex]].loc[cycleindex] = wholetc[col_labels].iloc[i]
    #                 cycleindex = cycleindex + 1
    #             elif num == cycles:
    #                 d[datalabels[dataindex]].loc[cycleindex] = wholetc[col_labels].iloc[i]
    #                 cycleindex = 0
    #                 dataindex = dataindex + 1
    #         except ValueError:
    #             continue

    #Check for case #2
    elif horz==1:

        print('table oriented vertically - need to adapt code to not use panels.')
    #     t = wholetc.iloc[0,1:cycles+1].values/float(3600)
    #     for i in range(len(wholetc.iloc[:,0])):
    #         if (wholetc.iloc[i,0] in col_labels and wholetc.iloc[i,0] != 'H12'):
    #             d[datalabels[dataindex]][col_labels[c]] = (wholetc.iloc[i,1:cycles+1])
    #             cycleindex = cycleindex + 1
    #         elif wholetc.iloc[i,0] == 'H12':
    #             d[datalabels[dataindex]][col_labels[c]] = (wholetc.iloc[i,1:cycles+1])
    #             cycleindex = 0
    #             dataindex = dataindex + 1
    #         else:
    #             continue

    #use .any to report when "OVER" is present
    #replace "OVER" with np.nan .replace
    return d

def readplate_mult_loc(plate_fname, well_arr, final_time_point):
    #Read in multiple location file

    plate_dict = {}

    current_well = 'None'

    well_arr_flat = well_arr.flatten()

    with open(plate_fname) as f:
        cont_loop = True
        while cont_loop:
            line = next(f, 'stop')
            linesp = line.split(',')
            line_start = linesp[0]
            if line_start in well_arr_flat: # Find lines that start with Well Name
                #Build table from rows below that

                if not(line_start == current_well): #Save old set of tables and start new table
                    if not(current_well=='None'):
                        #combine tables
                            clean_tabs = []
                            for table in tables:
                                clean_tab = table
                                clean_tab = clean_tab.drop(0)
                                clean_tab = clean_tab.drop(len(clean_tab))
                                clean_tab = clean_tab.set_index(current_well)
                                clean_tabs.append(clean_tab)
                            clean_tabs_concat = pd.concat(clean_tabs)
                            clean_tabs_concat = clean_tabs_concat.loc[[str(item) for item in range(1,final_time_point + 1)],:] #Subset to final time point
                            #clean_tabs_concat.astype(float)

                            for col in clean_tabs_concat:
                                clean_tabs_concat[col] = pd.to_numeric(clean_tabs_concat[col])
                            plate_dict[current_well] = clean_tabs_concat

                    tables=[]
                    current_well=line_start

                table = {line_start:linesp}
                while not(line_start==''):
                    line = next(f, 'stop')
                    linesp = line.split(',')
                    line_start = linesp[0]
                    table[line_start] = linesp

                tables.append(pd.DataFrame(table))

            if line=='stop':
                cont_loop=False

    #Make Last table
    clean_tabs = []
    for table in tables:
        clean_tab = table
        clean_tab = clean_tab.drop(0)
        clean_tab = clean_tab.drop(len(clean_tab))
        clean_tab = clean_tab.set_index(current_well)
        clean_tabs.append(clean_tab)
    clean_tabs_concat = pd.concat(clean_tabs)
    clean_tabs_concat = clean_tabs_concat.loc[[str(item) for item in range(1,final_time_point + 1)],:] #Subset to final time point
    #clean_tabs_concat.astype(float)

    for col in clean_tabs_concat:
        clean_tabs_concat[col] = pd.to_numeric(clean_tabs_concat[col])

    plate_dict[current_well] = clean_tabs_concat

    return(plate_dict)

def computegrowthrate(OD,t):
    #Calculate the growth rate in doublings per hour

    #One step
    onestep = pd.DataFrame(index = OD.index[0:-1], columns = OD.columns)
    for idx, index in enumerate(OD.index[0:-1]):
        ODdiff = (OD.iloc[idx+1,:]-OD.iloc[idx,:])
        tdiff = t[idx+1]-t[idx]
        onestep.set_value(index, OD.columns, ODdiff/tdiff)

    #Two step
    twostep = pd.DataFrame(index = OD.index[0:-2], columns = OD.columns)
    for idx, index in enumerate(OD.index[0:-2]):
        ODdiff = (OD.iloc[idx+2,:]-OD.iloc[idx,:])
        tdiff = t[idx+2]-t[idx]
        twostep.set_value(index, OD.columns, ODdiff/tdiff)

    #Find the max growth rate for each well

    maxind = twostep.idxmax()

    maxgrowth = twostep.max()

    maxOD = OD.max()

    return [twostep, maxind, maxgrowth, maxOD]

def exponentialvalues(maxind,vals):
    idx = [string.uppercase[i] for i in range(8)]
    x = range(12)
    cols = [col+1 for col in x]

    plate = pd.DataFrame(index = idx, columns = cols)

    for i in idx:
        for j in cols:
            index = i + str(j)
            if math.isnan(maxind[index]):
                plate.set_value(i,j,np.nan)
            else:
                plate.set_value(i,j,np.nanmean([vals.loc[int(maxind[index])-1,index],vals.loc[int(maxind[index]),index],vals.loc[int(maxind[index])+1,index]]))
    return plate

def tptoplate(cycle,df):
    #takes a cycle number (or an array of cycle numbers) and generates a 96 well plate formatted array from the data
    idx = [string.uppercase[i] for i in range(8)]
    x = range(12)
    cols = [col+1 for col in x]

    plate = pd.DataFrame(index = idx, columns = cols)

    if type(cycle) == int:
        for i in idx:
            for j in cols:
                index = i + str(j)
                plate.set_value(i,j,df.loc[cycle-1,index])
    else:
        for i in idx:
            for j in cols:
                index = i + str(j)
                plate.set_value(i,j,df.loc[cycle[i*12+j]-1,index])

    return plate

def subplot_array(input_data, well_arr, time_list,axis_arr = [], figsize=(15,10)):
    #input_data is a pandas dataframe with wells for columns and with each row as a time point.
    #The data does not have to have the actual times as the index .
    #
    #well_arr is an NP array with the names of the wells (e.g. 'A1') in the location in which
    #you want to plot the data.
    #
    #time_list is an np array with each entry as a time point in whatever units you use.
    #readplate returns time in units of hours.
    #
    #axis_arr allows you to pass an array of axes to the function and use that.
    nrows = int(well_arr.shape[0])
    ncols = int(well_arr.shape[1])
    fig, axarr = plt.subplots(nrows,ncols, sharex=True, sharey=True, figsize=figsize)

    #axarr[0, 0].plot(x, y)
    for jj in range(nrows):
        for kk in range(ncols):
            yy = input_data.loc[:,well_arr[jj,kk]]
            axarr[jj, kk].plot(time_list, yy)
            axarr[jj, kk].set_title(well_arr[jj,kk])
            if axis_arr != []:
                axarr[jj, kk].axis(axis_vec)

    return fig

def subplot_array_single(plate_data, letter_range = ['A','B','C','D','E','F','G','H'], number_range = range(1,13), col_to_plot='Mean'):
    #plate_data is a pandas dataframe with wells as the index and columns of data.
    #
    #letter_range is list of the rows on the plate you want to plot (default is all rows)
    #number range is a range of column numbers you want to plot (default is all columns)
    #
    #time_list is an np array with each entry as a time point in whatever units you use.
    #readplate returns time in units of hours.
    #

    well_arr = well_array_builder(letter_range,number_range)

    plate_dict = dict(plate_data[col_to_plot])
    plate_vals = np.vectorize(plate_dict.get)(well_arr)

    fig, ax = plt.subplots()
    im = ax.imshow(plate_vals)

    # Show all ticks and label them with the respective list entries
    ax.set_yticks(range(0, len(letter_range)))
    ax.set_yticklabels(letter_range)
    ax.set_xticks(range(0, len(number_range)))
    ax.set_xticklabels(number_range)

    # Loop over data dimensions and create text annotations.
    for i in range(len(letter_range)):
        for j in range(len(number_range)):
            text = ax.text(j, i, "{0:0.2f}".format(plate_vals[i, j]),
                           ha="center", va="center", color="w")

    ax.set_title("Plate Layout " + col_to_plot)
    fig.tight_layout()

    return fig

def subplot_array_mult_loc(plate_dict, well_arr, time_list,axis_arr = [], figsize=(15,10), col_to_plot='Mean'):
    #Plots an array of growh curves for each well for a file in which multiple locations were measured.

    #input_data is a pandas dataframe with wells for columns and with each row as a time point.
    #The data does not have to have the actual times as the index .
    #
    #well_arr is an NP array with the names of the wells (e.g. 'A1') in the location in which
    #you want to plot the data.
    #
    #time_list is an np array with each entry as a time point in whatever units you use.
    #readplate returns time in units of hours.
    #
    #axis_arr allows you to pass an array of axes to the function and use that.
    nrows = int(well_arr.shape[0])
    ncols = int(well_arr.shape[1])
    fig, axarr = plt.subplots(nrows,ncols, sharex=True, sharey=True, figsize=figsize)

    #axarr[0, 0].plot(x, y)
    for jj in range(nrows):
        for kk in range(ncols):
            yy = plate_dict[well_arr[jj,kk]][col_to_plot].astype(float)
            axarr[jj, kk].plot(time_list, yy)
            axarr[jj, kk].set_title(well_arr[jj,kk])
            if axis_arr != []:
                axarr[jj, kk].axis(axis_vec)

    return fig

def well_array_builder(letter_range,number_range):
    #letter_range is a list of letters that you want to be part of the array
    # e.g. ['A','B','C'].  They will appear as rows.
    #number_range is a list of number taht you want to be part of the array
    #not necessarily consecutive: ['1','4','3'].  They will appear as columns.
    wells = []
    for jj in range(len(letter_range)):
        well_cols = []
        for kk in range(len(number_range)):
            well_cols.append(letter_range[jj]+str(number_range[kk]))
        wells.append(well_cols)
    well_arr = np.array(wells)

    return well_arr

def over_filter(input_dataframe):
    #input is the dataframe you want to filter OVER values out of.
    #note: it is not the panel of dataframes.
    OVER_list = [index for (index, value) in input_dataframe.isin(['OVER']).any().iteritems() if value]
    if len(OVER_list)==0:
        print('No OVER values in data')
        data_filtered = input_dataframe
    else:
        print('OVER value found in well(s): \n' + '\n'.join(OVER_list))
        data_filtered = input_dataframe.replace('OVER',np.nan)
    return data_filtered, OVER_list

def view_or_input_exp_design(data_index):
    view_or_input = input("print out list (1) or add wells one by one (2)")

    if view_or_input =="1":
        print(data_index)
#         for jj in range(0,len(data_index.labels[0])):
#             levels = data_index.levels
#             labels = data_index.labels
#             condition_description = []
#             for kk in range(0,len(labels)):
#                 condition_description.append(levels[kk][labels[kk][jj]])
#             print(condition_description)
        return
    elif view_or_input == "2":
        class BreakIt(Exception): pass

        try:
            well_list = []
            for jj in range(0,len(data_index.labels[0])):
                input_accepted = "0"
                while input_accepted=="0":
                    levels = data_index.levels
                    labels = data_index.labels
                    condition_description = []
                    for kk in range(0,len(labels)):
                        condition_description.append(levels[kk][labels[kk][jj]])
                    new_well = input("input well for " + str(condition_description) + " : ")
                    input_accepted = input("correct well: " + new_well + "? 1=Yes, 0 = No, exit = break loop")
                    if input_accepted =="exit":
                        print("exiting loop")
                        raise BreakIt
                well_list.append(new_well)
                print(well_list)
        except BreakIt:
            pass
        return well_list
    else:
        print("Didn't pick 1 or 2")

def delete_multiindex_for_missing_conditions(missing_combos, data_index):

    #This should be replaced with something like this:

    # data_index_df = data_index.to_frame()
    # data_index_df.drop(('WT','0.5x','TR1'), inplace=True)
    # data_index_df.drop(('WT','1x','TR2'), inplace=True)

    # #data_index_adjusted, inds_to_remove = plate_reader_tools.delete_multiindex_for_missing_conditions(missing_items, data_index)

    # data_index_adjusted = pd.MultiIndex.from_frame(data_index_df)

    #gives a new multiindex from a full multiindex with specified missing conditions.
    #missing items is a list of tuples.  The tuples are of the form:
    #(Level1,Item missing from level 1, Level2, Item missing from level 2, Level 3, Item missing from level 3, ...)
    #for instance if strain ABC is missing technical replicate 3, you would put:
    #("strain", "ABC", "tech_rep", "TR3")

    inds_to_remove = []
    for missing_combo in missing_combos:
        layers_involved = [missing_combo[jj] for jj in 2*np.array(range(int(len(missing_combo)/2)))]
        layers_involved_inds = []
        for layer in layers_involved:
            layers_involved_inds.append([i for i,name in enumerate(data_index.names) if name == layer][0])
        missing_layers = [missing_combo[jj] for jj in 2*np.array(range(int(len(missing_combo)/2)))+1]
        missing_layers_inds = []
        for jj,layer in enumerate(missing_layers):
            missing_layers_inds.append([i for i,name in enumerate(data_index.levels[layers_involved_inds[jj]]) if name == layer][0])

        combined_labels = zip(*[data_index.labels[jj] for jj in layers_involved_inds])

        test_label = tuple(missing_layers_inds)
        inds_to_remove_for_missing_combo = []
        for ii,label in enumerate(combined_labels):
            if label==test_label:
                inds_to_remove_for_missing_combo.append(ii)

        inds_to_remove_for_missing_combo
        inds_to_remove.append(inds_to_remove_for_missing_combo)

    #flatten out list of indices and remove duplicates.
    inds_to_remove = list(set(chain.from_iterable(inds_to_remove)))

    new_labels =  [(np.delete(label_level,inds_to_remove)) for label_level in data_index.labels]
    data_index_adjusted = pd.MultiIndex(levels = data_index.levels, labels = new_labels , names = data_index.names)

    return data_index_adjusted, inds_to_remove

def get_slope(series):
    #returns the slope of a line when the x axis is the indices of a series and the
    #y axis is the values.
    t = series.index
    lst_sqrs_mat = np.vstack([t, np.ones(len(t))]).T
    slope, intercept = np.linalg.lstsq(lst_sqrs_mat, series)[0]

    return slope


# set up dependencies
import datetime as dt
import numpy as np
import pandas as pd
import sqlalchemy
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine, func

from flask import Flask, jsonify

engine = create_engine("sqlite:///hawaii.sqlite",
                       connect_args={'check_same_thread': False})

# reflect an existing database into a new model
Base = automap_base()
# reflect the tables
Base.prepare(engine, reflect=True)

# Save references to each table
Measurement = Base.classes.measurement
Station = Base.classes.station

# Create our session (link) from Python to the DB
session = Session(engine)

app = Flask(__name__)

@app.route("/")
def welcome():
    return (
        f"Welcome to the Hawaii Climate Analysis App Homepage!
"
        f"Available Routes Below:
"
        f"Precipitation measurement over the last 12 months: /api/v1.0/precipitation
"
        f"A list of stations and their respective station numbers: /api/v1.0/stations
"
        f"Temperatures observations at the most active station over the previous 12 months: /api/v1.0/tobs
"
        f"Enter a start date (yyyy-mm-dd) to retrieve the minimum, maximum, and average temperatures for all dates after the specified date: /api/v1.0/<start>
"
        f"Enter both a start and end dates (yyyy-mm-dd) to retrieve the minimum, maximum and average temperatures for that date range: /api/v1.0/<start>/<end>"
    )

@app.route("/api/v1.0/precipitation")
def precipitation():

    # Query Measurement
    results = (session.query(Measurement.date, Measurement.tobs)
                      .order_by(Measurement.date))

    # Create a dictionary
    precipitation_date_tobs = []
    for each_row in results:
        dt_dict = {}
        dt_dict["date"] = each_row.date
        dt_dict["tobs"] = each_row.tobs
        precipitation_date_tobs.append(dt_dict)

    return jsonify(precipitation_date_tobs)

@app.route("/api/v1.0/stations")
def stations():

    # Query Measurement
    results = session.query(Station.name).all()

    # Convert list of tuples into normal list
    station_details = list(np.ravel(results))
    return jsonify(station_details)

@app.route("/api/v1.0/tobs")
def temp_monthly():
    # Calculate the date 1 year ago from last date in database
    prev_year = dt.date(2017, 8, 23) - dt.timedelta(days=365)

    # Query the primary station for all tobs from the last year
    results = session.query(Measurement.tobs).\
        filter(Measurement.station == 'USC00519281').\
        filter(Measurement.date >= prev_year).all()

    # Convert list of tuples into normal list
    temps_detail = list(np.ravel(results))

    return jsonify(temps_detail)

@app.route("/api/v1.0/<start>")
def start_only(start):

    # Query the max date
    date_max = session.query(Measurement.date).order_by(Measurement.date.desc()).first()
    date_max_str = str(date_max)
    date_max_str = re.sub("'|,", "",date_max_str)
    print (date_max_str)

    # Query the min date
    date_min = session.query(Measurement.date).first()
    date_min_str = str(date_min)
    date_min_str = re.sub("'|,", "",date_min_str)
    print (date_min_str)

    # Check for valid start date
    start_entry = session.query(exists().where(Measurement.date == start)).scalar()

    if start_entry:

        results = (session.query(func.min(Measurement.tobs)
                    ,func.avg(Measurement.tobs)
                    ,func.max(Measurement.tobs))
                   .filter(Measurement.date >= start).all())

        tmin =results[0][0]
        tavg ='{0:.2}'.format(results[0][1])
        tmax =results[0][2]

        result_temps =( ['Entered Start Date: ' + start,
                            'Lowest Temperature: '  + str(tmin),
                            'Average Temperature: ' + str(tavg),
                            'Highest Temperature: ' + str(tmax)])
        return jsonify(result_temps)

@app.route("/api/v1.0/<start>/<end>")
def start_end(start_entry, end_entry):

    # Query the max date
    date_max = session.query(Measurement.date).order_by(Measurement.date.desc()).first()
    date_max_str = str(date_max)
    date_max_str = re.sub("'|,", "",date_max_str)
    print (date_max_str)

    # Query the min date
    date_min = session.query(Measurement.date).first()
    date_min_str = str(date_min)
    date_min_str = re.sub("'|,", "",date_min_str)
    print (date_min_str)

     # Check for valid start date
    start_entry = session.query(exists().where(Measurement.date == start)).scalar()

     # Check for valid end date
    end_entry = session.query(exists().where(Measurement.date == end)).scalar()

    if start_entry and end_entry:

        results = (session.query(func.min(Measurement.tobs)
                    ,func.avg(Measurement.tobs)
                    ,func.max(Measurement.tobs))
                        .filter(Measurement.date >= start)
                        .filter(Measurement.date <= end).all())

        tmin =results[0][0]
        tavg ='{0:.2}'.format(results[0][1])
        tmax =results[0][2]

        result_temps=( ['Entered Start Date: ' + start,
                            'Entered End Date: ' + end,
                            'Lowest Temperature: '  + str(tmin),
                            'Average Temperature: ' + str(tavg),
                            'Highest Temperature: ' + str(tmax)])
        return jsonify(result_temps)

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


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

"""Gère le joueur"""

import pygame as pg
from copy import deepcopy

import save

class Player(pg.sprite.Sprite):
    """Représente le joueur"""

    TEXTURE_FILE_LOCATION = 'res/textures/m2.png'

    SPEED_NORMALISATION = 1/(2**0.5)
    SPRINT_WALK_SPEED_MULTIPLIER = 8 # Multiplicateur de vitesse en cas de sprint
    WALK_ANIMATION_COOLDOWN = 8 # Cooldown entre deux changements d'animations (en frames)
    SPRINT_ANIMATION_COOLDOWN = 3 # Cooldown entre deux changements d'animations (en frames)

    FEET_SIZE = 12 # Hauteur de la zone de collision (en pixels)

    ANIMATION_DICT = {
    "1,1" : "down-right",
    "1,0" : "right",
    "0,1" : "down",
    "1,-1" : "up-right",
    "0,-1" : "up",
    "-1,1" : "down-left",
    "-1,0" : "left",
    "-1,-1" : "up-left"}

    def __init__(self, game):
        super().__init__()
        self.game = game

        # Variables d'état
        self.is_animated = False        # Le sprite du joueur défile
        self.is_sprinting = False       # Le joueur sprinte
        self.can_move = True            # Le joueur est capable de bouger
        self.boop = False               # Le joueur est en collision

        # Chargement de la position dans la sauvegarde
        config = save.load_config("player")
        self.position = config["position"]
        self.base_walk_speed = config["speed"] #Vitesse du joueur sans multiplicateur (en pixel/frame)

        # Graphique
        self.drawing_layer = 1
        self.sprite_sheet = pg.image.load(self.TEXTURE_FILE_LOCATION)
        self.image = self.get_image(0, 0)  # en bas par défaut
        self.image.set_colorkey([0, 0, 0])  # transparence
        self.rect = self.image.get_rect()  # rectangle autour du joueur
        self.feet = pg.Rect(0, 0, self.rect.width * 0.5, self.FEET_SIZE)
        self.current_sprite = 0

        self.IMAGES = {
        'down': [self.get_image(0, 0), self.get_image(32, 0), self.get_image(64, 0)],
        'down-left': [self.get_image(0, 0), self.get_image(32, 0), self.get_image(64, 0)],
        'down-right': [self.get_image(0, 0), self.get_image(32, 0), self.get_image(64, 0)],
        'left': [self.get_image(0, 32), self.get_image(32, 32), self.get_image(64, 32)],
        'right': [self.get_image(0, 64), self.get_image(32, 64), self.get_image(64, 64)],
        'up': [self.get_image(0, 96), self.get_image(32, 96), self.get_image(64, 96)],
        'up-left': [self.get_image(0, 96), self.get_image(32, 96), self.get_image(64, 96)],
        'up-right': [self.get_image(0, 96), self.get_image(32, 96), self.get_image(64, 96)]
        }

    def save(self):
        """Sauvegarde lors de la fermeture du jeu"""
        save.save_config("player", map_id = self.game.map_manager.map_id, position = self.position, speed = self.base_walk_speed)

    def change_animation(self, direction):  # change l'image en fonction du sens 'sens'
        """Change l'image de l'animation du joueur"""
        animation = self.ANIMATION_DICT[str(direction[0])+","+str(direction[1])]
        self.image = self.IMAGES[animation][int(self.current_sprite)]
        self.image.set_colorkey([0, 0, 0])  # transparence

    def is_colliding(self):
        """Vérifie la collision avec un mur ou un portail"""
        # Collision avec un portail
        index = self.feet.collidelist(self.game.map_manager.portals)
        if index >= 0:   # Le joueur est dans un portail
            # On récupère l'endroit où téléporter le joueur
            [to_world, to_point] = self.game.game_data_db.execute("SELECT to_world, to_point FROM portals WHERE id = ?", (self.game.map_manager.portals_id[index],)).fetchall()[0]
            old_bgm = self.game.map_manager.sound_manager.music_file
            self.game.map_manager.load_map(to_world, old_bgm) # On charge la nouvelle carte
            self.game.map_manager.teleport_player(to_point)  # on téléporte le joueur à la destination
            return True
        else:
            # Collision avec les murs
            return True if self.feet.collidelist(self.game.map_manager.walls) > -1 else False

    def move(self, list_directions, sprinting):
        """Méthode de déplacement du joueur"""
        if list_directions.count(True) > 0: # Si au moins une touche de déplacement est préssée
            if self.can_move: # Le joueur n'est pas en dialogue
                self.boop = False # Le joueur a de nouveau bougé depuis la dernière collision
                speed_multiplier = self.SPRINT_WALK_SPEED_MULTIPLIER if sprinting else 1
                self.is_sprinting = True if sprinting else False

                # On calcule le déplacement potentiel en x et en y en fonction des touche préssées
                deplacement = [0, 0]
                if list_directions[0]: #Haut
                    deplacement[1] -= 1
                if list_directions[1]: #Droite
                    deplacement[0] += 1
                if list_directions[2]: #Bas
                    deplacement[1] += 1
                if list_directions[3]: #Gauche
                    deplacement[0] -= 1

                if deplacement[0] != 0 or deplacement[1] != 0: # Si le déplacement n'est pas nul

                    # Si le déplacement est non nul selon les deux coordonées, on se déplace en diagonale, il faut normaliser le vecteur déplacement
                    if deplacement[0] != 0 and deplacement[1] != 0:
                        speed_normalisation = self.SPEED_NORMALISATION
                    else:
                        speed_normalisation = 1

                    # On traite les deux coordonées x et y
                    for coord_id in [0, 1]:
                        # On déplace le sprite et on recalcule la position
                        self.position[coord_id] += deplacement[coord_id]*self.base_walk_speed*speed_multiplier*speed_normalisation
                        self.rect.topleft = self.position
                        self.feet.midbottom = self.rect.midbottom

                        # Si il y a collision, on annule le dernier déplacement
                        if self.is_colliding():
                            self.boop = True # Enregistrement de la collision
                            self.position[coord_id] -= deplacement[coord_id]*self.base_walk_speed*speed_multiplier*speed_normalisation
                            self.rect.topleft = self.position
                            self.feet.midbottom = self.rect.midbottom
                    else:
                        self.is_animated = True
                        self.change_animation(deplacement)
            else:
                self.is_animated = False

    def update(self):
        """Mise à jour graphique"""
        self.rect.topleft = self.position
        self.feet.midbottom = self.rect.midbottom

        # Recalcul de l'image à utiliser
        animation_cooldown = self.SPRINT_ANIMATION_COOLDOWN if self.is_sprinting else self.WALK_ANIMATION_COOLDOWN
        if self.is_animated == True:
            self.current_sprite = (int(self.game.tick_count/animation_cooldown) % 3)

    def get_image(self, x, y):
        """Retourne une partie de l'image du joueur"""
        image = pg.Surface([32, 32])
        image.blit(self.sprite_sheet, (0, 0), (x, y, 32, 32))
        return image


from statistics import mean, stdev
from enum import Enum
import numpy as np

class TableFormat(Enum):
    TEXTUAL = 1
    CSV = 2

    def format(self, table):
        if self == TableFormat.TEXTUAL:
            for col in range(len(table[0])):
                max_strlen = max(len(table[i][col]) for i in range(len(table)))
                for i in range(len(table)):
                    if col == 0:
                        table[i][col] = table[i][col].ljust(max_strlen, " ")
                    else:
                        table[i][col] = table[i][col].rjust(max_strlen, " ")
            return "\n".join("  ".join(row) for row in table)
        assert self == TableFormat.CSV
        return "\n".join(",".join(row) for row in table)

    def get_file_extension(self):
        if self == TableFormat.TEXTUAL:
            return 'txt'
        else:
            return 'csv'

def summary_datas_to_absolute_and_relative_means_and_stdevs(summary_datas):
    """
    Accepts multiple summary datas (one from each run of the same strategy),
    computes and returns strings describing the mean and standard variation of different properties,
    both absolute (i.e. 100 +- 20 infected) and relative (i.e. 30% +- 5% infected).
    In the case where there is only one summary data, does not
    compute standard deviation.
    :param summary_datas: A list of 'summary_data' dicts, one from each run
    :return: Two dicts from property names to "value"
    (string containing mean and standard variation).
    One for absolute amounts and another for relative amounts.
    """
    keys_to_data_arrays = {}
    for i, data in enumerate(summary_datas):
        assert len(data) == len(summary_datas[0])
        for key, val in data.items():
            if i == 0:
                keys_to_data_arrays[key] = []
            else:
                assert key in keys_to_data_arrays
            keys_to_data_arrays[key].append(val)
    absolute_data = {}
    relative_data = {}
    for key, absolute_array in keys_to_data_arrays.items():
        #relative_array = [x / y for (x, y) in zip(absolute_array, keys_to_data_arrays["Total people"])]
        relative_array = []
        for (x,y) in zip(absolute_array, keys_to_data_arrays["Total people"]):
            if y != 0:
                relative_array.append(x/y)
            else:
                relative_array.append(np.nan)

        if len(relative_array) == 1:
            absolute_data[key] = "{}".format(absolute_array[0])
            relative_data[key] = "{:3.3f}%".format(100 * relative_array[0])
        else:
            absolute_data[key] = "{m} ±{s:6.1f}".format(m=mean(absolute_array), s=stdev(absolute_array))
            relative_data[key] = "{m}% ±{s:3.3f}%".format(m=100 * mean(relative_array), s=100 * stdev(relative_array))
    return absolute_data, relative_data

def make_summary_by_age_table(age_group_to_summary_tables, table_format, is_relative=True):
    """
    :param age_group_to_summary_tables: A table from age_group to
    a list of 'summary_data's on that age group
    :return: A short readable text containing a table of
    age-stratified results (total deceased, total infected, ...)
    """
    assert isinstance(table_format, TableFormat)
    age_group_to_absolute_data = {}
    age_group_to_relative_data = {}
    for age_group, summary_datas in age_group_to_summary_tables.items():
        age_group_to_absolute_data[age_group], age_group_to_relative_data[age_group] = \
            summary_datas_to_absolute_and_relative_means_and_stdevs(summary_datas)
    age_groups = list(age_group_to_summary_tables.keys())
    table = []
    age_groups_text = ['Age group']
    for age_group in age_groups:
        if age_group is None:
            age_groups_text.append("Total")
        else:
            age_groups_text.append("{}-{}".format(*age_group))
    table.append(age_groups_text)
    keys = ["Total people"] + [key for key in age_group_to_relative_data[age_groups[0]] if key != "Total people"]
    for key in keys:
        curr = [key]
        for age_group in age_groups:
            if (key == "Total people") or not is_relative:
                curr.append(age_group_to_absolute_data[age_group][key])
            else:
                curr.append(age_group_to_relative_data[age_group][key])
        table.append(curr)
    return table_format.format(table)


import datetime

months = [
    "Январь",
    "Февраль",
    "Март",
    "Апрель",
    "Май",
    "Июнь",
    "Июль",
    "Август",
    "Сентябрь",
    "Октябрь",
    "Ноябрь",
    "Декабрь",
]

today = datetime.datetime.today()
today_month = months[today.month-1]
today_day = str(today.day)

after_21_days = datetime.date(today.year, today.month, today.day) + datetime.timedelta(days=21)
after_month = months[after_21_days.month-1]
after_day = str(after_21_days.day)


from django.contrib import admin
from .models import Order, OrderItem

# Register your models here.

class OrderItemAdmin(admin.TabularInline):
    """Admin settings for the OrderItem class"""

    model = OrderItem
    list_display = ("product", "order")
    list_display_link = ("product", "order")
    readonly_fields = ("item_total",)

class OrderAdmin(admin.ModelAdmin):
    """Admin settings for the Order class"""

    inlines = (OrderItemAdmin,)

    readonly_fields = (
        "delivery_costs",
        "sub_total",
        "grand_total",
        "created",
    )

    list_display = (
        "full_name",
        "created",
        "email",
        "postcode",
    )

    list_display_links = (
        "email",
        "created",
    )

    search_fields = (
        "full_name",
        "email",
        "postcode",
        "created",
    )

    ordering = ("-created",)

admin.site.register(Order, OrderAdmin)


#####################################################
# Comparison of AB Test and Conversion of Bidding Methods
#####################################################

import pandas as pd
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.stats import shapiro, levene, ttest_ind

pd.set_option('display.max_columns', None)
pd.set_option('display.expand_frame_repr', False)
pd.set_option('display.float_format', lambda x: '%.5f' % x)

dataframe_control = pd.read_excel("./Desktop/ab_testing.xlsx" , sheet_name="Control Group")
dataframe_test = pd.read_excel("./Desktop/ab_testing.xlsx" , sheet_name="Test Group")

df_control = dataframe_control.copy()
df_test = dataframe_test.copy()

def check_df(dataframe, head=5):
    '''
    It is the function that looks at the overall picture with the given dataframe

    Parameters
    ----------
    dataframe: dataframe

    head : function of dataframe

    Returns
    -------
    '''

    print("##################### Shape #####################")
    print(dataframe.shape)
    print("##################### Types #####################")
    print(dataframe.dtypes)
    print("##################### Head #####################")
    print(dataframe.head(head))
    print("##################### Tail #####################")
    print(dataframe.tail(head))
    print("##################### NA #####################")
    print(dataframe.isnull().sum())
    print("##################### Quantiles #####################")
    print(dataframe.describe([0, 0.05, 0.50, 0.95, 0.99, 1]).T)

# df_control['Purchase'].mean() # 550.8940587702316
# df_test['Purchase'].mean() # 582.1060966484677

df_ = pd.concat([df_control.add_suffix('_control'),df_test.add_suffix('_test')], axis=1)
df = df_.copy()

######################################################

# H0: M1=M2
# (There is no significant difference between M1 and M2.)

# H0: M1!=M2
# (There is a significant difference between M1 and M2.)

######################################################

######################################################
# Normal Distribution
######################################################

# The argument H0 has a normal distribution could not be rejected with 95% confidence p-value > 0.05

test_stat, pvalue = shapiro(df[['Purchase_test','Purchase_control']].dropna())
print('Test Stat = %.4f, p-value = %.4f' % (test_stat, pvalue))

######################################################

######################################################
# Variance Distributions
######################################################

# The H0 variance distributions are homogeneous argument could not be rejected with 95% confidence. p-value >0.05

test_stat, pvalue = levene(df['Purchase_test'],
                           df['Purchase_control'])
print('Test Stat = %.4f, p-value = %.4f' % (test_stat, pvalue))
######################################################

######################################################
# Two Sample T test
######################################################

test_stat, pvalue = ttest_ind(df['Purchase_test'],
                               df['Purchase_control'],
                              equal_var=True)
######################################################

######################################################
# SUMMARY

# Firstly, I used Shapiro wilks test for normality test, then I used Levene test for variance homogeneity.
# My assumption checks were met and I could not reject either hypothesis. That's why I used a two-sample t-test.


import numpy as np
import random
import torch
from torch.utils.data import DataLoader
from torch.utils.data.sampler import Sampler
from torchvision import transforms
from dataset import BasicDataset
from dataset_train import BasicDataset_train
import os

def load_data_cache2(img_dir_train, mask_dir_train, img_dir_test, mask_dir_test, sup_idx, k_spt,  batch_size):
    dataset_train = BasicDataset_train(img_dir_train, mask_dir_train)
    dataset_test = BasicDataset(img_dir_test, mask_dir_test)
    setsz = k_spt
    querysz = 1

    img_spts = torch.FloatTensor(batch_size, setsz, 3, 512, 512)
    mask_spts = torch.FloatTensor(batch_size, setsz, 1, 512, 512)
    img_qrys = torch.FloatTensor(batch_size, querysz, 3, 512, 512)
    mask_qrys = torch.FloatTensor(batch_size, querysz, 1, 512, 512)

    #if not os.path.exists('./test_idx'):
     #   os.mkdir('./test_idx')

    #txt1 = './test_idx/spt_ids.txt'
    #txt2 = './test_idx/qry_ids.txt'
    #f1 = open(txt1, 'w+')
    #f2 = open(txt2, 'w+')
    for i in range(batch_size):
        img_spt = torch.FloatTensor(setsz, 3, 512, 512)
        mask_spt = torch.FloatTensor(setsz, 1, 512, 512)
        img_qry = torch.FloatTensor(querysz, 3, 512, 512)
        mask_qry = torch.FloatTensor(querysz, 1, 512, 512)

        #selected_datas_idx = random.sample(range(len(dataset_test)), setsz+querysz)###测试

        #selected_datas_spt_idx = random.sample(range(len(dataset_train)), setsz)
        selected_datas_spt_idx = sup_idx[i,:]

        #print(selected_datas_spt_idx )
        selected_que_idx = range(len(dataset_test))
        #selected_datas_qry_idx = random.sample(range(len(dataset_test)), querysz)
        selected_datas_qry_idx = selected_que_idx[i*querysz:(i+1)*querysz]
        #print(selected_datas_qry_idx)

        #selected_datas_spt_idx = selected_datas_idx[:setsz]
        #selected_datas_qry_idx = selected_datas_idx[setsz:]
        # img_spt, mask_spt, img_qry, mask_qry = [], [], [], []
        # selected_datas_spt = np.random.choice(dataset, setsz, replace=True)
        # selected_datas_query = np.random.choice(dataset, querysz, replace=True)
        for j, data in enumerate(selected_datas_spt_idx):
            img_spt[j] = dataset_train[data]['image']##j是batch里面第几个，data是数据里面第几个
            mask_spt[j] = dataset_train[data]['mask']
            context1 = str(i) + '\t' + str(data) + '\n'
            #f1.write(context1)
        for m, data in enumerate(selected_datas_qry_idx):
            img_qry[m] = dataset_test[data]['image']
            mask_qry[m] = dataset_test[data]['mask']
            context2 = str(i) + '\t' + str(data) + '\n'
            #f2.write(context2)

        img_spts[i] = img_spt
        mask_spts[i] = mask_spt
        img_qrys[i] = img_qry
        mask_qrys[i] = mask_qry

    return img_spts, mask_spts, img_qrys, mask_qrys


import os
import tensorflow as tf
import numpy as np
from tensorflow import keras
# from skimage import io
from tensorflow.keras.preprocessing import image
# from keras.models import Sequential
# from tensorflow._api.v1.keras import layers

# Flask utils
from flask import Flask, redirect, url_for, request, render_template, jsonify
from werkzeug.utils import secure_filename
from gevent.pywsgi import WSGIServer
import pandas as pd
import pickle

import warnings
from sklearn.exceptions import InconsistentVersionWarning

warnings.filterwarnings("ignore", category=InconsistentVersionWarning)

app = Flask(__name__, static_folder=r"C:\Users\Deepak\Desktop\crop\static")

model2 = tf.keras.models.load_model("best_plant_model.h5")
data = pd.DataFrame(pd.read_csv("final.csv"))
model = pickle.load(open(r"model.pkl", "rb"))
crop = pd.read_csv(r"final_dataset.csv").copy()
area = pd.read_csv(r"final_data.csv")
commodity = pd.read_csv(r"commodities.csv")

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/predictor')
def predictor():
    season = crop['Season'].unique()
    return render_template('predictor.html', seasons=season)

@app.route('/market')
def market():
    state1 = sorted(area['State'].unique())
    # print(states)  # Add this line to print the states

    area["District"] = area["State"] + "_" + area["District"]
    district1 = sorted(area['District'].unique())
    # print(district1)
    # area['Market'] = area['District'] + "_" + area['Market']
    markets = sorted(area['Market'])
    commodities = commodity["Commodities"].unique()
    return render_template('market.html', states=state1, districts=district1, commodities=commodities, markets=markets)

@app.route('/commodities')
def commodities():
    state1 = sorted(area['State'].unique())

    crop["District"] = area["State"] + "_" + area["District"]
    district1 = sorted(area['District'].unique())

    return render_template('commodities.html', states=state1, district1=district1)

@app.route('/predict', methods=['POST'])
def predict():
    pH = float(request.form.get('ph'))
    rainfall = float(request.form.get('rainfall'))
    temperature = float(request.form.get('temperature'))
    nitrogen = int(request.form.get('nitrogen'))
    phosphorus = int(request.form.get('phosphorus'))
    potassium = int(request.form.get('potassium'))
    humidity = float(request.form.get('humidity'))
    output = model.predict([[nitrogen, phosphorus, potassium, temperature, humidity, pH, rainfall]]),

    return ("{} Crop can be Grown".format(str(output[0])))

def about_disease(filtered_df, column):
    cause_values = filtered_df[column]

    f = ""
    for cause in cause_values:
        f = f + cause + ", "  # Separate multiple causes with a comma
    return f.rstrip(", ")  # Remove trailing comma and spaces

def load_prep(img_path):
    img = tf.io.read_file(img_path)

    img = tf.image.decode_image(img)

    img = tf.image.resize(img, size=(224, 224))

    return img

def model_predict(img_path, model2):
    image = load_prep(img_path)
    preds = model2.predict(tf.expand_dims(image, axis=0))
    return preds

@app.route('/disease', methods=['GET'])
def disease():
    # Main page
    return render_template('disease.html')

@app.route('/disease_pred', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        # Get the file from post request
        f = request.files['file']

        # Save the file to ./uploads
        basepath = os.path.dirname(__file__)
        file_path = os.path.join(
            basepath, 'uploads', secure_filename(f.filename))
        f.save(file_path)

        # Make prediction
        preds = model_predict(file_path, model2)
        print(preds)

        # x = x.reshape([64, 64]);
        disease_class = ['Apple___Apple_scab',
                         'Apple___Black_rot',
                         'Apple___Cedar_apple_rust',
                         'Apple___healthy',
                         'Blueberry___healthy',
                         'Cherry_(including_sour)___Powdery_mildew',
                         'Cherry_(including_sour)___healthy',
                         'Corn_(maize)___Cercospora_leaf_spot Gray_leaf_spot',
                         'Corn_(maize)___Common_rust_',
                         'Corn_(maize)___Northern_Leaf_Blight',
                         'Corn_(maize)___healthy',
                         'Grape___Black_rot',
                         'Grape___Esca_(Black_Measles)',
                         'Grape___Leaf_blight_(Isariopsis_Leaf_Spot)',
                         'Grape___healthy',
                         'Orange___Haunglongbing_(Citrus_greening)',
                         'Peach___Bacterial_spot',
                         'Peach___healthy',
                         'Pepper,_bell___Bacterial_spot',
                         'Pepper,_bell___healthy',
                         'Potato___Early_blight',
                         'Potato___Late_blight',
                         'Potato___healthy',
                         'Raspberry___healthy',
                         'Soybean___healthy',
                         'Squash___Powdery_mildew',
                         'Strawberry___Leaf_scorch',
                         'Strawberry___healthy',
                         'Tomato___Bacterial_spot',
                         'Tomato___Early_blight',
                         'Tomato___Late_blight',
                         'Tomato___Leaf_Mold',
                         'Tomato___Septoria_leaf_spot',
                         'Tomato___Spider_mites Two-spotted_spider_mite',
                         'Tomato___Target_Spot',
                         'Tomato___Tomato_Yellow_Leaf_Curl_Virus',
                         'Tomato___Tomato_mosaic_virus',
                         'Tomato___healthy']

        result = disease_class[preds.argmax()]

        filtered_df = data[data['Type'] == result]

        symptoms = about_disease(filtered_df, 'Symptoms')
        cause = about_disease(filtered_df, 'Cause')
        prevention = about_disease(filtered_df, 'Prevention')

        response = {
            'disease': result,
            'cause': cause,
            'symptoms': symptoms,
            'prevention': prevention
        }

        return jsonify(response)

if __name__ == '__main__':
    app.run();


# coding: utf-8

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import os
import io
import ConfigParser
from StringIO import StringIO

class Item(tuple):
  def __new__(cls, name, value, source):
    result = super(Item, cls).__new__(cls, (name, value))
    result.source = source
    return result

class DiffForUnknownOptionError(ConfigParser.Error):
  def __init__(self, option, section):
    ConfigParser.Error.__init__(self, 'Failed to apply diff for unknown option '
                                      '%r in section %r' % (option, section))
    self.option = option
    self.section = section
    self.args = (option, section)

class ChainedConfigParser(ConfigParser.SafeConfigParser):
  '''
    This class provides essentially the same interfaces as SafeConfigParser but
    allows chaining configuration files so that one config file provides the
    default values for the other. To specify the config file to inherit from
    a config file needs to contain the following option:

    [default]
    inherit = foo/bar.config

    It is also possible to add values to or remove values from
    whitespace-separated lists given by an inherited option:

    [section]
    opt1 += foo
    opt2 -= bar

    The value of the inherit option has to be a relative path with forward
    slashes as delimiters. Up to 5 configuration files can be chained this way,
    longer chains are disallowed to deal with circular references.

    As opposed to SafeConfigParser, files are decoded as UTF-8 while
    reading. Also, ChainedConfigParser data is read-only. An additional
    option_source(section, option) method is provided to get the path
    of the configuration file defining this option (for relative paths).
    Items returned by the items() function also have a source attribute
    serving the same purpose.
  '''

  def __init__(self):
    ConfigParser.SafeConfigParser.__init__(self)
    self._origin = {}

  def _make_parser(self, filename):
    parser = ConfigParser.SafeConfigParser()
    parser.optionxform = lambda option: option

    with io.open(filename, encoding='utf-8') as file:
      parser.readfp(file, filename)

    return parser

  def _get_parser_chain(self, parser, filename):
    parsers = [(parser, filename)]

    try:
      inherit = parser.get('default', 'inherit')
    except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
      return parsers

    dirname = os.path.dirname(filename)
    for parent in inherit.split():
      parent_filename = os.path.join(dirname, *parent.split('/'))
      parent_parser = self._make_parser(parent_filename)
      parsers[:0] = self._get_parser_chain(parent_parser, parent_filename)

    return parsers

  def _apply_diff(self, section, option, value):
    is_addition = option.endswith('+')
    is_diff = is_addition or option.endswith('-')

    if is_diff:
      option = option[:-1].rstrip()
      try:
        orig_value = self.get(section, option)
      except ConfigParser.NoOptionError:
        raise DiffForUnknownOptionError(option, section)

      orig_values = orig_value.split()
      diff_values = value.split()

      if is_addition:
        new_values = orig_values + [v for v in diff_values if v not in orig_values]
      else:
        new_values = [v for v in orig_values if v not in diff_values]

      value = ' '.join(new_values)

    return is_diff, option, value

  def _process_parsers(self, parsers):
    for parser, filename in parsers:
      for section in parser.sections():
        if not self.has_section(section):
          try:
            ConfigParser.SafeConfigParser.add_section(self, section)
          except ValueError:
            # add_section() hardcodes 'default' and raises a ValueError if
            # you try to add a section called like that (case insensitive).
            # This bug has been fixed in Python 3.
            ConfigParser.SafeConfigParser.readfp(self, StringIO('[%s]' % section))

        for option, value in parser.items(section):
          is_diff, option, value = self._apply_diff(section, option, value)
          ConfigParser.SafeConfigParser.set(self, section, option, value)

          if not is_diff:
            self._origin[(section, self.optionxform(option))] = filename

  def read(self, filenames):
    if isinstance(filenames, basestring):
      filenames = [filenames]

    read_ok = []
    for filename in filenames:
      try:
        parser = self._make_parser(filename)
      except IOError:
        continue
      self._process_parsers(self._get_parser_chain(parser, filename))
      read_ok.append(filename)

    return read_ok

  def items(self, section, *args, **kwargs):
    items = []
    for option, value in ConfigParser.SafeConfigParser.items(self, section, *args, **kwargs):
      items.append(Item(
        option, value,
        self._origin[(section, self.optionxform(option))]
      ))
    return items

  def option_source(self, section, option):
    option = self.optionxform(option)
    try:
      return self._origin[(section, option)]
    except KeyError:
      if not self.has_section(section):
        raise ConfigParser.NoSectionError(section)
      raise ConfigParser.NoOptionError(option, section)

  def readfp(self, fp, filename=None):
    raise NotImplementedError

  def set(self, section, option, value=None):
    raise NotImplementedError

  def add_section(self, section):
    raise NotImplementedError

  def remove_option(self, section, option):
    raise NotImplementedError

  def remove_section(self, section):
    raise NotImplementedError


#%%
import typing
import numpy as np
from collections import namedtuple
import matplotlib.pyplot as plt
from pxr import Usd, UsdGeom, Gf, Vt

class SPHGeom:
    def __init__(self):
        self.sources = None
        self.boundaries = None
        self.sinks = None

class CubeGeom(SPHGeom):

    def __init__(self, x_lim=2*np.pi, y_lim=2*np.pi, z_lim=2*np.pi, halfres=None):
        super().__init__()
        self.x_lim = x_lim
        self.y_lim = y_lim
        self.z_lim = z_lim

        if halfres is not None:
            self.init_meshgrid(halfres)

    def init_meshgrid(self, halfres):
        """
        produces grid of 2^halfres x 2^halfres x 2^halfres number of particles
        """
        x_ = np.linspace((self.x_lim/(2**halfres)), self.x_lim, 2**halfres, endpoint=True)
        y_ = np.linspace((self.y_lim/(2**halfres)), self.y_lim, 2**halfres, endpoint=True)
        z_ = np.linspace((self.y_lim/(2**halfres)), self.z_lim, 2**halfres, endpoint=True)

        meshgrid = np.meshgrid(x_, y_, z_, indexing='ij')

        self.meshgrid = np.array(meshgrid).T.reshape(-1,3)
        self.N = self.meshgrid.shape[0]

        return self.meshgrid

MeshPoints = namedtuple('MeshPoints', ['counts', 'faces', 'points', 'normals'])

def transform_coords_xform(prim: Usd.Prim, points:Vt.Vec3fArray, normals:Vt.Vec3fArray) -> typing.Tuple[np.ndarray, np.ndarray]:
    world_transform = get_world_transform_xform(prim)
    newpoints = [world_transform.Transform(points[i]) for i in range(points.__len__())]
    newnormals = [world_transform.TransformDir(normals[i]) for i in range(normals.__len__())]
    return np.array(newpoints), np.array(newnormals)

def get_world_transform_xform(prim: Usd.Prim) -> Gf.Matrix4d:
    """
    Get the world transformation of a prim using Xformable.
    See https://graphics.pixar.com/usd/release/api/class_usd_geom_xformable.html
    or https://docs.omniverse.nvidia.com/prod_usd/prod_kit/programmer_ref/usd/transforms/get-world-transforms.html
    Args:
        prim: The prim to calculate the world transformation.
    Returns:
        The global transformation as a Matrix4d
    """
    xform = UsdGeom.Xformable(prim)
    time = Usd.TimeCode.Default() # The time at which we compute the bounding box
    world_transform: Gf.Matrix4d = xform.ComputeLocalToWorldTransform(time)
    return world_transform

def get_local_transform_xform(prim: Usd.Prim) -> Gf.Matrix4d:
    """
    Get the local transformation of a prim using Xformable.
    See https://graphics.pixar.com/usd/release/api/class_usd_geom_xformable.html
    Args:
        prim: The prim to calculate the local transformation.
    Returns:
        The local tranformation of that matrix as a Mtrix4d
    """
    xform = UsdGeom.Xformable(prim)
    local_transformation: Gf.Matrix4d = xform.GetLocalTransformation()
    return local_transformation

class USDAGeom(SPHGeom):
    def __init__(self, filename):
        super().__init__()
        self.filename = filename
        self.stage = Usd.Stage.Open(self.filename)
        self.boundaries = self.get_children_meshpoints('/Boundaries')
        self.sources = self.get_children_meshpoints('/Sources')

    def get_children_meshpoints(self, primname: str) -> typing.List[MeshPoints]:
        root = self.stage.GetPrimAtPath(primname)
        children: Usd.Prim = root.GetChildren()
        children_mesh = [child.GetChildren()[0] for child in children if child.GetChildren()[0].IsA(UsdGeom.Mesh)]

        mespoints_list = []
        for child in children_mesh:
            # print(bd.GetPath())
            counts = np.array(child.GetAttribute('faceVertexCounts').Get())
            faces = np.array(child.GetAttribute('faceVertexIndices').Get())
            points = child.GetAttribute('points').Get()
            normals = child.GetAttribute('normals').Get()

            newpoints, newnormals = transform_coords_xform(child, points, normals)
            meshpoints = MeshPoints(counts, faces, newpoints, newnormals)
            mespoints_list.append(meshpoints)

        return mespoints_list

    def visualize(self, how="mpl"):
        """
        visualize the geometry in usdview if available, otherwise use matplotlib
        """
        exit_status = 0

        if how=="usdview":
            import os
            print("Running comand: 'usdview' "+self.filename)
            exit_status = os.system("usdview "+self.filename)

        if how=="matplotlib" or exit_status != 0:
            print("usdview not available, using matplotlib")
            fig = plt.figure()
            ax = fig.add_subplot(projection='3d')

            for meshpoints in self.boundaries + self.sources:
                points = np.array([meshpoints.points[i] for i in meshpoints.faces])
                normals = meshpoints.normals

                ax.scatter(points[:,0], points[:,1], points[:,2], marker='o', label="points", color='r')

                q = ax.quiver(points[:,0], points[:,1], points[:,2], normals[:,0], normals[:,1], normals[:,2], label="normals", normalize=True, alpha=0.5, length=0.05)

            ax.set_xlabel('X')
            ax.set_ylabel('Y')
            ax.set_zlabel('Z')
            # plt.legend()
            # plt.show()
            return ax

if __name__=="__main__":
    geometry = USDAGeom("../demos/data/meshes/glass.usda")
    geometry.visualize()