from json import loads
from os import getenv
from urllib import request as url_request, parse
from urllib.error import HTTPError

from sqlalchemy import desc

from app import session

from ..models.game import Game as GameModel
from ..models.game_player import GamePlayer as GamePlayerModel
from ..models.game_team_info import GameTeamInfo as GameTeamInfoModel
from ..models.solo_most_champion import SoloMostChampion as SoloMostChampionModel
from ..models.flex_most_champion import FlexMostChampion as FlexMostChampionModel
from .player import PlayerController
from .item import ItemController

from ..util.single_ton import Singleton

from ..util import response, riot_url, version as version_util
from re import compile, sub

from ..util.constants import *
from ..exception.data_not_found import DataNotFound
from ..exception.forbidden import Forbidden
from ..exception.internal_server_error import InternalServerError

from datetime import datetime, timedelta

class GameController(metaclass=Singleton):
    @staticmethod
    def insert_game(puuid, page, count, queue, current_timestamp):
        try:
            url = riot_url.matches_url(puuid, (page * count), count, queue)
            headers = {
                getenv('RIOT_HEADER_KEY'): getenv('RIOT_API_KEY')
            }
            req = url_request.Request(url, None, headers)

            with url_request.urlopen(req) as res:
                match_data = loads(res.read().decode())

            games = []
            game_players = []
            game_team_info = []

            for game_id in match_data:
                duplicated_game = [x.serialize for x in session.query(GameModel).filter_by(game_id=game_id)]

                if duplicated_game:
                    continue

                url = riot_url.matches_info_url(game_id)
                req = url_request.Request(url, None, headers)

                try:
                    with url_request.urlopen(req) as res:
                        game = loads(res.read().decode())

                        # 밀리초 제거
                        game_end_timestamp = str(game['info']['gameEndTimestamp'])[:-3]
                        played_time = datetime.fromtimestamp(int(game_end_timestamp))

                        # 게임 전적이 3달전이라면
                        if not played_time > current_timestamp:
                            break

                        games.append(GameModel(
                            game_id=game_id,
                            queue_id=game['info']['queueId'],
                            puuid=puuid,
                            game_duration=game['info']['gameDuration'],
                            team_win=100 if game['info']['teams'][0]['win'] else 200,
                            played_time=played_time,
                            # created_time=datetime.fromtimestamp(str(game['info']['gameCreation'])[:-3])
                        ))

                        blue_total_gold = 0
                        red_total_gold = 0

                        blue_champion_deaths = 0
                        red_champion_deaths = 0

                        blue_champion_assists = 0
                        red_champion_assists = 0

                        control_wards_placed = 0

                        for game_info in game['info']['participants']:
                            if game_info['pentaKills'] > 0:
                                kill_type = '펜타킬'
                            elif game_info['quadraKills'] > 0:
                                kill_type = '쿼드라킬'
                            elif game_info['tripleKills'] > 0:
                                kill_type = '트리플킬'
                            elif game_info['doubleKills'] > 0:
                                kill_type = '더블킬'
                            else:
                                kill_type = ''

                            if game_info['teamId'] == 100:
                                blue_total_gold += int(game_info['goldEarned'])
                                blue_champion_assists += game_info['assists']
                                blue_champion_deaths += game_info['deaths']
                            else:
                                red_total_gold += int(game_info['goldEarned'])
                                red_champion_assists += game_info['assists']
                                red_champion_deaths += game_info['deaths']

                            if 'challenges' in game_info:
                                kda = game_info['challenges']['kda']
                                control_wards_placed = game_info['challenges']['controlWardsPlaced']
                            else:
                                # -1은 Perfect 게임
                                # URF 같은 특수모드는 kda를 주지 않음 (0으로 나눌 시 ZeroDivision Error 발생)
                                if game_info['deaths'] == 0:
                                    kda = -1
                                else:
                                    kda = (game_info['kills'] + game_info['assists']) / game_info['deaths']

                            game_players.append(GamePlayerModel(
                                game_id=game_id,
                                team_id=game_info['teamId'],
                                puuid=puuid,
                                summoner_id=game_info['summonerId'],
                                summoner_name=game_info['summonerName'],
                                champion_id=game_info['championId'],
                                champion_level=game_info['champLevel'],
                                item0_id=game_info['item0'],
                                item1_id=game_info['item1'],
                                item2_id=game_info['item2'],
                                item3_id=game_info['item3'],
                                item4_id=game_info['item4'],
                                item5_id=game_info['item5'],
                                item6_id=game_info['item6'],
                                primary_rune_build='dummy1',
                                sub_rune_build='dummy2',
                                stat='dummy',
                                skill_build='dummy4',
                                team_position=game_info['teamPosition'],
                                # kda=kda,
                                first_blood=game_info['firstBloodKill'],
                                kills=game_info['kills'],
                                deaths=game_info['deaths'],
                                assists=game_info['assists'],
                                max_kill_type=kill_type,
                                total_damage_to_champions=game_info['totalDamageDealtToChampions'],
                                cs=game_info['totalMinionsKilled'] + game_info['neutralMinionsKilled'],
                                gold_earned=game_info['goldEarned'],
                                vision_score=game_info['visionScore'],
                                wards_placed=100,  # Dummy Data
                                control_wards_placed=control_wards_placed,
                                summoner1_id=game_info['summoner1Id'],
                                summoner2_id=game_info['summoner2Id'],
                            ))
                        print("check10")
                        # team_win = (100 if game['info']['teams'][0]['win'] else 200)

                        game_team_info.append(GameTeamInfoModel(
                            game_id=game_id,
                            # team_win=team_win,
                            blue_baron_kills=game['info']['teams'][0]['objectives']['baron']['kills'],
                            blue_dragon_kills=game['info']['teams'][0]['objectives']['dragon']['kills'],
                            blue_tower_kills=game['info']['teams'][0]['objectives']['tower']['kills'],
                            blue_champion_kills=game['info']['teams'][0]['objectives']['champion']['kills'],
                            blue_champion_deaths=blue_champion_deaths,
                            blue_champion_assists=blue_champion_assists,
                            blue_total_gold=blue_total_gold,
                            red_baron_kills=game['info']['teams'][1]['objectives']['baron']['kills'],
                            red_dragon_kills=game['info']['teams'][1]['objectives']['dragon']['kills'],
                            red_tower_kills=game['info']['teams'][1]['objectives']['tower']['kills'],
                            red_champion_kills=game['info']['teams'][1]['objectives']['champion']['kills'],
                            red_champion_deaths=red_champion_deaths,
                            red_champion_assists=red_champion_assists,
                            red_total_gold=red_total_gold,
                        ))
                    print('check11')
                # except url_request.error.HTTPError as error:
                except HTTPError as error:
                    print('check22')
                    if error.status == 429:
                        return 'Too Many Request', 429
            print(game_team_info)
            session.add_all(games)
            print("check1")
            session.add_all(game_players)
            print("check2")
            session.add_all(game_team_info)
            print("check3")
            session.commit()
            print('check2')
            status_code = CREATED
        except Exception as e:
            print(e)
            session.rollback()
            status_code = 500

        return '', status_code

    @staticmethod
    def get_game(puuid, page, count, queue):
        history = list()
        players = list()

        count *= count

        if page == 1:
            start = 0
        else:
            start = (page - 1) * count

        if queue is None:
            game_info = [x for x in session.query(GameModel, GamePlayerModel, GameTeamInfoModel)
            .filter(GameModel.puuid == puuid).join(GamePlayerModel, GameModel.game_id == GamePlayerModel.game_id)
            .join(GameTeamInfoModel, GameModel.game_id == GameTeamInfoModel.game_id)
            .order_by(desc(GameModel.played_time)).offset(start).limit(count)]
        else:
            game_info = [x for x in session.query(GameModel, GamePlayerModel, GameTeamInfoModel)
            .filter(GameModel.puuid == puuid, GameModel.queue_id == queue)
            .join(GamePlayerModel, GameModel.game_id == GamePlayerModel.game_id)
            .join(GameTeamInfoModel, GameModel.game_id == GameTeamInfoModel.game_id)
            .order_by(desc(GameModel.played_time)).offset(start).limit(count)]

        # 데이터 가공
        for i, game in enumerate(game_info):
            info = dict()
            i += 1
            players.append(game[1].serialize)

            # 10개당(플레이어) 1개의 게임
            if i % 10 == 0:
                for key, value in game[0].serialize.items():
                    info[key] = value

                for key, value in game[2].serialize.items():
                    info[key] = value

                info['players'] = players
                players = list()
                history.append(info)

        res = response.response_data(history)

        return res

    @staticmethod
    def get_game_with_game_id(game_id):
        history = list()
        players = list()
        game_info = [x for x in
                     session.query(GameModel, GamePlayerModel, GameTeamInfoModel).filter(GameModel.game_id == game_id)
                     .join(GamePlayerModel, GameModel.game_id == GamePlayerModel.game_id)
                     .join(GameTeamInfoModel, GameModel.game_id == GameTeamInfoModel.game_id)]

        # 데이터 가공
        for i, game in enumerate(game_info):
            info = dict()
            i += 1
            players.append(game[1].serialize)

            # 10개당(플레이어) 1개의 게임
            if i % 10 == 0:
                for key, value in game[0].serialize.items():
                    info[key] = value

                for key, value in game[2].serialize.items():
                    info[key] = value

                info['players'] = players
                players = list()
                history.append(info)
        res = response.response_data(history)

        return res

    def get_game_id_filter_queue(self, puuid, queue):
        print(puuid, queue)
        if queue is None:
            res = [dict(x) for x in session.query(GameModel)
            .with_entities(GameModel.game_id)
            .filter_by(puuid=puuid)]
        else:
            res = [dict(x) for x in session.query(GameModel)
            .with_entities(GameModel.game_id)
            .filter_by(puuid=puuid, queue_id=queue)]
        return res

    def post_most_champion(self, summoner_id, queue, game_id):
        game_info = self.get_game_with_game_id(game_id['game_id'])
        print("TAKE")
        for player in game_info['results'][0]['players']:
            for key, value in player.items():
                if key == 'summoner_id':
                    if value == summoner_id:
                        most_champion = []
                        champion_ids = [x for x in
                                        session.query(SoloMostChampionModel).with_entities(
                                            SoloMostChampionModel.champion_id).filter_by(
                                            summoner_id=summoner_id)]
                        if player['champion_id'] in champion_ids[0]:
                            champion_exist = True
                        else:
                            champion_exist = False
                        print("Check1")
                        if str(game_info['results'][0]['team_win']) == str(player['team_id']):
                            win = 1
                            lose = 0
                        else:
                            win = 0
                            lose = 1
                        print("Check2")
                        if champion_exist:
                            most_champion_temp = [dict(x) for x in
                                                  session.query(SoloMostChampionModel).with_entities(
                                                      SoloMostChampionModel.total_kill,
                                                      SoloMostChampionModel.total_death,
                                                      SoloMostChampionModel.total_assist,
                                                      SoloMostChampionModel.total_win,
                                                      SoloMostChampionModel.total_lose,
                                                      SoloMostChampionModel.sample_match)
                                                  .filter_by(summoner_id=summoner_id,
                                                             champion_id=player['champion_id'])]
                            print("Check3")
                            most_champion.append(SoloMostChampionModel(
                                summoner_id=summoner_id,
                                champion_id=player['champion_id'],
                                total_kill=most_champion_temp[0]['total_kill'] + player['kills'],
                                total_death=most_champion_temp[0]['total_death'] + player['deaths'],
                                total_assist=most_champion_temp[0]['total_assist'] + player['assists'],
                                total_win=most_champion_temp[0]['total_win'] + win,
                                total_lose=most_champion_temp[0]['total_lose'] + lose,
                                sample_match=most_champion_temp[0]['sample_match'] + 1
                            ))
                            print("Check4")
                        else:
                            most_champion.append(SoloMostChampionModel(
                                summoner_id=summoner_id,
                                champion_id=player['champion_id'],
                                total_kill=player['kills'],
                                total_death=player['deaths'],
                                total_assist=player['assists'],
                                total_win=win,
                                total_lose=lose,
                                sample_match=1
                            ))
                        session.add_all(most_champion)
                        session.commit()
        return OK

    def get_test_game(self, game_id, summoner_id):
        try:
            headers = {
                getenv('RIOT_HEADER_KEY'): getenv('RIOT_API_KEY')
            }
            url = riot_url.matches_info_url(game_id)
            req = url_request.Request(url, None, headers)

            games = {'history': ''}
            print("ck")
            try:
                with url_request.urlopen(req) as res:
                    game = loads(res.read().decode())
                    print("ck2")
                    # 밀리초 제거
                    game_end_timestamp = str(game['info']['gameEndTimestamp'])[:-3]
                    played_time = datetime.fromtimestamp(int(game_end_timestamp))
                    print("ck33")

                    tmp = {'gameId': game['metadata']['matchId'],
                           'gameDuration': game['info']['gameDuration'],
                           'playedTime': played_time,
                           'queueId': game['info']['queueId'],
                           'teamWin': "100",
                           'players': {},
                           'teamInfos': {},
                           'itemBuild': {},
                           'skillsBuild': {}
                           }
                    games['history'] = tmp
                    player_index = 0
                    blue_total_gold = 0
                    red_total_gold = 0
                    blue_champion_deaths = 0
                    red_champion_deaths = 0
                    blue_champion_assists = 0
                    red_champion_assists = 0
                    for participant in game['info']['participants']:
                        print("ck4")
                        player = PlayerController.get_player_with_summoner_id(participant['summonerId'])
                        if participant['pentaKills'] > 0:
                            kill_type = '펜타킬'
                        elif participant['quadraKills'] > 0:
                            kill_type = '쿼드라킬'
                        elif participant['tripleKills'] > 0:
                            kill_type = '트리플킬'
                        elif participant['doubleKills'] > 0:
                            kill_type = '더블킬'
                        else:
                            kill_type = ''

                        if participant['teamId'] == 100:
                            blue_total_gold += int(participant['goldEarned'])
                            blue_champion_assists += participant['assists']
                            blue_champion_deaths += participant['deaths']
                        else:
                            red_total_gold += int(participant['goldEarned'])
                            red_champion_assists += participant['assists']
                            red_champion_deaths += participant['deaths']

                        if 'challenges' in participant:
                            kda = participant['challenges']['kda']
                            control_wards_placed = participant['challenges']['controlWardsPlaced']
                        else:
                            # -1은 Perfect 게임
                            # URF 같은 특수모드는 kda를 주지 않음 (0으로 나눌 시 ZeroDivision Error 발생)
                            if participant['deaths'] == 0:
                                kda = -1
                            else:
                                kda = (participant['kills'] + participant['assists']) / participant['deaths']

                        player_data = {
                            'teamId': participant['teamId'],
                            'puuid': player[0]['puuid'],
                            'summonerId': participant['summonerId'],
                            'summonerName': participant['summonerName'],
                            'level': player[0]['level'],
                            'soloTier': player[0]['solo_tier'],
                            'soloRank': player[0]['solo_rank'],
                            'soloPoint': player[0]['solo_point'],
                            'flexTier': player[0]['flex_tier'],
                            'flexRank': player[0]['flex_rank'],
                            'flexPoint': player[0]['flex_point'],
                            'championId': participant['championId'],
                            'championLevel': participant['champLevel'],
                            'item0Id': participant['item0'],
                            'item1Id': participant['item1'],
                            'item2Id': participant['item2'],
                            'item3Id': participant['item3'],
                            'item4Id': participant['item4'],
                            'item5Id': participant['item5'],
                            'item6Id': participant['item6'],
                            'teamPosition': participant['teamPosition'],
                            'killInvolvement': 80, # 뭔지 모르겠음.
                            'kda': kda,
                            'firstBlood': 1 if participant['firstBloodKill'] else 0,
                            'kills': participant['kills'],
                            'deaths': participant['deaths'],
                            'assists': participant['assists'],
                            'maxKillType': kill_type,
                            'totalDamageToChampions': participant['totalDamageDealtToChampions'],
                            'cs': participant['totalMinionsKilled'] + participant['neutralMinionsKilled'],
                            'goldEarned': participant['goldEarned'],
                            'visionScore': participant['visionScore'],
                            'wardsPlaced': participant['wardsPlaced'],
                            'controlWardsPlaced': control_wards_placed,
                            'summoner1Id': participant['summoner1Id'],
                            'summoner2Id': participant['summoner2Id'],
                            'itemsBuild': {}
                        }
                        print(participant['item0'])
                        print(participant['item1'])
                        print(participant['item2'])
                        print(participant['item3'])
                        print(participant['item4'])
                        print(participant['item5'])
                        print(participant['item6'])
                        player_data['itemsBuild'][0] = ItemController.get_item_with_id(participant['item0'])
                        player_data['itemsBuild'][1] = ItemController.get_item_with_id(participant['item1'])
                        player_data['itemsBuild'][2] = ItemController.get_item_with_id(participant['item2'])
                        player_data['itemsBuild'][3] = ItemController.get_item_with_id(participant['item3'])
                        player_data['itemsBuild'][4] = ItemController.get_item_with_id(participant['item4'])
                        player_data['itemsBuild'][5] = ItemController.get_item_with_id(participant['item5'])
                        player_data['itemsBuild'][6] = ItemController.get_item_with_id(participant['item6'])
                        games['history']['players'][player_index] = player_data
                        player_index += 1

                    teaminfos_data_blue = {
                        "teamId": 100,
                        "baronKills": game['info']['teams'][0]['objectives']['baron']['kills'],
                        "dragonKills": game['info']['teams'][0]['objectives']['dragon']['kills'],
                        "towerKills": game['info']['teams'][0]['objectives']['tower']['kills'],
                        "championKills": game['info']['teams'][0]['objectives']['champion']['kills'],
                        "totalGold": blue_total_gold,
                        "totalKills": game['info']['teams'][0]['objectives']['champion']['kills'],
                        "totalDeaths": blue_champion_deaths,
                        "totalAssist": blue_champion_assists
                    }
                    teaminfos_data_red = {
                        "teamId": 100,
                        "baronKills": game['info']['teams'][1]['objectives']['baron']['kills'],
                        "dragonKills": game['info']['teams'][1]['objectives']['dragon']['kills'],
                        "towerKills": game['info']['teams'][1]['objectives']['tower']['kills'],
                        "championKills": game['info']['teams'][1]['objectives']['champion']['kills'],
                        "totalGold": red_total_gold,
                        "totalKills": game['info']['teams'][1]['objectives']['champion']['kills'],
                        "totalDeaths": red_champion_deaths,
                        "totalAssist": red_champion_assists
                    }
                    games['history']['teamInfos'][0] = teaminfos_data_blue
                    games['history']['teamInfos'][1] = teaminfos_data_red

                    print(games)

                    return '', OK

            except HTTPError as error:
                if error.status == 429:
                    return 'Too Many Request', 429

            status_code = CREATED
        except Exception as e:
            print(e)
            session.rollback()
            status_code = 500

        return '', status_code

#aldlqjdjqowiryrqhwoeqiwjediqiwiejfjllsdnfqpwodqfnpqiofnqpwadoqndnqfoqwidqnwdoqwllqkwdnqowdinnfnqosinfoqfnqpoqoodnqdnqn
#adlalskdkdkqkwdmfbnqowidiqjdlannincludeoqdoodjqjdiwidnfooddooieidndqjsldnowinclude stdio.h void main(){printf("hello
#world ");dddjwowueiqcnqcoqociwncoqwicnqcnndkqbfii89928euifkfkexepiton as e dldjjjdiwehfhqoeuuedbfbqofiifqbfbdjqoqiwidnqdb
#dhffbfoooo01028837u1vbvveveiqwesymmner?=api_keu?_seritorindfn


import random
from dataset import get_pet_dataloader
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F

batch_size = 64

def plot_inference(ckpt_path, unet):

    _, test_loader = get_pet_dataloader(".", batch_size=batch_size)
    checkpoint = torch.load(ckpt_path, map_location=torch.device('cpu'))

    # Extract the model's state_dict from the checkpoint
    model_state_dict = checkpoint['state_dict']

    # Load the state_dict into your model
    unet.load_state_dict(model_state_dict)

    itera = iter(test_loader)
    for _ in range(random.randint(1, 5)):
        batch = next(itera)
        inputs, target_mask = batch
        idx = random.randint(0, batch_size)

    input_image = inputs[idx].squeeze(0).cpu().numpy()
    ground_truth_mask = target_mask[idx]
    ground_truth_mask = F.one_hot(
        ground_truth_mask, num_classes=unet.num_classes
    ).squeeze(0) * 255

    input_image_tensor = inputs[idx].unsqueeze(0)

    # Make predictions using the U-Net model
    with torch.no_grad():
        predicted_mask = unet(input_image_tensor.to("cpu"))

    # Convert the predicted mask tensor to a NumPy array
    predicted_mask = predicted_mask.squeeze(0).argmax(axis=0).unsqueeze(0)
    print(predicted_mask.shape)
    predicted_mask = F.one_hot(predicted_mask, num_classes=3)\
        .squeeze(0) * 255
    predicted_mask = predicted_mask.cpu().numpy()

    # Plot the results
    plt.figure(figsize=(12, 4))

    # Plot the input image
    plt.subplot(131)
    plt.imshow(input_image.transpose(1,2,0), cmap='gray')
    plt.title('Input Image')
    plt.xticks([])
    plt.yticks([])

    plt.subplot(132)
    plt.imshow(ground_truth_mask, cmap='jet')
    plt.title('Ground Truth Mask')
    plt.xticks([])
    plt.yticks([])

    # Plot the predicted mask
    plt.subplot(133)
    plt.imshow(predicted_mask, cmap='jet')
    plt.title('Predicted Mask')
    plt.xticks([])
    plt.yticks([])

    plt.tight_layout()
    plt.show()


import logging
import itertools

from flask import g, jsonify
from flask_login import current_user

from app import db, constants
from app.utils import scoped_session
from app.models import create_destination_plate
from app.dbmodels import NGS_BARCODE_PLATE  # , NGS_BARCODE_PLATE_TYPE

from twistdb import create_unique_id
from twistdb.sampletrack import (Sample, Plate, Transform, PlateType,
                                 TransformDetail)

IGNORE_MISSING_SOURCE_PLATE_WELLS = True  # FIXME: this allows silent failures

logger = logging.getLogger(name="Spreadsheet")

def error_response(status_code, message):
    # TODO: remove duplicate code -- use JSON-API?
    response = jsonify({'success': False, 'message': message})
    response.status_code = status_code
    return response

#
# If the user uploaded a spreadsheet with each row representing a well-to-well transform, this is where we
# process that spreadsheet data.
#

def create_step_record_adhoc(transform_type_id,
                             transform_template_id,
                             transform_map):

    with scoped_session(db.engine) as db_session:
        result = create_adhoc_sample_movement(db_session,
                                              transform_type_id,
                                              transform_template_id,
                                              transform_map)
        if result["success"]:
            return jsonify({
                "success": True
            })
        else:
            return error_response(400, result["errorMessage"])

def create_adhoc_sample_movement(db_session,
                                 transform_type_id,
                                 transform_template_id, transform_map,
                                 transform_spec_id=None):
    #
    # FIRST. Create a "sample_transform" row representing this row's transform.
    #
    operator = g.user
    sample_transform = Transform(transform_type_id=transform_type_id,
                                 transform_spec_id=transform_spec_id,
                                 operator_id=operator.operator_id)
    db_session.add(sample_transform)
    db_session.flush()

    import time
    start = time.time()

    # Cache all source plates, raising an error if any are not found
    plate_cache = {}
    srcs = set([d['source_plate_barcode'] for d in transform_map])
    logging.info("Caching source plates: %s" % list(srcs))
    for src_barcode in srcs:
        try:
            source_plate = db_session.query(Plate) \
                                     .filter(Plate.external_barcode == src_barcode).one()
        except:
            logging.warn(" %s encountered error creating sample transform. "
                         "There is no source plate with the barcode: [%s]",
                         g.user.first_and_last_name, src_barcode)
            return {
                "success": False,
                "errorMessage": "There is no source plate with the barcode: [%s]" % (src_barcode)
            }
        else:
            plate_cache[src_barcode] = source_plate

    # Cache all destination plates, creating any that are not found

    dests = set([(d['destination_plate_barcode'],
                  d['destination_plate_type']) for d in transform_map])
    logging.info("Caching dest plates: %s" % list(dests))
    for dest_barcode, dtype in dests:
        try:
            dest_plate = db_session.query(Plate).\
                filter(Plate.external_barcode == dest_barcode).one()
        except:
            logging.info("There is no dest plate [%s], creating it",
                         dest_barcode)
            # This is a transform that requires creating a new plate in DB
            try:
                dest_plate = create_destination_plate(
                    db_session,
                    operator,
                    dest_barcode,
                    dtype,
                    "Unknown location",  # FIXME find a better default for this
                    transform_template_id)
                db_session.flush()
            except IndexError:
                err_msg = ("Encountered error creating sample "
                           "transform. Could not create destination plate: [%s]"
                           )
                logging.error(err_msg)
                return {
                    "success": False,
                    "errorMessage": err_msg
                }
        plate_cache[dest_barcode] = dest_plate

    # We always operate on a plate's current contents so we pull that
    # in a single query so that we have it on-hand and can then single out
    # samples for transfer.
    sample_cache = {}
    logging.info("Caching plate samples.")
    for barcode, plate in plate_cache.iteritems():
        for sample in plate.current_well_contents(db_session):
            sample_cache[(barcode, sample.well.well_number)] = sample

    # Inject well_number by well_name into transform_map, if necessary.
    # Also make sure source_well_sample is consistent.
    for oper in transform_map:
        if "source_well_number" not in oper:
            s_bc = oper["source_plate_barcode"]
            s_label = str(oper["source_well_name"])
            s_type = plate_cache[s_bc].plate_type
            s_num = s_type.layout.get_well_by_label(s_label).well_number
            oper["source_well_number"] = s_num

        if "source_well_sample" in oper:
            assert oper["source_well_sample"] == sample_cache[(s_bc, s_num)].id

        if "destination_well_number" not in oper:
            # lookup well number based on well name
            # (quick fix for qpix log upload)
            # not sure how many other code paths reach this
            # TODO: if destination_well_number is in oper, crosscheck well_name
            # TODO: speed up / cache dest_type query as needed
            d_type = oper["destination_plate_type"]
            dest_type = db.session.query(PlateType).get(d_type)
            d_label = str(oper["destination_well_name"])
            d_num = dest_type.layout.get_well_by_label(d_label).well_number
            oper["destination_well_number"] = d_num

    # Also cache a map of well number to well instance for all dest wells
    well_cache = {}
    for dest_barcode in [d[0] for d in dests]:
        plate = plate_cache[dest_barcode]
        well_ids = [d['destination_well_number']
                    if d['destination_plate_barcode'] == dest_barcode
                    else None for d in transform_map]
        well_ids = [x for x in well_ids if x is not None]  # There must be a better way!
        for id in well_ids:
            well_cache[(dest_barcode, id)] = plate.get_well_by_number(id)

    dest_grouping_func = lambda oper: (oper['destination_plate_barcode'],
                                       oper['destination_well_number'])
    transforms_by_dest = sorted(transform_map, key=dest_grouping_func)

    new_rows = []
    logging.info("Iterating over operations...")
    for dest_key, operation_group in itertools.groupby(transforms_by_dest,
                                                       dest_grouping_func):

        # get sources -- one or more going into the same destination
        source_samples = [sample_cache[(oper["source_plate_barcode"],
                                        oper["source_well_number"])]
                          for oper in operation_group]

        # get destination plate
        destination_plate_barcode, destination_well_number = dest_key
        try:
            dplate = plate_cache[destination_plate_barcode]
        except KeyError:
            msg = "Failed to lookup destination plate from cache [%s]."
            msg %= destination_plate_barcode
            logging.error("Invalid xfer: %s", msg)
            return {"success": False, "errorMessage": msg}

        # get "destination" sample (if present, this will become a parent)
        try:
            dest_s = sample_cache[(destination_plate_barcode,
                                   destination_well_number)]
        except KeyError:
            dest_s = None

        # create and add the new sample
        s = sample_handler(sample_transform,
                           well_cache, source_samples, dplate,
                           destination_well_number, dest_s)
        new_rows.append(s)

    logging.info("Bulk inserting samples and relationships.")

    db_session.bulk_save_objects(new_rows)
    db_session.commit()

    logger.info("Adhoc movement took: " + str(time.time() - start))

    return {
        "success": True
    }

def sample_handler(transform, well_cache,
                   source_samples, destination_plate,
                   destination_well_id, destination_sample=None):
    """Accessions a new sample into the designated well,
    using the source sample(s) as parents and/or reagents.
    Note: destination_sample, if present, will become a parent
    of the new sample that this routine will accession.

    This loop is now oriented towards many-samples-to-one-sample
    merge transforms.  len(source_samples) shows the type of transform:

        len(source_samples) == 1: copy sample, one parent
        len(source_samples) >  1: merge sample, multiple parents
        len(source_samples) == 0: create fresh sample, no parents (TBD)

    Handles mixing operations (pooling, NGS barcoding, primer addition,
    etc) as well as non-mixing steps
    """

    logging.debug("sample_handler: src=[%s] dest=[%s]", source_samples, destination_sample)

    new_id = create_unique_id(Sample.id_prefix)

    parent_samples = ( source_samples + [destination_sample]
                       if destination_sample
                       else source_samples )

    # Copy all extant metadata except transform, parents, children, is_clonal
    if len(parent_samples) > 1:
        logging.debug("Merging %d samples into %s",  len(parent_samples), destination_sample)
        new_s = merged_sample(parent_samples)
    elif len(parent_samples) == 1:
        new_s = copied_sample(parent_samples[0])
    else:
        raise NotImplementedError("TODO?: Create samples from scratch")

    # Set attributes unique to this sample
    new_s.id = new_id()
    new_s.plate_id = destination_plate.id
    new_s.transform_id = transform.id
    new_s.operator_id = g.user.operator_id
    well = well_cache[(destination_plate.external_barcode, destination_well_id)]
    new_s.plate_well_code = well.well_code

    # Type-specific logic
    handle_transform_specific_logic(transform, new_s)
    true_parent_samples = parse_source_reagents(transform, parent_samples, new_s)

    # Link up the source sample(s) and any "destination" sample as parent(s)
    for source_well_sample in true_parent_samples:
        source_to_dest_well_transform = TransformDetail(
            transform=transform,
            parent_sample_id=source_well_sample.id,
            child_sample_id=new_s.id
        )

    # NOTE that we don't have to explicitly return the TransformDetail instances
    # created because they are linked to the new_s Sample instance by virtue
    # of setting new_s.id as the child ID. I tried to actually return these
    # instances directly and commit them in the bulk commit and that ended up
    # double-adding rows for each TransformDetail, one with the transform ID
    # properly populated and one without. Strange!
    #
    # I also verified that even though nothing is technically *done* with the
    # instance variables source_to_dest_well_transform and
    # dest_well_parent_transform that it *is* necessary to create them like
    # this to properly populated the TransformDetail table. SQLAlchemy magic.

    return new_s

def handle_transform_specific_logic(transform, new_s):

    if transform.transform_type_id in (constants.TRANS_TYPE_QPIX_PICK_COLONIES,
                                       constants.TRANS_TYPE_QPIX_TO_384_WELL):
        # We just cloned this so it's clonal
        new_s.is_clonal = True
        # FIXME hardcoding this for Warp2 for now - should derive
        # this from the A/B rebatching metadata somehow (@sucheta!)
        new_s.cloning_process_id = 'CLO_564c1af300bc150fa632c63d'

def parse_source_reagents(transform, source_samples, new_s):
    """Splits out the "reagent" style parent samples (e.g. ngs barcodes)
    from the true parent samples (e.g. oligo pooling)."""

    true_parent_samples = []

    for src_s in source_samples:
        if src_s.id[0:4] == 'BCS_':
            # FIXME: identify barcode samples via a type_id instead?
            logging.info("REAGENT: %s", src_s)
            n_added = 0
            for attrname in ('i5_sequence_id', 'i7_sequence_id'):
                seq_id = getattr(src_s, attrname)
                if seq_id is not None:
                    setattr(new_s, attrname, seq_id)
                    n_added += 1
            if n_added == 0:
                raise ValueError("%s is missing barcode seqs, please add"
                                 % src_s)
            elif n_added > 1:
                raise ValueError("%s has too %d barcode seqs, expected only 1"
                                 % (src_s, n_added))
        else:
            true_parent_samples.append(src_s)

    return true_parent_samples

def safe_sqlalchemy_copy(session, object_handle):
    """Copy a sample, this approach copies a little too much,
    including parent transform details etc.

    Implement a safe copy.copy().

    Based on http://permalink.gmane.org/gmane.comp.python.sqlalchemy.user/39675

    SQLAlchemy-mapped objects travel with an object
    called an InstanceState, which is pegged to that object
    specifically and tracks everything about that object.  It's
    critical within all attribute operations, including gets
    and deferred loading.   This object definitely cannot be
    shared among two instances, and must be handled.

    The copy routine here makes use of session.merge() which
    already essentially implements a "copy" style of operation,
    which produces a new instance with a new InstanceState and copies
    all the data along mapped attributes without using any SQL.

    The mode we are using here has the caveat that the given object
    must be "clean", e.g. that it has no database-loaded state
    that has been updated and not flushed.   This is a good thing,
    as creating a copy of an object including non-flushed, pending
    database state is probably not a good idea; neither represents
    what the actual row looks like, and only one should be flushed.

    """
    copy = session.merge(object_handle, load=False)
    session.expunge(copy)
    return copy

def transient_copy(session, inst):
    """Copy a sample, this approach forces a bunch of flushes"""
    from sqlalchemy.orm import make_transient
    session.expunge(inst)
    make_transient(inst)
    inst.id = None
    session.add(inst)
    session.flush()
    return inst

def copied_sample(orig_obj):
    """Copy a sample, this approach is hard to maintain though"""

    copy = Sample()
    attrs_to_ignore = ("details", "operator_id")
    attrs_to_propagate = ("order_item_id", "type_id",
                          "external_barcode", "name", "description",
                          "work_order_id", "synthesis_run_pk", "cluster_num",
                          "cloning_process_id",
                          "mol_type", "is_circular", "is_clonal",
                          "is_assembly", "is_external", "external_id",
                          "host_cell_pk", "growth_medium", "i5_sequence_id",
                          "i7_sequence_id")
    for attrname in attrs_to_propagate:
        setattr(copy, attrname, getattr(orig_obj, attrname))
    return copy

def filter_real_samples( samples ):
    from twistdb.work_order import Vector
    # FIXME: this is a hacky sort of way to filter out VECtors, but we can't actually use
    #    the Sample.order_item relationship until the sample itself has been commited to the db
    return [s for s in samples if s.order_item_id and not s.order_item_id.startswith('VEC')]

def merged_sample(parent_samples):
    """Merge a set of samples."""

    filtered_parents = filter_real_samples( parent_samples )

    result = Sample()
    attrs_to_ignore = ("is_clonal", "details", "operator_id")
    attrs_to_merge = ("order_item_id", "type_id",
                      "external_barcode", "name", "description",
                      "work_order_id", "synthesis_run_pk", "cluster_num",
                      "cloning_process_id",
                      "mol_type", "is_circular",
                      "is_assembly", "is_external", "external_id",
                      "host_cell_pk", "growth_medium", "i5_sequence_id",
                      "i7_sequence_id")
    for attrname in attrs_to_merge:
        source_vals = set([getattr(par, attrname) for par in filtered_parents])
        if len(source_vals) == 1:
            setattr(result, attrname, source_vals.pop())
    if len(parent_samples) > 1:
        result.is_pooled = True

    return result


import vtk
import geo
import defopt
import numpy
from horizgrid import HorizGrid
import mint
# to read the target points from file
from latlonreader import LatLonReader
from field import Field
import re
import glob

# callback class called when the user interacts with the visualization
class CallBack(object):

    def __init__(self, fluxviz):
        self.fluxviz = fluxviz

    def execute(self, obj, event):
        key = obj.GetKeySym()
        self.fluxviz.update(key)
        self.fluxviz.renWin.Render()

class FluxViz(object):

    def __init__(self, tFile, uFile, vFile, lonLatZPoints, sverdrup=False):

        self.field = Field(tFile, uFile, vFile, lonLatZPoints, sverdrup)
        self.buildTargetLineGrid(lonLatZPoints)
        self.buildEdgeUVGrids()

    def update(self, key):

        camera = self.ren.GetActiveCamera()
        x, y, z = camera.GetPosition()

        if key == 't':
            # forward in time
            self.field.timeIndex = (self.field.timeIndex + 1) % self.field.nt
        elif key == 'T':
            # backward in time
            self.field.timeIndex = (self.field.timeIndex - 1) % self.field.nt
        else:
            if key == 'r':
                # reset
                lon, lat = 0.5*(self.field.lonmin + self.field.lonmax), \
                           0.5*(self.field.latmin + self.field.latmax)
                camera.SetFocalPoint((lon, lat, 0.))
                camera.SetPosition((lon, lat, 2*self.field.dx*max(self.field.ny, self.field.nx)))
                camera.SetViewUp((0., 1., 0.))
            elif  key == 'x':
                camera.SetPosition(x + self.field.dx, y, z)
                camera.SetFocalPoint(x + self.field.dx, y, 0.)
            elif key == 'X':
                camera.SetPosition(x - self.field.dx, y, z)
                camera.SetFocalPoint(x - self.field.dx, y, 0.)
            elif key == 'y':
                camera.SetPosition(x, y + self.field.dx, z)
                camera.SetFocalPoint(x, y + self.field.dx, 0.)
            elif key == 'Y':
                camera.SetPosition(x, y - self.field.dx, z)
                camera.SetFocalPoint(x, y - self.field.dx, 0.)
            elif key == 'z':
                camera.SetPosition(x, y, z + self.field.dx)
            elif key == 'Z':
                camera.SetPosition(x, y, z - self.field.dx)
            elif key == 'v':
                self.targetGlyphs.SetScaleFactor(1.3*self.targetGlyphs.GetScaleFactor())
            elif key == 'V':
                self.targetGlyphs.SetScaleFactor(self.targetGlyphs.GetScaleFactor()/1.3)
            elif key == 's':
                # screenshot
                w2f = vtk.vtkWindowToImageFilter()
                w2f.Modified()
                w2f.SetInput(self.renWin)
                w2f.Update()
                wr = vtk.vtkPNMWriter()
                wr.SetInputConnection(w2f.GetOutputPort())
                filename = f'fluxviz_{self.field.timeIndex:04d}.pnm'
                wr.SetFileName(filename)
                wr.Write()
                print(f'saved screen shot for time {self.field.timeIndex} in file {filename}')
            elif key == 'm':
                # save all frames
                for i in range(self.field.nt):
                    self.update(key='t')
                    self.update(key='s')
            camera.Modified()
            return

        # update the data
        self.field.update()
        nvpts = self.field.vectorPoints.shape[0]
        maxVectorLength = max([numpy.sqrt(self.field.vectorValues[i, :].dot(self.field.vectorValues[i, :])) for i in range(nvpts)])
        self.field.vectorValues /= maxVectorLength

        # update the pipeline
        self.lut.SetTableRange(0., self.field.maxAbsFlux)
        self.lut.Modified()
        self.cbar.Modified()
        self.title.SetInput(f'flux = {self.field.getFluxText()} {self.field.timeObj.getTimeAsString(self.field.timeIndex)}')
        self.title.Modified()
        self.edgeFluxesU.Modified()
        self.edgeFluxesV.Modified()
        self.targetVectorValues.Modified()
        print(f'time index now {self.field.timeIndex} max |flux|: {self.field.maxAbsFlux:10.3f} nt = {self.field.nt}')

    def buildTargetLineGrid(self, lonLatZPoints):

        ptIds = vtk.vtkIdList()
        ptIds.SetNumberOfIds(2)

        # build the target point mesh
        self.targetPointData = vtk.vtkDoubleArray()
        self.targetPointData.SetNumberOfComponents(3)
        self.gridTargetLine = vtk.vtkPolyData()
        self.gridTargetLine.Allocate()
        ptId = 0
        for segment in lonLatZPoints:
            numPoints = len(segment)
            assert(numPoints >= 2)
            for i0 in range(numPoints - 1):
                p0 = segment[i0]
                self.targetPointData.InsertNextTuple(p0)
                ptIds.SetId(0, ptId)
                ptIds.SetId(1, ptId + 1)
                self.gridTargetLine.InsertNextCell(vtk.VTK_LINE, ptIds)
                ptId += 1
            # add last point
            p0 = segment[numPoints - 1]
            self.targetPointData.InsertNextTuple(p0)
            ptId += 1

        self.targetPoints = vtk.vtkPoints()
        self.targetPoints.SetData(self.targetPointData)
        self.gridTargetLine.SetPoints(self.targetPoints)

    def buildEdgeUVGrids(self):

        numCells = self.field.ny * self.field.nx

        self.pointData = vtk.vtkDoubleArray()
        self.pointData.SetNumberOfComponents(3)
        self.pointData.SetNumberOfTuples(4 * numCells)
        self.pointData.SetVoidArray(self.field.lonlat, 4 * numCells * 3, 1)

        self.points = vtk.vtkPoints()
        self.points.SetData(self.pointData)

        # 1 grid for the U fluxes, 1 grid for the V fluxes
        self.gridU = vtk.vtkPolyData()
        self.gridU.SetPoints(self.points)
        self.edgeFluxesU = vtk.vtkDoubleArray()
        self.edgeFluxesU.SetName('U')
        self.edgeFluxesU.SetNumberOfComponents(1)
        self.edgeFluxesU.SetNumberOfTuples(numCells)
        self.edgeFluxesU.SetVoidArray(self.field.edgeFluxesUArray, numCells, 1)

        self.gridV = vtk.vtkPolyData()
        self.gridV.SetPoints(self.points)
        self.edgeFluxesV = vtk.vtkDoubleArray()
        self.edgeFluxesV.SetName('V')
        self.edgeFluxesV.SetNumberOfComponents(1)
        self.edgeFluxesV.SetNumberOfTuples(numCells)
        self.edgeFluxesV.SetVoidArray(self.field.edgeFluxesVArray, numCells, 1)

        self.gridU.Allocate()
        self.gridV.Allocate()

        self.gridU.GetCellData().SetScalars(self.edgeFluxesU)
        self.gridU.GetCellData().SetActiveScalars('U')
        self.gridV.GetCellData().SetScalars(self.edgeFluxesV)
        self.gridV.GetCellData().SetActiveScalars('V')

        ptIds = vtk.vtkIdList()
        ptIds.SetNumberOfIds(2)

        # assemble the cells
        cellId = 0
        for j in range(self.field.ny):
            for i in range(self.field.nx):

                ptIds.SetId(0, 4*cellId + 1)
                ptIds.SetId(1, 4*cellId + 2)
                self.gridU.InsertNextCell(vtk.VTK_LINE, ptIds)

                ptIds.SetId(0, 4*cellId + 3)
                ptIds.SetId(1, 4*cellId + 2)
                self.gridV.InsertNextCell(vtk.VTK_LINE, ptIds)

                # increment the cell counter
                cellId += 1

    def show(self, npx=1260, npy=960):

        np = max(npx, npy)

        self.title = vtk.vtkTextActor()
        self.title.SetTextScaleMode(1)
        self.title.GetTextProperty().SetFontSize(int(0.12*np))
        self.title.SetInput(f"flux = {self.field.getFluxText()} {self.field.timeObj.getTimeAsString(self.field.timeIndex)}")

        # water lookup table
        self.lut = vtk.vtkLookupTable()
        nc1 = 10001
        self.lut.SetNumberOfTableValues(nc1)
        for i in range(nc1):
            x = (float(i)/float(nc1-1))**0.5
            r = 0.9*numpy.sqrt(x) # x**2
            g = 0.9*numpy.sqrt(x) # numpy.sin(numpy.pi*x)
            b = numpy.sqrt(x) #0.6 + 0.4*numpy.sqrt(x)
            a = 1.0
            if x < 0.0001:
                # land or zero flux
                r, g, b, a = 1.0, 0.9, 0.8, 1.0
            self.lut.SetTableValue(i, r, g, b, a)
        self.lut.SetTableRange(0.0, self.field.maxAbsFlux)
        self.lut.Build()

        # colorbar
        self.cbar = vtk.vtkScalarBarActor()
        self.cbar.UnconstrainedFontSizeOn()
        self.cbar.GetLabelTextProperty().SetFontSize(int(0.05*np))
        self.cbar.GetTitleTextProperty().SetFontSize(int(0.08*np))
        self.cbar.SetLookupTable(self.lut)
        if self.field.sverdrup:
            self.cbar.SetTitle('flux (Sv)')
        else:
            self.cbar.SetTitle('flux (A m^2/s)')
        self.cbar.SetBarRatio(0.08)
        self.cbar.Modified()

        # tubes for the u fluxes
        self.tubesU = vtk.vtkTubeFilter()
        self.tubesU.SetRadius(self.field.dx * 0.2)
        self.tubesU.SetNumberOfSides(16)
        self.tubesU.SetInputData(self.gridU)
        self.mapperU = vtk.vtkPolyDataMapper()
        self.mapperU.SetInputConnection(self.tubesU.GetOutputPort())
        self.mapperU.SetLookupTable(self.lut)
        self.mapperU.SetUseLookupTableScalarRange(1)
        self.actorU = vtk.vtkActor()
        self.actorU.SetMapper(self.mapperU)
        self.actorU.GetProperty().SetInterpolationToPhong()

        # tubes for the v fluxes
        self.tubesV = vtk.vtkTubeFilter()
        self.tubesV.SetRadius(self.field.dx * 0.2)
        self.tubesV.SetNumberOfSides(16)
        self.tubesV.SetInputData(self.gridV)
        self.mapperV = vtk.vtkPolyDataMapper()
        self.mapperV.SetInputConnection(self.tubesV.GetOutputPort())
        self.mapperV.SetLookupTable(self.lut)
        self.mapperV.SetUseLookupTableScalarRange(1)
        self.actorV = vtk.vtkActor()
        self.actorV.SetMapper(self.mapperV)
        self.actorV.GetProperty().SetInterpolationToPhong()

        # target line
        self.tubePoints = vtk.vtkTubeFilter()
        self.tubePoints.SetRadius(self.field.dx * 0.3)
        self.tubePoints.SetNumberOfSides(16)
        self.tubePoints.SetInputData(self.gridTargetLine)
        self.mapperPoints = vtk.vtkPolyDataMapper()
        self.mapperPoints.SetInputConnection(self.tubePoints.GetOutputPort())
        self.actorPoints = vtk.vtkActor()
        self.actorPoints.SetMapper(self.mapperPoints)
        self.actorPoints.GetProperty().SetColor(1.0, 1.0, 0.1) # transect's color

        # add vector plot to target line
        nvpts = self.field.vectorPoints.shape[0]
        maxVectorLength = max([numpy.sqrt(self.field.vectorValues[i, :].dot(self.field.vectorValues[i, :])) for i in range(nvpts)])
        self.field.vectorValues /= maxVectorLength

        self.targetArrow = vtk.vtkArrowSource()
        self.targetGlyphs = vtk.vtkGlyph3D()
        self.targetVectorPointData = vtk.vtkDoubleArray()
        self.targetVectorValues = vtk.vtkDoubleArray()
        self.targetVectorPoints = vtk.vtkPoints()
        self.targetVectorGrid = vtk.vtkStructuredGrid()
        self.targetVectorMapper = vtk.vtkPolyDataMapper()
        self.targetVectorActor = vtk.vtkActor()

        self.targetArrow.SetShaftResolution(8)
        self.targetArrow.SetTipResolution(16)
        self.targetGlyphs.SetScaleModeToScaleByVector()
        self.targetGlyphs.SetColorModeToColorByVector()
        self.targetVectorPointData.SetNumberOfComponents(3)
        self.targetVectorPointData.SetNumberOfTuples(nvpts)
        # move the point a little up for visualization
        self.field.vectorPoints[:, 2] = 0.5*self.field.dx
        self.targetVectorPointData.SetVoidArray(self.field.vectorPoints, nvpts*3, 1)
        self.targetVectorPoints.SetNumberOfPoints(nvpts)
        self.targetVectorPoints.SetData(self.targetVectorPointData)

        self.targetVectorValues.SetNumberOfComponents(3)
        self.targetVectorValues.SetNumberOfTuples(nvpts)
        self.targetVectorValues.SetVoidArray(self.field.vectorValues, nvpts*3, 1)

        self.targetVectorGrid.SetDimensions(nvpts, 1, 1)
        self.targetVectorGrid.SetPoints(self.targetVectorPoints)
        self.targetVectorGrid.GetPointData().SetVectors(self.targetVectorValues)

        self.targetGlyphs.SetInputData(self.targetVectorGrid)
        self.targetGlyphs.SetVectorModeToUseVector()
        self.targetGlyphs.SetScaleModeToScaleByVector()
        self.targetGlyphs.SetSourceConnection(self.targetArrow.GetOutputPort())
        self.targetGlyphs.SetScaleFactor(5*self.field.dx)
        self.targetGlyphs.Update()

        self.targetVectorMapper.SetInputConnection(self.targetGlyphs.GetOutputPort())
        self.targetVectorMapper.CreateDefaultLookupTable()
        self.targetVectorMapper.GetLookupTable().SetHueRange(0.667, 0.)
        self.targetVectorMapper.GetLookupTable().SetTableRange(0., 1.0)
        self.targetVectorMapper.GetLookupTable().SetVectorModeToMagnitude()
        self.targetVectorMapper.GetLookupTable().SetVectorSize(2)

        self.targetVectorActor.SetMapper(self.targetVectorMapper)

        # Create the graphics structure. The renderer renders into the render
        # window. The render window interactor captures mouse events and will
        # perform appropriate camera or actor manipulation depending on the
        # nature of the events.
        self.ren = vtk.vtkRenderer()
        self.renWin = vtk.vtkRenderWindow()
        self.renWin.AddRenderer(self.ren)
        self.iren = vtk.vtkRenderWindowInteractor()
        self.iren.SetRenderWindow(self.renWin)

        # Add the actors to the renderer, set the background and size
        self.ren.AddActor(self.actorU)
        self.ren.AddActor(self.actorV)
        self.ren.AddActor(self.actorPoints)
        #self.ren.AddActor(self.cbar)
        self.ren.AddActor(self.title)
        self.ren.AddActor(self.targetVectorActor)
        self.ren.SetBackground((0., 0., 0.))
        camera = self.ren.GetActiveCamera()
        lon, lat = 0.5*(self.field.lonmin + self.field.lonmax), 0.5*(self.field.latmin + self.field.latmax)
        camera.SetFocalPoint((lon, lat, 0.))
        camera.SetPosition((lon, lat, 2*self.field.dx*max(self.field.ny, self.field.nx)))
        camera.SetViewUp((0., 1., 0.))
        self.renWin.SetSize(npx, npy)
        self.renWin.SetWindowName('Vertically integrated edge flux')

        # allow the user to interact with the visualisation
        self.callBack = CallBack(self)
        self.iren.AddObserver('KeyPressEvent', self.callBack.execute)
        print('type "t" to step forward in time')

        # This allows the interactor to initalize itself. It has to be
        # called before an event loop.
        self.iren.Initialize()

        self.renWin.Render()

        # Start the event loop.
        self.iren.Start()

def __del__(self):
    self.ncU.close()
    self.ncV.close()

def main(*, tFile: str, uFile: str, vFile: str, lonLatPoints: str='', iFiles: str='', sverdrup: bool=False):
    """Visualize fluxes
    :param tFile: netcdf file holding the T-grid
    :param uFile: netcdf file holding u data
    :param vFile: netcdf file holding v data
    :param lonLatPoints: target points "[(lon0, lat0), (lon1, lat1),...],[...]"
    :param iFiles: alternatively read target points from text files "['file1', 'file2',...]"
    :param sverdrup: whether or not to use Sverdrup units (default is A m^2/s)
    """
    if lonLatPoints:
        lonLatZPoints = [numpy.array([(ll[0], ll[1], 0.0) for ll in llp]) for llp in eval(lonLatPoints)]
    elif iFiles:
        lonLatZPoints = []
        listOfFiles = []
        try:
            listOfFiles = eval(iFiles)
        except:
            try:
                listOfFiles = glob.glob(iFiles)
            except:
                # single target line file?
                listOfFiles.append(iFiles)
        print(f'list of target surfaces: {listOfFiles}')
        for iFile in listOfFiles:
            llreader = LatLonReader(iFile)
            lonLatZPoints.append([(ll[0], ll[1], 0.) for ll in llreader.getLonLats()])
    else:
        raise RuntimeError('ERROR must provide either iFiles (-i) or lonLatPoints (-l)!')
    print(f'target points:\n {lonLatZPoints}')
    fv = FluxViz(tFile, uFile, vFile, lonLatZPoints, sverdrup)
    fv.show()

if __name__ == '__main__':
    defopt.run(main)


import streamlit as st
from PIL import Image
import SpokenToWritten
import spacy
##from spacy.matcher import Matcher
##from spacy.tokens import Span
##from spacy import displacy
##from word2number import w2n
import webbrowser # inbuilt module

#=================================== Title ===============================
st.title("""
Spoken English to Written English Translator
	""")

#================================= Title Image ===========================
st.text("""""")
image = Image.open("static/image_1.jpg")
st.image(
	        image,
	        use_column_width=True,
	    )

#================================= About =================================
st.write("""
## 1⃣ About
	""")
st.write("""
Hi all, Welcome to this project. It is a Spoken English to Written English Translator!!!
	""")
st.write("""
You have to write the spoken english in the text box!!!
	""")

#============================ How To Use It ===============================
st.write("""
## 2⃣ How To Use It
	""")
st.write("""
Well, it's pretty simple!!!
- Please write or copy paste the spoken english in the text box below.
- Press the **👉🏼 Translate** button to see the magic!!!

🔘 **NOTE : ** * This translator is basic and not advanced one*
	""")

#============================ Behind The Scene ==========================
st.write("""
## 5⃣ Behind The Scene
	""")
st.write("""
To see how it works, please click the button below!
	""")
st.text("""""")
github = st.button("👉🏼 Click Here To See How It Works")
if github:
	github_link = "https://github.com/praveen-jalaja/streamlit-hatefulmemedection"
	try:
		webbrowser.open(github_link)
	except:
		st.write("""
    		⭕ Something Went Wrong!!! Please Try Again Later!!!
    		""")

#======================== Time To See The Magic ===========================
st.write("""
## 👁🗨 Time To See the Translation 🌀
	""")

##================================Intiating the object function=======================================

trans = SpokenToWritten.spk2wrt()

#========================== text Uploader ===================================
st.text("Sample")
st.text("Copy Paste the below text and translate")
st.text("My life is Triple B . European authorities fined Google a record sixty five thousand dollars on Wednesday for abusing its power in the mobile phone market and ordered the company to alter its practices . Furthermore , My T - Shirt size is double X in 2019 and it costs six dollars . My weight is fifty kilograms.")

user_input = st.text_area("Paragraph here", "")

#================================= Predict Button ============================
st.text("""""")
submit = st.button("👉🏼 Translate")

##=================prediction================================================#
def generate_result(translated_text):
	st.write("""
	## 🎯 RESULT
		""")
	st.write(translated_text)

#=========================== Predict Button Clicked ==========================
if submit:

  # Predicting
  st.write("👁 Translate...")
  translated_text = trans.translate(user_input)
  generate_result(translated_text)

#=============================== Copy Right ==============================
st.text("""""")
st.text("""""")
st.text("""""")
st.text("""""")
st.text("""""")
st.text("""""")
st.text("""""")
st.text("""""")
st.text("""""")
st.text("""""")
st.write("""
### © Created By Praveen Jalaja
	""")


import unicodedata
import json
import unicodedata
import joblib
import string
import pickle
import nltk
import numpy as np
from scipy import sparse
from sklearn.preprocessing import LabelEncoder
from concurrent.futures import ProcessPoolExecutor, as_completed
from tqdm.autonotebook import tqdm

FEVER_LABELS = {'SUPPORTS': 0, 'REFUTES': 1}

def tokenize_helper(inp):
    print(inp)
    return tokenize_claim(inp[0], inp[1], inp[2])

class ClaimEncoder(object):
    def __init__(self):
        self.feature_encoder = joblib.load("feature_encoder.pkl")
        self.encoder = joblib.load("encoder.pkl")

    def tokenize_claim(self, c):
        """
        Input: a string that represents a single claim
        Output: a list of 3x|vocabulary| arrays that has a 1 where the letter-gram exists.
        """
        encoded_vector = []
        c = preprocess_article_name(c)
        c = "! {} !".format(c)
        for ngram in nltk.ngrams(nltk.word_tokenize(c), 3):
            arr = sparse.lil_matrix((3, len(self.encoder.__dict__['classes_'])))
            for idx, word in enumerate(ngram):
                for letter_gram in nltk.ngrams("#" + word + "#", 3):
                    s = "".join(letter_gram)
                    if s in self.feature_encoder:
                        letter_idx = self.feature_encoder[s]
                    else:
                        # note: lowercase OOV is actually in the dictionary, uppercase OOV is not in vocab.
                        letter_idx = self.feature_encoder['OOV']
                    arr[idx, letter_idx] = 1
            encoded_vector.append(arr)
        return encoded_vector

    def create_encodings(self, claims, train_dict, write_to_file=False):
        processed_claims = generate_all_tokens(claims)
        all_evidence = []

        for query in tqdm(train_dict):
            all_evidence.extend([preprocess_article_name(i) for i in query['evidence']])

        processed_claims.extend(generate_all_tokens(list(set(all_evidence))))

        possible_tokens = list(set(processed_claims))
        possible_tokens.append("OOV")

        self.encoder = LabelEncoder()
        self.encoder.fit(np.array(sorted(possible_tokens)))

        self.feature_encoder = {}
        for idx, e in tqdm(enumerate(self.encoder.classes_)):
            self.feature_encoder[e] = idx

        if write_to_file:
            joblib.dump(self.feature_encoder, "feature_encoder.pkl")
            joblib.dump(self.encoder, "encoder.pkl")

def generate_all_tokens(arr):
    all_tokens = []
    for unprocessed_claim in tqdm(arr):
        c = preprocess_article_name(unprocessed_claim)
        c = "! {} !".format(c)
        for word in c.split():
            letter_tuples = list(nltk.ngrams("#" + word + "#", 3))
            letter_grams = []
            for l in letter_tuples:
                letter_grams.append("".join(l))
            all_tokens.extend(letter_grams)
    return all_tokens

def extract_fever_jsonl_data(path):
    '''
    HELPER FUNCTION

    Extracts lists of headlines, labels, articles, and a set of
    all distinct claims from a given FEVER jsonl file.

    Inputs:
      path: path to FEVER jsonl file
    Outputs:
      claims: list of claims for each data point
      labels: list of labels for each claim (see FEVER_LABELS in
        var.py)
      article_list: list of names of articles corresponding to
        each claim
      claim_set: set of distinct claim
    '''
    num_train = 0
    total_ev = 0

    claims = []
    labels = []
    article_list = []
    claim_set = set()
    claim_to_article = {}
    with open(path, 'r') as f:
        for item in f:
            data = json.loads(item)
            claim_set.add(data["claim"])
            if data["verifiable"] == "VERIFIABLE":
                evidence_articles = set()
                for evidence in data["evidence"][0]:
                    article_name = unicodedata.normalize('NFC', evidence[2])
                    article_name = preprocess_article_name(article_name)

                    # Ignore evidence if the same article has
                    # already been used before as we are using
                    # the entire article and not the specified
                    # sentence.
                    if article_name in evidence_articles:
                        continue
                    else:
                        article_list.append(article_name)
                        evidence_articles.add(article_name)
                        claims.append(data["claim"])
                        labels.append(FEVER_LABELS[data["label"]])
                        if data['claim'] not in claim_to_article:
                            claim_to_article[data['claim']] = [article_name]
                        else:
                            claim_to_article[data['claim']].append(article_name)

                    total_ev += 1
                num_train += 1

    print("Num Distinct Claims", num_train)
    print("Num Data Points", total_ev)

    return claims, labels, article_list, claim_set, claim_to_article

def preprocess_article_name(s):
    s = s.replace("_", " ")
    s = s.replace("-LRB-", "(")
    s = s.replace("-RRB-", ")")
    s = s.translate(str.maketrans(string.punctuation, ' '*len(string.punctuation)))
    s = strip_accents(s)
    s = s.replace("’", "")
    s = s.replace("“", '')
    s = ''.join([i if ord(i) < 128 else ' ' for i in s])
    s = ' '.join(s.split())
    return s.lower().rstrip()

def strip_accents(s):
    return ''.join(c for c in unicodedata.normalize('NFD', s)
                  if unicodedata.category(c) != 'Mn')

def char_ngrams(s, n):
    s = "#" + s + "#"
    return [s[i:i+n] for i in range(len(s) - 2)]

def parallel_process(array, function, n_jobs=12, use_kwargs=False, front_num=3):
    """
        A parallel version of the map function with a progress bar.

        Args:
            array (array-like): An array to iterate over.
            function (function): A python function to apply to the elements of array
            n_jobs (int, default=16): The number of cores to use
            use_kwargs (boolean, default=False): Whether to consider the elements of array as dictionaries of
                keyword arguments to function
            front_num (int, default=3): The number of iterations to run serially before kicking off the parallel job.
                Useful for catching bugs
        Returns:
            [function(array[0]), function(array[1]), ...]
    """
    #We run the first few iterations serially to catch bugs
    if front_num > 0:
        front = [function(**a) if use_kwargs else function(a) for a in array[:front_num]]
    #If we set n_jobs to 1, just run a list comprehension. This is useful for benchmarking and debugging.
    if n_jobs==1:
        return front + [function(**a) if use_kwargs else function(a) for a in tqdm(array[front_num:])]
    #Assemble the workers
    with ProcessPoolExecutor(max_workers=n_jobs) as pool:
        #Pass the elements of array into function
        if use_kwargs:
            futures = [pool.submit(function, **a) for a in array[front_num:]]
        else:
            futures = [pool.submit(function, a) for a in array[front_num:]]
        kwargs = {
            'total': len(futures),
            'unit': 'it',
            'unit_scale': True,
            'leave': True
        }
        #Print out the progress as tasks complete
        for f in tqdm(as_completed(futures), **kwargs):
            pass
    out = []
    #Get the results from the futures.
    for i, future in tqdm(enumerate(futures)):
        try:
            out.append(future.result())
        except Exception as e:
            out.append(e)
    return front + out

def sparsify_evidences(train, n_jobs=15, jsonl_file="train.jsonl"):
    encoder = ClaimEncoder()
    evidence_set = []
    for fact in train:
        evidence_set.extend(fact['evidence'])
    _, _, _, _, claim_to_article = extract_fever_jsonl_data(jsonl_file)
    flattened_claims = [item for sublist in (list(claim_to_article.values())) for item in sublist]
    evidence_set.extend(flattened_claims)
    evidence_set = list(set(evidence_set))
    print("Total number of evidences: {}".format(len(evidence_set)))
    result = joblib.Parallel(n_jobs=n_jobs, verbose=1, prefer="threads")(joblib.delayed(process)(evidence=i, encoder=encoder) for i in evidence_set)
    # result = parallel_process(evidence_set, process, n_jobs=15)
    evidences = {}
    for e in result:
        if e is not None:
            k, v = e
            evidences[k] = v

    return evidences

def process(evidence, encoder):
    if "http://wikipedia" in evidence:
        processed = preprocess_article_name(evidence.split("http://wikipedia.org/wiki/")[1])
    else:
        processed = preprocess_article_name(evidence)
    evidence = encoder.tokenize_claim(processed)
    if len(evidence)>0:
        evidence = sparse.vstack(evidence)
        return processed, evidence
    return None

def calculate_recall(retrieved, relevant, k=None):
    """
        retrieved: a list of sorted documents that were retrieved
        relevant: a list of sorted documents that are relevant
        k: how many documents to consider, all by default.
    """
    if k==None:
        k = len(retrieved)
    return len(set(retrieved[:k]).intersection(set(relevant))) / len(set(relevant))


from datetime import datetime
from ProteinBoxBot_Core import PBB_Core
from ProteinBoxBot_Core import PBB_Helpers

strain_info = {
    "organism_type": "fungal",
    "organism_name": "Saccharomyces cerevisiae S288c",
    "organism_wdid": "Q27510868",
    # strain-specific chromosome to Refseq Genome ID mapping
    "chrom_genomeid_map": {
        'I': 'NC_001133.9',
        'II': 'NC_001134.8',
        'III': 'NC_001135.5',
        'IV': 'NC_001136.10',
        'IX': 'NC_001141.2',
        'MT': 'NC_001224.1',
        'Mito': 'NC_001224.1',  # ensembl calls it Mito (from mygene)
        'V': 'NC_001137.3',
        'VI': 'NC_001138.5',
        'VII': 'NC_001139.9',
        'VIII': 'NC_001140.6',
        'X': 'NC_001142.9',
        'XI': 'NC_001143.9',
        'XII': 'NC_001144.5',
        'XIII': 'NC_001145.3',
        'XIV': 'NC_001146.8',
        'XV': 'NC_001147.6',
        'XVI': 'NC_001148.4'
    }
}

go_props = {'MF': 'P680',
            'CC': 'P681',
            'BP': 'P682'
            }
go_evidence_codes = {
    'EXP': 'Q23173789',
    'IDA': 'Q23174122',
    'IPI': 'Q23174389',
    'IMP': 'Q23174671',
    'IGI': 'Q23174952',
    'IEP': 'Q23175251',
    'ISS': 'Q23175558',
    'ISO': 'Q23190637',
    'ISA': 'Q23190738',
    'ISM': 'Q23190825',
    'IGC': 'Q23190826',
    'IBA': 'Q23190827',
    'IBD': 'Q23190833',
    'IKR': 'Q23190842',
    'IRD': 'Q23190850',
    'RCA': 'Q23190852',
    'TAS': 'Q23190853',
    'NAS': 'Q23190854',
    'IC': 'Q23190856',
    'ND': 'Q23190857',
    'IEA': 'Q23190881',
    'IMR': 'Q23190842'
}

source_items = {'Uniprot': 'Q905695',
                'ncbi_gene': 'Q20641742', # these two are the same?  --v
                'Entrez':    'Q20641742',
                'ncbi_taxonomy': 'Q13711410',
                'swiss_prot': 'Q2629752',
                'trembl': 'Q22935315',
                'Ensembl': 'Q1344256',
                'refseq': 'Q7307074'}

prop_ids = {'uniprot': 'P352',
            'ncbi_gene': 'P351',
            'entrez_gene': 'P351',
            'ncbi_taxonomy': 'P685',
            'ncbi_locus_tag': 'P2393',
            'ensembl_gene': 'P594',
            'ensembl_protein': 'P705',
            'refseq_protein': 'P637'
            }

def make_ref_source(source_doc, id_prop, identifier, login=None):
    """
    Reference is made up of:
    stated_in: if the source has a release #:
        release edition
        else, stated in the source
    link to id: link to identifier in source
    retrieved: only if source has no release #
    login: must be passed if you want to be able to create new release items

    :param source_doc:
    :param id_prop:
    :param identifier:
    :return:
    """
    # source_doc = {'_id': 'uniprot', 'timestamp': '20161006'}
    # source_doc = {'_id': 'ensembl', 'release': 86, 'timestamp': '20161005'}
    source = source_doc['_id']
    if source not in source_items:
        raise ValueError("Unknown source for reference creation: {}".format(source))
    if id_prop not in prop_ids:
        raise ValueError("Unknown id_prop for reference creation: {}".format(id_prop))

    link_to_id = PBB_Core.WDString(value=str(identifier), prop_nr=prop_ids[id_prop], is_reference=True)

    if "release" in source_doc:
        source_doc['release'] = str(source_doc['release'])
        title = "{} Release {}".format(source_doc['_id'], source_doc['release'])
        description = "Release {} of {}".format(source_doc['release'], source_doc['_id'])
        edition_of_wdid = source_items[source_doc['_id']]
        release = PBB_Helpers.Release(title, description, source_doc['release'],
                                      edition_of_wdid=edition_of_wdid).get_or_create(login)

        stated_in = PBB_Core.WDItemID(value=release, prop_nr='P248', is_reference=True)
        reference = [stated_in, link_to_id]
    else:
        date_string = source_doc['timestamp']
        retrieved = datetime.strptime(date_string,"%Y%m%d")
        stated_in = PBB_Core.WDItemID(value=source_items[source], prop_nr='P248', is_reference=True)
        retrieved = PBB_Core.WDTime(retrieved.strftime('+%Y-%m-%dT00:00:00Z'), prop_nr='P813', is_reference=True)
        reference = [stated_in, retrieved, link_to_id]
    return reference

def make_reference(source, id_prop, identifier, retrieved):
    reference = [
        PBB_Core.WDItemID(value=source_items[source], prop_nr='P248', is_reference=True),  # stated in
        PBB_Core.WDString(value=str(identifier), prop_nr=prop_ids[id_prop], is_reference=True),  # Link to ID
        PBB_Core.WDTime(retrieved.strftime('+%Y-%m-%dT00:00:00Z'), prop_nr='P813', is_reference=True)]
    return reference


# 导入sys模块
import sys
# 导入PyQt5的QtWidgets和QtCore模块
from PyQt5 import QtWidgets

# 创建一个QApplication实例，用于管理应用程序的事件循环和GUI基础设施
app = QtWidgets.QApplication(sys.argv)
# 创建一个QWidget实例，作为所有用户界面对象的基类
widget = QtWidgets.QWidget()
# 设置QWidget窗口的大小为720x360像素
widget.resize(720, 360)
# 设置QWidget窗口的标题为'hello'
widget.setWindowTitle('hello')
# 显示QWidget窗口
widget.show()
# 启动应用程序的事件循环，直到应用程序被终止或退出
sys.exit(app.exec_())

基础知识学习/01_第一个窗口.py


from utils.request import request_telgram, request_pwrtelgram
import json

def check_querys(chat_id=None, text=None, parse_mode=None, disable_web_page_preview=None,
				disable_notification=None, reply_to_message_id=None, reply_markup=None,
				inline_keyboard=None, photo=None, caption=None, audio=None, duration=None,
				performer=None, title=None, document=None, sticker=None, video=None,
				width=None,height=None, voice=None, latitude=None, longitude=None,
				address=None, foursquare_id=None, phone_number=None,
				first_name=None, last_name=None, action=None, user_id=None, offset=None,
				limit=None, file__id=None, callback_querys_id=None, show_alert=None,
				inline_message_id=None, message_id=None, timeout=None, from_chat_id=None,
				inline_query_id=None, results=None, cache_time=None, is_personal=None,
				next_offset=None, switch_pm_text=None, switch_pm_parameter=None, file=None,
				name=None):

	querys = {}
	file_ = {}
	if chat_id:
		querys['chat_id'] = chat_id
	if text:
		querys['text'] = text
	if parse_mode:
		querys['parse_mode'] = parse_mode
	if disable_web_page_preview:
		querys['disable_web_page_preview'] = disable_web_page_preview
	if disable_notification:
		querys['disable_notification'] = disable_notification
	if reply_to_message_id:
		querys['reply_to_message_id'] = reply_to_message_id
	if reply_markup:
		querys['reply_markup'] = reply_markup
	if inline_keyboard:
		querys['reply_markup'] = '{"inline_keyboard":' + inline_keyboard + '}'
	if from_chat_id:
		querys['from_chat_id'] = from_chat_id
	if photo:
		file_['photo'] = photo
	if caption:
		querys['caption'] = caption
	if audio:
		file_['audio'] = audio
	if duration:
		querys['duration'] = duration
	if performer:
		querys['performer'] = performer
	if title:
		querys['title'] = title
	if document:
		file_['document'] = document
	if sticker:
		file_['sticker'] = sticker
	if video:
		file_['video'] = video
	if width:
		querys['width'] = width
	if height:
		querys['height'] = height
	if voice:
		file_['voice'] = voice
	if latitude:
		querys['latitude'] = latitude
	if longitude:
		querys['longitude'] = longitude
	if address:
		querys['address'] = address
	if foursquare_id:
		querys['foursquare_id'] = foursquare_id
	if phone_number:
		querys['phone_number'] = phone_number
	if first_name:
		querys['first_name'] = first_name
	if last_name:
		querys['last_name'] = last_name
	if action:
		querys['action'] = action
	if user_id:
		querys['user_id'] = user_id
	if offset:
		querys['offset'] = offset
	if limit:
		querys['limit'] = limit
	if file__id:
		querys['file__id'] = file__id
	if callback_querys_id:
		querys['callback_querys_id'] = callback_querys_id
	if show_alert:
		querys['show_alert'] = show_alert
	if inline_message_id:
		querys['inline_message_id'] = inline_message_id
	if message_id:
		querys['message_id'] = message_id
	if timeout:
		querys['timeout'] = timeout
	if name:
		querys['name'] = name
	if file:
		querys['file'] = file
	#Inline
	if inline_query_id:
		querys['inline_query_id'] = inline_query_id
	if results:
		querys['results'] = results
	if cache_time:
		querys['cache_time'] = cache_time
	if is_personal:
		querys['is_personal'] = is_personal
	if next_offset:
		querys['next_offset'] = next_offset
	if switch_pm_text:
		querys['switch_pm_text'] = switch_pm_text
	if switch_pm_parameter:
		querys['switch_pm_parameter'] = switch_pm_parameter
	return querys, file_

#https://core.telegram.org/bots/api/#available-methods
def getMe():
	return request_telgram('getMe')

def getUpdates(offset=None, limit=None, timeout=None):
	querys, file_ = check_querys(offset=offset,
							limit=limit,
							timeout=timeout)
	return request_telgram('getUpdates', querys, file_)

def sendMessage(chat_id=None, text=None, parse_mode=None, disable_web_page_preview=None,
				disable_notification=None, reply_to_message_id=None, reply_markup=None,
				inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							text=text,
							parse_mode=parse_mode,
							disable_web_page_preview=disable_web_page_preview,
							disable_notification=disable_notification,
							reply_to_message_id=reply_to_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('sendMessage', querys, file_)

def forwardMessage(chat_id=None, from_chat_id=None, disable_notification=None,
					message_id=None):

	querys, file_ = check_querys(chat_id=chat_id,
							from_chat_id=from_chat_id,
							disable_notification=disable_notification,
							message_id=message_id)
	return request_telgram('forwardMessage', querys, file_)

def sendPhoto(chat_id=None, photo=None, caption=None, disable_notification=None,
				reply_markup=None, inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							photo=photo,
							caption=caption,
							disable_notification=disable_notification,
							reply_to_message_id=reply_to_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('sendPhoto', querys, file_)

def sendAudio(chat_id=None, audio=None, duration=None, performer=None, title=None,
			disable_notification=None, reply_to_message_id=None, reply_markup=None,
			inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							audio=audio,
							duration=duration,
							performer=performer,
							title=title,
							disable_notification=disable_notification,
							reply_to_message_id=reply_to_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('sendAudio', querys, file_)

def sendDocument(chat_id=None, document=None, caption=None, disable_notification=None,
				reply_markup=None, inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							document=document,
							caption=caption,
							disable_notification=disable_notification,
							reply_to_message_id=reply_to_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('sendDocument', querys, file_)

def sendSticker(chat_id=None, sticker=None, disable_notification=None, reply_to_message_id=None,
				reply_markup=None, inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							sticker=sticker,
							disable_notification=disable_notification,
							reply_to_message_id=reply_to_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('sendSticker', querys, file_)

def sendVideo(chat_id=None, video=None, duration=None, width=None, height=None,
				caption=None, disable_notification=None, reply_to_message_id=None,
				reply_markup=None, inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							video=video,
							duration=duration,
							width=width,
							height=height,
							caption=caption,
							disable_notification=disable_notification,
							reply_to_message_id=reply_to_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('sendVideo', querys, file_)

def sendVoice(chat_id=None, voice=None, duration=None, disable_notification=None,
				reply_to_message_id=None, reply_markup=None, inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							voice=voice,
							duration=duration,
							disable_notification=disable_notification,
							reply_to_message_id=reply_to_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('sendVoice', querys, file_)

def sendLocation(chat_id=None, latitude=None, longitude=None, disable_notification=None,
				reply_to_message_id=None, reply_markup=None, inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							latitude=latitude,
							longitude=longitude,
							disable_notification=disable_notification,
							reply_to_message_id=reply_to_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('sendLocation', querys, file_)

def sendVenue(chat_id=None, latitude=None, longitude=None, title=None, address=None,
				foursquare_id=None, disable_notification=None, reply_markup=None,
				inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							latitude=latitude,
							longitude=longitude,
							title=title,
							address=address,
							foursquare_id=foursquare_id,
							disable_notification=disable_notification,
							reply_to_message_id=reply_to_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('sendVenue', querys, file_)

def sendContact(chat_id=None, phone_number=None, first_name=None, last_name=None,
				disable_notification=None, reply_to_message_id=None, reply_markup=None,
				inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							phone_number=phone_number,
							first_name=first_name,
							last_name=last_name,
							disable_notification=disable_notification,
							reply_to_message_id=reply_to_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('sendContact', querys, file_)

def sendChatAction(chat_id=None, action=None):

	querys, file_ = check_querys(chat_id=chat_id,
							action=action)
	return request_telgram('sendChatAction', querys, file_)

def sendFile(chat_id=None, file=None, name=None):

	querys, file_ = check_querys(chat_id=chat_id,
							file=file,
							name=name)
	return request_pwrtelgram('sendFile', querys, file_)

def getUserProfile_Photos(user_id=None, offset=None, limit=None):

	querys, file_ = check_querys(user_id=user_id,
							offset=offset,
							limit=limit)
	return request_telgram('getUserProfile_Photos', querys, file_)

def getfile_(file__id=None):

	querys, file_ = check_querys(file__id=file__id)
	return request_telgram('getfile_', querys, file_)

def kickChatMember(chat_id=None, user_id=None):

	querys, file_ = check_querys(chat_id=chat_id,
							user_id=user_id)
	return request_telgram('kickChatMember', querys, file_)

def leaveChat(chat_id=None):

	querys, file_ = check_querys(chat_id=chat_id)
	return request_telgram('leaveChat', querys, file_)

def unbanChatMember(chat_id=None, user_id=None):

	querys, file_ = check_querys(chat_id=chat_id,
							user_id=user_id)
	return request_telgram('unbanChatMember', querys, file_)

def getChat(chat_id=None):

	querys, file_ = check_querys(chat_id=chat_id)
	return request_telgram('getChat', querys, file_)

def getChatAdministrators(chat_id=None):

	querys, file_ = check_querys(chat_id=chat_id)
	return request_telgram('getChatAdministrators', querys, file_)

def getChatMembersCount(chat_id=None):

	querys, file_ = check_querys(chat_id=chat_id)
	return request_telgram('getChatMembersCount', querys, file_)

def getChatMember(chat_id=None, user_id=None):

	querys, file_ = check_querys(chat_id=chat_id,
							user_id=user_id)
	return request_telgram('getChatMember', querys, file_)

def answerInlinequerys(callback_querys_id=None, text=None, show_alert=None):

	querys, file_ = check_querys(callback_querys_id=callback_querys_id,
							text=text,
							show_alert=show_alert)
	return request_telgram('answerInlinequerys', querys, file_)

#https://core.telegram.org/bots/api/#updating-messages
def editMessageText(chat_id=None, message_id=None, inline_message_id=None, text=None,
				parse_mode=None, disable_web_page_preview=None, reply_markup=None,
				inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							message_id=message_id,
							inline_message_id=inline_message_id,
							text=text,
							parse_mode=parse_mode,
							disable_web_page_preview=disable_web_page_preview,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('editMessageText', querys, file_)

def editMessageCaption(chat_id=None, message_id=None, inline_message_id=None, caption=None,
				reply_markup=None, inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							message_id=message_id,
							inline_message_id=inline_message_id,
							caption=caption,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('editMessageCaption', querys, file_)

def editMessageReplyMarkup(chat_id=None, message_id=None, inline_message_id=None,
				reply_markup=None, inline_keyboard=None):

	querys, file_ = check_querys(chat_id=chat_id,
							message_id=message_id,
							inline_message_id=inline_message_id,
							reply_markup=reply_markup,
							inline_keyboard=inline_keyboard)
	return request_telgram('editMessageReplyMarkup', querys, file_)

#https://core.telegram.org/bots/api/#inline-mode
def sendInline(inline_query_id=None, results=None, cache_time=None, is_personal=None,
				next_offset=None, switch_pm_text=None, switch_pm_parameter=None):

	querys, file_ = check_querys(inline_query_id=inline_query_id,
							results=results,
							cache_time=cache_time,
							is_personal=is_personal,
							next_offset=next_offset,
							switch_pm_text=switch_pm_text,
							switch_pm_parameter=switch_pm_parameter)
	return request_telgram('answerInlineQuery', querys, file_)


import os
import re
import argparse
import numpy

parser = argparse.ArgumentParser()
parser.add_argument('--train_file', type=str, required=True, help='Finetuning file')
parser.add_argument('--dataset', type=str, required=True, help='Dataset')
parser.add_argument('--data_dir', type=str, required=True, help='Data Directory')
parser.add_argument('--suffix', type=str, required=True, help='Data Directory')
parser.add_argument('--prompt', type=str, required=True, help='Data Directory')
parser.add_argument('--template', type=str, required=True, help='Data Directory')
parser.add_argument('--gpu', type=str, default="0", help='GPU ids separated by "," to use for computation')

args = parser.parse_known_args()[0]

suffices = [args.suffix + "_9999", args.suffix + "_1337", args.suffix + "_2021", args.suffix + "_5555", args.suffix + "_42"]
seeds = ['42', '1337', '2021']

cmds = []
log_files = []
model_folders = []
for suffix in suffices:
    for seed in seeds:
        log_file = "logs/" + args.dataset + "/" + args.train_file.split('.')[0] + "_" + args.prompt + "_" + args.template + "_" + suffix + "_" + seed + ".txt"
        model_folder = "models/" + args.dataset + "/" + args.train_file.split('.')[0] + "_" + args.prompt + "_" + args.template + "_"  + suffix + "_" + seed
        predict_cmd = \
            "CUDA_VISIBLE_DEVICES=" + str(args.gpu) + \
            " python3 " + args.train_file + \
            " --dataset " + args.dataset + \
            " --data_dir " + args.data_dir + \
            " --model_folder " + model_folder + \
            " --device cuda:0" + \
            " --percent_filename_suffix " + suffix + \
            " --num_epochs 50" + \
            " --prompt " + args.prompt + \
            " --template " + args.template + \
            " --seed " + seed + " > " + log_file
        log_files.append(log_file)
        model_folders.append(model_folder)
        cmds.append(predict_cmd)
        # print(predict_cmd, "\n")
        # os.system(predict_cmd)

# for model_folder in model_folders:
#     rm_cmd = "rm -rf model_files/" + model_folder
#     os.system(rm_cmd)

ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
f1_scores = []
for i,file in enumerate(log_files):
    with open(file, 'r') as reader:
        for line in reader:
            pass
        last_line = line
        print(last_line)
        try:
            f1_scores.append(float(ansi_escape.sub('', last_line.split()[-1])))
        except:
            continue

averages = []
tmp_nums = []
for i, score in enumerate(f1_scores):
    tmp_nums.append(score)
    if len(tmp_nums) == 3:
        arr = numpy.array(tmp_nums)
        averages.append(numpy.mean(arr, axis=0))
        tmp_nums = []

print(averages)
arr = numpy.array(averages)
mean = numpy.mean(arr, axis=0)
std = numpy.std(arr, axis=0)
print("average: ", numpy.mean(arr, axis=0))
print("std: ", numpy.std(arr, axis=0))

with open(args.dataset + "_" + args.train_file.split('.')[0] + "_" + args.prompt + "_" + args.template + "_" + args.suffix + ".txt", 'w') as file:
    file.write("average: " + str(mean))
    file.write("std: " + str(std))


import PIL.Image, PIL.ImageDraw, PIL.ImageFont
import random

def drawBBox(img, format, bboxInfo, color):
    #img: pillow图像
    #format: 格式值，可以为0, 1
    #bboxInfo: 二维列表
    #   当format = 0，结构为[[xmin, ymin, xmax, ymax, classname],[...], ...]
    #   当format = 1，结构为[[xmin, ymin, xmax, ymax, classname, score], [...], ...]
    #color: 格式为(R, G, B)

    draw = PIL.ImageDraw.Draw(img)
    font_consola = PIL.ImageFont.truetype("./fonts/consola.ttf", 20)
    for obj in bboxInfo:
        draw.rectangle(xy = (obj[0], obj[1], obj[2], obj[3]), fill = None, outline = color, width = 2)
        objText = ""
        if format == 0:
            objText = obj[4]
        elif format == 1:
            objText = "{} [{:.2f}]".format(obj[4], obj[5])
        draw.text(xy = (obj[0], obj[1] - 20), text = objText, fill = color, font = font_consola)
    return img

def getRandomColor():
    return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))


import argparse
import json
import secrets

from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = "Load users [(name, email)] from a json file"

    def add_arguments(self, parser):
        parser.add_argument("file", type=argparse.FileType("r"))

    def handle(self, *args, **options):
        f = options["file"]

        from church.models import User

        nusers = 0
        with f:
            data = json.load(f)
            for username, firstname, lastname, email in data:
                token = secrets.token_hex(8)
                nusers += 1
                try:
                    User.objects.get(email=email)
                except User.DoesNotExist:
                    User.objects.create(
                        username=username,
                        first_name=firstname,
                        last_name=lastname,
                        email=email,
                        token=token,
                    )

        self.stdout.write(self.style.SUCCESS(f"Successfully created {nusers} users"))