import typing  # noqa: F401

from kubernetes import client  # noqa: F401
from kuber import kube_api as _kube_api  # noqa: F401

from kuber import definitions as _kuber_definitions  # noqa: F401
from kuber import _types  # noqa: F401
from kuber.v1_17.meta_v1 import ListMeta  # noqa: F401
from kuber.v1_17.meta_v1 import ObjectMeta  # noqa: F401

class AuditSink(_kuber_definitions.Resource):
    """
    AuditSink represents a cluster level audit sink
    """

    def __init__(
        self,
        metadata: "ObjectMeta" = None,
        spec: "AuditSinkSpec" = None,
    ):
        """Create AuditSink instance."""
        super(AuditSink, self).__init__(
            api_version="auditregistration/v1alpha1", kind="AuditSink"
        )
        self._properties = {
            "metadata": metadata if metadata is not None else ObjectMeta(),
            "spec": spec if spec is not None else AuditSinkSpec(),
        }
        self._types = {
            "apiVersion": (str, None),
            "kind": (str, None),
            "metadata": (ObjectMeta, None),
            "spec": (AuditSinkSpec, None),
        }

    @property
    def metadata(self) -> "ObjectMeta":
        """ """
        return typing.cast(
            "ObjectMeta",
            self._properties.get("metadata"),
        )

    @metadata.setter
    def metadata(self, value: typing.Union["ObjectMeta", dict]):
        """ """
        if isinstance(value, dict):
            value = typing.cast(
                ObjectMeta,
                ObjectMeta().from_dict(value),
            )
        self._properties["metadata"] = value

    @property
    def spec(self) -> "AuditSinkSpec":
        """
        Spec defines the audit configuration spec
        """
        return typing.cast(
            "AuditSinkSpec",
            self._properties.get("spec"),
        )

    @spec.setter
    def spec(self, value: typing.Union["AuditSinkSpec", dict]):
        """
        Spec defines the audit configuration spec
        """
        if isinstance(value, dict):
            value = typing.cast(
                AuditSinkSpec,
                AuditSinkSpec().from_dict(value),
            )
        self._properties["spec"] = value

    def create_resource(self, namespace: "str" = None):
        """
        Creates the AuditSink in the currently
        configured Kubernetes cluster.
        """
        names = ["create_namespaced_audit_sink", "create_audit_sink"]

        _kube_api.execute(
            action="create",
            resource=self,
            names=names,
            namespace=namespace,
            api_client=None,
            api_args={"body": self.to_dict()},
        )

    def replace_resource(self, namespace: "str" = None):
        """
        Replaces the AuditSink in the currently
        configured Kubernetes cluster.
        """
        names = ["replace_namespaced_audit_sink", "replace_audit_sink"]

        _kube_api.execute(
            action="replace",
            resource=self,
            names=names,
            namespace=namespace,
            api_client=None,
            api_args={"body": self.to_dict(), "name": self.metadata.name},
        )

    def patch_resource(self, namespace: "str" = None):
        """
        Patches the AuditSink in the currently
        configured Kubernetes cluster.
        """
        names = ["patch_namespaced_audit_sink", "patch_audit_sink"]

        _kube_api.execute(
            action="patch",
            resource=self,
            names=names,
            namespace=namespace,
            api_client=None,
            api_args={"body": self.to_dict(), "name": self.metadata.name},
        )

    def get_resource_status(self, namespace: "str" = None):
        """This resource does not have a status."""
        pass

    def read_resource(self, namespace: str = None):
        """
        Reads the AuditSink from the currently configured
        Kubernetes cluster and returns the low-level definition object.
        """
        names = [
            "read_namespaced_audit_sink",
            "read_audit_sink",
        ]
        return _kube_api.execute(
            action="read",
            resource=self,
            names=names,
            namespace=namespace,
            api_client=None,
            api_args={"name": self.metadata.name},
        )

    def delete_resource(
        self,
        namespace: str = None,
        propagation_policy: str = "Foreground",
        grace_period_seconds: int = 10,
    ):
        """
        Deletes the AuditSink from the currently configured
        Kubernetes cluster.
        """
        names = [
            "delete_namespaced_audit_sink",
            "delete_audit_sink",
        ]

        body = client.V1DeleteOptions(
            propagation_policy=propagation_policy,
            grace_period_seconds=grace_period_seconds,
        )

        _kube_api.execute(
            action="delete",
            resource=self,
            names=names,
            namespace=namespace,
            api_client=None,
            api_args={"name": self.metadata.name, "body": body},
        )

    @staticmethod
    def get_resource_api(
        api_client: client.ApiClient = None, **kwargs
    ) -> "client.AuditregistrationV1alpha1Api":
        """
        Returns an instance of the kubernetes API client associated with
        this object.
        """
        if api_client:
            kwargs["apl_client"] = api_client
        return client.AuditregistrationV1alpha1Api(**kwargs)

    def __enter__(self) -> "AuditSink":
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return False

class AuditSinkList(_kuber_definitions.Collection):
    """
    AuditSinkList is a list of AuditSink items.
    """

    def __init__(
        self,
        items: typing.List["AuditSink"] = None,
        metadata: "ListMeta" = None,
    ):
        """Create AuditSinkList instance."""
        super(AuditSinkList, self).__init__(
            api_version="auditregistration/v1alpha1", kind="AuditSinkList"
        )
        self._properties = {
            "items": items if items is not None else [],
            "metadata": metadata if metadata is not None else ListMeta(),
        }
        self._types = {
            "apiVersion": (str, None),
            "items": (list, AuditSink),
            "kind": (str, None),
            "metadata": (ListMeta, None),
        }

    @property
    def items(self) -> typing.List["AuditSink"]:
        """
        List of audit configurations.
        """
        return typing.cast(
            typing.List["AuditSink"],
            self._properties.get("items"),
        )

    @items.setter
    def items(self, value: typing.Union[typing.List["AuditSink"], typing.List[dict]]):
        """
        List of audit configurations.
        """
        cleaned: typing.List[AuditSink] = []
        for item in value:
            if isinstance(item, dict):
                item = typing.cast(
                    AuditSink,
                    AuditSink().from_dict(item),
                )
            cleaned.append(typing.cast(AuditSink, item))
        self._properties["items"] = cleaned

    @property
    def metadata(self) -> "ListMeta":
        """ """
        return typing.cast(
            "ListMeta",
            self._properties.get("metadata"),
        )

    @metadata.setter
    def metadata(self, value: typing.Union["ListMeta", dict]):
        """ """
        if isinstance(value, dict):
            value = typing.cast(
                ListMeta,
                ListMeta().from_dict(value),
            )
        self._properties["metadata"] = value

    @staticmethod
    def get_resource_api(
        api_client: client.ApiClient = None, **kwargs
    ) -> "client.AuditregistrationV1alpha1Api":
        """
        Returns an instance of the kubernetes API client associated with
        this object.
        """
        if api_client:
            kwargs["apl_client"] = api_client
        return client.AuditregistrationV1alpha1Api(**kwargs)

    def __enter__(self) -> "AuditSinkList":
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return False

class AuditSinkSpec(_kuber_definitions.Definition):
    """
    AuditSinkSpec holds the spec for the audit sink
    """

    def __init__(
        self,
        policy: "Policy" = None,
        webhook: "Webhook" = None,
    ):
        """Create AuditSinkSpec instance."""
        super(AuditSinkSpec, self).__init__(
            api_version="auditregistration/v1alpha1", kind="AuditSinkSpec"
        )
        self._properties = {
            "policy": policy if policy is not None else Policy(),
            "webhook": webhook if webhook is not None else Webhook(),
        }
        self._types = {
            "policy": (Policy, None),
            "webhook": (Webhook, None),
        }

    @property
    def policy(self) -> "Policy":
        """
        Policy defines the policy for selecting which events should
        be sent to the webhook required
        """
        return typing.cast(
            "Policy",
            self._properties.get("policy"),
        )

    @policy.setter
    def policy(self, value: typing.Union["Policy", dict]):
        """
        Policy defines the policy for selecting which events should
        be sent to the webhook required
        """
        if isinstance(value, dict):
            value = typing.cast(
                Policy,
                Policy().from_dict(value),
            )
        self._properties["policy"] = value

    @property
    def webhook(self) -> "Webhook":
        """
        Webhook to send events required
        """
        return typing.cast(
            "Webhook",
            self._properties.get("webhook"),
        )

    @webhook.setter
    def webhook(self, value: typing.Union["Webhook", dict]):
        """
        Webhook to send events required
        """
        if isinstance(value, dict):
            value = typing.cast(
                Webhook,
                Webhook().from_dict(value),
            )
        self._properties["webhook"] = value

    def __enter__(self) -> "AuditSinkSpec":
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return False

class Policy(_kuber_definitions.Definition):
    """
    Policy defines the configuration of how audit events are
    logged
    """

    def __init__(
        self,
        level: str = None,
        stages: typing.List[str] = None,
    ):
        """Create Policy instance."""
        super(Policy, self).__init__(
            api_version="auditregistration/v1alpha1", kind="Policy"
        )
        self._properties = {
            "level": level if level is not None else "",
            "stages": stages if stages is not None else [],
        }
        self._types = {
            "level": (str, None),
            "stages": (list, str),
        }

    @property
    def level(self) -> str:
        """
        The Level that all requests are recorded at. available
        options: None, Metadata, Request, RequestResponse required
        """
        return typing.cast(
            str,
            self._properties.get("level"),
        )

    @level.setter
    def level(self, value: str):
        """
        The Level that all requests are recorded at. available
        options: None, Metadata, Request, RequestResponse required
        """
        self._properties["level"] = value

    @property
    def stages(self) -> typing.List[str]:
        """
        Stages is a list of stages for which events are created.
        """
        return typing.cast(
            typing.List[str],
            self._properties.get("stages"),
        )

    @stages.setter
    def stages(self, value: typing.List[str]):
        """
        Stages is a list of stages for which events are created.
        """
        self._properties["stages"] = value

    def __enter__(self) -> "Policy":
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return False

class ServiceReference(_kuber_definitions.Definition):
    """
    ServiceReference holds a reference to Service.legacy.k8s.io
    """

    def __init__(
        self,
        name: str = None,
        namespace: str = None,
        path: str = None,
        port: int = None,
    ):
        """Create ServiceReference instance."""
        super(ServiceReference, self).__init__(
            api_version="auditregistration/v1alpha1", kind="ServiceReference"
        )
        self._properties = {
            "name": name if name is not None else "",
            "namespace": namespace if namespace is not None else "",
            "path": path if path is not None else "",
            "port": port if port is not None else None,
        }
        self._types = {
            "name": (str, None),
            "namespace": (str, None),
            "path": (str, None),
            "port": (int, None),
        }

    @property
    def name(self) -> str:
        """
        `name` is the name of the service. Required
        """
        return typing.cast(
            str,
            self._properties.get("name"),
        )

    @name.setter
    def name(self, value: str):
        """
        `name` is the name of the service. Required
        """
        self._properties["name"] = value

    @property
    def namespace(self) -> str:
        """
        `namespace` is the namespace of the service. Required
        """
        return typing.cast(
            str,
            self._properties.get("namespace"),
        )

    @namespace.setter
    def namespace(self, value: str):
        """
        `namespace` is the namespace of the service. Required
        """
        self._properties["namespace"] = value

    @property
    def path(self) -> str:
        """
        `path` is an optional URL path which will be sent in any
        request to this service.
        """
        return typing.cast(
            str,
            self._properties.get("path"),
        )

    @path.setter
    def path(self, value: str):
        """
        `path` is an optional URL path which will be sent in any
        request to this service.
        """
        self._properties["path"] = value

    @property
    def port(self) -> int:
        """
        If specified, the port on the service that hosting webhook.
        Default to 443 for backward compatibility. `port` should be
        a valid port number (1-65535, inclusive).
        """
        return typing.cast(
            int,
            self._properties.get("port"),
        )

    @port.setter
    def port(self, value: int):
        """
        If specified, the port on the service that hosting webhook.
        Default to 443 for backward compatibility. `port` should be
        a valid port number (1-65535, inclusive).
        """
        self._properties["port"] = value

    def __enter__(self) -> "ServiceReference":
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return False

class Webhook(_kuber_definitions.Definition):
    """
    Webhook holds the configuration of the webhook
    """

    def __init__(
        self,
        client_config: "WebhookClientConfig" = None,
        throttle: "WebhookThrottleConfig" = None,
    ):
        """Create Webhook instance."""
        super(Webhook, self).__init__(
            api_version="auditregistration/v1alpha1", kind="Webhook"
        )
        self._properties = {
            "clientConfig": client_config
            if client_config is not None
            else WebhookClientConfig(),
            "throttle": throttle if throttle is not None else WebhookThrottleConfig(),
        }
        self._types = {
            "clientConfig": (WebhookClientConfig, None),
            "throttle": (WebhookThrottleConfig, None),
        }

    @property
    def client_config(self) -> "WebhookClientConfig":
        """
        ClientConfig holds the connection parameters for the webhook
        required
        """
        return typing.cast(
            "WebhookClientConfig",
            self._properties.get("clientConfig"),
        )

    @client_config.setter
    def client_config(self, value: typing.Union["WebhookClientConfig", dict]):
        """
        ClientConfig holds the connection parameters for the webhook
        required
        """
        if isinstance(value, dict):
            value = typing.cast(
                WebhookClientConfig,
                WebhookClientConfig().from_dict(value),
            )
        self._properties["clientConfig"] = value

    @property
    def throttle(self) -> "WebhookThrottleConfig":
        """
        Throttle holds the options for throttling the webhook
        """
        return typing.cast(
            "WebhookThrottleConfig",
            self._properties.get("throttle"),
        )

    @throttle.setter
    def throttle(self, value: typing.Union["WebhookThrottleConfig", dict]):
        """
        Throttle holds the options for throttling the webhook
        """
        if isinstance(value, dict):
            value = typing.cast(
                WebhookThrottleConfig,
                WebhookThrottleConfig().from_dict(value),
            )
        self._properties["throttle"] = value

    def __enter__(self) -> "Webhook":
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return False

class WebhookClientConfig(_kuber_definitions.Definition):
    """
    WebhookClientConfig contains the information to make a
    connection with the webhook
    """

    def __init__(
        self,
        ca_bundle: str = None,
        service: "ServiceReference" = None,
        url: str = None,
    ):
        """Create WebhookClientConfig instance."""
        super(WebhookClientConfig, self).__init__(
            api_version="auditregistration/v1alpha1", kind="WebhookClientConfig"
        )
        self._properties = {
            "caBundle": ca_bundle if ca_bundle is not None else "",
            "service": service if service is not None else ServiceReference(),
            "url": url if url is not None else "",
        }
        self._types = {
            "caBundle": (str, None),
            "service": (ServiceReference, None),
            "url": (str, None),
        }

    @property
    def ca_bundle(self) -> str:
        """
        `caBundle` is a PEM encoded CA bundle which will be used to
        validate the webhook's server certificate. If unspecified,
        system trust roots on the apiserver are used.
        """
        return typing.cast(
            str,
            self._properties.get("caBundle"),
        )

    @ca_bundle.setter
    def ca_bundle(self, value: str):
        """
        `caBundle` is a PEM encoded CA bundle which will be used to
        validate the webhook's server certificate. If unspecified,
        system trust roots on the apiserver are used.
        """
        self._properties["caBundle"] = value

    @property
    def service(self) -> "ServiceReference":
        """
        `service` is a reference to the service for this webhook.
        Either `service` or `url` must be specified.

        If the webhook is running within the cluster, then you
        should use `service`.
        """
        return typing.cast(
            "ServiceReference",
            self._properties.get("service"),
        )

    @service.setter
    def service(self, value: typing.Union["ServiceReference", dict]):
        """
        `service` is a reference to the service for this webhook.
        Either `service` or `url` must be specified.

        If the webhook is running within the cluster, then you
        should use `service`.
        """
        if isinstance(value, dict):
            value = typing.cast(
                ServiceReference,
                ServiceReference().from_dict(value),
            )
        self._properties["service"] = value

    @property
    def url(self) -> str:
        """
        `url` gives the location of the webhook, in standard URL
        form (`scheme://host:port/path`). Exactly one of `url` or
        `service` must be specified.

        The `host` should not refer to a service running in the
        cluster; use the `service` field instead. The host might be
        resolved via external DNS in some apiservers (e.g., `kube-
        apiserver` cannot resolve in-cluster DNS as that would be a
        layering violation). `host` may also be an IP address.

        Please note that using `localhost` or `127.0.0.1` as a
        `host` is risky unless you take great care to run this
        webhook on all hosts which run an apiserver which might need
        to make calls to this webhook. Such installs are likely to
        be non-portable, i.e., not easy to turn up in a new cluster.

        The scheme must be "https"; the URL must begin with
        "https://".

        A path is optional, and if present may be any string
        permissible in a URL. You may use the path to pass an
        arbitrary string to the webhook, for example, a cluster
        identifier.

        Attempting to use a user or basic auth e.g. "user:password@"
        is not allowed. Fragments ("#...") and query parameters
        ("?...") are not allowed, either.
        """
        return typing.cast(
            str,
            self._properties.get("url"),
        )

    @url.setter
    def url(self, value: str):
        """
        `url` gives the location of the webhook, in standard URL
        form (`scheme://host:port/path`). Exactly one of `url` or
        `service` must be specified.

        The `host` should not refer to a service running in the
        cluster; use the `service` field instead. The host might be
        resolved via external DNS in some apiservers (e.g., `kube-
        apiserver` cannot resolve in-cluster DNS as that would be a
        layering violation). `host` may also be an IP address.

        Please note that using `localhost` or `127.0.0.1` as a
        `host` is risky unless you take great care to run this
        webhook on all hosts which run an apiserver which might need
        to make calls to this webhook. Such installs are likely to
        be non-portable, i.e., not easy to turn up in a new cluster.

        The scheme must be "https"; the URL must begin with
        "https://".

        A path is optional, and if present may be any string
        permissible in a URL. You may use the path to pass an
        arbitrary string to the webhook, for example, a cluster
        identifier.

        Attempting to use a user or basic auth e.g. "user:password@"
        is not allowed. Fragments ("#...") and query parameters
        ("?...") are not allowed, either.
        """
        self._properties["url"] = value

    def __enter__(self) -> "WebhookClientConfig":
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return False

class WebhookThrottleConfig(_kuber_definitions.Definition):
    """
    WebhookThrottleConfig holds the configuration for throttling
    events
    """

    def __init__(
        self,
        burst: int = None,
        qps: int = None,
    ):
        """Create WebhookThrottleConfig instance."""
        super(WebhookThrottleConfig, self).__init__(
            api_version="auditregistration/v1alpha1", kind="WebhookThrottleConfig"
        )
        self._properties = {
            "burst": burst if burst is not None else None,
            "qps": qps if qps is not None else None,
        }
        self._types = {
            "burst": (int, None),
            "qps": (int, None),
        }

    @property
    def burst(self) -> int:
        """
        ThrottleBurst is the maximum number of events sent at the
        same moment default 15 QPS
        """
        return typing.cast(
            int,
            self._properties.get("burst"),
        )

    @burst.setter
    def burst(self, value: int):
        """
        ThrottleBurst is the maximum number of events sent at the
        same moment default 15 QPS
        """
        self._properties["burst"] = value

    @property
    def qps(self) -> int:
        """
        ThrottleQPS maximum number of batches per second default 10
        QPS
        """
        return typing.cast(
            int,
            self._properties.get("qps"),
        )

    @qps.setter
    def qps(self, value: int):
        """
        ThrottleQPS maximum number of batches per second default 10
        QPS
        """
        self._properties["qps"] = value

    def __enter__(self) -> "WebhookThrottleConfig":
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return False


# -*- coding: utf-8 -*-
"""
Created on Tue Jun 26 16:42:39 2018
    DL4CV_StarterBundle_CH9.4.4:
        9.4.4 Regularization Applied to Image Classification

@author: lq
"""

from sklearn.linear_model import SGDClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from pyimagesearch.preprocessing.simplepreprocessor import SimplePreprocessor
from pyimagesearch.datasets.simpledatasetloader import SimpleDatasetLoader
from imutils import paths
import argparse

# construct the argument parse and parse arguments
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True, help="path to input dataset")
args = vars(ap.parse_args())

# grab the list of image paths
print("[INFO] loading images...")
imagePaths = list(paths.list_images(args["dataset"]))

# initialize the image preprocessor, load the dataset from disk
# and reshape the data matrix
sp =SimplePreprocessor(32, 32)
sd1 = SimpleDatasetLoader(preprocessors=[sp])
(data, labels) = sd1.load(imagePaths, verbose=500)
data = data.reshape((data.shape[0], 3072))

# encode the labels as integers
le = LabelEncoder()
labels = le.fit_transform(labels)

# partition the data
(trainX, testX, trainY, testY) = train_test_split(data, labels,
    test_size=0.25, random_state=5)

# loop over our set of regularizers
for r in (None, "l1", "l2"):
    # train a SGD classifier using a softmax loss function and the
    # specified regularization function for 10 epochs
    print("[INFO] training model with '{}' penalty".format(r))
    # Linear classifiers (SVM, logistic regression, a.o.) with SGD training.
    model = SGDClassifier(loss="log", penalty=r, max_iter=10,
                          learning_rate="constant", eta0=0.01,random_state=42)
    model.fit(trainX, trainY)

    # evaluate the classifier
    # return: Mean accuracy of self.predict(X) wrt. y.
    acc = model.score(testX, testY)
    print("[INFO] '{}' penalty accuracy: {:.2f}%".format(r, acc * 100))


import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier, export_graphviz

X1 = np.linspace(-2, 2, 7)
t = 0
y1 = X1 ** 3

df = pd.read_csv('../mlbootcamp5_train.csv',sep=";",index_col="id")
X = df.drop(['cardio'],axis=1)
y = df['cardio']

def f(x):
    return x ** 3

def graph():
    plt.scatter(X1, f(X1))
    plt.xlabel(r'$x$')
    plt.ylabel(r'$y$');
    plt.show()

def D(x):
    return np.mean(np.power(f(x) - np.mean(f(x)), 2))

def regression_var_criterion(X, y, t):
    loneX = len(X[X < t]) / len(X)
    roneX = len(X[X >= t]) / len(X)
    lD = D(X[X < t])
    rD = D(X[X >= t])

    print("D(X):{:0.2f}".format(D(X) - loneX * lD - roneX * rD))

def preq1():
    g = np.mean(f(X1))
    plt.scatter(X1, f(X1))
    plt.plot(X1, np.linspace(g,g,7))
    plt.xlabel(r'$x$')
    plt.ylabel(r'$y$');
    plt.show()

def ppreq1():
    pass
def q3():
    X['age_years'] = (X['age'] // 365.25).astype(int)
    chol = X['cholesterol']
    gluc = X['gluc']
    X.drop(['cholesterol','gluc'],axis=1,inplace = True)
    c = pd.get_dummies(chol,prefix="chol")
    g = pd.get_dummies(gluc,prefix="gluc")
    new = pd.concat([df,c,g],axis=1)
    X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=.3, random_state=17)
    tree = DecisionTreeClassifier()
    tree.fit(X_train,y_train)

    export_graphviz(tree, out_file='../tree.dot',
               feature_names=X.columns, filled=True)
if __name__ == "__main__":
    # graph()
    # preq1()
    ppreq1()
    # question1
    # regression_var_criterion(X, y, t)

    # q3()
    pass


#!/usr/bin/env python
"""
   Call antsCorticalThickness.sh in stages. This was a misguided attempt to understand antsCorticalThickness.sh.
   Users should just use ants_ct.py instead.
"""

import sys
import os                                               # system functions
import glob
import shutil
import datetime
import argparse
import json

import _qa_utilities as qa
import _utilities as util
import labels
import json_utils

from collections import OrderedDict
import getpass
import pandas

QA_CHOICES=['input', 'results', 'methods', 'segment', 'thickness', 'extract', 'normalize']

def qa_methods_extract(output_files):
     qa_display(output_files, 'extract')

def qa_methods_segment(ants_ct_info):

     output_segment_files   = [[ ants_ct_info['input']['t1'],':visible=1:colormap=grayscale'],
                               [ ants_ct_info['segment']['p_csf'], ':visible=0:colormap=heat:heatscale=0.1,0.5,1:opacity=0.5'],
                               [ ants_ct_info['segment']['p_gm_cortical'],':visible=0:colormap=heat:heatscale=0.1,0.5,1:opacity=0.5'],
                               [ ants_ct_info['segment']['p_wm'], ':visible=0:colormap=jet:colorscale=0.2,0.1:opacity=0.5'],
                               [ ants_ct_info['segment']['segment'], ':visible=1:colormap=lut:colorscale=0,6:opacity=0.75:lut='+
                                 brain_segmentation_lut]
                               ]

     qa_display(output_segment_files, 'segment')

def qa_methods_thickness(output_files):
     qa_display(output_files, 'thickness')

def qa_methods_normalize(output_files):
     qa_display(output_files, 'normalize')

def qa_results(output_files, ants_ct_info, verbose=True):

     if verbose:
         json_utils.print_json_redcap_instrument(ants_ct_info['results']['json'])

     qa_display(output_files, 'results')

def qa_display(output_files, method):

     if qa.qa_exist(output_files, False):
          qa.freeview( output_files, True, inArgs.verbose )

     else:
          print('Unable to QA ' + method + ' ants_ct.py')
          qa.qa_exist( output_files, True )
          print('\n')

brain_segmentation_files = ( 'BrainSegmentation0N4.nii.gz',
                       'BrainSegmentationConvergence.txt',
                       'BrainSegmentation.nii.gz',
                       'BrainSegmentationPosteriors1.nii.gz',
                       'BrainSegmentationPosteriors2.nii.gz',
                       'BrainSegmentationPosteriors3.nii.gz',
                       'BrainSegmentationPosteriors4.nii.gz',
                       'BrainSegmentationPosteriors5.nii.gz',
                       'BrainSegmentationPosteriors6.nii.gz'
                       )

registration_files = ( 'BrainNormalizedToTemplate.nii.gz',
                 'BrainSegmentationTiledMosaic.png',
                 'brainvols.csv',
                 'CorticalThickness.nii.gz',
                 'CorticalThicknessNormalizedToTemplate.nii.gz',
                 'CorticalThicknessTiledMosaic.png',
                 'BrainExtractionBrain.nii.gz',
                 'ExtractedBrain0N4.nii.gz',
                 'ExtractedTemplateBrain.nii.gz',
                 'RegistrationTemplateBrainMask.nii.gz',
                 'SubjectToTemplate0GenericAffine.mat',
                 'SubjectToTemplate1Warp.nii.gz',
                 'SubjectToTemplateLogJacobian.nii.gz',
                 'TemplateToSubject0Warp.nii.gz',
                 'TemplateToSubject1GenericAffine.mat'
                 )

def get_info(input_dir, subject_id=None, methods_dir='../methods', results_dir='../results',
             t1=None, t2=None, flair=None, verbose=False):

    base = OrderedDict(( ('subject_id', subject_id),
                         ('input', input_dir),
                         ('methods', util.path_relative_to(input_dir, methods_dir)),
                         ('results', util.path_relative_to(input_dir, results_dir))
                        ))

    t1 =  util.path_relative_to(input_dir, t1) if t1 else None
    t2 =  util.path_relative_to(input_dir, t2) if t2 else None
    flair =  util.path_relative_to(input_dir, flair) if flair else None

    input_files = OrderedDict(( ('t1', os.path.abspath(t1) if t1 else None),
                                ('t2', os.path.abspath(t2) if t2 else None),
                                ('flair',  os.path.abspath(flair) if flair else None)
                               ))

    extract_files = {'mask':os.path.join(base['methods'],'BrainExtractionMask.nii.gz')}

    segment_files = OrderedDict(( ('n4', os.path.join(base['methods'],'BrainSegmentation0N4.nii.gz')),
                                 ('convergence',os.path.join(base['methods'],'BrainSegmentationConvergence.txt')),
                                 ('segment',os.path.join(base['methods'],'BrainSegmentation.nii.gz')),
                                 ('p_csf',os.path.join(base['methods'],'BrainSegmentationPosteriors1.nii.gz')),
                                 ('p_gm_cortical',os.path.join(base['methods'],'BrainSegmentationPosteriors2.nii.gz')),
                                 ('p_wm',os.path.join(base['methods'],'BrainSegmentationPosteriors3.nii.gz')),
                                 ('p_gm_subcortical',os.path.join(base['methods'],'BrainSegmentationPosteriors4.nii.gz')),
                                 ('p_brainstem',os.path.join(base['methods'],'BrainSegmentationPosteriors5.nii.gz')),
                                 ('p_cerebellum',os.path.join(base['methods'],'BrainSegmentationPosteriors6.nii.gz'))
                               ))

    register_files = OrderedDict(( ('brain_to_template',os.path.join(base['methods'],'BrainNormalizedToTemplate.nii.gz')),
                                 ('brainseg_mosaic',os.path.join(base['methods'],'BrainSegmentationTiledMosaic.png')),
                                 ('brainvols',os.path.join(base['methods'],'brainvols.csv')),
                                 ('ct',os.path.join(base['methods'],'CorticalThickness.nii.gz')),
                                 ('ct_to_template',os.path.join(base['methods'],'CorticalThicknessNormalizedToTemplate.nii.gz')),
                                 ('ct_mosaic',os.path.join(base['methods'],'CorticalThicknessTiledMosaic.png')),
                                 ('extracted_brain_n4',os.path.join(base['methods'],'ExtractedBrain0N4.nii.gz',)),
                                 ('template_brain_mask',os.path.join(base['methods'],'RegistrationTemplateBrainMask.nii.gz',)),
                                 ('subject_to_template_affine',os.path.join(base['methods'],'SubjectToTemplate0GenericAffine.mat',)),
                                 ('subject_to_template_warp',os.path.join(base['methods'],'SubjectToTemplate1Warp.nii.gz',)),
                                 ('subject_to_template_jacobian',os.path.join(base['methods'],'SubjectToTemplateLogJacobian.nii.gz',)),
                                 ('template_to_subject_warp',os.path.join(base['methods'],'TemplateToSubject0Warp.nii.gz',)),
                                 ('template_to_subject_affine',os.path.join(base['methods'],'TemplateToSubject1GenericAffine.mat'))
                                 ))

    results_files = OrderedDict(( ('json', os.path.join(base['results'], 'ants_ct.json')),
                                  ('segment', os.path.join(base['results'], 'BrainSegmentation.nii.gz')),
                                  ('ct',os.path.join(base['results'],'CorticalThickness.nii.gz')),
                                  ('p_gm', os.path.join(base['results'], 'gm_posterior.nii.gz')),
                                  ('p_wm', os.path.join(base['results'], 'wm_posterior.nii.gz')),
                                  ('subject_to_template_affine',os.path.join(base['results'],'SubjectToTemplate0GenericAffine.mat',)),
                                  ('subject_to_template_warp',os.path.join(base['results'],'SubjectToTemplate1Warp.nii.gz',)),
                                  ('subject_to_template_jacobian',os.path.join(base['results'],'SubjectToTemplateLogJacobian.nii.gz',)),
                                  ('template_to_subject_warp',os.path.join(base['results'],'TemplateToSubject0Warp.nii.gz',)),
                                  ('template_to_subject_affine',os.path.join(base['results'],'TemplateToSubject1GenericAffine.mat'))
                                  ))

    ants_ct_info = {'base': base, 'input': input_files, 'extract': extract_files,
            'segment':segment_files, 'register':register_files, 'results':results_files}

    return ants_ct_info

#endregion

def status_methods( ants_ct_info, verbose=False, debug=False ):

     register_files =  [ value for key, value in ants_ct_info['register'].items() ]

     ants_ct_status = util.check_files(register_files,debug)

     if verbose:
          print( ants_ct_info['base']['input'] + ', ants_ct, ' + 'methods' + ', ' + str(ants_ct_status) )

     return ants_ct_status

def status_results( ants_ct_info, verbose=False, debug=False ):

     result_files =  [ value for key, value in ants_ct_info['results'].items() ]

     ants_ct_status = util.check_files(result_files, debug)

     if verbose:
          print( ants_ct_info['base']['input'] + ', ants_ct, ' + 'results' + ', ' + str(ants_ct_status) )

     return ants_ct_status

def ants_ct_status( out_directory, out_prefix):

     check_files =  [os.path.abspath( os.path.join(out_directory, out_prefix + f)) for f in brain_segmentation_files ]
     check_files += [os.path.abspath( os.path.join(out_directory, out_prefix + f)) for f in registration_files ]

     ants_ct_status = False

     for ii in check_files:
          if os.path.isfile(ii):
               return True

     return ants_ct_status

def clean( out_dir ):

     os.chdir(out_dir)

     for ii in registration_files + brain_segmentation_files:
          delete_files = glob.glob('*' + ii )     # Delete files regardless of prefix

          for jj in delete_files:
               os.remove( jj )

def archive( out_dir, in_archive_dir='archive' ):

     archive_dir = util.path_relative_to(out_dir,in_archive_dir)
     files_to_move = os.listdir(out_dir)

     if os.path.isdir(archive_dir):
          print('\nArchive directory already exists. Only one archive directory per output directory is allowed\n')
          exit()
     else:
          os.mkdir(archive_dir)

     for item_path in files_to_move:
          shutil.move(os.path.join(out_dir, item_path) , os.path.join(archive_dir, item_path))

def results(ants_ct_info, verbose=False):

     # Create results directory and populate

     util.mkcd_dir( [ ants_ct_info['base']['results'] ], True )

     files_to_link = [ ( ants_ct_info['segment']['p_wm'], ants_ct_info['results']['p_wm']),
                       ( ants_ct_info['segment']['segment'], ants_ct_info['results']['segment']),
                       ( ants_ct_info['register']['ct'], ants_ct_info['results']['ct']),
                       ( ants_ct_info['register']['subject_to_template_affine'], ants_ct_info['results']['subject_to_template_affine']),
                       ( ants_ct_info['register']['subject_to_template_warp'], ants_ct_info['results']['subject_to_template_warp']),
                       ( ants_ct_info['register']['subject_to_template_jacobian'], ants_ct_info['results']['subject_to_template_jacobian']),
                       ( ants_ct_info['register']['template_to_subject_affine'], ants_ct_info['results']['template_to_subject_affine']),
                       ( ants_ct_info['register']['template_to_subject_warp'], ants_ct_info['results']['template_to_subject_warp'])
                       ]

     for ii in files_to_link:
          util.force_hard_link( ii[0],ii[1])

     fsl_command = ['fslmaths', ants_ct_info['segment']['p_gm_cortical'], '-add',  ants_ct_info['segment']['p_gm_subcortical'],
                    ants_ct_info['results']['p_gm']]

     util.iw_subprocess(fsl_command)

     methods_write_json_redcap_ants_ct_instrument(ants_ct_info, verbose)

def methods_write_json_redcap_ants_ct_instrument(ants_ct_info, verbose):
    """ Write ANTs CT Instrument to JSON output file"""

    df_stats = labels.properties(ants_ct_info['segment']['segment'])

    dict_redcap = OrderedDict((('subject_id', ants_ct_info['base']['subject_id']),
                               ('ants_ct_analyst', getpass.getuser()),
                               ('ants_ct_datetime', '{:%Y-%b-%d %H:%M:%S}'.format(datetime.datetime.now())),
                               ('ants_ct_csf_volume_mm3', '{0:4.3f}'.format(df_stats.iloc[0]['volume_mm3'])),
                               ('ants_ct_gm_cortical_volume_mm3', '{0:4.3f}'.format(df_stats.iloc[1]['volume_mm3'])),
                               ('ants_ct_wm_volume_mm3', '{0:4.3f}'.format(df_stats.iloc[2]['volume_mm3'])),
                               ('ants_ct_gm_subcortical_volume_mm3','{0:4.3f}'.format(df_stats.iloc[3]['volume_mm3'])),
                               ('ants_ct_brainstem_volume_mm3','{0:4.3f}'.format(df_stats.iloc[4]['volume_mm3'])),
                               ('ants_ct_cerebellum_volume_mm3', '{0:4.3f}'.format(df_stats.iloc[5]['volume_mm3']))
                               )
                              )

    with open( ants_ct_info['results']['json'], 'w') as outfile:
        json.dump(dict_redcap, outfile, indent=4, ensure_ascii=True, sort_keys=False)

    if verbose:
        print(json.dumps(dict_redcap, indent=4, ensure_ascii=True, sort_keys=False))

    return

def methods( t1full, t2full, t2flair, options, verbose=False, debug=False, nohup=False):

     print('\nRunnning ants_ct.py\n')

     if  qa.qa_input_files( input_files, False):

          if not os.path.exists( out_directory ):
               os.makedirs( out_directory )

          callCommand = ['antsCorticalThickness.sh', '-d', '3', '-t', options['t_option'], '-w', '0.25',
                         '-e', options['e_option'], '-m', options['m_option'], '-f', options['f_option'], '-p', options['p_option'],
                         '-o', options['o_option']
                         ]

          callCommand = callCommand + [ '-a', t1full ]

          if not t2full == None:
               callCommand = callCommand + [ '-a', t2full ]

          if not inArgs.t2flair == None:
               callCommand = callCommand + [ '-a', t2flair ]

          util.iw_subprocess( callCommand, verbose, debug,  nohup )

     else:
          print('\nUnable to run iwAntsCT.py. Failed input QA.')
          qa.qa_exist( input_files, True )
          print('\n')

#
# Main Function
#

if __name__ == '__main__':

     ## Parsing Arguments
     #
     #

     usage = 'usage: %prog [options] arg1 arg2'

     parser = argparse.ArgumentParser(prog='ants_ct')
     parser.add_argument('--t1full',          help='Full T1w image (default = t1w.nii.gz )', default = 't1w.nii.gz' )
     parser.add_argument('--t2full',          help='T2 TSE used in QI and QO (default = None )', default = None )
     parser.add_argument('--t2flair',         help='T2 Flair used in QI and QO (default = None )', default = None )

     parser.add_argument('-i', '--indir',           help='Input directory', default = os.getcwd() )
     parser.add_argument('--outdir',          help='Output directory', default = '../methods' )

     parser.add_argument('--outprefix',       help='Output prefix', default = '' )

     parser.add_argument('--mask',            help='Mask to use for antsCorticalThickness.sh.', default = None)

     parser.add_argument('-d','--display',    help='Display Results', action='store_true', default=False )
     parser.add_argument('-t','--template',   help='Template', default='inia19', choices=['inia19', 'ixi'])
     parser.add_argument('-v','--verbose',    help='Verbose flag',      action='store_true', default=False )
     parser.add_argument('--debug',           help='Debug flag',      action='store_true', default=False )
     parser.add_argument('--clean',           help=('Clean --outdir by removing files created during'
                                                    'antsCorticalThickness.sh Segmentation and Registration stages. '
                                                    'This will allow you to rerun antsCorticalThickness.sh after you '
                                                    'have edited BrainExtractionMask.nii.gz '),
                         action='store_true', default=False )

     parser.add_argument('--archive',           help=('Archive the files in --outdir by moving them to the subdirectory archive'
                                                    'This will allow you to rerun antsCorticalThickness.sh after you '
                                                    'have edited BrainExtractionMask.nii.gz and compare the results. '),
                         action='store_true', default=False )

     parser.add_argument("--status", help="Status check. choices=[methods,results]", nargs='*',
                        choices=['methods','results'], default=[None])

     parser.add_argument('--methods',         help='Run processing pipeline',      action='store_true', default=False )
     parser.add_argument('--nohup',           help='nohup',           action='store_true', default=False )

     parser.add_argument('--qa', help='QA methods (input, results, methods)', nargs='*', choices=QA_CHOICES, default=[None])

     parser.add_argument('--results',         help='Create JSON file', action='store_true', default=False)
     parser.add_argument('--results_dir',     help='Results directory', default = '../results/' )

     parser.add_argument('--subject_id',      help='Subject ID. Only used for dumping JSON file.  If not defined then '
                                                   'and empyt Subject ID is used.', default='')

     inArgs = parser.parse_args()

     # Change director to input directory

     input_files = [[ inArgs.t1full,':colormap=grayscale']]

     optional_files = [[inArgs.t2flair, ':visible=0:colormap=grayscale']]

     if inArgs.template == 'ixi':

          template_dir    =  os.getenv('TEMPLATE_IXI')
          template_prefix = 'ixiTemplate2'

          e_option = template_dir +  template_prefix + '_e_T1wFullImage.nii.gz'
          t_option = template_dir +  template_prefix + '_t_T1wSkullStripped.nii.gz'
          m_option = template_dir +  template_prefix + '_m_BrainCerebellumProbabilityMask.nii.gz'
          f_option = template_dir +  template_prefix + '_f_BrainCerebellumExtractionMask.nii.gz'
          p_option = template_dir + 'priors%d.nii.gz'

          p1_option = template_dir + 'priors1.nii.gz'
          p2_option = template_dir + 'priors2.nii.gz'
          p3_option = template_dir + 'priors3.nii.gz'
          p4_option = template_dir + 'priors4.nii.gz'
          p5_option = template_dir + 'priors5.nii.gz'
          p6_option = template_dir + 'priors6.nii.gz'

     elif inArgs.template == 'inia19':

          template_dir    =  os.getenv('TEMPLATE_INIA19')
          template_prefix = 'inia19'

          e_option = os.path.join( template_dir, template_prefix + '_e_T1wFullImage.nii.gz')
          t_option = os.path.join( template_dir, template_prefix + '_t_T1wSkullStripped.nii.gz')
          m_option = os.path.join( template_dir, template_prefix + '_m_BrainProbabilityMask.nii.gz')
          f_option = os.path.join( template_dir, template_prefix + '_f_BrainExtractionMask.nii.gz')
          p_option = os.path.join( template_dir, template_prefix + '_priors0%d.nii.gz')

          p1_option = os.path.join( template_dir, template_prefix + '_priors01.nii.gz')
          p2_option = os.path.join( template_dir, template_prefix + '_priors02.nii.gz')
          p3_option = os.path.join( template_dir, template_prefix + '_priors03.nii.gz')
          p4_option = os.path.join( template_dir, template_prefix + '_priors04.nii.gz')
          p5_option = os.path.join( template_dir, template_prefix + '_priors05.nii.gz')
          p6_option = os.path.join( template_dir, template_prefix + '_priors06.nii.gz')

     else:
          print('Unknown template')
          quit()

     # Grab info
     ants_ct_info = get_info( os.path.abspath(inArgs.indir), subject_id=inArgs.subject_id, methods_dir=inArgs.outdir,
                             results_dir=inArgs.results_dir, t1=inArgs.t1full, t2=inArgs.t2full, flair=inArgs.t2flair,
                             verbose=inArgs.verbose)

     out_directory = ants_ct_info['base']['methods']

     #

     brain_segmentation_lut = os.path.abspath( os.path.join( os.path.dirname(os.path.abspath(__file__)), 'AntsCorticalThicknessColorLUT.txt'))

     outFull       = os.path.join(out_directory, inArgs.outprefix)

     output_extract_files =  [[ ants_ct_info['input']['t1'],':visible=1:colormap=grayscale'],
                              [ ants_ct_info['extract']['mask'], ':visible=1:colormap=jet:opacity=0.5']
                              ]

     output_thickness_files =   [[ outFull+'ExtractedBrain0N4.nii.gz',':visible=1:colormap=grayscale'],
                                 [ outFull+'CorticalThickness.nii.gz',':visible=1:colormap=heat:opacity=0.75']
                                 ]

     output_normalize_files =   [[ t_option,                                    ':visible=0:colormap=grayscale'],
                                 [ outFull+'BrainNormalizedToTemplate.nii.gz',  ':visible=1:colormap=grayscale'],
                                 [ outFull+'CorticalThicknessNormalizedToTemplate.nii.gz', ':visible=1:colormap=heat:opacity=0.75']
                                 ]

     output_result_files   = [[ ants_ct_info['input']['t1'],':visible=1:colormap=grayscale'],
                              [ ants_ct_info['results']['p_gm'], ':visible=0:colormap=heat:heatscale=0.1,0.5,1:opacity=0.5'],
                              [ ants_ct_info['results']['p_wm'], ':visible=0:colormap=heat:heatscale=0.1,0.5,1:opacity=0.5'],
                              [ ants_ct_info['results']['ct'],':visible=0:colormap=heat:opacity=0.75'],
                              [ ants_ct_info['results']['segment'], ':visible=1:colormap=lut:colorscale=0,6:opacity=0.75:lut='+
                                brain_segmentation_lut],
                               ]

     input_files = [[ inArgs.t1full,':visible=1:colormap=grayscale'],
                    [ inArgs.t2full,':visible=1:colormap=jet:opacity=0.5'],
                    [ e_option, ':visible=0:colormap=grayscale'],
                    [ t_option, ':visible=0:colormap=grayscale'],
                    [ m_option, ':visible=0:colormap=grayscale'],
                    [ f_option, ':visible=0:colormap=grayscale'],
                    [ p1_option, ':visible=0:colormap=jet'],
                    [ p2_option, ':visible=0:colormap=jet'],
                    [ p3_option, ':visible=0:colormap=jet'],
                    [ p4_option, ':visible=0:colormap=jet'],
                    [ p5_option, ':visible=0:colormap=jet'],
                    [ p6_option, ':visible=0:colormap=jet']]

     options = { 'e_option': e_option, 't_option':t_option, 'm_option':m_option, 'f_option':f_option,
                 'p_option': p_option, 'p_options':[p1_option, p2_option, p3_option, p4_option, p5_option, p6_option],
                 'o_option': inArgs.outdir + '/' + inArgs.outprefix }

     # QA inputs
     #

     if 'input' in inArgs.qa:
          qa.qa_input_files( input_files, True, False )
          qa.freeview( input_files[:2], True, inArgs.verbose )
          qa.freeview( input_files[2:], True, inArgs.verbose )

     # Archive/Clean Directory

     if inArgs.archive:
          archive( out_directory, 'archive')

     if inArgs.clean:
          clean( out_directory )

     # Replace Mask

     if inArgs.mask is not None:

          if not os.path.exists(out_directory):
               os.makedirs(out_directory)
          else:
               if ants_ct_status( out_directory, inArgs.outprefix):
                    print('\nThe output directory should be cleaned before proceeding \n'
                          'or a new output directory should be set. \n')
                    exit()

          shutil.copy2( util.path_relative_to(ants_ct_info['base']['input'], inArgs.mask ), ants_ct_info['extract']['mask'] )

     # Methods
     #

     if  inArgs.methods or inArgs.nohup:
          methods(inArgs.t1full, inArgs.t2full, inArgs.t2flair, options, inArgs.verbose, inArgs.debug, inArgs.nohup)

     if 'extract' in inArgs.qa or 'methods' in inArgs.qa:
          qa_methods_extract(output_extract_files)

     if 'segment' in inArgs.qa or 'methods' in inArgs.qa:
          qa_methods_segment(ants_ct_info)

     if 'thickness' in inArgs.qa or 'methods' in inArgs.qa:
          qa_methods_normalize(output_thickness_files)

     if 'normalize' in inArgs.qa or 'methods' in inArgs.qa:
          qa_methods_normalize(output_normalize_files)

     # Results
     #

     if inArgs.results:
          results(ants_ct_info, inArgs.verbose)

     # Status

     if 'methods' in inArgs.status  or 'all' in inArgs.status:
          status_methods(ants_ct_info, True, inArgs.debug)

     if 'results' in inArgs.status  or 'all' in inArgs.status:
          status_results(ants_ct_info, True, inArgs.debug)

     # QA Results
     #

     if 'results' in inArgs.qa:
          qa_results(output_result_files, ants_ct_info, inArgs.verbose)


class StrKeyDict0(dict):
    def __missing__(self, key):
        if isinstance(key,str):
            raise KeyError(key)
        return self[str(key)]

    def get(self,key,defalut=None):
        try:
            return self[key]
        except KeyError:
            return defalut

    def __setitem__(self, key, value):
        self[str(key)]=value

    def __contains__(self, key):
        return key in self.keys() or str(key) in  self.keys()

d=StrKeyDict0({'2':'two','4':'four'})
print(d['2'])
print(d[4])
# print(d[5])

d.get('2')
d.get(4)
d.get(1)


from random import *
import queue

# def linear_search(array, t):  # O(length of array)
#     for i in range(len(array)):
#         if t == array[i]:
#             return i
#     return -1

def merge_sort(a):
    merge_sort_real(a,0,len(a)-1)

def merge_sort_real(a, l, r):
    if l >= r:
        return
    m = int(l / 2 + r / 2)
    merge_sort_real(a, l, m)
    merge_sort_real(a, m + 1, r)
    merge(a, l, m, r)

def merge(a, l, m, r):
    t1 = []
    for i in range(l, m + 1):
        t1.append(a[i])
    t2 = []
    for i in range(m + 1, r + 1):
        t2.append(a[i])
    len1 = m - l + 1
    len2 = r - m
    p1 = 0
    p2 = 0
    p = l
    while p1 < len1 and p2 < len2:
        if t1[p1] < t2[p2]:
            a[p] = t1[p1]
            p1 += 1
            p += 1
        else:
            a[p] = t2[p2]
            p2 += 1
            p += 1
    while p1 < len1:
        a[p] = t1[p1]
        p1 += 1
        p += 1
    while p2 < len2:
        a[p] = t2[p2]
        p2 += 1
        p += 1

# def BFS(board):
#     q = queue.Queue()
#     parent = [][] Empty
#     visited = [][] False
#     q.put(board[x1][y1])
#     while not q.empty():
#         cell = q.get()
#         if cell == dest
#             break
#         for all neighbors
#             if not visited[x][y]
#                 q.put([x][y])
#                 visited = True
#                 parent = cell
#
#     while parent[cell] != 's'
#         trace

if __name__ == '__main__':
    size = 100
    a = []
    for i in range(size):
        a.append(randint(1, size))
    print(a)

    merge_sort(a)
    # a.sort()

    print(a)
    # target = int(input("Please enter the value: "))
    # index = linear_search(a, target)
    # print(index)


# coding=utf-8
# f = open('alice.txt', 'rU')
#
# dic1 = {}
# for line in f:
#     spl = line.split()
#     for x in spl:
#         splw = x.lower()
#         splw = splw.strip('.,:\'"!@#$%^&*()_+|}{:?><\\/~`*-+=')
#         #for kwd in splw:
#         if splw in dic1:
#             dic1[splw] += 1
#         else:
#             dic1[splw] = int('1')
#             sorted(dic1)
#
# print dic1.values()
#
# D = {}.fromkeys(['name', 'age'], 123)
# print D
# d = dict((x, x ** 2) for x in xrange(5))
# print d

import os, re

def wor_ser(word, path):
    ''' подсчёт кол-во вхождений строки в файлах указанной диреткории
    '''
    word = word.strip()
    for file in os.listdir(path):
        fe = (path + file).endswith('.txt')
        if fe == True:
            c = 0
            cn = 0
            f = open(path + file, 'rU')
            for line in f.readlines():
                match = re.findall(word, line, flags=re.IGNORECASE)
                for yes in match:
                    c += 1
            for line in f.readlines():
                match1 = re.findall(word, line)
                for yes in match1:
                    cn += 1
            print ('В файле: %s встречено: %d раз  слово %s без учёта регистра') % (path + file, c, word)
            print ('В файле: %s встречено: %d раз  слово %s') % (path + file, cn, word)
    return

wor_ser(raw_input('Введите слово для поиска: '), 'd:\\test\\')

# #coding=cp1251
# import re
# import os
#
# PatternYear = 'Popularity in (\d+)'
# PatternTop = '(<tr align="right"><td>)(\d+)(<\/td>)'
# PatternMale = '(<\/td><td>)(.*)(<\/td><td>)'
# PatternFemale = '(<\/td><td>)(.*)(<\/td><td>)(.*)(<\/td>)'
#
# for file in os.listdir('.'
#                        ''):
#     print( file)
#     if file.startswith('baby'):
#         if file.endswith('.html'):
#             FileOpen = open(file, 'rU')
#             dic = {}
#             dic1 = {}
#             x = 0
#             ff = FileOpen.readlines()
#             for lines in ff:
#
#                 FileLine = lines
#                 StringsYear = re.search(PatternYear, FileLine)
#                 if StringsYear:
#                     x = StringsYear.group(1)
#
#             for lines1 in ff:
#                 FileLine = lines1
#                 StringsTop = re.search(PatternTop, FileLine)
#                 StringsMale = re.search(PatternMale, FileLine)
#                 StringsFemale = re.search(PatternFemale, FileLine)
#
#                 if StringsTop:
#                     Strings = []
#                     Strings.append(StringsMale.group(2))
#                     Strings.append(StringsFemale.group(4))
#                     y = StringsTop.group(2)
#                     dic1[y] = Strings
#                     dic[x] = dic1
#
#             print dic
#
# import os
#
# def list_dir(dir, higlight):
#     '''Выводит через print содержимое директории. перемещает указатель-индекс конкретной позиции в директории'''
#     files = os.listdir(dir)
#     x = []
#     for file in files:
#         x.append(file)
#
#     for file in files:
#         if x[int(higlight)] == file:
#             higlight = x.index(file)
#             print '=>', file
#         else:
#             print file
#
#     return higlight
#
# di = 'c:\\'
# x = 0
# higlight = 0
# files = os.listdir(di)
# list_dir(di, '0')
# while True:
#     x = raw_input()
#     if x in ['w', 's', 'a', 'd']:
#         if x == 's':
#             higlight += 1
#             if higlight>(len(files)-1):
#                 higlight=0
#             z = list_dir(di, higlight)
#         if x == 'w':
#             higlight -= 1
#             if higlight<-len(files):
#                 higlight=-1
#             z = list_dir(di, higlight)

#
# переход в директорию, если директория, если файл - открываем и list
# if x=='d':
#     try:
#       Exception:
#
# выход в предыдущую директорию, пока не корень.
# if x=='a':
#     try:
#       Exception
#
# else:
#     z = list_dir(di, higlight)
# print 'директория:',di,'позиция:', higlight


from typing import List

class Solution:

    def __init__(self):
        self.result = []
        self.N = None

    def solveNQueens(self, n: int) -> List[List[str]]:
        """
            https://leetcode.com/problems/n-queens/
            Time Complexity: O(n!)
                'n' is the size of the board
            Space Complexity: O(n) -> Recursive Stack Space
        """
        # edge case
        if not n:
            return self.result
        # no. of rows and cols
        self.N = n
        board = [[0 for _ in range(n)] for _ in range(n)]
        self._place_queen(board, 0)
        return self.result

    def _place_queen(self, board: List[List[int]], row: int) -> None:

        # base case
        # we reach out of bounds, done with all the rows
        if row == self.N:
            cur_result = []
            for r in range(self.N):
                cur_row = ''
                for c in range(self.N):
                    if board[r][c] == 1:
                        cur_row += 'Q'
                    else:
                        cur_row += '.'
                cur_result.append(cur_row)
            self.result.append(cur_result)
            return

        # logic
        # for each row in the board
        for col in range(self.N):
            # place queen at each position
            if self._is_safe(board, row, col):
                board[row][col] = 1
                # recursively placing at subsequent rows
                self._place_queen(board, row + 1)
                # backtrack
                board[row][col] = 0

    def _is_safe(self, board: List[List[int]], row: int, col: int) -> bool:

        # check current col, row changes
        for r in range(row):
            # if current position already has  a Queen
            if board[r][col] == 1:
                return False

        # check upper left diagonal
        r = row - 1
        c = col - 1
        while r >= 0 and c >= 0:
            if board[r][c] == 1:
                return False
            r -= 1
            c -= 1

        # check upper right diagonal
        r = row - 1
        c = col + 1
        while r >= 0 and c <= (self.N - 1):
            if board[r][c] == 1:
                return False
            r -= 1
            c += 1
        return True

if __name__ == '__main__':
    print(Solution().solveNQueens(4))
    print(Solution().solveNQueens(2))
    print(Solution().solveNQueens(3))


import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

labels = {1: '小学', 2: '初中', 3: '高中', 4: '大一', 5: '大二', 6: '大三'}
factors = {
    '身高': [1.45, 1.65, 1.75, 1.77, 1.77, 1.77],
    '近视度数': [.0, 175., 250., 275., 275., 275.],
    '离家距离': [.0, .0, .03, 1., 1., 1.],
    '中二程度': [.5, 1.3, 1.5, 1.2, 1.0, 1.0],
    '独立思考能力': [.0, .0, .1, .3, .7, 1.],
    '独立生活能力': [.0, .0, .5, .9, .95, 1.],
    '知识储备量': [.05, .1, .15, .35, .85, 1.],
    '努力程度': [.0, .5, 1.2, 0.9, 0.65, 1.],
}
font_path = '/usr/share/fonts/wenquanyi/wqy-microhei/wqy-microhei.ttc'

x = list(labels.keys())
font = FontProperties(fname=font_path)
for factor, value in factors.items():
    value = list(value)
    plt.plot(x, [v/value[-1] for v in value])
plt.title('成长曲线图', fontproperties=font)
plt.xticks(x, labels.values(), fontproperties=font)
plt.ylabel('以当前时间点为基准进行评价', fontproperties=font)
plt.legend(factors.keys(), prop=font)
plt.show()


# Balance Point <-- between indices

# Write a function that returns whether the given
# list has a balance point between indices,
# where one side’s sum is equal to the other’s.

# Input: [1,2,3,4,10]
# Output: True ( between indices 3 & 4 )

# Input: [1,2,4,2,1]
# Output: False

# Input: [1, 2, 3, 6]
# Output: True

def balancePoint(list):
    front = 0
    back = list[len(list)-1]
    i = 0
    while i < len(list):
        front += list[i]
        i += 1

def balancePoint (list):
    front = 0
    mid = (sum(list))/2
    for i in list:
        if front == mid:
            return True
        else:
            front += i
    return False
print(balancePoint([1,2,3,4,10]))
print(balancePoint([1,2,4,2,1]))
print(balancePoint([1, 2, 3, 6]))

# missing something? LOL

# Balance Index <-- on and including index

# Here, a balance point is on an index, not between indices.
# Return the balance index where sums are equal on either side
# (exclude its own value).

# Return -1 if none exist.

# Input: [-2,5,7,0,3]
# Output: 2

# Input: [9,9]
# Output: -1

# This is not finsihed, but it at least returns -1 when appropriate
def balance_index(input):
    leftsum = 0
    rightsum = 0
    total = len(input)

    #check each index
    for i in range(total):
        leftsum = 0
        rightsum = 0

        for j in range(i):
            leftsum += input[j]

        for k in range(total, i, -1):
            rightsum += input[k]

        if leftsum == rightsum:
            return i

        return -1


from sets import Set

def pandigit(a, b):
    result = a * b
    s = str(a) + str(b) + str(result)
    if '0' in s:
        return False
    if len(s) == 9 and len(Set(s)) == 9:
        return True

    return False

def main():
    result = Set()
    for i in range(100):
        for j in range(10000):
            if pandigit(i, j):
                result.add(i * j)
                print(i, j, i * j)
    print("Sum >>", sum(list(result)))

if __name__ == '__main__':
    main()


from __future__ import absolute_import

import logging

from topik.tests import test_data_path

class Termite(object):
    """A Bokeh Termite Visualization for LDA results analysis.

    Parameters
    ----------
    input_file : str or pandas DataFrame
        A pandas dataframe from a topik model get_termite_data() containing columns "word", "topic" and "weight".
        May also be a string, in which case the string is a filename of a csv file with the above columns.
    title : str
        The title for your termite plot

    Examples
    --------
    >>> termite = Termite("{}/termite.csv".format(test_data_path),
    ...                   "My lda results")
    >>> termite.plot('my_termite.html')

    """
    def __init__(self, input_file, title):
        self.input_file = input_file
        self.title = title

    def plot(self, output_file="termite.html"):
        import blaze as blz
        from odo import into
        import pandas as pd
        import bokeh.plotting as plt
        from bokeh.models.sources import ColumnDataSource

        t = blz.Data(self.input_file)

        MAX = blz.compute(t.weight.max())
        MIN = blz.compute(t.weight.min())

        # Create a size variable to define the size of the the circle for the plot.
        t = blz.transform(t, size=blz.sqrt((t.weight - MIN)/(MAX - MIN))*50)

        WORDS = t['word'].distinct()
        WORDS = into(list, WORDS)
        topics = t['topic'].distinct()
        topics = into(list, topics)
        # Convert topics to strings
        TOPICS = [str(i) for i in topics]

        source = into(pd.DataFrame, t)

        plt.output_file(output_file)

        data_source = ColumnDataSource(source)

        p = plt.figure(x_range=TOPICS, y_range=WORDS,
                       plot_width=1000, plot_height=1700,
                       title=self.title)

        p.circle(x="topic", y="word", size="size", fill_alpha=0.6, source=data_source)
        plt.show(p)

def plot_lda_vis(model_data, mode='show', filename=None):
    """Designed to work with to_py_lda_vis() in the model classes."""
    from pyLDAvis import prepare, save_html, show
    model_vis_data = prepare(**model_data)
    if mode == 'save_html' and filename:
        save_html(model_vis_data, filename)
    else:
        show(model_vis_data)


import tkinter as tk
from .view import RemoveExperimentView

class RemoveExperimentController:

    def __init__(self, root_controller):
        self.root_controller = root_controller
        self.root_view = self.root_controller.view_init

        self.database = self.root_controller.database

        self.view = RemoveExperimentView(self.root_view)

        self.view.widget['experiment_name'].widget.config(values=self.database.get_table_list())
        self.view.widget['remove'].configure(command=self.remove_experiment)
        self.view.widget['cancel'].configure(command=self.view.window.destroy)

    def remove_experiment(self):
        try:
            name = self.view.widget['experiment_name'].get()
        except Exception as e:
            tk.messagebox.showinfo('Error', e, parent=self.view.window)
            return

        try:
            self.database.remove_table(name)
        except Exception as e:
            tk.messagebox.showinfo('Error', e, parent=self.view.window)
            return

        self.view.window.destroy()


# Databricks notebook source
# MAGIC %md
# MAGIC # Maple Lake "stabilization" utility helper notebook V2

# COMMAND ----------

import pyspark.sql.dataframe as dataframe

# COMMAND ----------

#notebookName = ""

# COMMAND ----------

# MAGIC %run ../../includes/ml_helper_v2

# COMMAND ----------

from datetime import datetime
from pyspark.sql.types import *
from pyspark.sql.functions import *

#print("loading ml_XTL_v2_helper")

# COMMAND ----------

# dropDatabaseScript = "DROP DATABASE IF EXISTS {0} CASCADE".format(processed_entity_DB_name)
# spark.sql(dropDatabaseScript)

# COMMAND ----------

# ConvertStrDateToWeekId(strDate)
# strDate is a string with one of the following formats: "%Y-%m-%d %H:%M:%S.%f", "%Y-%m-%d", or "%Y-%m-%d %H:%M:%S"

def ConvertStrDateToWeekId(strDate):
  try:
    if strDate == None :
      print("ERROR null value sent to ConvertStrDateToWeekId!")
   # strDate = trim(strDate)
   # strDate = strDate[0,10]
    if debugLevel == "verbose":
      print(">>> date is:" + strDate)
    if strDate.find(".") >0:
      daDate = datetime.strptime(strDate, "%Y-%m-%d %H:%M:%S.%f")
    elif strDate.find(":") == -1:
      daDate = datetime.strptime(strDate, "%Y-%m-%d")
    else:
      daDate = datetime.strptime(strDate, "%Y-%m-%d %H:%M:%S")
    #daDate = datetime.strptime(strDate, "%Y-%m-%d")
    wk = daDate.isocalendar()[1]
    yr = daDate.isocalendar()[0]
    Format_4_5_4_date = "{0:4d}{1:02d}".format((yr),(wk))
    return Format_4_5_4_date
  except Exception as e:
    print("exception in ConvertStrDateToWeekId:" + str(e) + "; strDate=")
    return None

spark.udf.register("ConvertStrDateToWeekId_udf",ConvertStrDateToWeekId, StringType())
ConvertStrDateToWeekId_udf = udf(ConvertStrDateToWeekId)

# COMMAND ----------

# FetchMapNSchemaByEntityHandle(handleList)
#
# returns a dataframe with mapping and Schema data for specified entities, if no entities are specified data for all entities will be returned.
# parameters: handleList - a pyspark list of entity handles or optionally a list with one of the key words "all", "allocations", or "assortments", if no list is provided all entities will be returned
#
def FetchMapNSchemaByEntityHandle(**kwargs):
  #print(str(kwargs))
  if 'handleList' in kwargs:
    handleList = kwargs['handleList']
  else:
    handleList = 'all'
  #data_contracts_df.show()
  data_contracts_df = spark.read.format("delta").load("/mnt/entadls/curated/internal/sales/maplelake/data_contracts/")
  if 'all' in handleList:
    return data_contracts_df
  if 'allocations' in handleList:
    return data_contracts_df.where("ml_group == 'allocations'")
  if 'assortments' in handleList:
    return data_contracts_df.where("ml_group == 'assortments'")
  return data_contracts_df.where(col("entity_handle").isin(handleList))

# COMMAND ----------

def ReadDataLakeEntity(**kwargs):
  #adlsUrl, fileSchema, creationDate
  adlsUrl = kwargs['adlsUrl']
  print("adlsUrl: " + adlsUrl)
  fileSchema_str = kwargs['fileSchema']
  print("fileSchema_str: " + fileSchema_str)
  file_format = kwargs['fileFormat']
  print("file_format: " + file_format)

#   if 'creationDate' in kwargs:
#     creationDate = kwargs['creationDate']
#   else:
  #try:

  if file_format == 'delta': # if full is part of the url then assume full formatted file otherwise assume its in delta format.
    print("Loading delta file:" + adlsUrl)
    entity_df = spark.read.format('delta').load(adlsUrl)
    print(entity_df.count())
    #entity_df.show(5)
    return entity_df

  if file_format == 'sap_parquet': #sap data is stored in a different folder structure than the D365 data
    print("loading sap_parquet file:" + adlsUrl)
    entity_df = spark.read.format('parquet').load(adlsUrl)
    print(entity_df.count())
    #entity_df.show(5)
    return entity_df

  # default is to get the most recent version of the requested entity
  # get the most recent "full" file.
  entitiesList = dbutils.fs.ls(adlsUrl)
  if len(entitiesList) < 1:
    print("ERROR: Nothing found in adls path:", entitiesList)
    #raise runtimeError("ERROR: Nothing found in adls path:", entitiesList)
  else:
    entitiesList = sorted(entitiesList, reverse = True)
    mostRecentEntity = entitiesList[0]
    entityPath = mostRecentEntity.path
    entity_df = spark.read.parquet(entityPath)
    return entity_df
#   except Exception as e:
#     raise Exception()
#       print('Exception:' + str(e))

# COMMAND ----------

# ApplyEntityPreprocessingSteps(srcEntity, processingSteps)
#
# Returns a datafame that has the preprocessing steps applied to the entity.
# parameters: entity - a dataframe containing the entity data read from data lake - required parameter
#             processingSteps - a string formated set of pyspark processing steps using the "dot" concatination - required parameter
#
def ApplyEntityPreprocessingSteps(**kwargs):
  entity = kwargs['srcEntity']
  processSteps_str = kwargs['processingSteps']
  try:
    sqlContext.registerDataFrameAsTable(entity, 'T')
    processedEntity = sqlContext.sql(processSteps_str)
    return processedEntity
  except Exception as e:
    print('Exception:' + str(e))

# COMMAND ----------

# create if not lready existing database
#CreateSQL_DB(processed_entity_DB_name, processed_entity_DB_path)

# COMMAND ----------

# StoreProcessedEntity(processedEntity, destinationUrl, entityHandle)
#
# Returns true if the delta table write succeeded, otherwise returns false
def StoreProcessedEntity(processedEntity: dataframe, destinationUrl: str, entityHandle: str):
  if (processedEntity != None):
    print("StoredProcessedEntityDataframeType: " + str(type(processedEntity)))
    #processed_entity = kwargs['processedEntity']
    #destination_url = kwargs['destinationUrl']
    #entity_handle = kwargs['entityHandle']
    processed_entity = processedEntity
    destination_url = destinationUrl
    entity_handle = entityHandle

    full_path = destination_url + entity_handle
    print("Destination Path: " + full_path)
    # mkdirs will create the folder if it does not exist otherwise the command is ignored
    dbutils.fs.rm(full_path, True)  #Band-Aid
    dbutils.fs.mkdirs(full_path)
    #dbutils.fs.rm(full_path, True)
    # save the processed data into its respective folder
    processed_entity.repartition(sc.defaultParallelism).write.format("delta").mode("overwrite").save(full_path)

    success = True
    if processed_entity_history_path != None:
      # add the rundatetime stamp column
      processed_entity = processed_entity.withColumn('ProcessedDate', lit(processingDateTime))
      processed_entity.write.format("delta").mode("append").save(processed_entity_history_path + entity_handle)
    return success
  else:
    return failure

# COMMAND ----------

def StoreProcessedEntityNew(processedEntity: dataframe, destinationUrl: str, entityHandle: str, historyPath: str = None):
  if (processedEntity != NoneType):
    processed_entity = processedEntity
    destination_url = destinationUrl
    entity_handle = entityHandle
    full_path = destination_url + entity_handle
    print("Destination Path: " + full_path)

    dbutils.fs.rm(full_path, True)  #Band-Aid
    dbutils.fs.mkdirs(full_path)

    processed_entity.repartition(sc.defaultParallelism).write.format("delta").mode("overwrite").save(full_path)

    success = True
    if historyPath != None:
      # add the rundatetime stamp column
      processed_entity = processed_entity.withColumn('ProcessedDate', lit(processingDateTime))
      processed_entity.write.format("delta").mode("append").save(processed_entity_history_path + entity_handle)
    return success
  else:
    return failure