import argparse
import math
import os
import random
import sys
import time
from copy import deepcopy
from datetime import datetime
from pathlib import Path
from collections import OrderedDict, namedtuple
from copy import copy

import numpy as np
import torch
import torch.distributed as dist
import torch.nn as nn
import yaml
from torch.cuda import amp
from torch.nn.parallel import DistributedDataParallel as DDP
from torch.optim import SGD, Adam, lr_scheduler
from tqdm import tqdm

import pandas as pd
import requests
from PIL import Image

###########   from export ###############3333

import json
import subprocess
from torch.utils.mobile_optimizer import optimize_for_mobile

##########    from detect   ###############
import cv2
import torch.backends.cudnn as cudnn

#display inference on ALL test images

FILE = Path(__file__).resolve()
ROOT = FILE.parents[0]  # YOLOv5 root directory
if str(ROOT) not in sys.path:
    sys.path.append(str(ROOT))  # add ROOT to PATH
ROOT = Path(os.path.relpath(ROOT, Path.cwd()))  # relative

print("train dataset path for example /content/yolov5/cokepepsi-3/data.yaml")
train_dataset_path='dataset/data.yaml'
#input()
#'/content/yolov5/cokepepsi-3/data.yaml'

print("test dataset path for example /content/yolov5/cokepepsi-3/test/images")
test_dataset_path='dataset/test/images'
#input()
#'/content/yolov5/cokepepsi-3/test/images'

# Opening JSON file
f_data = open('data.json')
data_f = json.load(f_data)

#print(data['epoch'],data['batch'])
 # Closing file
f_data.close()

print("enter  epoch number")
epoch=int(data_f['epoch'])
#input()

print("enter  batch size ")
batch=int(data_f['batch'])
#input()

print("enter  model type for example yolov5s.pt ")
model='yolov5s.pt'
#input()
#'yolov5s.pt'

print("enter  model height for example 416 ")
m_height=640
#int(input())

print("enter  model width for example 416 ")
m_width=640
#int(input())

import val  # for end-of-epoch mAP
from models.experimental import attempt_load
from models.yolo import Model

from models.common import Conv
from models.yolo import Detect
from utils.autoanchor import check_anchors
from utils.autobatch import check_train_batch_size
from utils.callbacks import Callbacks
from utils.datasets import create_dataloader
from utils.downloads import attempt_download
from utils.general import (LOGGER, check_dataset, check_file, check_git_status, check_img_size, check_requirements,
                           check_suffix, check_yaml, colorstr, get_latest_run, increment_path, init_seeds,
                           intersect_dicts, labels_to_class_weights, labels_to_image_weights, methods, one_cycle,
                           print_args, print_mutation, strip_optimizer)
from utils.loggers import Loggers
from utils.loggers.wandb.wandb_utils import check_wandb_resume
from utils.loss import ComputeLoss
from utils.metrics import fitness
from utils.plots import plot_evolve, plot_labels
from utils.torch_utils import EarlyStopping, ModelEMA, de_parallel, select_device, torch_distributed_zero_first

from utils.activations import SiLU
from utils.datasets import LoadImages
from utils.general import (LOGGER, check_dataset, check_img_size, check_requirements, colorstr, file_size, print_args,
                           url2file)
from utils.torch_utils import select_device

from models.common import DetectMultiBackend
from utils.datasets import IMG_FORMATS, VID_FORMATS, LoadImages, LoadStreams
from utils.general import (LOGGER, check_file, check_img_size, check_imshow, check_requirements, colorstr,
                           increment_path, non_max_suppression, print_args, scale_coords, strip_optimizer, xyxy2xywh)
from utils.plots import Annotator, colors, save_one_box
from utils.torch_utils import select_device, time_sync

LOCAL_RANK = int(os.getenv('LOCAL_RANK', -1))  # https://pytorch.org/docs/stable/elastic/run.html
RANK = int(os.getenv('RANK', -1))
WORLD_SIZE = int(os.getenv('WORLD_SIZE', 1))

############### train #############

def train(hyp,  # path/to/hyp.yaml or hyp dictionary
          opt,
          device,
          callbacks
          ):
    save_dir, epochs, batch_size, weights, single_cls, evolve, data, cfg, resume, noval, nosave, workers, freeze, = \
        Path(opt.save_dir), opt.epochs, opt.batch_size, opt.weights, opt.single_cls, opt.evolve, opt.data, opt.cfg, \
        opt.resume, opt.noval, opt.nosave, opt.workers, opt.freeze

    # Directories
    w = save_dir / 'weights'  # weights dir
    (w.parent if evolve else w).mkdir(parents=True, exist_ok=True)  # make dir
    last, best = w / 'last.pt', w / 'best.pt'

    # Hyperparameters
    if isinstance(hyp, str):
        with open(hyp, errors='ignore') as f:
            hyp = yaml.safe_load(f)  # load hyps dict
    LOGGER.info(colorstr('hyperparameters: ') + ', '.join(f'{k}={v}' for k, v in hyp.items()))

    # Save run settings
    if not evolve:
        with open(save_dir / 'hyp.yaml', 'w') as f:
            yaml.safe_dump(hyp, f, sort_keys=False)
        with open(save_dir / 'opt.yaml', 'w') as f:
            yaml.safe_dump(vars(opt), f, sort_keys=False)

    # Loggers
    data_dict = None
    if RANK in [-1, 0]:
        loggers = Loggers(save_dir, weights, opt, hyp, LOGGER)  # loggers instance
        if loggers.wandb:
            data_dict = loggers.wandb.data_dict
            if resume:
                weights, epochs, hyp = opt.weights, opt.epochs, opt.hyp

        # Register actions
        for k in methods(loggers):
            callbacks.register_action(k, callback=getattr(loggers, k))

    # Config
    plots = not evolve  # create plots
    cuda = device.type != 'cpu'
    init_seeds(1 + RANK)
    with torch_distributed_zero_first(LOCAL_RANK):
        data_dict = data_dict or check_dataset(data)  # check if None
    train_path, val_path = data_dict['train'], data_dict['val']
    nc = 1 if single_cls else int(data_dict['nc'])  # number of classes
    names = ['item'] if single_cls and len(data_dict['names']) != 1 else data_dict['names']  # class names
    assert len(names) == nc, f'{len(names)} names found for nc={nc} dataset in {data}'  # check
    is_coco = isinstance(val_path, str) and val_path.endswith('coco/val2017.txt')  # COCO dataset

    # Model
    check_suffix(weights, '.pt')  # check weights
    pretrained = weights.endswith('.pt')
    if pretrained:
        with torch_distributed_zero_first(LOCAL_RANK):
            weights = attempt_download(weights)  # download if not found locally
        ckpt = torch.load(weights, map_location=device)  # load checkpoint
        model = Model(cfg or ckpt['model'].yaml, ch=3, nc=nc, anchors=hyp.get('anchors')).to(device)  # create
        exclude = ['anchor'] if (cfg or hyp.get('anchors')) and not resume else []  # exclude keys
        csd = ckpt['model'].float().state_dict()  # checkpoint state_dict as FP32
        csd = intersect_dicts(csd, model.state_dict(), exclude=exclude)  # intersect
        model.load_state_dict(csd, strict=False)  # load
        LOGGER.info(f'Transferred {len(csd)}/{len(model.state_dict())} items from {weights}')  # report
    else:
        model = Model(cfg, ch=3, nc=nc, anchors=hyp.get('anchors')).to(device)  # create

    # Freeze
    freeze = [f'model.{x}.' for x in range(freeze)]  # layers to freeze
    for k, v in model.named_parameters():
        v.requires_grad = True  # train all layers
        if any(x in k for x in freeze):
            LOGGER.info(f'freezing {k}')
            v.requires_grad = False

    # Image size
    gs = max(int(model.stride.max()), 32)  # grid size (max stride)
    imgsz = check_img_size(opt.imgsz, gs, floor=gs * 2)  # verify imgsz is gs-multiple

    # Batch size
    if RANK == -1 and batch_size == -1:  # single-GPU only, estimate best batch size
        batch_size = check_train_batch_size(model, imgsz)

    # Optimizer
    nbs = 64  # nominal batch size
    accumulate = max(round(nbs / batch_size), 1)  # accumulate loss before optimizing
    hyp['weight_decay'] *= batch_size * accumulate / nbs  # scale weight_decay
    LOGGER.info(f"Scaled weight_decay = {hyp['weight_decay']}")

    g0, g1, g2 = [], [], []  # optimizer parameter groups
    for v in model.modules():
        if hasattr(v, 'bias') and isinstance(v.bias, nn.Parameter):  # bias
            g2.append(v.bias)
        if isinstance(v, nn.BatchNorm2d):  # weight (no decay)
            g0.append(v.weight)
        elif hasattr(v, 'weight') and isinstance(v.weight, nn.Parameter):  # weight (with decay)
            g1.append(v.weight)

    if opt.adam:
        optimizer = Adam(g0, lr=hyp['lr0'], betas=(hyp['momentum'], 0.999))  # adjust beta1 to momentum
    else:
        optimizer = SGD(g0, lr=hyp['lr0'], momentum=hyp['momentum'], nesterov=True)

    optimizer.add_param_group({'params': g1, 'weight_decay': hyp['weight_decay']})  # add g1 with weight_decay
    optimizer.add_param_group({'params': g2})  # add g2 (biases)
    LOGGER.info(f"{colorstr('optimizer:')} {type(optimizer).__name__} with parameter groups "
                f"{len(g0)} weight, {len(g1)} weight (no decay), {len(g2)} bias")
    del g0, g1, g2

    # Scheduler
    if opt.linear_lr:
        lf = lambda x: (1 - x / (epochs - 1)) * (1.0 - hyp['lrf']) + hyp['lrf']  # linear
    else:
        lf = one_cycle(1, hyp['lrf'], epochs)  # cosine 1->hyp['lrf']
    scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lf)  # plot_lr_scheduler(optimizer, scheduler, epochs)

    # EMA
    ema = ModelEMA(model) if RANK in [-1, 0] else None

    # Resume
    start_epoch, best_fitness = 0, 0.0
    if pretrained:
        # Optimizer
        if ckpt['optimizer'] is not None:
            optimizer.load_state_dict(ckpt['optimizer'])
            best_fitness = ckpt['best_fitness']

        # EMA
        if ema and ckpt.get('ema'):
            ema.ema.load_state_dict(ckpt['ema'].float().state_dict())
            ema.updates = ckpt['updates']

        # Epochs
        start_epoch = ckpt['epoch'] + 1
        if resume:
            assert start_epoch > 0, f'{weights} training to {epochs} epochs is finished, nothing to resume.'
        if epochs < start_epoch:
            LOGGER.info(f"{weights} has been trained for {ckpt['epoch']} epochs. Fine-tuning for {epochs} more epochs.")
            epochs += ckpt['epoch']  # finetune additional epochs

        del ckpt, csd

    # DP mode
    if cuda and RANK == -1 and torch.cuda.device_count() > 1:
        LOGGER.warning('WARNING: DP not recommended, use torch.distributed.run for best DDP Multi-GPU results.\n'
                       'See Multi-GPU Tutorial at https://github.com/ultralytics/yolov5/issues/475 to get started.')
        model = torch.nn.DataParallel(model)

    # SyncBatchNorm
    if opt.sync_bn and cuda and RANK != -1:
        model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(model).to(device)
        LOGGER.info('Using SyncBatchNorm()')

    # Trainloader
    train_loader, dataset = create_dataloader(train_path, imgsz, batch_size // WORLD_SIZE, gs, single_cls,
                                              hyp=hyp, augment=True, cache=opt.cache, rect=opt.rect, rank=LOCAL_RANK,
                                              workers=workers, image_weights=opt.image_weights, quad=opt.quad,
                                              prefix=colorstr('train: '), shuffle=True)
    mlc = int(np.concatenate(dataset.labels, 0)[:, 0].max())  # max label class
    nb = len(train_loader)  # number of batches
    assert mlc < nc, f'Label class {mlc} exceeds nc={nc} in {data}. Possible class labels are 0-{nc - 1}'

    # Process 0
    if RANK in [-1, 0]:
        val_loader = create_dataloader(val_path, imgsz, batch_size // WORLD_SIZE * 2, gs, single_cls,
                                       hyp=hyp, cache=None if noval else opt.cache, rect=True, rank=-1,
                                       workers=workers, pad=0.5,
                                       prefix=colorstr('val: '))[0]

        if not resume:
            labels = np.concatenate(dataset.labels, 0)
            # c = torch.tensor(labels[:, 0])  # classes
            # cf = torch.bincount(c.long(), minlength=nc) + 1.  # frequency
            # model._initialize_biases(cf.to(device))
            if plots:
                plot_labels(labels, names, save_dir)

            # Anchors
            if not opt.noautoanchor:
                check_anchors(dataset, model=model, thr=hyp['anchor_t'], imgsz=imgsz)
            model.half().float()  # pre-reduce anchor precision

        callbacks.run('on_pretrain_routine_end')

    # DDP mode
    if cuda and RANK != -1:
        model = DDP(model, device_ids=[LOCAL_RANK], output_device=LOCAL_RANK)

    # Model attributes
    nl = de_parallel(model).model[-1].nl  # number of detection layers (to scale hyps)
    hyp['box'] *= 3 / nl  # scale to layers
    hyp['cls'] *= nc / 80 * 3 / nl  # scale to classes and layers
    hyp['obj'] *= (imgsz / 640) ** 2 * 3 / nl  # scale to image size and layers
    hyp['label_smoothing'] = opt.label_smoothing
    model.nc = nc  # attach number of classes to model
    model.hyp = hyp  # attach hyperparameters to model
    model.class_weights = labels_to_class_weights(dataset.labels, nc).to(device) * nc  # attach class weights
    model.names = names

    # Start training
    t0 = time.time()
    nw = max(round(hyp['warmup_epochs'] * nb), 1000)  # number of warmup iterations, max(3 epochs, 1k iterations)
    # nw = min(nw, (epochs - start_epoch) / 2 * nb)  # limit warmup to < 1/2 of training
    last_opt_step = -1
    maps = np.zeros(nc)  # mAP per class
    results = (0, 0, 0, 0, 0, 0, 0)  # P, R, mAP@.5, mAP@.5-.95, val_loss(box, obj, cls)
    scheduler.last_epoch = start_epoch - 1  # do not move
    scaler = amp.GradScaler(enabled=cuda)
    stopper = EarlyStopping(patience=opt.patience)
    compute_loss = ComputeLoss(model)  # init loss class
    LOGGER.info(f'Image sizes {imgsz} train, {imgsz} val\n'
                f'Using {train_loader.num_workers * WORLD_SIZE} dataloader workers\n'
                f"Logging results to {colorstr('bold', save_dir)}\n"
                f'Starting training for {epochs} epochs...')
    for epoch in range(start_epoch, epochs):  # epoch ------------------------------------------------------------------
        model.train()

        # Update image weights (optional, single-GPU only)
        if opt.image_weights:
            cw = model.class_weights.cpu().numpy() * (1 - maps) ** 2 / nc  # class weights
            iw = labels_to_image_weights(dataset.labels, nc=nc, class_weights=cw)  # image weights
            dataset.indices = random.choices(range(dataset.n), weights=iw, k=dataset.n)  # rand weighted idx

        # Update mosaic border (optional)
        # b = int(random.uniform(0.25 * imgsz, 0.75 * imgsz + gs) // gs * gs)
        # dataset.mosaic_border = [b - imgsz, -b]  # height, width borders

        mloss = torch.zeros(3, device=device)  # mean losses
        if RANK != -1:
            train_loader.sampler.set_epoch(epoch)
        pbar = enumerate(train_loader)
        LOGGER.info(('\n' + '%10s' * 7) % ('Epoch', 'gpu_mem', 'box', 'obj', 'cls', 'labels', 'img_size'))
        if RANK in [-1, 0]:
            pbar = tqdm(pbar, total=nb, bar_format='{l_bar}{bar:10}{r_bar}{bar:-10b}')  # progress bar
        optimizer.zero_grad()
        for i, (imgs, targets, paths, _) in pbar:  # batch -------------------------------------------------------------
            ni = i + nb * epoch  # number integrated batches (since train start)
            imgs = imgs.to(device, non_blocking=True).float() / 255  # uint8 to float32, 0-255 to 0.0-1.0

            # Warmup
            if ni <= nw:
                xi = [0, nw]  # x interp
                # compute_loss.gr = np.interp(ni, xi, [0.0, 1.0])  # iou loss ratio (obj_loss = 1.0 or iou)
                accumulate = max(1, np.interp(ni, xi, [1, nbs / batch_size]).round())
                for j, x in enumerate(optimizer.param_groups):
                    # bias lr falls from 0.1 to lr0, all other lrs rise from 0.0 to lr0
                    x['lr'] = np.interp(ni, xi, [hyp['warmup_bias_lr'] if j == 2 else 0.0, x['initial_lr'] * lf(epoch)])
                    if 'momentum' in x:
                        x['momentum'] = np.interp(ni, xi, [hyp['warmup_momentum'], hyp['momentum']])

            # Multi-scale
            if opt.multi_scale:
                sz = random.randrange(imgsz * 0.5, imgsz * 1.5 + gs) // gs * gs  # size
                sf = sz / max(imgs.shape[2:])  # scale factor
                if sf != 1:
                    ns = [math.ceil(x * sf / gs) * gs for x in imgs.shape[2:]]  # new shape (stretched to gs-multiple)
                    imgs = nn.functional.interpolate(imgs, size=ns, mode='bilinear', align_corners=False)

            # Forward
            with amp.autocast(enabled=cuda):
                pred = model(imgs)  # forward
                loss, loss_items = compute_loss(pred, targets.to(device))  # loss scaled by batch_size
                if RANK != -1:
                    loss *= WORLD_SIZE  # gradient averaged between devices in DDP mode
                if opt.quad:
                    loss *= 4.

            # Backward
            scaler.scale(loss).backward()

            # Optimize
            if ni - last_opt_step >= accumulate:
                scaler.step(optimizer)  # optimizer.step
                scaler.update()
                optimizer.zero_grad()
                if ema:
                    ema.update(model)
                last_opt_step = ni

            # Log
            if RANK in [-1, 0]:
                mloss = (mloss * i + loss_items) / (i + 1)  # update mean losses
                mem = f'{torch.cuda.memory_reserved() / 1E9 if torch.cuda.is_available() else 0:.3g}G'  # (GB)
                pbar.set_description(('%10s' * 2 + '%10.4g' * 5) % (
                    f'{epoch}/{epochs - 1}', mem, *mloss, targets.shape[0], imgs.shape[-1]))
                callbacks.run('on_train_batch_end', ni, model, imgs, targets, paths, plots, opt.sync_bn)
            # end batch ------------------------------------------------------------------------------------------------

        # Scheduler
        lr = [x['lr'] for x in optimizer.param_groups]  # for loggers
        scheduler.step()

        if RANK in [-1, 0]:
            # mAP
            callbacks.run('on_train_epoch_end', epoch=epoch)
            ema.update_attr(model, include=['yaml', 'nc', 'hyp', 'names', 'stride', 'class_weights'])
            final_epoch = (epoch + 1 == epochs) or stopper.possible_stop
            if not noval or final_epoch:  # Calculate mAP
                results, maps, _ = val.run(data_dict,
                                           batch_size=batch_size // WORLD_SIZE * 2,
                                           imgsz=imgsz,
                                           model=ema.ema,
                                           single_cls=single_cls,
                                           dataloader=val_loader,
                                           save_dir=save_dir,
                                           plots=False,
                                           callbacks=callbacks,
                                           compute_loss=compute_loss)

            # Update best mAP
            fi = fitness(np.array(results).reshape(1, -1))  # weighted combination of [P, R, mAP@.5, mAP@.5-.95]
            if fi > best_fitness:
                best_fitness = fi
            log_vals = list(mloss) + list(results) + lr
            callbacks.run('on_fit_epoch_end', log_vals, epoch, best_fitness, fi)

            # Save model
            if (not nosave) or (final_epoch and not evolve):  # if save
                ckpt = {'epoch': epoch,
                        'best_fitness': best_fitness,
                        'model': deepcopy(de_parallel(model)).half(),
                        'ema': deepcopy(ema.ema).half(),
                        'updates': ema.updates,
                        'optimizer': optimizer.state_dict(),
                        'wandb_id': loggers.wandb.wandb_run.id if loggers.wandb else None,
                        'date': datetime.now().isoformat()}

                # Save last, best and delete
                torch.save(ckpt, last)
                if best_fitness == fi:
                    torch.save(ckpt, best)
                if (epoch > 0) and (opt.save_period > 0) and (epoch % opt.save_period == 0):
                    torch.save(ckpt, w / f'epoch{epoch}.pt')
                del ckpt
                callbacks.run('on_model_save', last, epoch, final_epoch, best_fitness, fi)

            # Stop Single-GPU
            if RANK == -1 and stopper(epoch=epoch, fitness=fi):
                break

            # Stop DDP TODO: known issues shttps://github.com/ultralytics/yolov5/pull/4576
            # stop = stopper(epoch=epoch, fitness=fi)
            # if RANK == 0:
            #    dist.broadcast_object_list([stop], 0)  # broadcast 'stop' to all ranks

        # Stop DPP
        # with torch_distributed_zero_first(RANK):
        # if stop:
        #    break  # must break all DDP ranks

        # end epoch ----------------------------------------------------------------------------------------------------
    # end training -----------------------------------------------------------------------------------------------------
    if RANK in [-1, 0]:
        LOGGER.info(f'\n{epoch - start_epoch + 1} epochs completed in {(time.time() - t0) / 3600:.3f} hours.')
        for f in last, best:
            if f.exists():
                strip_optimizer(f)  # strip optimizers
                if f is best:
                    LOGGER.info(f'\nValidating {f}...')
                    results, _, _ = val.run(data_dict,
                                            batch_size=batch_size // WORLD_SIZE * 2,
                                            imgsz=imgsz,
                                            model=attempt_load(f, device).half(),
                                            iou_thres=0.65 if is_coco else 0.60,  # best pycocotools results at 0.65
                                            single_cls=single_cls,
                                            dataloader=val_loader,
                                            save_dir=save_dir,
                                            save_json=is_coco,
                                            verbose=True,
                                            plots=True,
                                            callbacks=callbacks,
                                            compute_loss=compute_loss)  # val best model with plots
                    if is_coco:
                        callbacks.run('on_fit_epoch_end', list(mloss) + list(results) + lr, epoch, best_fitness, fi)

        callbacks.run('on_train_end', last, best, plots, epoch, results)
        LOGGER.info(f"Results saved to {colorstr('bold', save_dir)}")

    torch.cuda.empty_cache()
    return results

def parse_opttrain(known=False):
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', type=str, default=ROOT / model, help='initial weights path')
    parser.add_argument('--cfg', type=str, default='', help='model.yaml path')#data/coco128.yaml
    parser.add_argument('--data', type=str, default=ROOT/ train_dataset_path, help='dataset.yaml path')
    parser.add_argument('--hyp', type=str, default=ROOT / 'data/hyps/hyp.scratch.yaml', help='hyperparameters path')
    parser.add_argument('--epochs', type=int, default=epoch)
    parser.add_argument('--batch-size', type=int, default=batch, help='total batch size for all GPUs, -1 for autobatch')
    parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=int(m_height), help='train, val image size (pixels)')
    parser.add_argument('--rect', action='store_true', help='rectangular training')
    parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')
    parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
    parser.add_argument('--noval', action='store_true', help='only validate final epoch')
    parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')
    parser.add_argument('--evolve', type=int, nargs='?', const=300, help='evolve hyperparameters for x generations')
    parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
    parser.add_argument('--cache', type=str, nargs='?', const='ram', help='--cache images in "ram" (default) or "disk"')
    parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%')
    parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')
    parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')
    parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
    parser.add_argument('--workers', type=int, default=8, help='max dataloader workers (per RANK in DDP mode)')
    parser.add_argument('--project', default=ROOT / 'runs/train', help='save to project/name')
    parser.add_argument('--name', default='exp', help='save to project/name')
    parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
    parser.add_argument('--quad', action='store_true', help='quad dataloader')
    parser.add_argument('--linear-lr', action='store_true', help='linear LR')
    parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')
    parser.add_argument('--patience', type=int, default=100, help='EarlyStopping patience (epochs without improvement)')
    parser.add_argument('--freeze', type=int, default=0, help='Number of layers to freeze. backbone=10, all=24')
    parser.add_argument('--save-period', type=int, default=-1, help='Save checkpoint every x epochs (disabled if < 1)')
    parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')

    # Weights & Biases arguments
    parser.add_argument('--entity', default=None, help='W&B: Entity')
    parser.add_argument('--upload_dataset', nargs='?', const=True, default=False, help='W&B: Upload data, "val" option')
    parser.add_argument('--bbox_interval', type=int, default=-1, help='W&B: Set bounding-box image logging interval')
    parser.add_argument('--artifact_alias', type=str, default='latest', help='W&B: Version of dataset artifact to use')

    opt = parser.parse_known_args()[0] if known else parser.parse_args()
    return opt

def maintrain(opt, callbacks=Callbacks()):
    # Checks
    if RANK in [-1, 0]:
        print_args(FILE.stem, opt)
        check_git_status()
        check_requirements(exclude=['thop'])

    # Resume
    if opt.resume and not check_wandb_resume(opt) and not opt.evolve:  # resume an interrupted run
        ckpt = opt.resume if isinstance(opt.resume, str) else get_latest_run()  # specified or most recent path
        assert os.path.isfile(ckpt), 'ERROR: --resume checkpoint does not exist'
        with open(Path(ckpt).parent.parent / 'opt.yaml', errors='ignore') as f:
            opt = argparse.Namespace(**yaml.safe_load(f))  # replace
        opt.cfg, opt.weights, opt.resume = '', ckpt, True  # reinstate
        LOGGER.info(f'Resuming training from {ckpt}')
    else:
        opt.data, opt.cfg, opt.hyp, opt.weights, opt.project = \
            check_file(opt.data), check_yaml(opt.cfg), check_yaml(opt.hyp), str(opt.weights), str(opt.project)  # checks
        assert len(opt.cfg) or len(opt.weights), 'either --cfg or --weights must be specified'
        if opt.evolve:
            opt.project = str(ROOT / 'runs/evolve')
            opt.exist_ok, opt.resume = opt.resume, False  # pass resume to exist_ok and disable resume
        opt.save_dir = str(increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok))

    # DDP mode
    device = select_device(opt.device, batch_size=opt.batch_size)
    if LOCAL_RANK != -1:
        assert torch.cuda.device_count() > LOCAL_RANK, 'insufficient CUDA devices for DDP command'
        assert opt.batch_size % WORLD_SIZE == 0, '--batch-size must be multiple of CUDA device count'
        assert not opt.image_weights, '--image-weights argument is not compatible with DDP training'
        assert not opt.evolve, '--evolve argument is not compatible with DDP training'
        torch.cuda.set_device(LOCAL_RANK)
        device = torch.device('cuda', LOCAL_RANK)
        dist.init_process_group(backend="nccl" if dist.is_nccl_available() else "gloo")

    # Train
    if not opt.evolve:
        train(opt.hyp, opt, device, callbacks)
        if WORLD_SIZE > 1 and RANK == 0:
            LOGGER.info('Destroying process group... ')
            dist.destroy_process_group()

    # Evolve hyperparameters (optional)
    else:
        # Hyperparameter evolution metadata (mutation scale 0-1, lower_limit, upper_limit)
        meta = {'lr0': (1, 1e-5, 1e-1),  # initial learning rate (SGD=1E-2, Adam=1E-3)
                'lrf': (1, 0.01, 1.0),  # final OneCycleLR learning rate (lr0 * lrf)
                'momentum': (0.3, 0.6, 0.98),  # SGD momentum/Adam beta1
                'weight_decay': (1, 0.0, 0.001),  # optimizer weight decay
                'warmup_epochs': (1, 0.0, 5.0),  # warmup epochs (fractions ok)
                'warmup_momentum': (1, 0.0, 0.95),  # warmup initial momentum
                'warmup_bias_lr': (1, 0.0, 0.2),  # warmup initial bias lr
                'box': (1, 0.02, 0.2),  # box loss gain
                'cls': (1, 0.2, 4.0),  # cls loss gain
                'cls_pw': (1, 0.5, 2.0),  # cls BCELoss positive_weight
                'obj': (1, 0.2, 4.0),  # obj loss gain (scale with pixels)
                'obj_pw': (1, 0.5, 2.0),  # obj BCELoss positive_weight
                'iou_t': (0, 0.1, 0.7),  # IoU training threshold
                'anchor_t': (1, 2.0, 8.0),  # anchor-multiple threshold
                'anchors': (2, 2.0, 10.0),  # anchors per output grid (0 to ignore)
                'fl_gamma': (0, 0.0, 2.0),  # focal loss gamma (efficientDet default gamma=1.5)
                'hsv_h': (1, 0.0, 0.1),  # image HSV-Hue augmentation (fraction)
                'hsv_s': (1, 0.0, 0.9),  # image HSV-Saturation augmentation (fraction)
                'hsv_v': (1, 0.0, 0.9),  # image HSV-Value augmentation (fraction)
                'degrees': (1, 0.0, 45.0),  # image rotation (+/- deg)
                'translate': (1, 0.0, 0.9),  # image translation (+/- fraction)
                'scale': (1, 0.0, 0.9),  # image scale (+/- gain)
                'shear': (1, 0.0, 10.0),  # image shear (+/- deg)
                'perspective': (0, 0.0, 0.001),  # image perspective (+/- fraction), range 0-0.001
                'flipud': (1, 0.0, 1.0),  # image flip up-down (probability)
                'fliplr': (0, 0.0, 1.0),  # image flip left-right (probability)
                'mosaic': (1, 0.0, 1.0),  # image mixup (probability)
                'mixup': (1, 0.0, 1.0),  # image mixup (probability)
                'copy_paste': (1, 0.0, 1.0)}  # segment copy-paste (probability)

        with open(opt.hyp, errors='ignore') as f:
            hyp = yaml.safe_load(f)  # load hyps dict
            if 'anchors' not in hyp:  # anchors commented in hyp.yaml
                hyp['anchors'] = 3
        opt.noval, opt.nosave, save_dir = True, True, Path(opt.save_dir)  # only val/save final epoch
        # ei = [isinstance(x, (int, float)) for x in hyp.values()]  # evolvable indices
        evolve_yaml, evolve_csv = save_dir / 'hyp_evolve.yaml', save_dir / 'evolve.csv'
        if opt.bucket:
            os.system(f'gsutil cp gs://{opt.bucket}/evolve.csv {save_dir}')  # download evolve.csv if exists

        for _ in range(opt.evolve):  # generations to evolve
            if evolve_csv.exists():  # if evolve.csv exists: select best hyps and mutate
                # Select parent(s)
                parent = 'single'  # parent selection method: 'single' or 'weighted'
                x = np.loadtxt(evolve_csv, ndmin=2, delimiter=',', skiprows=1)
                n = min(5, len(x))  # number of previous results to consider
                x = x[np.argsort(-fitness(x))][:n]  # top n mutations
                w = fitness(x) - fitness(x).min() + 1E-6  # weights (sum > 0)
                if parent == 'single' or len(x) == 1:
                    # x = x[random.randint(0, n - 1)]  # random selection
                    x = x[random.choices(range(n), weights=w)[0]]  # weighted selection
                elif parent == 'weighted':
                    x = (x * w.reshape(n, 1)).sum(0) / w.sum()  # weighted combination

                # Mutate
                mp, s = 0.8, 0.2  # mutation probability, sigma
                npr = np.random
                npr.seed(int(time.time()))
                g = np.array([meta[k][0] for k in hyp.keys()])  # gains 0-1
                ng = len(meta)
                v = np.ones(ng)
                while all(v == 1):  # mutate until a change occurs (prevent duplicates)
                    v = (g * (npr.random(ng) < mp) * npr.randn(ng) * npr.random() * s + 1).clip(0.3, 3.0)
                for i, k in enumerate(hyp.keys()):  # plt.hist(v.ravel(), 300)
                    hyp[k] = float(x[i + 7] * v[i])  # mutate

            # Constrain to limits
            for k, v in meta.items():
                hyp[k] = max(hyp[k], v[1])  # lower limit
                hyp[k] = min(hyp[k], v[2])  # upper limit
                hyp[k] = round(hyp[k], 5)  # significant digits

            # Train mutation
            results = train(hyp.copy(), opt, device, callbacks)

            # Write mutation results
            print_mutation(results, hyp.copy(), save_dir, opt.bucket)

        # Plot results
        plot_evolve(evolve_csv)
        LOGGER.info(f'Hyperparameter evolution finished\n'
                    f"Results saved to {colorstr('bold', save_dir)}\n"
                    f'Use best hyperparameters example: $ python train.py --hyp {evolve_yaml}')

def runtrain(**kwargs):
    # Usage: import train; train.run(data='coco128.yaml', imgsz=320, weights='yolov5m.pt')
    opt = parse_opttrain(True)
    for k, v in kwargs.items():
        setattr(opt, k, v)
    maintrain(opt)

#####################   export start ##################33

def export_torchscript(model, im, file, optimize, prefix=colorstr('TorchScript:')):
    # YOLOv5 TorchScript model export
    try:
        LOGGER.info(f'\n{prefix} starting export with torch {torch.__version__}...')
        f = file.with_suffix('.torchscript')

        ts = torch.jit.trace(model, im, strict=False)
        d = {"shape": im.shape, "stride": int(max(model.stride)), "names": model.names}
        extra_files = {'config.txt': json.dumps(d)}  # torch._C.ExtraFilesMap()
        (optimize_for_mobile(ts) if optimize else ts).save(str(f), _extra_files=extra_files)

        LOGGER.info(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')
    except Exception as e:
        LOGGER.info(f'{prefix} export failure: {e}')

def export_onnx(model, im, file, opset, train, dynamic, simplify, prefix=colorstr('ONNX:')):
    # YOLOv5 ONNX export
    try:
        check_requirements(('onnx',))
        import onnx

        LOGGER.info(f'\n{prefix} starting export with onnx {onnx.__version__}...')
        f = file.with_suffix('.onnx')

        torch.onnx.export(model, im, f, verbose=False, opset_version=opset,
                          training=torch.onnx.TrainingMode.TRAINING if train else torch.onnx.TrainingMode.EVAL,
                          do_constant_folding=not train,
                          input_names=['images'],
                          output_names=['output'],
                          dynamic_axes={'images': {0: 'batch', 2: 'height', 3: 'width'},  # shape(1,3,640,640)
                                        'output': {0: 'batch', 1: 'anchors'}  # shape(1,25200,85)
                                        } if dynamic else None)

        # Checks
        model_onnx = onnx.load(f)  # load onnx model
        onnx.checker.check_model(model_onnx)  # check onnx model
        # LOGGER.info(onnx.helper.printable_graph(model_onnx.graph))  # print

        # Simplify
        if simplify:
            try:
                check_requirements(('onnx-simplifier',))
                import onnxsim

                LOGGER.info(f'{prefix} simplifying with onnx-simplifier {onnxsim.__version__}...')
                model_onnx, check = onnxsim.simplify(
                    model_onnx,
                    dynamic_input_shape=dynamic,
                    input_shapes={'images': list(im.shape)} if dynamic else None)
                assert check, 'assert check failed'
                onnx.save(model_onnx, f)
            except Exception as e:
                LOGGER.info(f'{prefix} simplifier failure: {e}')
        LOGGER.info(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')
        LOGGER.info(f"{prefix} run --dynamic ONNX model inference with: 'python detect.py --weights {f}'")
    except Exception as e:
        LOGGER.info(f'{prefix} export failure: {e}')

def export_coreml(model, im, file, prefix=colorstr('CoreML:')):
    # YOLOv5 CoreML export
    ct_model = None
    try:
        check_requirements(('coremltools',))
        import coremltools as ct

        LOGGER.info(f'\n{prefix} starting export with coremltools {ct.__version__}...')
        f = file.with_suffix('.mlmodel')

        model.train()  # CoreML exports should be placed in model.train() mode
        ts = torch.jit.trace(model, im, strict=False)  # TorchScript model
        ct_model = ct.convert(ts, inputs=[ct.ImageType('image', shape=im.shape, scale=1 / 255, bias=[0, 0, 0])])
        ct_model.save(f)

        LOGGER.info(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')
    except Exception as e:
        LOGGER.info(f'\n{prefix} export failure: {e}')

    return ct_model

def export_saved_model(model, im, file, dynamic,
                       tf_nms=False, agnostic_nms=False, topk_per_class=100, topk_all=100, iou_thres=0.45,
                       conf_thres=0.25, prefix=colorstr('TensorFlow saved_model:')):
    # YOLOv5 TensorFlow saved_model export
    keras_model = None
    try:
        import tensorflow as tf
        from tensorflow import keras

        from models.tf import TFDetect, TFModel

        LOGGER.info(f'\n{prefix} starting export with tensorflow {tf.__version__}...')
        f = str(file).replace('.pt', '_saved_model')
        batch_size, ch, *imgsz = list(im.shape)  # BCHW

        tf_model = TFModel(cfg=model.yaml, model=model, nc=model.nc, imgsz=imgsz)
        im = tf.zeros((batch_size, *imgsz, 3))  # BHWC order for TensorFlow
        y = tf_model.predict(im, tf_nms, agnostic_nms, topk_per_class, topk_all, iou_thres, conf_thres)
        inputs = keras.Input(shape=(*imgsz, 3), batch_size=None if dynamic else batch_size)
        outputs = tf_model.predict(inputs, tf_nms, agnostic_nms, topk_per_class, topk_all, iou_thres, conf_thres)
        keras_model = keras.Model(inputs=inputs, outputs=outputs)
        keras_model.trainable = False
        keras_model.summary()
        keras_model.save(f, save_format='tf')

        LOGGER.info(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')
    except Exception as e:
        LOGGER.info(f'\n{prefix} export failure: {e}')

    return keras_model

def export_pb(keras_model, im, file, prefix=colorstr('TensorFlow GraphDef:')):
    # YOLOv5 TensorFlow GraphDef *.pb export https://github.com/leimao/Frozen_Graph_TensorFlow
    try:
        import tensorflow as tf
        from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2

        LOGGER.info(f'\n{prefix} starting export with tensorflow {tf.__version__}...')
        f = file.with_suffix('.pb')

        m = tf.function(lambda x: keras_model(x))  # full model
        m = m.get_concrete_function(tf.TensorSpec(keras_model.inputs[0].shape, keras_model.inputs[0].dtype))
        frozen_func = convert_variables_to_constants_v2(m)
        frozen_func.graph.as_graph_def()
        tf.io.write_graph(graph_or_graph_def=frozen_func.graph, logdir=str(f.parent), name=f.name, as_text=False)

        LOGGER.info(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')
    except Exception as e:
        LOGGER.info(f'\n{prefix} export failure: {e}')

def export_tflite(keras_model, im, file, int8, data, ncalib, prefix=colorstr('TensorFlow Lite:')):
    # YOLOv5 TensorFlow Lite export
    try:
        import tensorflow as tf

        from models.tf import representative_dataset_gen

        LOGGER.info(f'\n{prefix} starting export with tensorflow {tf.__version__}...')
        batch_size, ch, *imgsz = list(im.shape)  # BCHW
        f = str(file).replace('.pt', '-fp16.tflite')

        converter = tf.lite.TFLiteConverter.from_keras_model(keras_model)
        converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS]
        converter.target_spec.supported_types = [tf.float16]
        converter.optimizations = [tf.lite.Optimize.DEFAULT]
        if int8:
            dataset = LoadImages(check_dataset(data)['train'], img_size=imgsz, auto=False)  # representative data
            converter.representative_dataset = lambda: representative_dataset_gen(dataset, ncalib)
            converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
            converter.target_spec.supported_types = []
            converter.inference_input_type = tf.uint8  # or tf.int8
            converter.inference_output_type = tf.uint8  # or tf.int8
            converter.experimental_new_quantizer = False
            f = str(file).replace('.pt', '-int8.tflite')

        tflite_model = converter.convert()
        open(f, "wb").write(tflite_model)
        LOGGER.info(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')

    except Exception as e:
        LOGGER.info(f'\n{prefix} export failure: {e}')

def export_tfjs(keras_model, im, file, prefix=colorstr('TensorFlow.js:')):
    # YOLOv5 TensorFlow.js export
    try:
        check_requirements(('tensorflowjs',))
        import re

        import tensorflowjs as tfjs

        LOGGER.info(f'\n{prefix} starting export with tensorflowjs {tfjs.__version__}...')
        f = str(file).replace('.pt', '_web_model')  # js dir
        f_pb = file.with_suffix('.pb')  # *.pb path
        f_json = f + '/model.json'  # *.json path

        cmd = f"tensorflowjs_converter --input_format=tf_frozen_model " \
              f"--output_node_names='Identity,Identity_1,Identity_2,Identity_3' {f_pb} {f}"
        subprocess.run(cmd, shell=True)

        json = open(f_json).read()
        with open(f_json, 'w') as j:  # sort JSON Identity_* in ascending order
            subst = re.sub(
                r'{"outputs": {"Identity.?.?": {"name": "Identity.?.?"}, '
                r'"Identity.?.?": {"name": "Identity.?.?"}, '
                r'"Identity.?.?": {"name": "Identity.?.?"}, '
                r'"Identity.?.?": {"name": "Identity.?.?"}}}',
                r'{"outputs": {"Identity": {"name": "Identity"}, '
                r'"Identity_1": {"name": "Identity_1"}, '
                r'"Identity_2": {"name": "Identity_2"}, '
                r'"Identity_3": {"name": "Identity_3"}}}',
                json)
            j.write(subst)

        LOGGER.info(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')
    except Exception as e:
        LOGGER.info(f'\n{prefix} export failure: {e}')

def export_engine(model, im, file, train, half, simplify, workspace=4, verbose=False, prefix=colorstr('TensorRT:')):
    try:
        check_requirements(('tensorrt',))
        import tensorrt as trt

        opset = (12, 13)[trt.__version__[0] == '8']  # test on TensorRT 7.x and 8.x
        export_onnx(model, im, file, opset, train, False, simplify)
        onnx = file.with_suffix('.onnx')
        assert onnx.exists(), f'failed to export ONNX file: {onnx}'

        LOGGER.info(f'\n{prefix} starting export with TensorRT {trt.__version__}...')
        f = file.with_suffix('.engine')  # TensorRT engine file
        logger = trt.Logger(trt.Logger.INFO)
        if verbose:
            logger.min_severity = trt.Logger.Severity.VERBOSE

        builder = trt.Builder(logger)
        config = builder.create_builder_config()
        config.max_workspace_size = workspace * 1 << 30

        flag = (1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
        network = builder.create_network(flag)
        parser = trt.OnnxParser(network, logger)
        if not parser.parse_from_file(str(onnx)):
            raise RuntimeError(f'failed to load ONNX file: {onnx}')

        inputs = [network.get_input(i) for i in range(network.num_inputs)]
        outputs = [network.get_output(i) for i in range(network.num_outputs)]
        LOGGER.info(f'{prefix} Network Description:')
        for inp in inputs:
            LOGGER.info(f'{prefix}\tinput "{inp.name}" with shape {inp.shape} and dtype {inp.dtype}')
        for out in outputs:
            LOGGER.info(f'{prefix}\toutput "{out.name}" with shape {out.shape} and dtype {out.dtype}')

        half &= builder.platform_has_fast_fp16
        LOGGER.info(f'{prefix} building FP{16 if half else 32} engine in {f}')
        if half:
            config.set_flag(trt.BuilderFlag.FP16)
        with builder.build_engine(network, config) as engine, open(f, 'wb') as t:
            t.write(engine.serialize())
        LOGGER.info(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')

    except Exception as e:
        LOGGER.info(f'\n{prefix} export failure: {e}')

@torch.no_grad()
def runexport(data=ROOT / 'data/coco128.yaml',  # 'dataset.yaml path'
        weights=ROOT / 'yolov5s.pt',  # weights path
        imgsz=(640, 640),  # image (height, width)
        batch_size=1,  # batch size
        device='cpu',  # cuda device, i.e. 0 or 0,1,2,3 or cpu
        include=('torchscript', 'onnx', 'coreml'),  # include formats
        half=False,  # FP16 half-precision export
        inplace=False,  # set YOLOv5 Detect() inplace=True
        train=False,  # model.train() mode
        optimize=False,  # TorchScript: optimize for mobile
        int8=False,  # CoreML/TF INT8 quantization
        dynamic=False,  # ONNX/TF: dynamic axes
        simplify=False,  # ONNX: simplify model
        opset=12,  # ONNX: opset version
        verbose=False,  # TensorRT: verbose log
        workspace=4,  # TensorRT: workspace size (GB)
        topk_per_class=100,  # TF.js NMS: topk per class to keep
        topk_all=100,  # TF.js NMS: topk for all classes to keep
        iou_thres=0.45,  # TF.js NMS: IoU threshold
        conf_thres=0.25  # TF.js NMS: confidence threshold
        ):
    t = time.time()
    include = [x.lower() for x in include]
    tf_exports = list(x in include for x in ('saved_model', 'pb', 'tflite', 'tfjs'))  # TensorFlow exports
    imgsz *= 2 if len(imgsz) == 1 else 1  # expand
    file = Path(url2file(weights) if str(weights).startswith(('http:/', 'https:/')) else weights)

    # Load PyTorch model
    device = select_device(device)
    assert not (device.type == 'cpu' and half), '--half only compatible with GPU export, i.e. use --device 0'
    model = attempt_load(weights, map_location=device, inplace=True, fuse=True)  # load FP32 model
    nc, names = model.nc, model.names  # number of classes, class names

    # Input
    gs = int(max(model.stride))  # grid size (max stride)
    imgsz = [check_img_size(x, gs) for x in imgsz]  # verify img_size are gs-multiples
    im = torch.zeros(batch_size, 3, *imgsz).to(device)  # image size(1,3,320,192) BCHW iDetection

    # Update model
    if half:
        im, model = im.half(), model.half()  # to FP16
    model.train() if train else model.eval()  # training mode = no Detect() layer grid construction
    for k, m in model.named_modules():
        if isinstance(m, Conv):  # assign export-friendly activations
            if isinstance(m.act, nn.SiLU):
                m.act = SiLU()
        elif isinstance(m, Detect):
            m.inplace = inplace
            m.onnx_dynamic = dynamic
            # m.forward = m.forward_export  # assign forward (optional)

    for _ in range(2):
        y = model(im)  # dry runs
    LOGGER.info(f"\n{colorstr('PyTorch:')} starting from {file} ({file_size(file):.1f} MB)")

    # Exports
    if 'torchscript' in include:
        export_torchscript(model, im, file, optimize)
    if 'onnx' in include:
        export_onnx(model, im, file, opset, train, dynamic, simplify)
    if 'engine' in include:
        export_engine(model, im, file, train, half, simplify, workspace, verbose)
    if 'coreml' in include:
        export_coreml(model, im, file)

    # TensorFlow Exports
    if any(tf_exports):
        pb, tflite, tfjs = tf_exports[1:]
        assert not (tflite and tfjs), 'TFLite and TF.js models must be exported separately, please pass only one type.'
        model = export_saved_model(model, im, file, dynamic, tf_nms=tfjs, agnostic_nms=tfjs,
                                   topk_per_class=topk_per_class, topk_all=topk_all, conf_thres=conf_thres,
                                   iou_thres=iou_thres)  # keras model
        if pb or tfjs:  # pb prerequisite to tfjs
            export_pb(model, im, file)
        if tflite:
            export_tflite(model, im, file, int8=int8, data=data, ncalib=100)
        if tfjs:
            export_tfjs(model, im, file)

    # Finish
    LOGGER.info(f'\nExport complete ({time.time() - t:.2f}s)'
                f"\nResults saved to {colorstr('bold', file.parent.resolve())}"
                f'\nVisualize with https://netron.app')

def parse_optexport():
    parser = argparse.ArgumentParser()#  yolov5s.pt  {dataset.location}/data.yaml
    parser.add_argument('--data', type=str, default=ROOT / train_dataset_path, help='dataset.yaml path')
    parser.add_argument('--weights', nargs='+', type=str, default=ROOT / best_weight_path, help='model.pt path(s)')
    parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[m_height,m_width], help='image (h, w)')
    parser.add_argument('--batch-size', type=int, default=1, help='batch size')
    parser.add_argument('--device', default='cpu', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--half', action='store_true', help='FP16 half-precision export')
    parser.add_argument('--inplace', action='store_true', help='set YOLOv5 Detect() inplace=True')
    parser.add_argument('--train', action='store_true', help='model.train() mode')
    parser.add_argument('--optimize', action='store_true', help='TorchScript: optimize for mobile')
    parser.add_argument('--int8', action='store_true', help='CoreML/TF INT8 quantization')
    parser.add_argument('--dynamic', action='store_true', help='ONNX/TF: dynamic axes')
    parser.add_argument('--simplify', action='store_true', help='ONNX: simplify model')
    parser.add_argument('--opset', type=int, default=14, help='ONNX: opset version')
    parser.add_argument('--verbose', action='store_true', help='TensorRT: verbose log')
    parser.add_argument('--workspace', type=int, default=4, help='TensorRT: workspace size (GB)')
    parser.add_argument('--topk-per-class', type=int, default=100, help='TF.js NMS: topk per class to keep')
    parser.add_argument('--topk-all', type=int, default=100, help='TF.js NMS: topk for all classes to keep')
    parser.add_argument('--iou-thres', type=float, default=0.45, help='TF.js NMS: IoU threshold')
    parser.add_argument('--conf-thres', type=float, default=0.25, help='TF.js NMS: confidence threshold')
    parser.add_argument('--include', nargs='+',
                        default=['tfjs'],
                        help='available formats are (torchscript, onnx, engine, coreml,torchscript, onnx saved_model, pb, tflite)')
    opt = parser.parse_args()
    print_args(FILE.stem, opt)
    return opt

def mainexport(opt):
    for opt.weights in (opt.weights if isinstance(opt.weights, list) else [opt.weights]):
        runexport(**vars(opt))

###############    detect start ####################33

@torch.no_grad()
def rundetect(weights=ROOT / 'yolov5s.pt',  # model.pt path(s)
        source=ROOT / 'data/images',  # file/dir/URL/glob, 0 for webcam
        imgsz=640,  # inference size (pixels)
        conf_thres=0.25,  # confidence threshold
        iou_thres=0.45,  # NMS IOU threshold
        max_det=1000,  # maximum detections per image
        device='',  # cuda device, i.e. 0 or 0,1,2,3 or cpu
        view_img=False,  # show results
        save_txt=False,  # save results to *.txt
        save_conf=False,  # save confidences in --save-txt labels
        save_crop=False,  # save cropped prediction boxes
        nosave=False,  # do not save images/videos
        classes=None,  # filter by class: --class 0, or --class 0 2 3
        agnostic_nms=False,  # class-agnostic NMS
        augment=False,  # augmented inference
        visualize=False,  # visualize features
        update=False,  # update all models
        project=ROOT / 'runs/detect',  # save results to project/name
        name='exp',  # save results to project/name
        exist_ok=False,  # existing project/name ok, do not increment
        line_thickness=3,  # bounding box thickness (pixels)
        hide_labels=False,  # hide labels
        hide_conf=False,  # hide confidences
        half=False,  # use FP16 half-precision inference
        dnn=False,  # use OpenCV DNN for ONNX inference
        ):
    source = str(source)
    save_img = not nosave and not source.endswith('.txt')  # save inference images
    is_file = Path(source).suffix[1:] in (IMG_FORMATS + VID_FORMATS)
    is_url = source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://'))
    webcam = source.isnumeric() or source.endswith('.txt') or (is_url and not is_file)
    if is_url and is_file:
        source = check_file(source)  # download

    # Directories
    save_dir = increment_path(Path(project) / name, exist_ok=exist_ok)  # increment run
    (save_dir / 'labels' if save_txt else save_dir).mkdir(parents=True, exist_ok=True)  # make dir

    # Load model
    device = select_device(device)
    model = DetectMultiBackend(weights, device=device, dnn=dnn)
    stride, names, pt, jit, onnx, engine = model.stride, model.names, model.pt, model.jit, model.onnx, model.engine
    imgsz = check_img_size(imgsz, s=stride)  # check image size

    # Half
    half &= (pt or jit or engine) and device.type != 'cpu'  # half precision only supported by PyTorch on CUDA
    if pt or jit:
        model.model.half() if half else model.model.float()

    # Dataloader
    if webcam:
        view_img = check_imshow()
        cudnn.benchmark = True  # set True to speed up constant image size inference
        dataset = LoadStreams(source, img_size=imgsz, stride=stride, auto=pt)
        bs = len(dataset)  # batch_size
    else:
        dataset = LoadImages(source, img_size=imgsz, stride=stride, auto=pt)
        bs = 1  # batch_size
    vid_path, vid_writer = [None] * bs, [None] * bs

    # Run inference
    model.warmup(imgsz=(1, 3, *imgsz), half=half)  # warmup
    dt, seen = [0.0, 0.0, 0.0], 0
    for path, im, im0s, vid_cap, s in dataset:
        t1 = time_sync()
        im = torch.from_numpy(im).to(device)
        im = im.half() if half else im.float()  # uint8 to fp16/32
        im /= 255  # 0 - 255 to 0.0 - 1.0
        if len(im.shape) == 3:
            im = im[None]  # expand for batch dim
        t2 = time_sync()
        dt[0] += t2 - t1

        # Inference
        visualize = increment_path(save_dir / Path(path).stem, mkdir=True) if visualize else False
        pred = model(im, augment=augment, visualize=visualize)
        t3 = time_sync()
        dt[1] += t3 - t2

        # NMS
        pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)
        dt[2] += time_sync() - t3

        # Second-stage classifier (optional)
        # pred = utils.general.apply_classifier(pred, classifier_model, im, im0s)

        # Process predictions
        for i, det in enumerate(pred):  # per image
            seen += 1
            if webcam:  # batch_size >= 1
                p, im0, frame = path[i], im0s[i].copy(), dataset.count
                s += f'{i}: '
            else:
                p, im0, frame = path, im0s.copy(), getattr(dataset, 'frame', 0)

            p = Path(p)  # to Path
            save_path = str(save_dir / p.name)  # im.jpg
            txt_path = str(save_dir / 'labels' / p.stem) + ('' if dataset.mode == 'image' else f'_{frame}')  # im.txt
            s += '%gx%g ' % im.shape[2:]  # print string
            gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  # normalization gain whwh
            imc = im0.copy() if save_crop else im0  # for save_crop
            annotator = Annotator(im0, line_width=line_thickness, example=str(names))
            if len(det):
                # Rescale boxes from img_size to im0 size
                det[:, :4] = scale_coords(im.shape[2:], det[:, :4], im0.shape).round()

                # Print results
                for c in det[:, -1].unique():
                    n = (det[:, -1] == c).sum()  # detections per class
                    s += f"{n} {names[int(c)]}{'s' * (n > 1)}, "  # add to string

                # Write results
                for *xyxy, conf, cls in reversed(det):
                    if save_txt:  # Write to file
                        xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()  # normalized xywh
                        line = (cls, *xywh, conf) if save_conf else (cls, *xywh)  # label format
                        with open(txt_path + '.txt', 'a') as f:
                            f.write(('%g ' * len(line)).rstrip() % line + '\n')

                    if save_img or save_crop or view_img:  # Add bbox to image
                        c = int(cls)  # integer class
                        label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')
                        annotator.box_label(xyxy, label, color=colors(c, True))
                        if save_crop:
                            save_one_box(xyxy, imc, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg', BGR=True)

            # Print time (inference-only)
            LOGGER.info(f'{s}Done. ({t3 - t2:.3f}s)')

            # Stream results
            im0 = annotator.result()
            if view_img:
                cv2.imshow(str(p), im0)
                cv2.waitKey(1)  # 1 millisecond

            # Save results (image with detections)
            if save_img:
                if dataset.mode == 'image':
                    cv2.imwrite(save_path, im0)
                else:  # 'video' or 'stream'
                    if vid_path[i] != save_path:  # new video
                        vid_path[i] = save_path
                        if isinstance(vid_writer[i], cv2.VideoWriter):
                            vid_writer[i].release()  # release previous video writer
                        if vid_cap:  # video
                            fps = vid_cap.get(cv2.CAP_PROP_FPS)
                            w = int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
                            h = int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
                        else:  # stream
                            fps, w, h = 30, im0.shape[1], im0.shape[0]
                            save_path += '.mp4'
                        vid_writer[i] = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
                    vid_writer[i].write(im0)

    # Print results
    t = tuple(x / seen * 1E3 for x in dt)  # speeds per image
    LOGGER.info(f'Speed: %.1fms pre-process, %.1fms inference, %.1fms NMS per image at shape {(1, 3, *imgsz)}' % t)
    if save_txt or save_img:
        s = f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir / 'labels'}" if save_txt else ''
        LOGGER.info(f"Results saved to {colorstr('bold', save_dir)}{s}")
    if update:
        strip_optimizer(weights)  # update model (to fix SourceChangeWarning)

#/content/yolov5/coke-1/data.yaml
def parse_optdetect():
    parser = argparse.ArgumentParser()#yolov5s.pt data/image {dataset.location}/test/images '{dataset.location}+"/data.yaml"'
    parser.add_argument('--weights', nargs='+', type=str, default=ROOT / best_weight_path, help='model path(s)')
    parser.add_argument('--source', type=str, default=ROOT / test_dataset_path, help='file/dir/URL/glob, 0 for webcam')
    parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[m_height,m_width], help='inference size h,w')
    parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold')
    parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold')
    parser.add_argument('--max-det', type=int, default=1000, help='maximum detections per image')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--view-img', action='store_true', help='show results')
    parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
    parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
    parser.add_argument('--save-crop', action='store_true', help='save cropped prediction boxes')
    parser.add_argument('--nosave', action='store_true', help='do not save images/videos')
    parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --classes 0, or --classes 0 2 3')
    parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
    parser.add_argument('--augment', action='store_true', help='augmented inference')
    parser.add_argument('--visualize', action='store_true', help='visualize features')
    parser.add_argument('--update', action='store_true', help='update all models')
    parser.add_argument('--project', default=ROOT / 'runs/detect', help='save results to project/name')
    parser.add_argument('--name', default='exp', help='save results to project/name')
    parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
    parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)')
    parser.add_argument('--hide-labels', default=False, action='store_true', help='hide labels')
    parser.add_argument('--hide-conf', default=False, action='store_true', help='hide confidences')
    parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')
    parser.add_argument('--dnn', action='store_true', help='use OpenCV DNN for ONNX inference')
    opt = parser.parse_args()
    opt.imgsz *= 2 if len(opt.imgsz) == 1 else 1  # expand
    print_args(FILE.stem, opt)
    return opt

def maindetect(opt):
    check_requirements(exclude=('tensorboard', 'thop'))
    rundetect(**vars(opt))

if __name__ == "__main__":
    opttrain = parse_opttrain()
    maintrain(opttrain)

    print("best weight path for example /content/yolov5/runs/train/exp/weights/best.pt \n if you run first time you cannot see the path just paste\n but if you run more than once then change it ")
    best_weight_path='runs/train/exp/weights/best.pt'
    #input()
    #'/content/yolov5/runs/train/exp/weights/best.pt'

    optexport = parse_optexport()
    mainexport(optexport)

    optdetect = parse_optdetect()
    maindetect(optdetect)


import os
import numpy as np
import matplotlib.pyplot as plt

def hentdata(filename1, filename2):  # Henter ut x, u og v fra filer
    x = []
    V_x = []
    U_x = []
    RelativeError = []
    AbsError = []

    infile = open(filename1, "r")

    for line in infile:
        numbers = line.split()
        x.append(float(numbers[0]))
        V_x.append(float(numbers[1]))
        RelativeError.append(float(numbers[2]))
        AbsError.append(float(numbers[3]))

    infile.close()
    infile = open(filename2, "r")

    for line in infile:
        numbers = line.split()
        U_x.append(float(numbers[1]))

    infile.close()

    X = np.array(x)
    U = np.array(U_x)
    V = np.array(V_x)

    return X, U, V, RelativeError, AbsError

# Lager lister med filnavnene vi skal hente ut data fra
filename1 = [
    "prob7_n_10.txt",
    "prob7_n_100.txt",
    "prob7_n_1000.txt",
    "prob7_n_10000.txt",
    "prob7_n_100000.txt",
    "prob7_n_1000000.txt",
    "prob7_n_10000000.txt",
]
filename2 = [
    "prob2_n_10.txt",
    "prob2_n_100.txt",
    "prob2_n_1000.txt",
    "prob2_n_10000.txt",
    "prob2_n_100000.txt",
    "prob2_n_1000000.txt",
    "prob2_n_10000000.txt",
]

n_list = [10 ** i for i in range(1, 8)]

# Plotter absolutt feil for ulike n

for i in range(3):
    x, u, v, rel_error, abs_error = hentdata(filename1[i], filename2[i])
    x = x[1:-1]
    u = u[1:-1]
    v = v[1:-1]
    abs_error = abs_error[1:-1]
    plt.plot(x, abs_error, label=f"n = {n_list[i]}")

# Lager mappe til bildene
path = "./results/"
if not os.path.exists(path):
    os.makedirs(path)

# Fullfører plott med absolutt error
fontsize = 14
ticksize = 14
plt.legend()
plt.title("Absolute error for different n")
plt.xlabel("x")
plt.ylabel("$\Delta_i$")
plt.xticks(size=ticksize)
plt.yticks(size=ticksize)
plt.savefig(path + "delta_i.pdf")
plt.show()

# Plotter absolutt feil for ulike n
for i in range(3):
    x, u, v, rel_error, abs_error = hentdata(filename1[i], filename2[i])
    x = x[1:-1]
    u = u[1:-1]
    v = v[1:-1]
    rel_error = rel_error[1:-1]
    plt.plot(x, rel_error, label=f"n = {n_list[i]}")

# Fullfører plott med relativ feil

plt.legend()
plt.title("Relative error for different n")
plt.xlabel("x", size=fontsize)
plt.ylabel("$\epsilon_i$", size=fontsize)
plt.xticks(size=ticksize)
plt.yticks(size=ticksize)
plt.savefig(path + "epsilon_i.pdf")
plt.show()

# Vil regne ut maksimum relativ feil for alle valg av n, opp til n = 10^7
epsilon_max = np.zeros(7)
for i in range(7):
    x, u, v, rel_error, abs_error = hentdata(filename1[i], filename2[i])
    x = x[1:-1]
    u = u[1:-1]
    v = v[1:-1]
    rel_error = rel_error[1:-1]
    epsilon_max[i] = np.max(rel_error)

# Printer maksimum relativ feil til bruk i tabell
print(epsilon_max)

# Plotter maksimum relativ feil for alle valg av n, opp til n = 10^7
plt.plot(np.log10(np.array(n_list)), epsilon_max)
plt.scatter(np.log10(np.array(n_list)), epsilon_max, label="data")
plt.show()


import uuid
import random
import sys
import select
import os
import datetime

# Imports the Google Cloud Client Library.
from google.cloud import spanner

def run_writer():

    # Instantiate a client.
    spanner_client = spanner.Client()

    # Your Cloud Spanner instance ID.
    instance_id = 'meetup'

    # Get a Cloud Spanner instance by ID.
    instance = spanner_client.instance(instance_id)

    # Your Cloud Spanner database ID.
    database_id = 'performance-log'

    # Get a Cloud Spanner database by ID.
    database = instance.database(database_id)

    while True:
        data = 'a' * 2000
        values = []
        row_id = (uuid.uuid4().int & (1<<63)-1)
        for i in range(500):
            row_id += 1
            utilization = random.randint(0,100)
            ts = datetime.datetime.now()
            values.append((row_id, data, ts, utilization))
        with database.batch() as batch:
            batch.insert(
                table='cpu',
                columns=('id', 'data', 'ts', 'utilization'),
                values=values)

if __name__ == '__main__':
    run_writer()


from typing import List

import os
import pathlib
import sys

import subprocess
import h5py
from machinable import Component
from neuroh5.io import read_population_names

def h5_copy_dataset(f_src, f_dst, dset_path):
    print(f"Copying {dset_path} from {f_src} to {f_dst} ...")
    target_path = str(pathlib.Path(dset_path).parent)
    f_src.copy(f_src[dset_path], f_dst[target_path])

class PrepareData(Component):
    def output_filepath(self, path: str = "cells") -> str:
        return self.local_directory(f"{path}.h5")

    def on_compute_predicate(self):
        def generate_uid(use):
            if getattr(use, "refreshed_at", None) is not None:
                return f"{use.uuid}-{use.refreshed_at}"
            return use.uuid

        return {
            "uses": sorted(
                map(
                    generate_uid,
                    self.uses,
                )
            )
        }

    def __call__(self):
        self.network = None
        self.spike_trains = None
        self.synapses = {}
        self.distance_connections = {}
        self.synapse_forest = {}
        for dependency in self.uses:
            if (
                dependency.module
                == "miv_simulator.interface.network_architecture"
            ):
                self.network = dependency
            elif (
                dependency.module
                == "miv_simulator.interface.legacy.derive_spike_trains"
            ):
                self.spike_trains = dependency
            elif dependency.module == "miv_simulator.interface.connections":
                populations = read_population_names(
                    dependency.config.forest_filepath
                )
                for p in populations:
                    if p in self.distance_connections:
                        # check for duplicates
                        raise ValueError(
                            f"Redundant distance connection specification for population {p}"
                            f"Found duplicate in {dependency.config.forest_filepath}, while already "
                            f"defined in {self.distance_connections[p].config.forest_filepath}"
                        )
                    self.distance_connections[p] = dependency
            elif dependency.module == "miv_simulator.interface.synapse_forest":
                if dependency.config.population in self.synapse_forest:
                    # check for duplicates
                    raise ValueError(
                        f"Redundant distance connection specification for population {dependency.config.population}"
                        f"Found duplicate in {dependency}, while already "
                        f"defined in {self.synapse_forest[dependency.config.population]}"
                    )
                self.synapse_forest[dependency.config.population] = dependency
            elif dependency.module == "miv_simulator.interface.synapses":
                if dependency.config.population in self.synapses:
                    # check for duplicates
                    raise ValueError(
                        f"Redundant specification for population {dependency.config.population}"
                        f"Found duplicate in {dependency}, while already "
                        f"defined in {self.synapses[dependency.config.population]}"
                    )
                self.synapses[dependency.config.population] = dependency

        print(f"Consolidating generated data files into unified H5")

        MiV_populations = ["PYR", "OLM", "PVBC", "STIM"]
        MiV_IN_populations = ["OLM", "PVBC"]
        MiV_EXT_populations = ["STIM"]

        print("Import H5Types")
        with h5py.File(self.output_filepath("cells"), "w") as f:
            input_file = h5py.File(self.network.config.filepath, "r")
            h5_copy_dataset(input_file, f, "/H5Types")
            input_file.close()

        print("Import coordinate entries")
        with h5py.File(self.output_filepath("cells"), "a") as f_dst:
            grp = f_dst.create_group("Populations")

            for p in MiV_populations:
                grp.create_group(p)

            for p in MiV_populations:
                coords_dset_path = f"/Populations/{p}/Generated Coordinates"
                coords_output_path = f"/Populations/{p}/Coordinates"
                distances_dset_path = f"/Populations/{p}/Arc Distances"
                with h5py.File(self.network.config.filepath, "r") as f_src:
                    h5_copy_dataset(f_src, f_dst, coords_dset_path)
                    h5_copy_dataset(f_src, f_dst, distances_dset_path)

        print("Create forest entries and synapse attributes")

        def _run(commands):
            cmd = " ".join(commands)
            print(cmd)
            subprocess.check_output(commands)

        for p in MiV_populations:
            if p not in ["OLM", "PVBC", "PYR"]:
                continue
            forest_file = self.synapse_forest[p].output_filepath
            synapses_file = self.synapses[p].output_filepath
            forest_syns_file = self.synapse_forest[p].output_filepath
            forest_dset_path = f"/Populations/{p}/Trees"
            forest_syns_dset_path = f"/Populations/{p}/Synapse Attributes"

            cmd = [
                "h5copy",
                "-p",
                "-s",
                forest_dset_path,
                "-d",
                forest_dset_path,
                "-i",
                forest_file,
                "-o",
                self.output_filepath(),
            ]
            _run(cmd)

            cmd = [
                "h5copy",
                "-p",
                "-s",
                forest_syns_dset_path,
                "-d",
                forest_syns_dset_path,
                "-i",
                synapses_file,
                "-o",
                self.output_filepath(),
            ]
            _run(cmd)

        print("Create vector stimulus entries")
        vecstim_file_dict = {"A Diag": self.spike_trains.output_filepath}

        vecstim_dict = {
            f"Input Spikes {stim_id}": stim_file
            for stim_id, stim_file in vecstim_file_dict.items()
        }
        for vecstim_ns, vecstim_file in vecstim_dict.items():
            for p in MiV_EXT_populations:
                vecstim_dset_path = f"/Populations/{p}/{vecstim_ns}"
                cmd = [
                    "h5copy",
                    "-p",
                    "-s",
                    vecstim_dset_path,
                    "-d",
                    vecstim_dset_path,
                    "-i",
                    vecstim_file,
                    "-o",
                    self.output_filepath(),
                ]
                _run(cmd)

        print("Copy coordinates for STIM cells")
        cmd = [
            "h5copy",
            "-p",
            "-s",
            "/Populations/STIM/Generated Coordinates",
            "-d",
            "/Populations/STIM/Coordinates",
            "-i",
            self.output_filepath(),
            "-o",
            self.output_filepath(),
        ]
        _run(cmd)

        with h5py.File(self.output_filepath("connections"), "w") as f:
            input_file = h5py.File(self.network.config.filepath, "r")
            h5_copy_dataset(input_file, f, "/H5Types")
            input_file.close()

        print("Create connectivity entries")
        for p, e in self.distance_connections.items():
            connectivity_file = e.output_filepath
            print(connectivity_file)
            projection_dset_path = f"/Projections/{p}"
            cmd = [
                "h5copy",
                "-p",
                "-s",
                projection_dset_path,
                "-d",
                projection_dset_path,
                "-i",
                connectivity_file,
                "-o",
                self.output_filepath("connections"),
            ]
            _run(cmd)


# coding: utf-8
from pymongo import MongoClient
from reppy.cache import RobotsCache

class Settings(object):
    START_LINK = 'http://example.com/'

    def __init__(self):
        self.DOMAIN = Settings.START_LINK.split('/')[2]
        self.ROBOTS_LINK = Settings.START_LINK + 'robots.txt'
        self.COUNT_URLS = 200000
        self.THREADS = 4
        self.RAND_NUM = 5
        self.TIMEOUT = 30
        self.AGENT = ''
        self.DATABASE = 'mongodb://localhost:27017/'
        self.DB_NAME = self.DOMAIN.replace('.', '_')
        self.REGULARS = {
            u'title': u'//title/text()',
            u'description': u'//meta[@name="description"]/@content',
            u'keywords': u'//meta[@name="keywords"]/@content',
            u'robots': u'//meta[@name="robots"]/@content',
            u'canonical': u'//link[@rel="canonical"]/@href',
            u'h1': u'//h1//text()',
            u'h2': u'//h2//text()',
            u'h3': u'//h3//text()',
            u'text': u'''//body//*[not(self::script or self::a or self::h1 or
            self::h2 or self::h3)]/text()[normalize-space()]''',
            u'script': u'//script//text()',
            u'p': u'//p//text()',
            u'anchors': u'//a//text()',
            u'alt': u'//img/@alt',
            u'title2': u'//@title'
            }
        self.robots = RobotsCache()
        self.rules = self.robots.cache(self.ROBOTS_LINK)
        self.client = MongoClient(self.DATABASE)
        self.db = self.client[self.DB_NAME]


#!/usr/bin/env python3
import time
import os
import datetime
from datetime import date
from datetime import datetime
from seeed_dht import DHT
from grove.display.jhd1802 import JHD1802
from grove.grove_light_sensor_v1_2 import GroveLightSensor
from grove.grove_moisture_sensor import GroveMoistureSensor

def main():

    #zmienna zapisujaca dane, kiedy czynnosc zostala wykonana
    now = datetime.now()
    dt_string = now.strftime("%d_%m_%Y_%H_%M_%S")
    print("date and time =", dt_string)
    time.sleep(1)

    #Wykonanie zdjęcia oraz jego zapis na karte pamieci
    os.system('fswebcam -r 1280x720 {}.jpg'.format(dt_string))
    time.sleep(2)
    os.system('cp {}.jpg /media/pi/KINGSTON'.format(dt_string))
    time.sleep(2)

    #Podpiecie czujnika swiatla pod port A0
    sensor = GroveLightSensor(0)

    #Podpiecie czujnika wiglotnosci pod port A2
    sensorMoist = GroveMoistureSensor(2)

    #Podpiecie wyswietlacza LCD pod port I2C
    lcd = JHD1802()

    #Podpiecie czujnika DHT pod port D5
    sensorDHT = DHT('11', 5)
    while True:

        #zczytanie wartosci temp. i wilgotnosci oraz ich wyswietlenie
        humi, temp = sensorDHT.read()
        print('temperature {}C, humidity {}%'.format(temp, humi))
        lcd.setCursor(0, 0)
        lcd.write('temperature: {0:2}C'.format(temp))
        lcd.setCursor(1, 0)
        lcd.write('humidity: {0:5}%'.format(humi))
        time.sleep(2)

        #zczytanie i wyswietlenie wartosci czujnika swiatla
        light = sensor.light
        print('light value {}'.format(sensor.light))
        lcd.setCursor(0, 0)
        lcd.write('light: {0:>9}'.format(sensor.light))
        time.sleep(2)

        #zczytanie i wyswietlenie wartosci sondy gleby
        mois = sensorMoist.moisture
        if 0 <= mois and mois < 300:
            level = 'dry'
        elif 300 <= mois and mois < 600:
            level = 'moist'
        else:
            level = 'wet'

        print('moisture: {}, {}'.format(mois, level))
        lcd.setCursor(0, 0)
        lcd.write('moisture: {0:>6}'.format(mois))
        lcd.setCursor(1, 0)
        lcd.write('{0:>16}'.format(level))
        time.sleep(2)

        #wartosci do zapisy na karte pamieci USB
        temperature = temp
        humidity = humi
        moist = mois
        row = (now, dt_string, temperature, humidity, moist, level, light)
        with open("/media/pi/KINGSTON/dane.txt", "a") as myfile:
            myfile.write("Dane: {}\n".format(row))

if __name__ == '__main__':
    main()


import subprocess
import os
import json
import argparse
import hashlib

ROOT_LIBIEML = os.path.dirname(os.path.dirname(__file__))

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("--output_folder", default=os.path.join(ROOT_LIBIEML, 'assets/erroneous_files'))
    parser.add_argument("--host", default='ec2-user@dev2.intlekt.io')
    parser.add_argument("--credential", default=os.path.join(os.path.dirname(ROOT_LIBIEML), '../../credentials/intlekt-2.pem'))

    args = parser.parse_args()

    os.makedirs(args.output_folder, exist_ok=True)

    stdout, stderr = subprocess.Popen(f"ssh -i {args.credential} {args.host} ./ieml-project/retrieve_errors.sh", shell=True, stdout=subprocess.PIPE).communicate()

    raw = stdout.decode('utf8')
    # with open(os.path.join(args.output_folder, f"raw"), 'w') as fp:
    #     fp.write(raw)

    files = json.loads(raw)

    for f in files:
        content = f['content']

        if isinstance(content, list):
            content = ''.join(content)

        hash = hashlib.sha224(content.encode('utf8')).hexdigest()

        with open(os.path.join(args.output_folder, f"{hash}.ieml"), 'w') as fp:
            fp.write(content)


import argparse
import logging
from flask import Flask, send_file

app = Flask(__name__)

try:
    from utils import (
        build_weather_data_from_locations,
        demo_groupings_aggregations_and_visualizations
    )
except(ModuleNotFoundError, ImportError):
    from .utils import (
        build_weather_data_from_locations,
        demo_groupings_aggregations_and_visualizations
    )

logger = logging.getLogger()
logging.basicConfig(level="INFO")
logger.setLevel("INFO")

def main(ip_address_path):
    """
    Main function which gets location and weather info from IP addresses
    and produces, groups, aggregates and plots
    :param ip_address_path: path to text file with list of ip addresses
    """
    build_weather_data_from_locations(ip_address_path)
    demo_groupings_aggregations_and_visualizations()
    logger.info(
        "Starting Flask app to show plots. This will be available on http://localhost:5000\n"
        "PLEASE DO NOT TRY TO ACCESS BY THE URL BELOW as it will not work"
    )
    app.run(port=5000, debug=False, host='0.0.0.0')

@app.route('/')
def deliver_plots():
    return send_file("figures.png", mimetype='image/png')

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--ips', dest='ips', default='ip_addresses.txt',
        help='Text file with list of ip addresses to get weather info on'
    )
    args = parser.parse_args()
    main(args.ips)


import logging
import os
import unittest

import numpy as num
from numpy.testing import assert_allclose
from pyrocko import orthodrome, plot, util

from beat import interseismic, pscmp
from beat.heart import (
    ReferenceLocation,
    velocities_from_pole,
    velocities_from_strain_rate_tensor,
)

km = 1000.0

logger = logging.getLogger("test_interseismic")

class TestInterseismic(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        unittest.TestCase.__init__(self, *args, **kwargs)

        self.reference = None
        self.amplitude = 0.02
        self.azimuth = 115.0
        self.locking_depth = [6.3, 5.0]

    def _get_store_superdir(self):
        return os.path.abspath("data/")

    def _get_gf_store(self, crust_ind):
        store_superdir = self._get_store_superdir(self)
        return os.path.join(store_superdir, "psgrn_green_%i" % crust_ind)

    def _get_synthetic_data(self):
        lon = num.linspace(10.5, 13.5, 100)
        lat = num.linspace(44.0, 46.0, 100)

        Lon, Lat = num.meshgrid(lon, lat)
        reference = ReferenceLocation(lon=5.0, lat=45.0)

        self.lons = Lon.flatten()
        self.lats = Lat.flatten()
        self.reference = reference

    def _get_sources(self, case=1):
        if case == 1:
            sources = [
                pscmp.PsCmpRectangularSource(
                    lon=12.0, lat=45.0, strike=20.0, dip=90.0, length=125.0 * km
                ),
                pscmp.PsCmpRectangularSource(
                    lon=11.25, lat=44.35, strike=70.0, dip=90.0, length=80.0 * km
                ),
            ]

        elif case == 2:
            sources = [
                pscmp.PsCmpRectangularSource(
                    lon=12.04,
                    lat=45.000,
                    strike=329.35 - 180,
                    dip=90.0,
                    length=117809.04,
                ),
                pscmp.PsCmpRectangularSource(
                    lon=11.5, lat=45.75, strike=357.04 - 180, dip=90.0, length=80210.56
                ),
            ]

        for source in sources:
            north_shift, east_shift = orthodrome.latlon_to_ne_numpy(
                self.reference.lat,
                self.reference.lon,
                source.effective_lat,
                source.effective_lon,
            )
            source.update(
                lat=self.reference.lat,
                lon=self.reference.lon,
                north_shift=north_shift,
                east_shift=east_shift,
            )
            print(source)

        return sources

    def old_test_backslip_params(self):
        azimuth = (90.0, 0.0)
        strike = (0.0, 0.0)
        dip = (90.0, 90.0)
        amplitude = (0.1, 0.1)
        locking_depth = (5000.0, 5000.0)

        test_opening = (-0.1, 0.0)
        test_slip = (0.0, 0.1)
        test_rake = (
            180.0,
            0.0,
        )

        for i, (a, s, d, am, ld) in enumerate(
            zip(azimuth, strike, dip, amplitude, locking_depth)
        ):

            d = interseismic.backslip_params(a, s, d, am, ld)

            num.testing.assert_allclose(
                d["opening"], test_opening[i], rtol=0.0, atol=1e-6
            )
            num.testing.assert_allclose(d["slip"], test_slip[i], rtol=0.0, atol=1e-6)
            num.testing.assert_allclose(d["rake"], test_rake[i], rtol=0.0, atol=1e-6)

    def old_test_block_geometry(self):

        if self.reference is None:
            self._get_synthetic_data()

        return interseismic.block_geometry(
            lons=self.lons,
            lats=self.lats,
            sources=self._get_sources(),
            reference=self.reference,
        )

    def old_test_block_synthetics(self):

        if self.reference is None:
            self._get_synthetic_data()

        return interseismic.geo_block_synthetics(
            lons=self.lons,
            lats=self.lats,
            sources=self._get_sources(),
            amplitude=self.amplitude,
            azimuth=self.azimuth,
            reference=self.reference,
        )

    def _test_backslip_synthetics(self, case=1):

        if self.reference is None:
            self._get_synthetic_data()

        return interseismic.geo_backslip_synthetics(
            store_superdir=self._get_store_superdir(),
            crust_ind=0,
            sources=self._get_sources(case),
            lons=self.lons,
            lats=self.lats,
            reference=self.reference,
            amplitude=self.amplitude,
            azimuth=self.azimuth,
            locking_depth=self.locking_depth,
        )

    def _old_test_plot_synthetics(self):
        from matplotlib import pyplot as plt

        fig, ax = plt.subplots(
            nrows=1, ncols=3, figsize=plot.mpl_papersize("a4", "portrait")
        )

        cmap = plt.cm.jet
        fontsize = 12
        sz = 10.0

        if self.reference is None:
            self._get_synthetic_data()

        #        disp = self.test_block_geometry()
        #        disp = self.test_block_synthetics()
        disp = self._test_backslip_synthetics(2)

        for i, comp in enumerate("NEZ"):
            im = ax[i].scatter(self.lons, self.lats, sz, disp[:, i], cmap=cmap)
            cblabel = "%s displacement [m]" % comp
            cbs = plt.colorbar(im, ax=ax[i], orientation="horizontal", cmap=cmap)
            cbs.set_label(cblabel, fontsize=fontsize)

        plt.show()

    def test_plate_rotation(self):
        v1_ref = num.array([-40.33431624537931, 27.59254158624030, 0.0]) / km
        v2_ref = num.array([35.47707891158412, -27.93047805570016, 0.0]) / km
        v1 = velocities_from_pole(37.0, -123.0, 48.7, -78.2, 0.78).ravel()
        from time import time

        t2 = time()
        v2 = velocities_from_pole(34.75, -116.5, 48.7, -78.2, -0.78).ravel()
        t3 = time()
        assert_allclose(v1, v1_ref, atol=1e-3, rtol=0.0)
        assert_allclose(v2, v2_ref, atol=1e-3, rtol=0.0)

        logger.info("One point %f" % (t3 - t2))
        t0 = time()
        v3 = velocities_from_pole([37.0, 37.1], [-123.0, -125.5], 48.7, -78.2, 0.78)
        t1 = time()

        logger.info("Two points %f" % (t1 - t0))
        assert v3.shape == (2, 3)
        assert_allclose(v3[0, :], v1_ref, atol=1e-3, rtol=0.0)

    def test_velocities_from_strain_rate_tensor(self):

        nanostrain = 1e-9
        lats_vec = num.linspace(37.0, 37.5, 5)
        lons_vec = num.linspace(-122.0, -121.0, 5)
        eps_xx = 0.0  # nanostrain South Bay Block from Jolivet et al. 2015
        eps_yy = 58  # - 115.
        eps_xy = 0  # - 58.
        rotation = 0  # 1009.5  # mm/ ( yr * km)

        lons, lats = num.meshgrid(lons_vec, lats_vec)
        print(lats, lons)

        v_x, v_y, v_z = velocities_from_strain_rate_tensor(
            lats.ravel(), lons.ravel(), eps_xx, eps_yy, eps_xy, rotation
        ).T

        print("vmagn", num.sqrt(v_x**2 + v_y**2))
        from matplotlib import pyplot as plt

        fig, axs = plt.subplots(1, 1)
        axs.quiver(lons, lats, v_x, v_y)
        plt.show()
        print(v_z)

if __name__ == "__main__":
    util.setup_logging("test_utility", "info")
    unittest.main()


"""
データ探索を行う
"""

import os
from glob import glob
import csv
import pandas as pd
import numpy as np
from collections import Counter
import re
from pathlib import Path

COLUMNS_NUM = 1500

def bname(object_name):
    return os.path.basename(object_name.rstrip(os.sep))

def make_data(path,floor_num):
    # WAYPOINT: 1列目TYPE_WAYPOINT,2列名x,3列目y
    # wifi: 0列目にtimestamp,1列目にTYPE_WIFI,3列目にbssid,4列目にRSSI,5列目に周波数
    # beacon: 0列目にtimestamp,1列目にTYPE_BEACON,7列目にdistance,8列目にmac_address
    way_point_list = []
    wifi_list = []
    beacon_list = []
    train_data = pd.DataFrame(columns=['floor','x','y'])
    with open(path,'r',encoding="utf-8") as f:
        for row in csv.reader(f, delimiter="\t", doublequote=True):
            # 教師データ取得
            if row[1] == 'TYPE_WAYPOINT':
                way_point_list.append([int(row[0]),row[2],row[3]])
            # 特徴量 wifi 取得
            elif row[1] == 'TYPE_WIFI':
                wifi_list.append([int(row[0]),row[3],row[4],row[5]])
            # 特徴量 beacon 取得
            elif row[1] == 'TYPE_BEACON':
                beacon_list.append([int(row[0]),row[7],row[8]])
    if len(wifi_list) == 0:
        return train_data
    for way_point in way_point_list:
        target_wifi_list,target_beacon_list =\
             get_nearest_data(way_point,wifi_list,beacon_list)
        # wifiの特徴量が取れないならスキップ
        if len(target_wifi_list) == 0:
            continue
        index, value = zip(*target_wifi_list)
        target_series = pd.Series(value, index=index)
        # beacon取らないときコメントアウト
        # if len(target_beacon_list) != 0:
        #     index, value = zip(*target_beacon_list)
        #     target_beacon_series = pd.Series(value, index=index)
        #     target_series = pd.concat([target_series, target_beacon_series])
        target_series['floor'] = floor_num
        target_series['x'] = way_point[1]
        target_series['y'] = way_point[2]
        # 重複したINDEXを削除
        target_series = target_series[np.logical_not(target_series.index.duplicated())]
        train_data = train_data.append(target_series,ignore_index=True)
    return train_data

def get_time_boundary(timedelta_list):
    v = timedelta_list[0]
    for i,d in enumerate(timedelta_list):
        if v != d:
            break
    return i

def get_nearest_data(way_point,wifi_list,beacon_list):
    """
    時刻が一番近い かつ 利用頻度ランキング上位の wifiとビーコンのデータを取得
    """
    # timestampだけをリスト化
    wifi_timestamp_list = np.asarray(wifi_list)[:,0].astype(np.int64)
    # waypointのtimestampとの時間差分リストを取得
    wifi_timedelta = np.abs(wifi_timestamp_list - way_point[0])
    # 時間差リストソートでwifi_listも一緒にソート
    c = zip(wifi_timedelta,wifi_list)
    c = sorted(c)
    wifi_timedelta,wifi_list = zip(*c)
    # 一番近いwifiデータを取得
    target_wifi_list = np.asarray(wifi_list)[:get_time_boundary(wifi_timedelta)]
    if len(target_wifi_list) != 0:
        target_wifi_list = np.array(target_wifi_list)[:,[1,2]]
    else:
        target_wifi_list = []

    if len(beacon_list) == 0:
        return target_wifi_list,[]
    # beaconは一番近いデータの±3000msを取得
    way_point_timestamp = way_point[0]
    beacon_timestamp_list = np.asarray(beacon_list)[:,0].astype(np.int64)
    beacon_min_timedelta = np.abs(beacon_timestamp_list - way_point_timestamp)
    # 一番近いtimestampを取得
    closest_beacon_time = beacon_timestamp_list[np.argmin(beacon_min_timedelta)]
    # 一番近いtimestamの±5000msの範囲のbeaconデータを取得
    beacon_min_idxs = [i for i, timestamp in enumerate(beacon_timestamp_list) if closest_beacon_time-5000 < timestamp and timestamp < closest_beacon_time+5000 ]
    target_beacon_list = np.asarray(beacon_list)[beacon_min_idxs]
    if len(target_beacon_list) != 0:
        target_beacon_list = np.array(target_beacon_list)[:,[2,1]]
    else:
        target_beacon_list = []
    return target_wifi_list,target_beacon_list

def get_floor_num(floor):
    # 数字が含まれていない or 2文字以下の場合スキップ
    if len(floor) < 2 or (not bool(re.search(r'\d', floor))):
        return -99
    FLOOR = ['F','L']
    BASEMENT = ['B']
    floor_num = int(re.sub(r"\D", "", floor))
    floor_str = re.sub(r"\d", "", floor)
    if floor_str in FLOOR:
        return floor_num - 1
    elif floor_str in BASEMENT:
        return -floor_num
    else:
        return -99

def get_target_facilities():
    """
    submitに使用する施設を取得
    """
    with open('./test_facilities.csv','r',encoding="utf-8") as f:
        for row in csv.reader(f, delimiter=",", doublequote=True):
            return row

def save_file(df,path,floor_name):
    if not os.path.exists(path):
        os.mkdir(path)
    df.to_csv(f'{path}/{floor_name}.csv')
    print(f'データを保存')

if __name__== "__main__":
    DIR = './download_data/indoor-location-navigation'
    SAVE_DIR = 'got_data_per_floor_wifi_only'
    # SAVE_DIR = 'got_data_per_floor'
    train_folders = glob(f'{DIR}/train/*')
    print(f'施設数: {len(train_folders)}')
    skip = True
    target_facilities = get_target_facilities()
    # 各施設 を順に走査
    for i,facility_id in enumerate(train_folders):
        print(f'{i}番目')
        if bname(facility_id) not in target_facilities:
            print(f'{bname(facility_id)}は載っていないため、スキップ')
            continue
        # if bname(facility_id) == '5d27099f03f801723c32511d':
        # if i == 120:
        #     skip = False
        #     continue
        # if skip:
        #     continue
        floor_folders = glob(f'{facility_id}/*')
        print(f'階層一覧: {[bname(p) for p in floor_folders]}')
        # 各フロア の調査データから訓練データ作成
        for floor_paths in [(glob(f'{p}/*')) for p in floor_folders]:
            train_data_parent = pd.DataFrame()
            floor_num = get_floor_num(Path(floor_paths[0]).parts[-2])
            if floor_num == -99:
                continue
            # 各調査データから特徴量作成
            for survey in floor_paths:
                print(f'{i}施設目: {bname(facility_id)} の {floor_num} を探索')
                print(f'ターゲットファイル: {bname(survey)}')
                # if bname(survey) != '5d0b164bea52920008961c9d.txt':
                #     continue
                train_data = make_data(survey,floor_num)
                train_data_parent = pd.concat([train_data_parent,train_data],axis=0)
                print(train_data_parent)
            save_file(train_data_parent,f'./{SAVE_DIR}/{bname(facility_id)}',floor_num)
    print('全て終了')