#!/usr/bin/env python3

import argparse
import dataclasses
import torch
import torch.utils.data
import yaml
import logging
import pathlib
import torchinfo
import utils
import loaders
import architectures
import losses
import losses.loss_mha as loss_mha
import transforms
import train
import numpy as np
from time import perf_counter
import torchvision.transforms as tf

RESULTS = "runs/"
MODELS = "models/"
HYPER_EXT = "txt"

@dataclasses.dataclass
class ProgramArguments:
    setup_config_path : str
    model_config_path : str

def parse_program_arguments():
    """
    Parse program arguments and create a program configuration.

    :return: program configuration
    """
    parser = argparse.ArgumentParser(
        description="Parser for the configuration file to begin testing of the Autoencoder testing")

    parser.add_argument(
        "--setup_config_path",
        type=str,
        help="Configuration file to use for inferencing")

    parser.add_argument(
        "--model_config_path",
        type=str,
        help="Configuration file for the model setup")

    args = parser.parse_args()

    return ProgramArguments(
        setup_config_path=args.setup_config_path,
        model_config_path=args.model_config_path)

class Tester:
    """
    Testing and its helper functions
    """
    def __init__(self,
                 setup_cfg,
                 model_cfg):
        """
        Read the contents of the config file

        :param setup_cfg: config file of the testing parameters
        :param model_cfg: config file of the model parameters
        """
        # General setup
        logging.basicConfig(level=logging.INFO)
        self.mode = setup_cfg["setup"]["mode"]
        self.num_images = setup_cfg["setup"]["num_images"]
        self.print_interval = setup_cfg["setup"]["print_interval"]
        self.num_workers = setup_cfg["setup"]["num_workers"]
        self.master_rank = setup_cfg["setup"]["master_rank"]

        # Test specific setup
        self.test_split = setup_cfg["testing"]["test_split"]
        self.val_split = setup_cfg["testing"]["val_split"]
        self.batch_size = setup_cfg["testing"]["batch_size"]
        self.model_path = setup_cfg["testing"]["model_path"]
        self.ae_model_path = setup_cfg["testing"]["ae_path"]
        self.semseg_model_path = setup_cfg["testing"]["semseg_path"]

        # Dataset specific setup
        self.dataset_name = model_cfg["dataset"]["name"]
        self.dataset_dict = model_cfg[self.dataset_name]
        self.input_res = model_cfg["dataset"]["input_res"]
        self.val_data_loader, self.test_data_loader = self.dataset()

        # Model, loss and optimiser setup
        self.model_name = model_cfg["model"]
        self.model_dict = {**model_cfg[self.model_name], **model_cfg["dataset"]}
        self.model_ae_name = model_cfg["model_ae"]
        self.model_ae_dict = {**model_cfg[self.model_ae_name], **model_cfg["dataset"]}
        self.model_semseg_name = model_cfg["model_semseg"]
        self.model_semseg_dict = {**model_cfg[self.model_semseg_name], **model_cfg["dataset"]}
        self.ae_loss_dict = setup_cfg["setup"]["autoencoder_loss"]
        self.semseg_loss_dict = setup_cfg["setup"]["segmentation_loss"]
        self.loss_weights = setup_cfg["setup"]["loss_weights"]
        self.device = self.device_check()

        # Semseg head setup
        self.num_classes = model_cfg[self.model_name]["num_classes"]
        self.running_metrics = utils.SegmentationMetric(self.num_classes)

        # Visualisation setup
        self.mean = setup_cfg["setup"]["mean"]
        self.std = setup_cfg["setup"]["std"]
        self.visualise_val_ae = utils.Visualise(dataloader=self.val_data_loader,
                                                num_images=self.num_images,
                                                device=self.device)
        self.visualise_test_ae = utils.Visualise(dataloader=self.test_data_loader,
                                                 num_images=self.num_images,
                                                 device=self.device)
        self.visualise_val_ss = utils.VisualiseSemSeg(num_images=self.num_images)
        self.visualise_test_ss = utils.VisualiseSemSeg(num_images=self.num_images)

        # Pathfiles setup
        self.models_save_path = pathlib.Path(MODELS) / self.model_name / self.dataset_name
        utils.mkdir(self.models_save_path)
        self.results_save_path = pathlib.Path(RESULTS) / self.model_name / self.dataset_name / "test"
        self.seed = setup_cfg.get("seed", 10)

        # Begin inference
        self.infer()

    def dataset(self):
        """
        Load the test set of the chosen dataset

        :return test_data_loader: the dataloader of the test set
        """
        data_loader, data_loader_params = loaders.get_loader(dataset_name=self.dataset_name,
                                                             dataset_dict=self.dataset_dict,
                                                             mode=self.mode)
        test_data = data_loader(**data_loader_params,
                                augments=None,
                                split=self.test_split,
                                input_res=self.input_res)
        test_data_loader = test_data.load_data(num_workers=self.num_workers,
                                               shuffle=False)

        val_data = data_loader(**data_loader_params,
                               augments=None,
                               split=self.val_split,
                               input_res=self.input_res)
        val_data_loader = val_data.load_data(num_workers=self.num_workers,
                                             shuffle=False)

        logging.info(f"Using dataset: {self.dataset_name}")

        return val_data_loader, test_data_loader

    def model(self,
              model_name,
              model_dict):
        """
        Establish the model

        :return model: model to perform inferencing on
        """
        model_name, model_params = architectures.get_arch(model_name=model_name,
                                                          model_dict=model_dict,
                                                          seed=self.seed)
        model = model_name(**model_params)

        return model

    def loss(self):
        """
        Establish the loss. The loss of both heads are established here and grouped as a list. The MultiHeadLoss is
        then instantiated with this loss list

        :return loss: the multi-head loss function
        """
        # Initialise individual head losses
        ae_loss_name, ae_loss_params = losses.get_loss(self.ae_loss_dict,
                                                       self.master_rank)
        semseg_loss_name, semseg_loss_params = losses.get_loss(self.semseg_loss_dict,
                                                               self.master_rank)

        ae_loss = ae_loss_name(**ae_loss_params).to(self.master_rank)
        semseg_loss = semseg_loss_name(**semseg_loss_params).to(self.master_rank)

        # Compile losses to list and initialise multi-head loss
        loss_all = [ae_loss, semseg_loss]
        loss = losses.loss_mha.MultiHeadLoss(losses=loss_all,
                                             loss_weights=self.loss_weights)

        return loss, (ae_loss_params, semseg_loss_params)

    def device_check(self):
        """
        Get the best device to test the model on

        :return device: the best device
        """
        device = utils.best_device(utils.devices())
        logging.info(f"Using device: {torch.cuda.get_device_name(device)}")

        return device

    def load_checkpoint(self):
        """
        Load in the model and optimiser state. Also load in the single head models for fps comparison

        :return model: the model for which inferencing is performed on
        """
        if pathlib.Path(self.model_path).is_file():
            # mha model
            checkpoint = torch.load(f=self.model_path,
                                    map_location='cpu')
            model = self.model(model_name=self.model_name,
                               model_dict=self.model_dict)
            model.to(self.device)
            model = utils.parallelise_model(model,
                                            checkpoint["model_state"])
            model.eval()

            # single head ae model
            checkpoint_ae = torch.load(f=self.ae_model_path,
                                       map_location='cpu')
            model_ae = self.model(model_name=self.model_ae_name,
                                  model_dict=self.model_ae_dict)
            model_ae.to(self.device)
            model_ae = utils.parallelise_model(model_ae,
                                               checkpoint_ae["model_state"])
            model_ae.eval()

            # single head semseg model
            checkpoint_semseg = torch.load(f=self.semseg_model_path,
                                           map_location='cpu')
            model_semseg = self.model(model_name=self.model_semseg_name,
                                      model_dict=self.model_semseg_dict)
            model_semseg.to(self.device)
            model_semseg = utils.parallelise_model(model_semseg,
                                                   checkpoint_semseg["model_state"])
            model_semseg.eval()

            return model, model_ae, model_semseg

        else:
            raise NotImplementedError("Re-check checkpoint path if it exists")

    def create_summary(self,
                       model):
        """
        Utilise torchinfo to display the architecture of the model in tabular form

        :param model: the model of interest
        :param model_summary: a summary of the model
        """
        C, H, W = self.test_data_loader.dataset[0][0].shape
        model_summary = torchinfo.summary(model, input_size=(self.batch_size, C, H, W))

        return model_summary

    def validation_set(self,
                       model,
                       model_ae,
                       model_semseg,
                       loss_function,
                       best_mha_fps):
        """
        Run inferencing on the model, gather inference results and visualisations
        Also gather latent space and feature space visualisations
        On the validation set -> semantic segmentation and autoencoder results and metrics

        :param model: mha model
        :param model_ae: single head autoencoder model
        :param model_semseg: single head semantic segmentation model
        :param loss_function: the multi-loss function
        :param best_mha_fps: current best mha fps
        :param best_sha_fps: current best sha fps
        """
        val_size = len(self.val_data_loader)
        val_loss_meter = utils.AverageTracker()
        ae_val_loss_meter = utils.AverageTracker()
        ss_val_loss_meter = utils.AverageTracker()

        vis_samples = int(len(self.val_data_loader) * 0.25)
        latent_space = utils.VisualiseLatentSpace(model=model,
                                                  mean=torch.tensor(self.mean),
                                                  std=torch.tensor(self.std),
                                                  num_samples=vis_samples)
        model.eval()

        with torch.no_grad():
            for i, (xs, ys, gt) in enumerate(self.val_data_loader):
                xs = xs.to(self.device)
                ys = ys.to(self.device)

                # mha prediction
                mha_start_t = perf_counter()
                preds = model(xs)
                mha_end_t = perf_counter()

                targets = [xs, ys]
                total_loss, head_losses = loss_function(preds,
                                                        targets)

                val_loss_meter.update(total_loss.item())
                ae_val_loss_meter.update(head_losses[0])
                ss_val_loss_meter.update(head_losses[1])
                mha_fps = utils.calc_fps(self.batch_size,
                                         mha_end_t,
                                         mha_start_t)

                if mha_fps > best_mha_fps:
                    best_mha_fps = mha_fps

                    # sha prediction (for fps evaluation only)
                    sha_start_t = perf_counter()
                    ae_preds = model_ae(xs)
                    semseg_preds = model_semseg(xs)
                    sha_end_t = perf_counter()

                    best_sha_fps = utils.calc_fps(self.batch_size,
                                                  sha_end_t,
                                                  sha_start_t)

                # get semseg metrics
                semseg_pred = torch.argmax(preds[1], 1)
                semseg_pred = semseg_pred.to("cpu").data.numpy()
                self.running_metrics.update(semseg_pred, ys.to("cpu").numpy())

                if i % self.print_interval == 0:
                    val_loss, current = total_loss.item(), i * len(xs)
                    print(f"val loss: {val_loss}, best fps: {best_mha_fps}, [{current} / {val_size}]")

                # visualise semseg
                pred_img = semseg_pred.squeeze(0)
                mask = utils.get_colour_pallete(pred_img)
                mask_inv, xs_inv = transforms.inver_norm_pair(mean=torch.tensor(tuple(self.mean)),
                                                              std=torch.tensor(tuple(self.std)),
                                                              input=xs,
                                                              output=mask,
                                                              mode="semseg")
                self.visualise_val_ss.update(xs_inv.to("cpu"),
                                             mask_inv,
                                             gt)

                # viualise segmentation feature maps
                if i == 0:
                    utils.visualise_segmentation_features(model,
                                                          xs,
                                                          self.models_save_path)

                # visualise autoencoder
                ps_inv, _ = transforms.inver_norm_pair(mean=torch.tensor(self.mean),
                                                       std=torch.tensor(self.std),
                                                       input=xs,
                                                       output=preds[0],
                                                       mode=self.mode)
                self.visualise_val_ae.update(xs_inv,
                                             ps_inv)

                # visualise autoencoder latent space
                latent_space.update(xs)
            latent_space.visualise(self.models_save_path)

        # semseg metrics
        score, class_iou = self.running_metrics.get()
        mIoU = score["Mean IoU"]
        pix_acc = score["Overall Acc"]

        # loss metrics
        val_loss = val_loss_meter.avg
        ae_val_loss = ae_val_loss_meter.avg
        ss_val_loss = ss_val_loss_meter.avg

        return val_loss, ae_val_loss, ss_val_loss, best_mha_fps, best_sha_fps, pix_acc, mIoU, class_iou

    def test_set(self,
                 model,
                 model_ae,
                 model_semseg,
                 best_mha_fps):
        """
        Run inferencing on the model, gather inference visualisations
        On the test set -> semantic segmentation and autoencoder results and metrics (no loss recorded as cityscapes
        do not provide the test labels)

        :param model: model
        :param best_fps: current best fps
        """
        test_size = len(self.test_data_loader)
        model.eval()

        with torch.no_grad():
            for i, (xs, _, _) in enumerate(self.test_data_loader):
                xs = xs.to(self.device)

                start_t = perf_counter()
                preds = model(xs)
                end_t = perf_counter()

                fps = utils.calc_fps(self.batch_size,
                                     end_t,
                                     start_t)

                if fps > best_mha_fps:
                    best_mha_fps = fps

                    # sha prediction (for fps evaluation only)
                    sha_start_t = perf_counter()
                    ae_preds = model_ae(xs)
                    semseg_preds = model_semseg(xs)
                    sha_end_t = perf_counter()

                    best_sha_fps = utils.calc_fps(self.batch_size,
                                                  sha_end_t,
                                                  sha_start_t)

                if i % self.print_interval == 0:
                    current = i * len(xs)
                    print(f"Test Set, best fps: {best_mha_fps}, [{current} / {test_size}]")

                # visualise autoencoder
                ps_inv, xs_inv = transforms.inver_norm_pair(mean=torch.tensor(self.mean),
                                                       std=torch.tensor(self.std),
                                                       input=xs,
                                                       output=preds[0],
                                                       mode=self.mode)
                self.visualise_test_ae.update(xs_inv,
                                              ps_inv)

        return best_mha_fps, best_sha_fps

    def infer(self):
        """
        The complete inference process
        - load in the model and loss conditions
        - conduct inferencing
        - save the metrics and model summary
        - output the visualisation results to tensorboard
        """
        best_mha_fps_start = -1
        writer = utils.Logger(self.results_save_path)

        # Load conditions
        model, model_ae, model_semseg = self.load_checkpoint()
        logging.info(f"Loaded model: {type(model).__name__}")
        loss_function, loss_params = self.loss()
        ae_loss_params, ss_loss_params = loss_params[0], loss_params[1]
        logging.info(f"Using loss: {type(loss_function).__name__}")

        # Begin testing
        val_results = self.validation_set(model=model,
                                          model_ae=model_ae,
                                          model_semseg=model_semseg,
                                          loss_function=loss_function,
                                          best_mha_fps=best_mha_fps_start)
        val_loss, ae_val_loss, ss_val_loss, best_mha_fps, best_sha_fps, pix_acc, mIoU, class_iou = val_results

        best_mha_fps_test, best_sha_fps_test = self.test_set(model=model,
                                                             model_ae=model_ae,
                                                             model_semseg=model_semseg,
                                                             best_mha_fps=best_mha_fps_start)

        test_set_metrics = {
            "total_val_loss": val_loss,
            "ae_val_loss": ae_val_loss,
            "ss_val_loss": ss_val_loss,
            "best_mha_fps_val": best_mha_fps,
            "best_sha_fps_val": best_sha_fps,
            "best_mha_fps_test": best_mha_fps_test,
            "best_sha_fps_test": best_sha_fps_test,
            "pixel acc": pix_acc,
            "mean iou": mIoU,
            "class_iou": class_iou
        }

        # Save metrics
        params_filename = self.models_save_path / f"best_model_metrics.{HYPER_EXT}"
        utils.save_contents(test_set_metrics,
                            params_filename,
                            self.mode)

        # Output model summary
        model_summary = self.create_summary(model)
        model_summary_filename = self.models_save_path / f"model_summary.{HYPER_EXT}"
        utils.save_contents(model_summary,
                            model_summary_filename,
                            self.mode)

        # Gather visualisation results
        self.visualise_val_ae.create_visuals(writer,
                                             "val")
        self.visualise_test_ae.create_visuals(writer,
                                              "test")

        self.visualise_val_ss.create_visuals(writer,
                                             self.models_save_path)
        writer.close()

def main():
    args = parse_program_arguments()

    with open(args.setup_config_path) as fp:
        setup_cfg = yaml.safe_load(fp)

    with open(args.model_config_path) as fp:
        model_cfg = yaml.safe_load(fp)

    Tester(setup_cfg,
           model_cfg)

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np

from .signal_period import signal_period

def signal_rate(
    peaks,
    sampling_rate=1000,
    desired_length=None,
    interpolation_method="monotone_cubic",
    show=False,
):
    """**Compute Signal Rate**

    Calculate signal rate (per minute) from a series of peaks. It is a general function that works
    for any series of peaks (i.e., not specific to a particular type of signal). It is computed as
    ``60 / period``, where the period is the time between the peaks (see func:`.signal_period`).

    .. note:: This function is implemented under :func:`.signal_rate`, but it also re-exported under
       different names, such as :func:`.ecg_rate`, or :func:`.rsp_rate`. The
       aliases are provided for consistency.

    Parameters
    ----------
    peaks : Union[list, np.array, pd.DataFrame, pd.Series, dict]
        The samples at which the peaks occur. If an array is passed in, it is assumed that it was
        obtained with :func:`.signal_findpeaks`. If a DataFrame is passed in, it is assumed it is
        of the same length as the input signal in which occurrences of R-peaks are marked as "1",
        with such containers obtained with e.g., :func:.`ecg_findpeaks` or :func:`.rsp_findpeaks`.
    sampling_rate : int
        The sampling frequency of the signal that contains peaks (in Hz, i.e., samples/second).
        Defaults to 1000.
    desired_length : int
        If left at the default None, the returned rated will have the same number of elements as
        ``peaks``. If set to a value larger than the sample at which the last peak occurs in the
        signal (i.e., ``peaks[-1]``), the returned rate will be interpolated between peaks over
        ``desired_length`` samples. To interpolate the rate over the entire duration of the signal,
        set ``desired_length`` to the number of samples in the signal. Cannot be smaller than or
        equal to the sample at which the last peak occurs in the signal. Defaults to ``None``.
    interpolation_method : str
        Method used to interpolate the rate between peaks. See :func:`.signal_interpolate`.
        ``"monotone_cubic"`` is chosen as the default interpolation method since it ensures monotone
        interpolation between data points (i.e., it prevents physiologically implausible
        "overshoots" or "undershoots" in the y-direction). In contrast, the widely used cubic
        spline interpolation does not ensure monotonicity.
     show : bool
        If ``True``, shows a plot. Defaults to ``False``.

    Returns
    -------
    array
        A vector containing the rate (peaks per minute).

    See Also
    --------
    signal_period, signal_findpeaks, signal_fixpeaks, signal_plot

    Examples
    --------
    .. ipython:: python

      import neurokit2 as nk

      # Create signal of varying frequency
      freq = nk.signal_simulate(1, frequency = 1)
      signal = np.sin((freq).cumsum() * 0.5)

      # Find peaks
      info = nk.signal_findpeaks(signal)

      # Compute rate using 2 methods
      rate1 = nk.signal_rate(peaks=info["Peaks"],
                             desired_length=len(signal),
                             interpolation_method="nearest")

      rate2 = nk.signal_rate(peaks=info["Peaks"],
                             desired_length=len(signal),
                             interpolation_method="monotone_cubic")

      # Visualize signal and rate on the same scale
      @savefig p_signal_rate1.png scale=100%
      nk.signal_plot([signal, rate1, rate2],
                     labels = ["Original signal", "Rate (nearest)", "Rate (monotone cubic)"],
                     standardize = True)
      @suppress
      plt.close()

    """
    period = signal_period(peaks, sampling_rate, desired_length, interpolation_method)
    rate = 60 / period

    if show is True:
        _signal_rate_plot(rate, peaks, sampling_rate, interpolation_method)

    return rate

# =============================================================================
# Internals
# =============================================================================
def _signal_rate_plot(
    rate,
    peaks,
    sampling_rate=None,
    interpolation_method=None,
    title="Rate",
    ytitle="Cycle per minute",
    color="black",
    color_mean="orange",
    color_points="red",
    ax=None,
):
    # Prepare plot
    if ax is None:
        fig, ax = plt.subplots()

    if sampling_rate is None:
        x_axis = np.arange(0, len(rate))
        ax.set_xlabel("Time (samples)")
    else:
        x_axis = np.linspace(0, len(rate) / sampling_rate, len(rate))
        ax.set_xlabel("Time (seconds)")

    if interpolation_method is not None:
        title += " (interpolation method: " + str(interpolation_method) + ")"
    ax.set_title(title)
    ax.set_ylabel(ytitle)

    # Plot continuous rate
    ax.plot(
        x_axis,
        rate,
        color=color,
        label="Rate",
        linewidth=1.5,
    )

    # Plot points
    if peaks is not None:
        ax.scatter(
            x_axis[peaks],
            rate[peaks],
            color=color_points,
        )

    # Show average rate
    rate_mean = rate.mean()
    ax.axhline(y=rate_mean, label="Mean", linestyle="--", color=color_mean)

    ax.legend(loc="upper right")

    return ax


import sys
input = sys.stdin.readline
for _ in range(int(input())):
    m, n = map(int, input().split())
    box = [list(map(int, input().split())) for _ in range(m)]
    step = 0

    for j in range(n):
        #층마다 비교하기 위해 floor
        floor = m - 1
         #행을 먼저 비교하다
        for i in range(m-1, -1, -1):
            # 만약에 박스가 있으면
            if box[i][j] == 1:
                #층에서 i를 빼면 거리가 나온다.
                step += floor - i
                print(step)
                #1층씩 빼준다.
                floor -= 1

    print(step)


from flask import Flask, Response, request, render_template, make_response, redirect, url_for
import flask_excel as excel
from openpyxl import Workbook
import openpyxl
import pyexcel

from rq import Queue
from rq.job import Job

from worker import conn
from utils import count_words_at_url

import time

# fix dimensiones por la coma que hay se separan en dos valores distintos en el excel
app = Flask(__name__)

counter = 0

@app.route('/')
def homepage():
    return render_template('index.html', data=counter)

@app.route("/", methods=["POST"])
def getPlotCSV():
    text = request.form['text'] # url from webpage
    url = str(text)

    q = Queue(connection=conn) # create de queue
    task = q.enqueue(count_words_at_url, url)
    task_id = task.get_id()
    return redirect(url_for('waiting', task_id=task_id))

@app.route("/waiting/<task_id>")
def waiting(task_id):
    job = Job.fetch(task_id, connection=conn)
    start_time = time.time()
    while not job.is_finished:
        if time.time() - start_time > 25:
            print("la solicitud se ha demorado mas de 25 segundos, se redirege a la url waiting!!!!!!!!!!!!")
            return redirect(url_for('waiting', task_id=task_id))

    result = job.result
    my_workbook = Workbook()
    my_workbook_active = my_workbook.active

    # excel headers
    header=["Tipo", "Categoria", "Ubicacion", "Codigo", "Informacion",
    "Construido", "Terreno", "Valor(UF)", "UF/Construido", "UF/Terreno", "url"]
    my_workbook_active.append(header)

    for j in result:
        my_workbook_active.append(j)

    output = make_response(openpyxl.writer.excel.save_virtual_workbook(my_workbook))
    output.headers["Content-Disposition"] = "attachment; filename=Datos.xlsx"
    output.headers["Content-type"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    print("excel esta listo para ser retornado suerte")

    return output

if __name__ == '__main__':
    excel.init_excel(app)
    app.run(debug=True, use_reloader=True)
    # app.run()


"""
==========================================
 Title:  PyPlayer TestMarkov
 Author: @jaquielajoie
 Date:   9 July 2021
 Liscence: Apache 2.0
==========================================
"""

import unittest
import pyplayer.markov as mk

class TestMarkov(unittest.TestCase):
    # def assemble_note_map(nlen, midi_notes):
    def test_assemble_note_map(self):
        nlen = 2
        note_list = [1,2,3,4,5,6,7,8,6,5,4,2,3,4,1]
        comparison = {
                        (1, 2): [3],
                        (2, 3): [4, 4],
                        (3, 4): [5, 1],
                        (4, 5): [6],
                        (5, 6): [7],
                        (6, 7): [8],
                        (7, 8): [6],
                        (8, 6): [5],
                        (6, 5): [4],
                        (5, 4): [2],
                        (4, 2): [3]
                    }

        result = mk.assemble_note_map(nlen, note_list)
        self.assertEqual(result, comparison)

    # def cycle_note(note_key, note_map, midi_port):
    def test_cycle_note(self):
        nlen = 2
        note_list = [1,2,3,4,5,6,7,8,6,5,4,2,3,4,1]

        note_key = (1,2)
        note_map = mk.assemble_note_map(nlen, note_list)
        midi_port = 'IAC Driver Bus 1'

        note_key, note_map = mk.cycle_note(note_key, note_map, midi_port, test=True)
        self.assertEqual(note_key, (2,3))

    # class MarkovPlayer():
    #    def run(self, iters):
    def test_markov_player_run(self):
        try:
            nlen = 2
            note_list = [1,2,3,4,5,6,7,8,9,8,7,6,7,8,7,6,5,4,5,6,7,6,5,4,8,6,6,4,2,1,2,3,54,7,8,431,2,678,7,5,23,1] # replace with mido notes...
            midi_port = 'IAC Driver Bus 1'

            mp = mk.MarkovPlayer(nlen=nlen, note_list=note_list, interface=None, test=True)
            mp.run(1000)
            assert True
        except Exception as e:
            print(e)
            assert False


#|==============================================================|#
# Made by IntSPstudio
# Thank you for using this library!
# Plugin: Copa
#|==============================================================|#

#IMPORT
from it8c import data
from it8c import file
#READ FILE
def crf185319(fileName,separator):
	array1Content = file.crf1325420(fileName,separator)
	array1Height = len(array1Content)
	checka =0
	for zp in range(0,2):
		if zp == 1:
			checkd =0
			array2Height = checka
			array2Width =2
			array2Content = data.cbd325306(array2Height,array2Width,"")
		for yp in range(0,array1Height):
			checkb = array1Content[yp][0]
			checkc = checkb[0]
			if checkc != "#":
				if zp == 0:
					checka +=1
				if zp == 1:
					array2Content[checkd][0] = array1Content[yp][0]
					array2Content[checkd][1] = array1Content[yp][1]
					checkd +=1
	return array2Content
#WRITE FILE
def cwf235269(fileName,array1Content,separator):
	if separator =="":
		separator ="="
	array1Length = len(array1Content)
	array1Width = len(array1Content[0])
	if array1Width >= 2:
		array2Content = data.cad325305(array1Length,"")
		for i in range(0,array1Length):
			pointa = str(array1Content[i][0])
			pointb = str(array1Content[i][1])
			if pointa == "comment":
				pointa ="#"
				pointc = pointa + pointb
			else:
				pointc = pointa + separator + pointb
			array2Content[i] = pointc
		file.cwf135577(array2Content,fileName)
#MODIFY FILE
def cpf135315(fileName,parKey,parValue,copaMode,separator):
	if separator =="":
		separator ="="
	if copaMode == 0:
		if file.cfc1319459(fileName) == 1:
			pointc = crf185319(fileName,separator)
			pointaLength = len(pointc)
			success =0
			for i in range(0,pointaLength):
				pointd = pointc[i][0]
				if pointd == parKey:
					success =1
					pointc[i][1] = parValue
			if success == 0:
				pointd = data.cad325305(2,"")
				pointd[0] = parKey
				pointd[1] = parValue
				pointe = data.cbd125319(pointc,pointd)
				pointc = pointe
			cwf235269(fileName,pointc,separator)
		else:
			pointc = data.cbd325306(1,2,"")
			pointc[0][0] = parKey
			pointc[0][1] = parValue
			cwf235269(fileName,pointc,separator)


import numpy as np
import matplotlib.pyplot as plt
import struct
import config

##====================================================##
##            >>--regridMaster.py--<<
##
## Ryan Patmore 17/07/15
## Outputs all required for regridding in MITgcm
##====================================================##

if __name__ == '__main__':
    case_name = 'RDP_032'

    ps = None
    pe = None

    # Set grid
    cartesian    = 1
    res_multiplier = 2.0
    res          = 25000/res_multiplier
    ydim         = 288*res_multiplier
    xdim         = 288*res_multiplier
    latMax       = -1
    latMin       = -75
    z0           = 20

    # Set bathymetry
    depMax       = 5000
    wall_west    = 0
    wall_east    = xdim
    wall_south   = 1
    wall_north   = -1

    # Plateau
    plateau_height = 0

    # Ridge
    ridge        = 1 # 1 for ridge 0 for no ridge
    ridge_height  = 2000
    #ridge_width   = int(5/res)
    ridge_width   = 10*res_multiplier
    e_width = 10*res_multiplier # width of eastern ridge slope (sawtooth ridge)
    w_width = 10*res_multiplier # width of western ridge slope (sawtooth ridge)

    # Gap
    gap = 0
    #ridge_centre = 0
    v_centre = ydim/2.0
    #v_centre = 0.0 #y centre of rotation for ridge
    ridge_centre = int(0.5*xdim)
    #ridge_centre = 80*res_multiplier
    print ('RIDGE CENTRE', ridge_centre)
    y_0          = (ydim*(2.0/5.0))- ridge_width
    grad = 0.0

    # Wind
    windStrength = 2
    windStrength = 10
    curl         = 0
    zero_curl    = 1 #shifts point of zero curl n & s (n x>1, s x<1)

    # Density
    sigma_0      = 999.8
    tAlpha       = 0.0002
    sigmaMin     = 26.1
    sigmaMax     = 28.35
    rhoDiff = 1

    cd = 0.0012
    #cd = 0.00012
    rowa = 1.2

class Binary(object):

    def writeBin(self, inputArray, outFileName):
        w = np.float64(inputArray).flatten()
        with open(self.writePath + outFileName,'wb') as f:
            for i in w:
                f.write(struct.pack('>d', i))
    #def writeBin(self, inputArray, outFileName):
    #    print ('INPUT ARRAY SHAPE', inputArray.shape)
    #    inputArray.tofile(outFileName)

    def readBin(self, file, x=1, y=1, z=None, dtype='float64'):
        print ('PATH', self.writePath)
        print ('FILE', file)
        print ('dtype', dtype)
        file = np.fromfile(self.writePath + file,dtype=dtype).byteswap()
        print (file.shape)
        if z == None:
            matrix = file.reshape((y,x))
        else:
            matrix = file.reshape((z,y,x))
        print ('MATRICX SHAPE', matrix.shape)
        return matrix

class Grid(Binary):

    def __init__(self, ini_params):
        self.writePath = 'Binary/'
        self.ini_params = ini_params
        self.xdim = int(ini_params['xdim'])
        self.ydim = int(ini_params['ydim'])
        self.zdim = ini_params['zdim']
        #self.ps = ps
        #self.pe = pe
        self.grid()

    def grid(self):
        '''define coordinate axes'''
        print ('XDIM:', self.xdim)
        print ('YDIM:', self.ydim)
        self.gridz, self.gridy, self.gridx = np.meshgrid(np.arange(self.zdim),
                                                         np.arange(self.ydim),
                                                         np.arange(self.xdim),
                                                         indexing='ij')
        print ('XDIM:', self.gridx.shape)
        print ('YDIM:', self.gridy.shape)

    def sheer_coordinates(self):
        '''coordinate transform that sheers the y-axis through angle theta'''

        theta = 15*np.pi/32

        xdash = self.gridx + (1 / np.tan(theta)) * self.gridy
        ydash = self.gridy

        self.gridx = xdash
        self.gridy = ydash

    def shift_coordinates(self):
        '''coordinate transform that shifts the x and y axes to be ridge
           centred'''

        self.gridx -=  ridge_centre
        self.gridy -=  v_centre

    def latGrid(self):
        arr  = [-latMin for i in range(self.ydim+1)]
        DYC = [-latMin for i in range(self.ydim)]
        for i in range(self.ydim):
            DYC[i] = res*(lon2m(arr[i])/lat2m(arr[i]))
            arr[i+1] = arr[i]-DYC[i]
        self.DYC = DYC
        self.Y = arr

    def zGrid(self):
        gridSum = depMax+10.0
        depiter = 400.0
        while gridSum > depMax:
            c         = (self.zdim-1)/np.log(depiter/z0)
            zGrid     = [z0*np.exp(i/c) for i in range(self.zdim)]
            gridSum = np.sum(zGrid)
            depiter = depiter-1.0
        zGridNorm = (np.cumsum(zGrid)/np.sum(zGrid))*self.zdim
        zGridCum  = (np.cumsum(zGrid))
        self.drF  = np.array(zGrid),
        self.depth = zGridCum

class Bathymetry(Grid):

    def __init__(self, ini_params):
        Grid.__init__(self, ini_params)
        try:
            self.rw    = ridge_centre - ridge_width
            self.re    = ridge_centre + ridge_width
            self.rh    = ridge_height
        except:
            print ('no ridge')
        self.bathy = np.zeros((self.gridx[0,:,:].shape))
        self.bathy[:,:] = - ini_params['depMax']
        self.set_title = 'Bathymetry'
        self.set_save = 'Bathymetry'

    def get_bathy(self):
        return self.bathy

    def meridional_wall(self):
        self.bathy[self.gridx==0] = 0.0

    def ridge(self, north_atlantic=0):
        '''Generates a gaussian ridge'''

        msk = np.zeros((self.bathy.shape))

        msk[(self.gridx - ridge_width < 0) & (self.gridx + ridge_width > 0)] = 1
        self.bathy += msk * (
                      np.cos(self.gridx * np.pi/ridge_width) + 1) * self.rh / 2

        if north_atlantic:
            for i in range(int(ydim)):
                self.bathy[np.argmax(self.bathy[:,i]),i] = 0

    def sawtooth_ridge(self, peak_wall=0):
        '''
        Generates a gaussian ridge with differeing gradients either side

        peak_wall add 0.0 metre bathymetry to ridge peak.
        '''

        msk1 = np.zeros((self.bathy.shape))
        msk2 = np.zeros((self.bathy.shape))
        print ('msk shape', msk1.shape)
        print ('', msk1.shape)

        msk1[(self.gridx - w_width < 0) & (self.gridx > 0)] = 1
        msk2[(self.gridx < 0) & (self.gridx + e_width > 0)] = 1

        self.bathy += msk1 * (
                      np.cos(self.gridx * np.pi/w_width) + 1) * self.rh / 2
        self.bathy += msk2 * (
                      np.cos(self.gridx * np.pi/e_width) + 1) * self.rh / 2

        peak = 0.0 if peak_wall == 1 else self.rh - depMax
        self.bathy[self.gridx==0] = peak

    def boundary_slope(self):
        '''
        Adds a ridge that spans a preiodic boundary.
        '''

        msk1 = np.zeros((self.bathy.shape))
        msk2 = np.zeros((self.bathy.shape))
        #gridy, gridx = np.meshgrid(np.arange(msk1.shape[1]),
        #                           np.arange(msk2.shape[0]))

        msk1[self.gridx - ridge_width < 0] = 1
        self.pre_bathy = self.bathy.copy()
        self.bathy= self.bathy+ msk1*((np.cos( self.gridx*np.pi/(ridge_width) )
                                    * (self.rh/2)) + (self.rh/2))
        msk2[self.gridx[:,::-1] - ridge_width < 0] = 1
        self.bathy= self.bathy+ msk2*((np.cos( self.gridx*np.pi/ridge_width )
                                    * (self.rh/2)) + (self.rh/2))[:, ::-1]
        print (self.bathy[:,10])

    def gap(self):
        y_0 = (ydim/2.0)-ridge_width
        y_1 = (ydim/2.0)+ridge_width
        self.bathy[self.rw:self.re,y_0:y_1] = -depMax

    def north_south_boundary(self):
        self.bathy[int(-2*res_multiplier):,:] = 0.0
        self.bathy[:int(2*res_multiplier),:] = 0.0

    def east_west_boundary(self):
        self.bathy[-1:,:] = 0.0
        self.bathy[:1,:] = 0.0

    def chop_ridge_end(self):

        shift = self.shift
        ridge_end = ydim/2.0
        self.ridge_end= ridge_end
        msk = np.zeros((self.bathy.shape))
        msk_end = np.zeros((self.bathy.shape))
        gridy, gridx = np.meshgrid(np.arange(msk.shape[1]),
                                   np.arange(msk.shape[0]))
        line      = gridx - (grad * (gridy + v_centre))
        #perp_line = (grad*gridx+v_centre) + gridy
        line = line - line[0,0]- line[ridge_centre, 0]
        perp_line = line[:,::-1]
        perp_line = perp_line -\
                  perp_line[np.argmin(np.abs(line)[:,ridge_end]), ridge_end]
        msk[(line+shift>0) & (line-shift<0) & (perp_line<0)] = 1
        msk_end[(line+shift>0) & (line-shift<0) &
                (perp_line>=0) & (perp_line-shift<0)] = 1
        bump = (1+np.cos( (line)*np.pi/shift )) *\
              ((1+np.cos( (perp_line)*np.pi/shift )))* (self.rh/4)

        self.bathy = self.pre_bathy + (self.bathy+5000.0)*msk
        self.bathy = self.bathy + (msk_end * bump)

    def plateau_slope(self):
        msk = np.zeros((self.bathy.shape))
        gridy, gridx = np.meshgrid(np.arange(msk.shape[1]),
                                   np.arange(msk.shape[0]))
        line = gridx - (grad * gridy) - ridge_centre
        xlimit = 240*res_multiplier
        ylimit = self.ridge_end/2.0
        msk[(line>=0) & (gridy>1) & (gridx<xlimit) & (gridy<ylimit)] = 1
        plt.figure(11)
        plt.pcolor(gridx, gridy, msk)

        pre_plateau = (res_multiplier*241.0/(gridx+1.0)) - 1.0
        plateau = (1500.0*pre_plateau/(msk*pre_plateau).max()) - depMax
        plateaued = plateau*msk
        plateaued[plateaued == 0] = -depMax
        self.bathy = np.where(self.bathy >= plateaued, self.bathy, plateaued)

    def smooth_gap(self, orientation = 1):
        sigma =10
        y_0 = (ydim/2.0)-(orientation*ridge_width+sigma/2)
        w = ridge_width
        indy = np.arange(sigma)[::orientation]
        xlen = ((self.re-self.rw)/2.0)
        indx = np.arange(-sigma,sigma)
        self.bathy[self.rw:self.re,y_0:y_0+sigma] =\
        ((self.rh-(5000-depMax))/4)*(1+np.cos(np.arange(-xlen,xlen)*np.pi/(xlen)))[:,None]*\
                    (1+np.cos(indy*np.pi/xlen))[None,:] - depMax
        #self.bathy[self.rw:self.re,y_0:y_0+sigma] =\
        #(self.rh/4)*(1+np.cos(np.arange(-xlen,xlen)*np.pi/ridge_width))[:,None]*\
        #            (1+np.cos(indy*np.pi/ridge_width))[None,:] - depMax

    def plateau(self):
        intersection = max(np.where(self.bathy[:,30] > -4500.0)[0])
        self.bathy[intersection:intersection + 50,2:(ydim/2.0) - (ridge_width+5)] = self.bathy[intersection,3]

class Wind(Grid):

    def __init__(self):
        Grid.__init__(self)
        self.curl = curl
        self.wind_strength = windStrength
        self.set_save = 'wind'
        self.set_title = 'Wind'

    def tau(self, U):
        tau = cd*rowa*U**2
        return tau

#        wind1d = 0.5*self.tau(self.wind_strength)*
#       (1-self.curl*np.cos(2*np.pi*np.power((np.arange(float(self.ydim))/
#             self.ydim),zero_curl)))[None].T
#        self.wind = np.tile(wind1d,self.xdim)
#        return self.wind.T
    def wind_reverse(self):
        wind1d    = self.tau(self.wind_strength) *\
                    -np.sin(np.pi * np.arange(self.ydim)/self.ydim)[None].T
        self.wind = np.tile(wind1d, self.xdim)
        return self.wind.T
    def wind(self):
        #wind1d    = self.tau(self.wind_strength) *\
        #       np.sin(((np.pi * np.arange(self.ydim))+ (self.ydim *np.pi/2.0))/self.ydim )[::-1][None].T
        print ('WINDDDDD', self.tau(self.wind_strength))
        wind1d    = self.tau(self.wind_strength) *\
               np.sin(2*np.pi * np.arange(self.ydim) /self.ydim )[None].T
        self.wind = np.tile(wind1d, self.xdim)
        return self.wind.T

    def constant_wind(self):
        wind1d = self.tau(self.wind_strength)*np.ones(self.ydim)
        self.wind = np.tile(wind1d, self.xdim)
        return self.wind.T

    def constant_wind_west_only(self):
        res = res_multiplier
        wind1d = self.tau(self.wind_strength) * np.ones((self.xdim/2)-(100*res))
        print (wind1d)
        transition2 = 0.5*self.tau(self.wind_strength) * \
                     (1+np.cos(np.pi * np.arange(50*res)/(50*res)))
        transition1 = transition2[::-1]
        zeros = np.zeros(self.xdim/2)
        xwind = np.concatenate((transition1, wind1d, transition2, zeros))
        print('TYPE',type(xwind))
        print('SGHAPE',xwind.shape)
        self.wind = np.tile(xwind, (self.ydim))
        return self.wind

    def constant_wind_plateau(self):
        res = int(res_multiplier)
        wind1d = self.tau(self.wind_strength) * np.ones(50*res)
        print (wind1d.shape)
        transition = (1 - (np.arange(10*res)/(10*res))
                     ) * self.tau(self.wind_strength)
        zeros = np.zeros(self.xdim - (120 * res))
        xwind = np.concatenate((wind1d, transition, zeros, transition[::-1],
                                                           wind1d))
        print('SHAPE', xwind.shape)
        north  = np.zeros((self.xdim, int(self.ydim * 1 / 2)))
        south  = np.zeros((self.xdim, int(self.ydim * 1 / 4)))
        plateau = np.tile(xwind, (int(self.ydim/4), 1)).T
        print ('south shape', south.shape)
        print ('north shape', north.shape)
        print ('plateau shape', plateau.shape)
        self.wind = np.concatenate((south, plateau, north), axis=1).T
        print('SHAPE', self.wind.shape)
        return self.wind

    def shrunk_wind(self, half_y=1):
        print ('ydim', self.ydim)
        if half_y:
            ydim_w = (self.ydim) - (4.0 * res_multiplier)
        else:
            ydim_w = (self.ydim/2.0) - (4.0 * res_multiplier)
        #ydim_w = self.ydim - (4.0 * res_multiplier)
        #wind1d    = self.tau(self.wind_strength) *\
        #       np.sin(np.pi * np.arange(ydim_w) / ydim_w )
        wind1d    = 0.5 * self.tau(self.wind_strength) *\
               (1 + np.cos(np.pi + (2*np.pi * np.arange(ydim_w) / ydim_w )))
        pad1 = np.zeros((int(2 * res_multiplier)))
        if half_y:
            pad2 = np.zeros(( int(2 * res_multiplier) ))
        else:
            pad2 = np.zeros(( int((2 * res_multiplier) + (self.ydim/2.0)) ))
        wind1d = np.concatenate([pad1, wind1d, pad2], axis=0)
        print ('wind1d', wind1d.shape)
        self.wind = np.tile(wind1d, (self.xdim, 1))
        print ('wind', self.wind.shape)

    def shrunk_wind_test(self):
        ydim_w = self.ydim - (150.0 * res_multiplier)
        wind1d    = self.tau(self.wind_strength) *\
               np.sin(np.pi * np.arange(ydim_w) / ydim_w )
        pad1 = np.zeros((75 * res_multiplier))
        pad2 = np.zeros(( (75 * res_multiplier) ))
        wind1d = np.concatenate([pad1, wind1d, pad2], axis=0)[None].T
        self.wind = np.tile(wind1d, self.xdim)

    def no_wind_north(self):
        self.wind[self.ydim/2.0:] = 0.0

    def get_wind(self):
        return self.wind.T

class Restoring(Grid):

    def __init__(self):
        Grid.__init__(self)
        self.zGrid()
        rhoDiff = 1
        self.set_title= 'sal'
        self.set_save= 'sal'
        lat  = res*np.arange(ydim)
        self.DX, self.DY = np.meshgrid(lat,self.drF)

    def salt(self):
        self.zSal()
        northVariance = np.linspace(0,rhoDiff,self.ydim)
        self.salt = np.dstack([self.salt[:,None]-northVariance[None,:]]\
                         *self.xdim)
        return self.salt

    def zSal(self):
        alpha     = 0.0002 ;sBeta = 7.4e-4; sigma_0 = 999.8
        zMax  = self.depth[zdim-1]; zMin = self.depth[0]
        sigma = ((np.log(self.depth)-np.log(zMax))*(sigmaMax-sigmaMin)\
                / np.log(zMax/zMin)) + sigmaMax
        self.salt  = sigma/(sBeta*sigma_0)
        return self.salt

    def obc(self):
        obcts = self.salt[:,0,:]
        obctn = self.salt[:,-1,:]
        return obctn, obcts

class Velocities(Grid):

    def __init__(self, writeCase):
        Grid.__init__(self)
        self.writeCase = writeCase

    def extract_velocities(self, case):
        self.readPath = config.readPath(case)
        #vels_file = Dataset(self.readPath + 'vels.nc', mode='r')
        uvel = vels_file.variables['UVEL'][-1].T
        vvel = vels_file.variables['VVEL'][-1].T
        self.writeBin(uvel,self.writeCase + '_uvel.bin')
        self.writeBin(vvel,self.writeCase + '_vvel.bin')

class State(Grid):

    def __init__(self, ini_params):
        Grid.__init__(self, ini_params)
        self.ini_params = ini_params
        self.shape = (self.ini_params['zdim'],
                       self.ini_params['ydim'],
                       self.ini_params['xdim'])

    def ini_field_linear_grad(self, dimension, dimension_mesh, low, high):
        grad = (high - low) / (dimension -1)
        array = (dimension_mesh * grad) + low
        print ('dimension', dimension)
        print ('line of array', array.shape)
        return array

    def ini_field_hill(self, dimension, dimension_mesh, amp):
        array = amp * np.sin(dimension_mesh * np.pi / dimension)
        return array

    def ini_shice(self, iceDep, t, s, hFacC):
        '''
        initialise ice shelf's initial topography and pressure load along
        base
        '''

        # Remove Bathy
        z = int(self.ini_params['zdim'])
        y = int(self.ini_params['ydim'])
        x = int(self.ini_params['xdim'])
        hFacC_new = np.ones((z,y,x))
        for i in range(x):
            for j in range(y):
                for k in range(z):
                    if hFacC[k,j,i] < 1:
                        hFacC_new[k,j,i] = hFacC[k,j,i]
                    else:
                        break
        print ('hgac', hFacC_new[1,0,0])
        print ('hgac', hFacC_new[0,0,3])
        #shice_topo = - np.ones((self.xdim, self.ydim)) * iceDep
        shice_topo = iceDep
        tRef = -1.9
        sRef = 34.4

        # Calcualte density
        rho = self.ini_params['rhoConst'] * \
                            (- self.ini_params['tAlpha'] * (t - tRef)
                             + self.ini_params['sBeta']  * (s - sRef))

        # Depth integrate to ice base
        shice_ini_p = np.sum((1-hFacC_new) * self.ini_params['g'] * rho, axis=0)

        return shice_topo, shice_ini_p

    def add_heat_blob(self, x, y, x0, y0, r):
        amp = 0.001
        sigma = 1000
        array = amp * np.exp(-((x-x0)**2)/sigma - ((y-y0)**2)/sigma)
        return array

    def plot_shice():
        pass

    def ini_p_load(self, dimension, dimension_mesh, low, high):
        grad = (high - low) / (dimension -1)
        array = (dimension_mesh[0] * grad) + low
        return array

    def ini_p_force(self, dimension, dimension_mesh, low, high):
        resolution = 1
        rhoConst = 1030
        grad = (high - low) / ((dimension -1) * resolution * rhoConst)
        array = np.full(dimension_mesh.shape, grad)
        return array

bathy = 0
wind  = 0
vels  = 0
# MITgcm binary file is saved in (x,y) format

if vels:
    name = 'Binary/SPBC_303_uvel.bin'
    vels = Velocities('SPBC_303')
    vels.extract_velocities('SPBC_286')
    y = bathy.readBin(name,xdim,ydim)
    bathy.plot_single(y)

if bathy:
    name = case_name + '_bathy.bin'
    print (name)
    bathy = Bathymetry()
    bathy.shift_coordinates()
    #bathy.sheer_coordinates()
    bathy.sawtooth_ridge(peak_wall=0)
    #bathy.meridional_wall()
    #bathy.boundary_slope()
    #bathy.bathy[210:220,192:288]  = 0.0
    #bathy.gap()
    #bathy.smooth_gap()
    #bathy.chop_ridge_end()
    ###bathy.plateau_slope()
    bathy.north_south_boundary()
    #bathy.east_west_boundary()
    #bathy.smooth_gap(orientation=-1)
    b = bathy.get_bathy()#[::-1]
    #b1 = b[xdim/2:]
    #b2 = b[:xdim/2]
    #b = np.concatenate((b1,b2))
    bathy.writeBin(b,name)
    y = bathy.readBin(name,int(xdim),int(ydim))
    bathy.case = '001'
    fig = plt.figure(0)
    p = plt.pcolormesh(y)
    plt.axis('equal')
    plt.colorbar(p)
    #plt.figure(1)
    #plt.plot(y[:,int(ydim/2.0)])
#    plt.show()

if wind:
    wind_name = case_name + '_wind.bin'
    #print wind_name
    w = Wind()
    #w.ydim = 144
    #w.wind()
    w.shrunk_wind()
    wind = w.get_wind()
    #wind = np.hstack( (wind,np.zeros((288,144))) )
    #wind = np.hstack( (wind,-wind) )
    #wind = wind - wind.min()

    #wind = w.readBin(wind_name, xdim, ydim)
    #w.plot_single(wind)
    #wind[:,144:] = np.zeros((288,144))
    #w.plot_num = 1

    w.writeBin(wind, wind_name)
    wind = w.readBin(wind_name, int(xdim), int(ydim))
    w.case = '001'
    plt.figure(101)
    p = plt.pcolormesh(wind)
    plt.colorbar(p)
    #plt.figure(100)
    #plt.plot(wind[0,:])
    plt.show()

plt.show()


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

## time - O(N), space - O(1)
class Solution1:
    def reverseList(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head
        prev, curr = None, head
        nxt = curr.next
        while nxt:
            curr.next = prev
            prev, curr = curr, nxt
            nxt = nxt.next
        curr.next = prev
        return curr

# Definition for singly-linked list
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

## time, space - O(N)
class Solution2:
    def reverseList(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head
        nxt_node = head.next
        new_head = self.reverseList(nxt_node)
        nxt_node.next = head
        head.next = None
        return new_head

206. Reverse Linked List _ Linkedlist.py


import os, sys
# Change path so we find rdpy
sys.path.insert(1, os.path.join(sys.path[0], '..'))

import unittest
import rdpy.protocol.rdp.t125.per as per
import rdpy.core.type as type
import rdpy.core.error as error

class PERTest(unittest.TestCase):
    """
    @summary: test case for per layer (RDP)
    """

    def test_per_readLength(self):
        """
        @summary: test readLength function in per module
        """
        s1 = type.Stream()
        s1.writeType(type.UInt8(0x1a))
        s1.pos = 0

        l1 = per.readLength(s1)

        self.assertTrue(l1 == 0x1a, "readLength fail in small format")

        s2 = type.Stream()
        s2.writeType(type.UInt16Be(0x1abc | 0x8000))
        s2.pos = 0

        l2 = per.readLength(s2)

        self.assertTrue(l2 == 0x1abc, "readLength fail in big format")

    def test_per_writeLength(self):
        """
        @summary: test writeLength function in per module
        """
        l1 = per.writeLength(0x1a)
        self.assertTrue(isinstance(l1, type.UInt8), "bad write length type in small case")

        l2 = per.writeLength(0x7f)
        self.assertTrue(isinstance(l2, type.UInt8), "bad write length type in small case limit")

        l3 = per.writeLength(0x80)
        self.assertTrue(isinstance(l3, type.UInt16Be), "bad write length type in large case limit")

        l4 = per.writeLength(0xab)
        self.assertTrue(isinstance(l4, type.UInt16Be), "bad write length type in large case")

    def test_per_readInteger(self):
        """
        @summary: test readInteger function in per module
        """
        for t in [type.UInt8, type.UInt16Be, type.UInt32Be]:
            v = t(3)
            s = type.Stream()
            s.writeType((per.writeLength(type.sizeof(v)), v))
            s.pos = 0

            self.assertTrue(per.readInteger(s) == 3, "invalid readLength for type %s"%t)

        #error case
        for l in [0, 3, 5]:
            s = type.Stream()
            s.writeType(per.writeLength(l))
            s.pos = 0

            self.assertRaises(error.InvalidValue, per.readInteger, s)

    def test_per_writeInteger(self):
        """
        @summary: test writeInteger function in per module
        """
        (s, i) = per.writeInteger(0xaf)
        self.assertTrue(s.value == 1 and isinstance(i, type.UInt8), "invalid writeLength output in case of size 1")

        (s, i) = per.writeInteger(0xaff)
        self.assertTrue(s.value == 2 and isinstance(i, type.UInt16Be), "invalid writeLength output in case of size 2")

        (s, i) = per.writeInteger(0xaffff)
        self.assertTrue(s.value == 4 and isinstance(i, type.UInt32Be), "invalid writeLength output in case of size 4")


import re
import os

def remove_punctuation(line, strip_all=True):
    '''
    去掉中文中的标点符号
    :param line:
    :param strip_all:
    :return:
    '''
    if strip_all:
        # 去除所有半角全角符号，只留字母、数字、中文
        rule = re.compile(r"[^a-zA-Z0-9\u4e00-\u9fa5]")
        line = rule.sub('', line)
    else:
        # 去掉手工指定这些标点符号
        punctuation = """！？｡＂＃＄％＆＇（）＊＋－／：；＜＝＞＠［＼］＾＿｀｛｜｝～｟｠｢｣､、〃》「」『』【】〔〕〖〗〘〙〚〛〜〝〞〟〰〾〿–—‘'‛“”„‟…‧﹏"""
        re_punctuation = "[{}]+".format(punctuation)
        line = re.sub(re_punctuation, "", line)
    return line

def list_all_files(rootdir):
    '''
    # 列出文件夹下所有文件,包括子目录
    :param rootdir:
    :return:
    '''
    _files = []
    list = os.listdir(rootdir)
    for i in range(0, len(list)):
        path = os.path.join(rootdir, list[i])
        if os.path.isdir(path):
            _files.extend(list_all_files(path))
        if os.path.isfile(path):
            _files.append(path)

    return _files


#1
vetor = [1, 2, 3,4, 5]
print(vetor)
#2
v = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
v.reverse()
print(v)
#3
notas = [5, 7, 4, 10]
print(notas)
media = sum(notas) / 4
print('media: ',media)

#4
v = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
contador = 0
for va in v:
    if va != 'a' and 'e' and 'i' and 'o' and 'u':
        contador += 1

        print(va)

print(contador)
#5
v=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
impar=[]
par=[]

for numero in range(0,20):
    if v[numero] % 2 == 0:
        par.append(v[numero])
    else: impar.append(v[numero])

print("todos os numeros: " +str(v))
print("numeros impar: " +str(impar))
print("numeros pares:" +str(par))
#6
listaNotas = []
notasAluno = []
print ('Notas dos Alunos')
for i in range(10):
 	media = 0
 	notasAluno = []
 	print ('Aluno: ' + str(i + 1))
 	for j in range(4):
 		notasAluno.append(float(input('Nota: ' + str(j+1) + '\n')))
 		media += notasAluno[j]
 		print (media)
 	media = media/4
 	listaNotas.append(media)

#7
numeros = []
for i in range(0, 5):
  addnumero = int(input('Digite o número a ser adicionado:\n'))
  numeros.append(addnumero)

print(numeros)
print('A soma de todos os numeros é : ' + str(sum(numeros)))

multi = 1
for i in range(0, len(numeros)):
  multi *= numeros[i]

print('A multiplicação de todos os números é: ' + str(multi))

#8

for i in range(0, 5):
  nome = str(input('Digite o nome da pessoa:\n'))

  nomes.append(nome)
  altura = float(input('Digite a altura da respectiva pessoa:\n'))

  alturas.append(altura)

nomes.reverse()
alturas.reverse()
print('A ordem inversa dos nomes é: ' + str(nomes))
print('A ordem inversa das alturas é: ' + str(alturas))

#9
numeros = []
for i in range(0, 10):
  addnumero = int(input('Digite o número a ser adicionado:\n'))
  numeros.append(addnumero)

quadrado = 0
for i in range(0, len(numeros)):
  quadrado += (numeros[i] ** 2)

print('A soma dos quadrados dos elementos é: ' + str(quadrado))

#10
numbers = []
characters = []

for i in range(0, 10):
  addNumber = int(input('Digite um valor inteiro para ser adicionado:\n'))
  numbers.append(addNumber)

for i in range(0, 10):
  character = str(input('Digite um caracter para ser adicionado:\n'))
  while(len(character) != 1):
    character = str(input('Por favor, digite apenas um caracter:\n'))
  else:
    characters.append(character)

group = []
for i in range(0, len(numbers)):
  group.insert(len(group), numbers[i])
  group.insert(len(group), characters[i])

print(group)


import os
from typing import Any, Callable, List, Optional, Union

import torch
from pytorch_lightning import LightningDataModule
from torch.utils.data import DataLoader, Dataset, random_split
from torchvision import transforms as transform_lib
from torchvision.datasets import CIFAR10, MNIST
from torchvision.transforms import transforms

class CIFAR10DataModule(LightningDataModule):
    def __init__(
        self,
        data_dir: Optional[str] = None,
        val_split: Union[int, float] = 0.2,
        num_workers: int = 0,
        normalize: bool = False,
        batch_size: int = 32,
        seed: int = 42,
        shuffle: bool = True,
        pin_memory: bool = True,
        drop_last: bool = False,
    ) -> None:
        super().__init__()
        self.data_dir = data_dir if data_dir is not None else os.getcwd()
        self.val_split = val_split
        self.num_workers = num_workers
        self.normalize = normalize
        self.batch_size = batch_size
        self.seed = seed
        self.shuffle = shuffle
        self.pin_memory = pin_memory
        self.drop_last = drop_last

    @property
    def num_samples(self) -> int:
        train_len, _ = self._get_splits(len_dataset=50_000)
        return train_len

    @property
    def num_classes(self) -> int:
        return 10

    def prepare_data(self, *args: Any, **kwargs: Any) -> None:
        CIFAR10(self.data_dir, train=True, download=True)
        CIFAR10(self.data_dir, train=False, download=True)

    def setup(self, stage: Optional[str] = None) -> None:
        """Creates train, val, and test dataset."""
        train_transforms = transforms.Compose(
            [
                transforms.RandomCrop(32, padding=4),
                transforms.RandomHorizontalFlip(),
                transforms.ToTensor(),
                cifar10_normalization(),
            ]
        )

        if stage == "fit" or stage is None:
            dataset_train = CIFAR10(self.data_dir, train=True, transform=train_transforms)
            dataset_val = CIFAR10(self.data_dir, train=True, transform=self.default_transforms())

            # Split
            self.dataset_train = self._split_dataset(dataset_train)
            self.dataset_val = self._split_dataset(dataset_val, train=False)

        if stage == "test" or stage is None:
            self.dataset_test = CIFAR10(self.data_dir, train=False, transform=self.default_transforms())

    def _split_dataset(self, dataset: Dataset, train: bool = True) -> Dataset:
        """Splits the dataset into train and validation set."""
        len_dataset = len(dataset)
        splits = self._get_splits(len_dataset)
        dataset_train, dataset_val = random_split(dataset, splits, generator=torch.Generator().manual_seed(self.seed))

        if train:
            return dataset_train
        return dataset_val

    def _get_splits(self, len_dataset: int) -> List[int]:
        """Computes split lengths for train and validation set."""
        if isinstance(self.val_split, int):
            train_len = len_dataset - self.val_split
            splits = [train_len, self.val_split]
        elif isinstance(self.val_split, float):
            val_len = int(self.val_split * len_dataset)
            train_len = len_dataset - val_len
            splits = [train_len, val_len]
        else:
            raise ValueError(f"Unsupported type {type(self.val_split)}")

        return splits

    def default_transforms(self) -> Callable:
        if self.normalize:
            cf10_transforms = transform_lib.Compose([transform_lib.ToTensor(), cifar10_normalization()])
        else:
            cf10_transforms = transform_lib.Compose([transform_lib.ToTensor()])

        return cf10_transforms

    def train_dataloader(self, *args: Any, **kwargs: Any) -> DataLoader:
        return self._data_loader(self.dataset_train, shuffle=self.shuffle)

    def val_dataloader(self, *args: Any, **kwargs: Any) -> Union[DataLoader, List[DataLoader]]:
        return self._data_loader(self.dataset_val)

    def test_dataloader(self, *args: Any, **kwargs: Any) -> Union[DataLoader, List[DataLoader]]:
        return self._data_loader(self.dataset_test)

    def _data_loader(self, dataset: Dataset, shuffle: bool = False) -> DataLoader:
        return DataLoader(
            dataset,
            batch_size=self.batch_size,
            shuffle=shuffle,
            num_workers=self.num_workers,
            drop_last=self.drop_last,
            pin_memory=self.pin_memory,
        )

def cifar10_normalization():
    normalize = transforms.Normalize(
        mean=[x / 255.0 for x in [125.3, 123.0, 113.9]],
        std=[x / 255.0 for x in [63.0, 62.1, 66.7]],
    )
    return normalize

class MNISTDataModule(LightningDataModule):
    def __init__(
        self,
        data_dir: str = ".",
        val_split: int = 5000,
        num_workers: int = 0,
        normalize: bool = False,
        seed: int = 42,
        batch_size: int = 32,
        *args,
        **kwargs,
    ):
        super().__init__()
        self.data_dir = data_dir
        self.val_split = val_split
        self.num_workers = num_workers
        self.normalize = normalize
        self.seed = seed
        self.batch_size = batch_size
        self.dataset_train = ...
        self.dataset_val = ...

    @property
    def num_classes(self):
        return 10

    def prepare_data(self):
        """Saves MNIST files to `data_dir`"""
        MNIST(self.data_dir, train=True, download=True)
        MNIST(self.data_dir, train=False, download=True)

    def setup(self, stage: Optional[str] = None):
        """Split the train and valid dataset."""
        extra = dict(transform=self.default_transforms) if self.default_transforms else {}
        dataset = MNIST(self.data_dir, train=True, download=False, **extra)
        train_length = len(dataset)
        self.dataset_train, self.dataset_val = random_split(dataset, [train_length - self.val_split, self.val_split])

    def train_dataloader(self):
        """MNIST train set removes a subset to use for validation."""
        loader = DataLoader(
            self.dataset_train,
            batch_size=self.batch_size,
            shuffle=True,
            num_workers=self.num_workers,
            drop_last=True,
            pin_memory=True,
        )
        return loader

    def val_dataloader(self):
        """MNIST val set uses a subset of the training set for validation."""
        loader = DataLoader(
            self.dataset_val,
            batch_size=self.batch_size,
            shuffle=False,
            num_workers=self.num_workers,
            drop_last=True,
            pin_memory=True,
        )
        return loader

    def test_dataloader(self):
        """MNIST test set uses the test split."""
        extra = dict(transform=self.default_transforms) if self.default_transforms else {}
        dataset = MNIST(self.data_dir, train=False, download=False, **extra)
        loader = DataLoader(
            dataset,
            batch_size=self.batch_size,
            shuffle=False,
            num_workers=self.num_workers,
            drop_last=True,
            pin_memory=True,
        )
        return loader

    @property
    def default_transforms(self):
        if self.normalize:
            mnist_transforms = transform_lib.Compose(
                [
                    transform_lib.ToTensor(),
                    transform_lib.Normalize(mean=(0.5,), std=(0.5,)),
                ]
            )
        else:
            mnist_transforms = transform_lib.ToTensor()

        return mnist_transforms


import numpy as np
import os

def ReadFile(fileName):
  fileExist = os.path.isfile(fileName)
  if not fileExist:
    print('\nerror: file '+fileName+' does not exist.')
    print('terminated.')
    exit()

  f = open(fileName, 'r')
  file1 = f.readlines()
  f.close

  file2 = []
  for lines in file1:
    file2.append(lines.strip())
  return file2

def Read_zqp_opt_dat(nSites,fileName):
  f_ = np.zeros((nSites,nSites), dtype=complex)

  print('\nreading file '+fileName)
  data = ReadFile(fileName)
  data_list = data[0].split()
  print(len(data_list))

  for ii in range(nSites):
    for jj in range(nSites):
      data_ii_re = (data[0].split())[len(data_list)-3-3*(ii+jj*nSites)]
      data_ii_im = (data[0].split())[len(data_list)-2-3*(ii+jj*nSites)]
      f_[ii][jj] += float(data_ii_re) + 1.j * float(data_ii_im)
      print(ii,jj,f_[ii][jj])

  return f_

  #exit()

def Symmetrize_f_ij(nSites, f_):
  ftmp_ = np.zeros((nSites,nSites), dtype=complex)
  print('\nSymmetrizing f_ij from ./zqp_opt.dat')
  for ii in range(nSites):
    for jj in range(nSites):
      diff = (jj-ii)%nSites
      ftmp_[0][diff] += (1./nSites)*f_[ii][jj]
  for ii in range(nSites):
    for jj in range(nSites):
      diff = (jj-ii)%nSites
      ftmp_[ii][jj] = ftmp_[0][diff]
  return f_


class User:
    name = ""
    surname = ""
    age = 0
    email = ""

    def __init__(self, name = "", surname = "", age = None): # Пустой конструктор
        self.name = name
        self.surname = surname
        self.age = age

    def set(self, name, surname, age):
        self.name = name
        self.age = age
        self.surname = surname

    def printAll(self):
        print("User:", self.name, self.surname, "age:", self.age)

admin = User()
admin.name = "Alex"
admin.age = 23
admin.surname = "Pobeda"
print(admin.name)

bob = User("Bob", "Rogers", 33)
# bob.set("Bob", "Rogers", 33)
print(bob.name, bob.age)
bob.printAll()

construc = User("Constructor", "Constructorovich", 111)
construc.printAll()


#!/usr/bin/env python
# coding: utf-8

# In[17]:

# Shambhavi Awasthi
# Data Structures and Algorithms Nanodegree
# Project 2- Problems vs Algorithms
# Problem 2: Search in a Rotated Sorted Array

def binary_search(input_list,number, start, end): # recursive binary search function
    if start > end:
        return -1

    mid_index = (start + end) // 2      # finding the mid element of the list
    mid_element = input_list[mid_index]

    if mid_element == number:
        return mid_index

    index_left_side = binary_search(input_list,number, start, mid_index - 1) # searching left side
    index_right_side = binary_search(input_list,number, mid_index + 1, end)  # searching right side

    return max(index_left_side, index_right_side)  # returning max of both

def rotated_array_search(input_list, number):
    """
    Find the index by searching in a rotated sorted array

    Args:
       input_list(array), number(int): Input array to search and the target
    Returns:
       int: Index or -1
    """
    return binary_search(input_list,number, start=0, end=len(input_list)-1) # calling binay serach function for input_list

def linear_search(input_list, number):
    for index, element in enumerate(input_list):
        if element == number:
            return index
    return -1

def test_function(test_case):
    input_list = test_case[0]
    number = test_case[1]
    if linear_search(input_list, number) == rotated_array_search(input_list, number):
        print("Pass")
    else:
        print("Fail")

# TEST CASES:
print("Test cases : ")
test_function([[6, 7, 8, 9, 10, 1, 2, 3, 4], 6])
test_function([[6, 7, 8, 9, 10, 1, 2, 3, 4], 1])
test_function([[6, 7, 8, 1, 2, 3, 4], 8])
test_function([[6, 7, 8, 1, 2, 3, 4], 1])
test_function([[6, 7, 8, 1, 2, 3, 4], 10])
test_function([[], -1])
test_function([[1], 0])

# In[ ]:


from __future__ import absolute_import
from ..ndarray import (zeros, clip, sqrt, square)
from ..ndarray import sparse
from .optimizer import Optimizer, register

__all__ = ['AdaGrad']

@register
class AdaGrad(Optimizer):
    """AdaGrad optimizer.

    This class implements the AdaGrad optimizer described in *Adaptive Subgradient
    Methods for Online Learning and Stochastic Optimization*, and available at
    http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf.

    This optimizer updates each weight by::

        grad = clip(grad * rescale_grad, clip_gradient) + wd * weight
        history += square(grad)
        weight -= learning_rate * grad / (sqrt(history) + epsilon)

    This optimizer accepts the following parameters in addition to those accepted
    by :class:`.Optimizer`.

    See Also
    ----------
    :meth:`mxnet.ndarray.sparse.adagrad_update`.

    Parameters
    ----------
    learning_rate : float, default 0.01
        The initial learning rate. If None, the optimization will use the
        learning rate from ``lr_scheduler``. If not None, it will overwrite
        the learning rate in ``lr_scheduler``. If None and ``lr_scheduler``
        is also None, then it will be set to 0.01 by default.
    epsilon : float, default 1e-6
        Small value to avoid division by 0.
    use_fused_step : bool, default True
        Whether or not to use fused kernels for optimizer.
        When use_fused_step=False or grad is not sparse, step is called,
        otherwise, fused_step is called.

    """
    def __init__(self, learning_rate=0.01, epsilon=1e-6, use_fused_step=True, **kwargs):
        if kwargs.get("eps") is not None:
            raise DeprecationWarning(
                'parameter \'eps\' is deprecated. Please use \'epsilon\' instead...')
        super(AdaGrad, self).__init__(learning_rate=learning_rate,
                                      use_fused_step=use_fused_step,
                                      **kwargs)
        self.epsilon = epsilon

    def create_state(self, index, weight):
        return zeros(weight.shape, weight.context, stype=weight.stype)  # history

    def step(self, indices, weights, grads, states):
        """Perform an optimization step using gradients and states.

        Parameters
        ----------
        indices : list of int
            List of unique indices of the parameters into the individual learning rates
            and weight decays. Learning rates and weight decay may be set via `set_lr_mult()`
            and `set_wd_mult()`, respectively.
        weights : list of NDArray
            List of parameters to be updated.
        grads : list of NDArray
            List of gradients of the objective with respect to this parameter.
        states : List of any obj
            List of state returned by `create_state()`.
        """
        for index, weight, grad, state in zip(indices, weights, grads, states):
            self._update_count(index)
            lr = self._get_lr(index)
            wd = self._get_wd(index)

            # preprocess grad
            grad *= self.rescale_grad
            if self.clip_gradient is not None:
                grad = clip(grad, - self.clip_gradient, self.clip_gradient)
            grad += wd * weight

            # update history
            history = state
            history[:] += square(grad)
            d = grad / (sqrt(history) + self.epsilon)

            # update weight
            weight[:] -= lr * d

    def fused_step(self, indices, weights, grads, states):
        """Perform a fused optimization step using gradients and states.
        Fused kernel is used for update.

        Parameters
        ----------
        indices : list of int
            List of unique indices of the parameters into the individual learning rates
            and weight decays. Learning rates and weight decay may be set via `set_lr_mult()`
            and `set_wd_mult()`, respectively.
        weights : list of NDArray
            List of parameters to be updated.
        grads : list of NDArray
            List of gradients of the objective with respect to this parameter.
        states : List of any obj
            List of state returned by `create_state()`.
        """
        for index, weight, grad, state in zip(indices, weights, grads, states):
            is_sparse = grad.stype == 'row_sparse'

            if is_sparse:
                self._update_count(index)
                lr = self._get_lr(index)
                wd = self._get_wd(index)
                kwargs = {'epsilon': self.epsilon, 'rescale_grad': self.rescale_grad}
                if self.clip_gradient:
                    kwargs['clip_gradient'] = self.clip_gradient

                history = state

                # When grad is sparse, update weight with fused kernel
                sparse.adagrad_update(weight, grad, history, out=weight, lr=lr, wd=wd, **kwargs)
            else:
                # When the grad is not sparse, the func step is called to update weight and state
                self.step([index], [weight], [grad], [state])


def edit_mdp(mdp, new_mdp=None, extend_parameters=None, **substitutions):
    """Change values in a Gromacs mdp file.

    Parameters and values are supplied as substitutions, eg ``nsteps=1000``.

    By default the template mdp file is **overwritten in place**.

    If a parameter does not exist in the template then it cannot be substituted
    and the parameter/value pair is returned. The user has to check the
    returned list in order to make sure that everything worked as expected. At
    the moment it is not possible to automatically append the new values to the
    mdp file because of ambiguities when having to replace dashes in parameter
    names with underscores (see the notes below on dashes/underscores).

    If a parameter is set to the value ``None`` then it will be ignored.

    :Arguments:
        *mdp* : filename
            filename of input (and output filename of ``new_mdp=None``)
        *new_mdp* : filename
            filename of alternative output mdp file [None]
        *extend_parameters* : string or list of strings
            single parameter or list of parameters for which the new values
            should be appended to the existing value in the mdp file. This
            makes mostly sense for a single parameter, namely 'include', which
            is set as the default. Set to ``[]`` to disable. ['include']
        *substitutions*
            parameter=value pairs, where parameter is defined by the Gromacs
            mdp file; dashes in parameter names have to be replaced by
            underscores. If a value is a list-like object then the items are
            written as a sequence, joined with spaces, e.g. ::

               ref_t=[310,310,310] --->  ref_t = 310 310 310

    :Returns:
        Dict of parameters that have *not* been substituted.

    **Example** ::

       edit_mdp('md.mdp', new_mdp='long_md.mdp', nsteps=100000, nstxtcout=1000, lincs_iter=2)

    .. Note::

       * Dashes in Gromacs mdp parameters have to be replaced by an underscore
         when supplied as python keyword arguments (a limitation of python). For example
         the MDP syntax is  ``lincs-iter = 4`` but the corresponding  keyword would be
         ``lincs_iter = 4``.
       * If the keyword is set as a dict key, eg ``mdp_params['lincs-iter']=4`` then one
         does not have to substitute.
       * Parameters *aa_bb* and *aa-bb* are considered the same (although this should
         not be a problem in practice because there are no mdp parameters that only
         differ by a underscore).
       * This code is more compact in ``Perl`` as one can use ``s///`` operators:
         ``s/^(\s*${key}\s*=\s*).*/$1${val}/``

    .. SeeAlso:: One can also load the mdp file with
                :class:`gromacs.formats.MDP`, edit the object (a dict), and save it again.
    """
    if new_mdp is None:
        new_mdp = mdp
    if extend_parameters is None:
        extend_parameters = ['include']
    else:
        extend_parameters = list(asiterable(extend_parameters))

    # None parameters should be ignored (simple way to keep the template defaults)
    substitutions = {k: v for k,v in substitutions.items() if v is not None}

    params = list(substitutions.keys())   # list will be reduced for each match

    def demangled(p):
        """Return a RE string that matches the parameter."""
        return p.replace('_', '[-_]')  # must catch either - or _

    patterns = {parameter:
                      re.compile("""\
                       (?P<assignment>\s*{0!s}\s*=\s*)  # parameter == everything before the value
                       (?P<value>[^;]*)              # value (stop before comment=;)
                       (?P<comment>\s*;.*)?          # optional comment
                       """.format(demangled(parameter)), re.VERBOSE)
                     for parameter in substitutions}

    with tempfile.TemporaryFile() as target:
        with open(mdp, 'rb') as src:
            logger.info("editing mdp = {0!r}: {1!r}".format(mdp, substitutions.keys()))
            for line in src:
                line = line.decode('utf-8')
                new_line = line.strip()  # \n must be stripped to ensure that new line is built without break
                for p in params[:]:
                    m = patterns[p].match(new_line)
                    if m:
                        # I am too stupid to replace a specific region in the string so I rebuild it
                        # (matching a line and then replacing value requires TWO re calls)
                        #print 'line:' + new_line
                        #print m.groupdict()
                        if m.group('comment') is None:
                            comment = ''
                        else:
                            comment = " "+m.group('comment')
                        assignment = m.group('assignment')
                        if not assignment.endswith(' '):
                            assignment += ' '
                        # build new line piece-wise:
                        new_line = assignment
                        if p in extend_parameters:
                            # keep original value and add new stuff at end
                            new_line += str(m.group('value')) + ' '
                        # automatically transform lists into space-separated string values
                        value = " ".join(map(str, asiterable(substitutions[p])))
                        new_line += value + comment
                        params.remove(p)
                        break
                target.write((new_line+'\n').encode('utf-8'))
        target.seek(0)
        # XXX: Is there a danger of corrupting the original mdp if something went wrong?
        with open(new_mdp, 'wb') as final:
            shutil.copyfileobj(target, final)

     # return all parameters that have NOT been substituted
    if len(params) > 0:
        logger.warn("Not substituted in {new_mdp!r}: {params!r}".format(**vars()))
    return {p: substitutions[p] for p in params}


import sys
sys.stdin = open("../implement/input.txt", "r")
n, m, k, c = map(int, input().split())
treemap = [list(map(int, input().split())) for _ in range(n)]
danger = [[0]*n for _ in range(n)] # 제초제 남은 년 수
dx = [1, -1, -1, 1]
dy = [1, 1, -1, -1]

def growtree(treemap, time):
    newtree = [[0]*n for _ in range(n)]
    for i in range(n):
        for j in range(n):
            if treemap[i][j] > 0:
                maketree, count = 0, 0
                for ni, nj in [(i+1, j), (i, j+1), (i-1,j), (i, j-1)]:
                    if 0 <= ni < n and 0 <= nj < n and treemap[ni][nj] >= 0:
                        if treemap[ni][nj] == 0 and not danger[ni][nj] >= time:
                            maketree += 1
                        elif treemap[ni][nj] > 0:
                            count += 1
                treemap[i][j] += count
                for ni, nj in [(i + 1, j), (i, j + 1), (i - 1, j), (i, j - 1)]:
                    if (0 <= ni < n and 0 <= nj < n) and treemap[ni][nj] == 0 and not danger[ni][nj] >= time:
                        newtree[ni][nj] += treemap[i][j] // maketree
    for i in range(n):
        for j in range(n):
            treemap[i][j] += newtree[i][j]

    return treemap
def print_array(array):
    for i in range(len(array)):
        for j in range(len(array[0])):
            print(array[i][j], end = " ")
        print()
def dietree(treemap, danger, time):
    maxdie = 0
    diex, diey = 0, 0
    for i in range(n):
        for j in range(n):
            nowdie = 0
            if treemap[i][j] > 0:
                nowdie += treemap[i][j]
                for u in range(4):
                    for d in range(1, k+1):
                        ni = i + d * dx[u]
                        nj = j + d * dy[u]
                        if 0> ni or ni >= n or 0> nj or nj >= n or treemap[ni][nj] <= 0:
                            break
                        nowdie += treemap[ni][nj]
            if nowdie > maxdie:
                maxdie = nowdie
                diex, diey = i, j
    danger[diex][diey] = c + time
    treemap[diex][diey] = 0
    for u in range(4):
        for d in range(1, k + 1):
            ni = diex + d * dx[u]
            nj = diey + d * dy[u]
            if 0 > ni or ni >= n or 0 > nj or nj >= n or treemap[ni][nj] < 0:
                break
            if treemap[ni][nj] == 0:
                danger[ni][nj] = c + time
                break
            danger[ni][nj] = c + time
            treemap[ni][nj] = 0
    return treemap, danger, maxdie

answer = 0
for time in range(1, m+1):
    treemap = growtree(treemap, time)
    treemap, danger, nowdie = dietree(treemap, danger, time)
    answer += nowdie
print(answer)


# -*- coding:utf-8 -*-
from sqlalchemy import func

from app.main import db
from app.room_scheduler.models import RoomResource
from app.staff.models import StaffAccount

class ComplaintCategory(db.Model):
    __tablename__ = 'complaint_categories'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    category = db.Column('category', db.String(255), nullable=False)

    def __str__(self):
        return u'{}'.format(self.category)

class ComplaintTopic(db.Model):
    __tablename__ = 'complaint_topics'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    topic = db.Column('topic', db.String(255), nullable=False)
    category_id = db.Column('category_id', db.ForeignKey('complaint_categories.id'))
    category = db.relationship(ComplaintCategory, backref=db.backref('topics', cascade='all, delete-orphan'))

    def __str__(self):
        return u'{}'.format(self.topic)

class ComplaintAdmin(db.Model):
    __tablename__ = 'complaint_admins'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    staff_account = db.Column('staff_account', db.ForeignKey('staff_account.id'))
    is_supervisor = db.Column('is_supervisor', db.Boolean(), default=False)
    topic_id = db.Column('topic_id', db.ForeignKey('complaint_topics.id'))
    topic = db.relationship(ComplaintTopic, backref=db.backref('admins', cascade='all, delete-orphan'))
    admin = db.relationship(StaffAccount)

    def __str__(self):
        return u'{}'.format(self.admin.fullname)

class ComplaintPriority(db.Model):
    __tablename__ = 'complaint_priorities'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    priority = db.Column('priority', db.Integer, nullable=False)
    priority_text = db.Column('priority_text', db.String(255), nullable=False)

    def __str__(self):
        return u'{}'.format(self.priority_text)

class ComplaintStatus(db.Model):
    __tablename__ = 'complaint_statuses'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    status = db.Column('status', db.String(), nullable=False)
    icon = db.Column('icon', db.String())
    color = db.Column('color', db.String())

    def __str__(self):
        return u'{}'.format(self.status)

class ComplaintRecord(db.Model):
    __tablename__ = 'complaint_records'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    desc = db.Column('desc', db.Text(), nullable=False, info={'label': u'รายละเอียด'})
    topic_id = db.Column('topic_id', db.ForeignKey('complaint_topics.id'))
    topic = db.relationship(ComplaintTopic, backref=db.backref('records', cascade='all, delete-orphan'))
    priority_id = db.Column('priority_id', db.ForeignKey('complaint_priorities.id'))
    priority = db.relationship(ComplaintPriority, backref=db.backref('records', cascade='all, delete-orphan'))
    status_id = db.Column('status', db.ForeignKey('complaint_statuses.id'))
    status = db.relationship(ComplaintStatus, backref=db.backref('records', cascade='all, delete-orphan'))
    origin_id = db.Column('origin_id', db.ForeignKey('complaint_records.id'))
    children = db.relationship('ComplaintRecord', backref=db.backref('parent', remote_side=[id]))
    created_at = db.Column('created_at', db.DateTime(timezone=True), server_default=func.now())
    room_id = db.Column('room_id', db.ForeignKey('scheduler_room_resources.id'))
    room = db.relationship(RoomResource, backref=db.backref('room_records', lazy='dynamic'))

class ComplaintActionRecord(db.Model):
    __tablename__ = 'complaint_action_records'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    record_id = db.Column('record_id', db.ForeignKey('complaint_records.id'))
    record = db.relationship(ComplaintRecord, backref=db.backref('actions', cascade='all, delete-orphan'))
    reviewer_id = db.Column('reviewer_id', db.ForeignKey('complaint_admins.id'))
    reviewer = db.relationship(ComplaintAdmin, backref=db.backref('actions', cascade='all, delete-orphan'),
                               foreign_keys=[reviewer_id])
    review_comment = db.Column('review_comment', db.Text(), info={'label': u'บันทึกจากผู้รีวิว'})
    approver_id = db.Column('approver_id', db.ForeignKey('complaint_admins.id'))
    approver = db.relationship(ComplaintAdmin, foreign_keys=[approver_id])
    approved = db.Column('approved', db.DateTime(timezone=True))
    approver_comment = db.Column('approver_comment', db.Text())
    deadline = db.Column('deadline', db.DateTime(timezone=True))


### for the user accessible sensitivity functions
import numpy as _np
import matplotlib.pyplot as plt
from ._sensitivityclasses import *

def setup(emul,  m, v, case="case2"):
    #print("\nsetup function for initialising Sensitivity class")
    m = _np.array(m)
    v = _np.array(v)
    s = Sensitivity(emul, m, v)
    return s

def sense_table(sense_list, inputNames, outputNames, rowHeight=6):
    rows = len(sense_list)
    cols = len(sense_list[0].m) + 1
    if inputNames == []:
        inputNames = ["input " + str(i) for i in range(cols-1)]
    inputNames.append("E*[var[f(X)]]")
    print(inputNames)
    if outputNames == []:
        outputNames = ["output " + str(i) for i in range(rows)]
    #print("rows X cols:" , rows , "X" , cols)
    cells = np.zeros([rows, cols])
    #cells_col = np.zeros([rows, cols])
    si = 0
    for s in sense_list:
        #print("Inside loop over sensitivity instances")
        cells[si,0:cols-1] = s.senseindex/s.uEV
        cells[si,cols-1] = np.sum(s.senseindex/s.uEV)
        #cells_col[si,0:cols-1] = s.senseindex/s.uEV
        #cells_col[si,cols-1] = 1.0
        #print(cells[si])
        si = si + 1

    #### create the sensitivity table
    #fig = plt.figure(figsize=(8,4))
    fig = plt.figure(figsize=(16,8))
    ax = fig.add_subplot(111, frameon=False, xticks = [], yticks = [])
    #img = plt.imshow(cells, cmap="hot")
    img = plt.imshow(cells, cmap="hot", vmin=0.0, vmax=1.0)
    #plt.colorbar()
    img.set_visible(False)
    tb = plt.table(cellText = cells,
        colLabels = inputNames,
        rowLabels = outputNames,
        loc = 'center',
        cellColours = img.to_rgba(cells))
        #cellColours = img.to_rgba(cells_col))
    #tb.set_fontsize(34)
    tb.scale(1,rowHeight)
    for i in range(1, rows+1):
        for j in range(0, cols):
            tb._cells[(i,j)]._text.set_color('green')
    # ax.add_table(tb)
    plt.show()


data = { "nouns" :
      #['nouns'][0]
      {"example" :
           #['nouns'][0][0]
           ["plural form",
            #['nouns'][0][1]
            ["tags"],
            #['nouns'][0][2]
            ["synonyms"],
            #['nouns'][0][3]
            "usage ranking"],
       "cat" :
           ["cats",
            ["pet", "animal", "feline", "meow", "paws", "fur"]
            [0],
            5]
          },
  "verbs" :
      #['verbs'][0]
      {"example":
           #['verbs'][0][0]
           ["is irregular",
            #['verbs'][0][1]
            ["ed equivalent", "ing equivalent"],
            #['verbs'][0][2]
            "is participle",
            #['verbs'][0][3]
            ["tags"],
            #['verbs'][0][4]
            ["synonyms"],
            #['verbs'][0][5]
            "usage ranking"],
       "walk":
           [False,
            ["walked",
             "walking"],
            False,
            ["movement", "exercise"],
            ["meander"],
            5]
        },
  "adjectives":
      #['adjectives'][0]
      {"example" :
           #['adjectives'][0][0]
           [["tags"],
            #['adjectives'][0][1]
            ["synonyms"],
            #['adjectives'][0][2]
            ["antonyms"],
            #['adjectives'][0][3]
            "positivity",
            #['adjectives'][0][4]
            "usage ranking"]},
  "adverbs" :
      #['adverbs'][0]
      {"example" :
           #['adjectives'][0][0]
           [["tags"],
            #['adjectives'][0][1]
            ["synonyms"],
            #['adjectives'][0][2]
            ["antonyms"],
            #['adjectives'][0][3]
            "usage ranking"],
       "quickly" :
           [["speed", "movement", "action", "thought"],
            ["fast", "speedily"],
            ["slowly", "lazily"],
            5]
       },
  "particles" :
      #['particles'][0]
      {"example" :
           #['particles'][0][0]
           [["type"]]}
  }