import torch
import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow import keras
import zipfile
import math
import geopandas
from shapely import geometry
import os
import torch
import sys
from sklearn.preprocessing import MinMaxScaler

# load some default Python modules
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
import pandas as pd

#geo data
data = geopandas.read_file("taxi_zones.json")

data['centroid_column'] = data.centroid
coord_list = [(x,y) for x,y in zip(data['centroid_column'].x , data['centroid_column'].y)]
coord_list = np.array(coord_list)
from sklearn.preprocessing import MinMaxScaler
#coord_list_min_max = MinMaxScaler().fit_transform(coord_list)

scaler = MinMaxScaler()
scaler.fit(coord_list)
coord_list_min_max = scaler.transform(coord_list)
#scaler.inverse_transform()
#coord_list_min_max
print("—————————js file loaded———————————")

df_train_6 =  pd.read_csv('06.csv',  parse_dates=["tpep_pickup_datetime"])#nrows = 2_000_000,
df_train_7 =  pd.read_csv('07.csv',  parse_dates=["tpep_pickup_datetime"])
df_train_8 =  pd.read_csv('08.csv',  parse_dates=["tpep_pickup_datetime"])
df_train = pd.concat([df_train_6, df_train_7, df_train_8],axis=0,ignore_index=True)

df_train["tpep_dropoff_datetime"] =pd.to_datetime(df_train["tpep_dropoff_datetime"])

x = df_train.copy()

train_X = pd.DataFrame()
#train_X["year"] = x['tpep_dropoff_datetime'].map(lambda x:x.year)
train_X["month"] = x['tpep_dropoff_datetime'].map(lambda x:x.month)
train_X["day"] = x['tpep_dropoff_datetime'].map(lambda x:x.day)
train_X["hour"] = x['tpep_dropoff_datetime'].map(lambda x:x.hour)
train_X["minute"] = x['tpep_dropoff_datetime'].map(lambda x:x.minute)
train_X["second"] = x['tpep_dropoff_datetime'].map(lambda x:x.second)

#train_X = train_X.values.reshape(train_X.shape[0],train_X.shape[1])
#train_X.to_csv("total_data.csv")
#y.to_csv("y.csv")
##########################################################
#train_X = pd.read_csv('total_data.csv')
#print(train_X.head())
#y =  pd.read_csv('y.csv')
#print(y.head())
########################################################
print("—————————csv loading finished———————————")

#y = pd.DataFrame()

#y['DOLocationID'] = df_train['DOLocationID']
coord_list = np.r_[coord_list,[[np.nan,np.nan]]]
coord_list = np.r_[coord_list,[[np.nan,np.nan]]]
train_y = coord_list[y['DOLocationID'].values-1]

a = np.concatenate((train_X,train_y),axis=1)
train = a[~np.isnan(a).any(axis=1)]

#train = a[:n_train_samples, :]
#test = a[n_train_samples:, :]

train_X,train_y = train[:,1:6],train[:,6  :8]

train_X = train_X.reshape(train_X.shape[0],1,train_X.shape[1])
train_y[:,0] = -train_y[:,0]
print("train_X.shape,train_y.shape:", train_X.shape,train_y.shape)

"""
A Mixture Density Layer for Keras
cpmpercussion: Charles Martin (University of Oslo) 2018
https://github.com/cpmpercussion/keras-mdn-layer
Hat tip to [Omimo's Keras MDN layer](https://github.com/omimo/Keras-MDN)
for a starting point for this code.
Provided under MIT License
"""
#from .version import __version__
from tensorflow.compat.v1 import keras
from tensorflow.compat.v1.keras import backend as K
from tensorflow.compat.v1.keras import layers
import numpy as np
import tensorflow.compat.v1 as tf
from tensorflow_probability import distributions as tfd

def elu_plus_one_plus_epsilon(x):
    """ELU activation with a very small addition to help prevent
    NaN in loss."""
    return keras.backend.elu(x) + 1 + keras.backend.epsilon()

class MDN(layers.Layer):
    """A Mixture Density Network Layer for Keras.
    This layer has a few tricks to avoid NaNs in the loss function when training:
        - Activation for variances is ELU + 1 + 1e-8 (to avoid very small values)
        - Mixture weights (pi) are trained in as logits, not in the softmax space.
    A loss function needs to be constructed with the same output dimension and number of mixtures.
    A sampling function is also provided to sample from distribution parametrised by the MDN outputs.
    """

    def __init__(self, output_dimension, num_mixtures, **kwargs):
        self.output_dim = output_dimension
        self.num_mix = num_mixtures
        with tf.name_scope('MDN'):
            self.mdn_mus = layers.Dense(self.num_mix * self.output_dim, name='mdn_mus')  # mix*output vals, no activation
            self.mdn_sigmas = layers.Dense(self.num_mix * self.output_dim, activation=elu_plus_one_plus_epsilon, name='mdn_sigmas')  # mix*output vals exp activation
            self.mdn_pi = layers.Dense(self.num_mix, name='mdn_pi')  # mix vals, logits
        super(MDN, self).__init__(**kwargs)

    def build(self, input_shape):
        with tf.name_scope('mus'):
            self.mdn_mus.build(input_shape)
        with tf.name_scope('sigmas'):
            self.mdn_sigmas.build(input_shape)
        with tf.name_scope('pis'):
            self.mdn_pi.build(input_shape)
        super(MDN, self).build(input_shape)

    @property
    def trainable_weights(self):
        return self.mdn_mus.trainable_weights + self.mdn_sigmas.trainable_weights + self.mdn_pi.trainable_weights

    @property
    def non_trainable_weights(self):
        return self.mdn_mus.non_trainable_weights + self.mdn_sigmas.non_trainable_weights + self.mdn_pi.non_trainable_weights

    def call(self, x, mask=None):
        with tf.name_scope('MDN'):
            mdn_out = layers.concatenate([self.mdn_mus(x),
                                          self.mdn_sigmas(x),
                                          self.mdn_pi(x)],
                                         name='mdn_outputs')
        return mdn_out

    def compute_output_shape(self, input_shape):
        """Returns output shape, showing the number of mixture parameters."""
        return (input_shape[0], (2 * self.output_dim * self.num_mix) + self.num_mix)

    def get_config(self):
        config = {
            "output_dimension": self.output_dim,
            "num_mixtures": self.num_mix
        }
        base_config = super(MDN, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

    # classmethod
    # def from_config(cls, config):
    #     return cls(**config)

def get_mixture_loss_func(output_dim, num_mixes):
    """Construct a loss functions for the MDN layer parametrised by number of mixtures."""
    # Construct a loss function with the right number of mixtures and outputs
    def mdn_loss_func(y_true, y_pred):
        # Reshape inputs in case this is used in a TimeDistribued layer

        y_pred = tf.reshape(y_pred, [-1, (2 * num_mixes * output_dim) + num_mixes], name='reshape_ypreds')
        y_true = tf.reshape(y_true, [-1, output_dim], name='reshape_ytrue')

        # Split the inputs into paramaters
        out_mu, out_sigma, out_pi = tf.split(y_pred, num_or_size_splits=[num_mixes * output_dim,
                                                                         num_mixes * output_dim,
                                                                         num_mixes],
                                             axis=-1, name='mdn_coef_split')
        # Construct the mixture models

        cat = tfd.Categorical(logits=out_pi)
        component_splits = [output_dim] * num_mixes
        mus = tf.split(out_mu, num_or_size_splits=component_splits, axis=1)
        sigs = tf.split(out_sigma, num_or_size_splits=component_splits, axis=1)
        coll = [tfd.MultivariateNormalDiag(loc=loc, scale_diag=scale) for loc, scale
                in zip(mus, sigs)]
        mixture = tfd.Mixture(cat=cat, components=coll)
        loss = mixture.log_prob(y_true)
        loss = tf.negative(loss)
        loss = tf.reduce_mean(loss)
        return loss

    # Actually return the loss function
    with tf.name_scope('MDN'):
        return mdn_loss_func

def get_mixture_sampling_fun(output_dim, num_mixes):
    """Construct a TensorFlor sampling operation for the MDN layer parametrised
    by mixtures and output dimension. This can be used in a Keras model to
    generate samples directly."""

    def sampling_func(y_pred):
        # Reshape inputs in case this is used in a TimeDistribued layer
        y_pred = tf.reshape(y_pred, [-1, (2 * num_mixes * output_dim) + num_mixes], name='reshape_ypreds')
        out_mu, out_sigma, out_pi = tf.split(y_pred, num_or_size_splits=[num_mixes * output_dim,
                                                                         num_mixes * output_dim,
                                                                         num_mixes],
                                             axis=1, name='mdn_coef_split')
        cat = tfd.Categorical(logits=out_pi)
        component_splits = [output_dim] * num_mixes
        mus = tf.split(out_mu, num_or_size_splits=component_splits, axis=1)
        sigs = tf.split(out_sigma, num_or_size_splits=component_splits, axis=1)
        coll = [tfd.MultivariateNormalDiag(loc=loc, scale_diag=scale) for loc, scale
                in zip(mus, sigs)]
        mixture = tfd.Mixture(cat=cat, components=coll)
        samp = mixture.sample()
        # Todo: temperature adjustment for sampling function.
        return samp

    # Actually return the loss_func
    with tf.name_scope('MDNLayer'):
        return sampling_func

def get_mixture_mse_accuracy(output_dim, num_mixes):
    """Construct an MSE accuracy function for the MDN layer
    that takes one sample and compares to the true value."""
    # Construct a loss function with the right number of mixtures and outputs
    def mse_func(y_true, y_pred):
        # Reshape inputs in case this is used in a TimeDistribued layer
        y_pred = tf.reshape(y_pred, [-1, (2 * num_mixes * output_dim) + num_mixes], name='reshape_ypreds')
        y_true = tf.reshape(y_true, [-1, output_dim], name='reshape_ytrue')
        out_mu, out_sigma, out_pi = tf.split(y_pred, num_or_size_splits=[num_mixes * output_dim,
                                                                         num_mixes * output_dim,
                                                                         num_mixes],
                                             axis=1, name='mdn_coef_split')
        cat = tfd.Categorical(logits=out_pi)
        component_splits = [output_dim] * num_mixes
        mus = tf.split(out_mu, num_or_size_splits=component_splits, axis=1)
        sigs = tf.split(out_sigma, num_or_size_splits=component_splits, axis=1)
        coll = [tfd.MultivariateNormalDiag(loc=loc, scale_diag=scale) for loc, scale
                in zip(mus, sigs)]
        mixture = tfd.Mixture(cat=cat, components=coll)
        samp = mixture.sample()
        mse = tf.reduce_mean(tf.square(samp - y_true), axis=-1)
        # Todo: temperature adjustment for sampling functon.
        return mse

    # Actually return the loss_func
    with tf.name_scope('MDNLayer'):
        return mse_func

def split_mixture_params(params, output_dim, num_mixes):
    """Splits up an array of mixture parameters into mus, sigmas, and pis
    depending on the number of mixtures and output dimension.
    Arguments:
    params -- the parameters of the mixture model
    output_dim -- the dimension of the normal models in the mixture model
    num_mixes -- the number of mixtures represented
    """
    mus = params[:num_mixes * output_dim]
    sigs = params[num_mixes * output_dim:2 * num_mixes * output_dim]
    pi_logits = params[-num_mixes:]
    return mus, sigs, pi_logits

def softmax(w, t=1.0):
    """Softmax function for a list or numpy array of logits. Also adjusts temperature.
    Arguments:
    w -- a list or numpy array of logits
    Keyword arguments:
    t -- the temperature for to adjust the distribution (default 1.0)
    """
    e = np.array(w) / t  # adjust temperature
    e -= e.max()  # subtract max to protect from exploding exp values.
    e = np.exp(e)
    dist = e / np.sum(e)
    return dist

def sample_from_categorical(dist):
    """Samples from a categorical model PDF.
    Arguments:
    dist -- the parameters of the categorical model
    Returns:
    One sample from the categorical model, or -1 if sampling fails.
    """
    r = np.random.rand(1)  # uniform random number in [0,1]
    accumulate = 0
    for i in range(0, dist.size):
        accumulate += dist[i]
        if accumulate >= r:
            return i
    tf.logging.info('Error sampling categorical model.')
    return -1

def sample_from_output(params, output_dim, num_mixes, temp=1.0, sigma_temp=1.0):
    """Sample from an MDN output with temperature adjustment.
    This calculation is done outside of the Keras model using
    Numpy.
    Arguments:
    params -- the parameters of the mixture model
    output_dim -- the dimension of the normal models in the mixture model
    num_mixes -- the number of mixtures represented
    Keyword arguments:
    temp -- the temperature for sampling between mixture components (default 1.0)
    sigma_temp -- the temperature for sampling from the normal distribution (default 1.0)
    Returns:
    One sample from the the mixture model.
    """
    mus, sigs, pi_logits = split_mixture_params(params, output_dim, num_mixes)
    pis = softmax(pi_logits, t=temp)
    m = sample_from_categorical(pis)
    # Alternative way to sample from categorical:
    # m = np.random.choice(range(len(pis)), p=pis)
    mus_vector = mus[m * output_dim:(m + 1) * output_dim]
    sig_vector = sigs[m * output_dim:(m + 1) * output_dim]
    scale_matrix = np.identity(output_dim) * sig_vector  # scale matrix from diag
    cov_matrix = np.matmul(scale_matrix, scale_matrix.T)  # cov is scale squared.
    cov_matrix = cov_matrix * sigma_temp  # adjust for sigma temperature
    sample = np.random.multivariate_normal(mus_vector, cov_matrix, 1)
    return sample

from tensorflow import keras
from keras.utils import plot_model
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from matplotlib import pyplot
from keras.utils import plot_model
OUTPUT_DIMS = 2
N_MIXES =40 #用来拟合分布的个数
N_HIDDEN_1 = 100
N_HIDDEN_2 = 100

model = Sequential()
model.add(keras.layers.Dense(N_HIDDEN_1, batch_input_shape=(None, 5), activation='sigmoid'))
model.add(keras.layers.Dense(N_HIDDEN_2, activation='sigmoid'))
#model.add(LSTM(200, input_shape=(train_X.shape[1], train_X.shape[2])))
#model.add(Dense(200))
model.add(MDN(OUTPUT_DIMS, N_MIXES))
model.compile(loss=get_mixture_loss_func(OUTPUT_DIMS,N_MIXES), optimizer=keras.optimizers.Adam())

model.summary()
plot_model(model, to_file='model.png')

print("—————————模型搭建完成———————————")
from keras.callbacks import EarlyStopping, ModelCheckpoint

filepath = "Model_M=40_n1=100_n2=100sigmoid.h5" #'my_model_3.h5'#保存的模型名字
#callbacks = [EarlyStopping(monitor='val_loss', patience=10, verbose=0),ModelCheckpoint(filepath, monitor='val_loss', save_best_only=True, verbose=0),]
checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=0, save_best_only=True, mode='max', period=1)
callbacks_list = [checkpoint]

history = model.fit(x=train_X, y=train_y, epochs=100,batch_size=100000,  validation_split=0.30, callbacks= callbacks_list)#batch_size=72,

###################################储存model###############################################

#model.save(filepath)

###################################储存history###############################################

import pickle
with open('Model_M=40_n1=100_n2=100sigmoid.pickle', 'wb') as file_pi:
	pickle.dump(history.history, file_pi)

from matplotlib import pyplot

pyplot.plot(history.history['loss'], label='train')
pyplot.plot(history.history['val_loss'], label='test')
pyplot.savefig("history.png")
pyplot.legend()
pyplot.show()
plt.figure(0)
pyplot.figure(0)
#model.load_weights("vi_128_lrdefault.hdf5")

train_X = train_X.reshape(train_X.shape[0],train_X.shape[2])
y_input = train_X[200:500]

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

print("y_input:",y_input)
x_test = model.predict(y_input)
print("x_test:",x_test)

y_samples = np.apply_along_axis(sample_from_output, 1, x_test, OUTPUT_DIMS, N_MIXES, temp=1.0, sigma_temp=1.0)
#print("y_samples:",y_samples)
import matplotlib.pyplot as plt
y_samples = y_samples.reshape(y_samples.shape[0],y_samples.shape[2])
image = plt.scatter(y_samples[:,0],y_samples[:,1])
#image.show()
plt.savefig("Model_M=40_n1=100_n2=100sigmoid.png")
plt.show
plt.close(0)
plt.figure(0)

#y_samples = train_y
#import matplotlib.pyplot as plt
#image = plt.scatter(y_samples[:,0],y_samples[:,1])

#plt.savefig("scatter_plot_true.png")
#plt.show
#plt.close(0)
#plt.figure(0)

import matplotlib.pyplot as pl
import scipy.stats as st

data = train_y[1:100000]

x = data[:, 0]

y = data[:, 1]

xmin, xmax = data[:, 0].max(), data[:, 0].min()

ymin, ymax = data[:, 1].max(), data[:, 1].min()

# Peform the kernel density estimate

xx, yy = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]

positions = np.vstack([xx.ravel(), yy.ravel()])

values = np.vstack([x, y])

kernel = st.gaussian_kde(values)

f = np.reshape(kernel(positions).T, xx.shape)

fig = pl.figure()

ax = fig.gca()

ax.set_xlim(xmin, xmax)

ax.set_ylim(ymin, ymax)

# Contourf plot

cfset = ax.contourf(xx, yy, f, cmap='Blues')

## Or kernel density estimate plot instead of the contourf plot

#ax.imshow(np.rot90(f), cmap='Blues', extent=[xmin, xmax, ymin, ymax])

# Contour plot

cset = ax.contour(xx, yy, f, colors='k')

# Label plot

ax.clabel(cset, inline=1, fontsize=10)

ax.set_xlabel('Y1')

ax.set_ylabel('Y0')

pl.show()


#!/usr/bin/python3

import sys
import heapq

class BiDij:
    def __init__(self, n):
        self.n = n   # Number of nodes
        self.inf = n*10**6  # All distances in the graph are smaller
        # Initialize distances for forward and backward searches
        # visited[v] == True iff v was visited by forward or backward search
        self.workset = set()  # Nodes visited by forward or backward search
        self.set_memory()

    def set_memory(self):
        """
        Defaults the dist and proc variables
        """
        self.dist = {}
        self.dist_r = {}
        self.proc = {}
        self.proc_r = {}

    def clear(self):
        """
        Reinitialize the data structures for the next query after
        the previous query.
        """
        self.set_memory()
        self.workset = set()
        self.q = []
        self.q_r = []

    def shortest_distance(self, v):
        """
        Retrieve the shortest distance from s to t by finding the
        best middle node.
        """
        try:
            distance = self.dist[v] + self.dist_r[v]
        except KeyError:
            return -1
        for vertex in self.workset:
            dst = self.dist.get(vertex, self.inf) + \
                self.dist_r.get(vertex, self.inf)
            if dst < distance:
                distance = dst
        return distance

    def process(self, q, v, vs, weights, dist):
        """
        Process a node and relax all the edges adjoining the node.
        """
        for id, u in enumerate(vs):
            if dist.get(u, self.inf) > dist.get(v, self.inf) + weights[id]:
                dist[u] = dist.get(v, self.inf) + weights[id]
                heapq.heappush(q, (dist[u], u))
            self.workset.add(u)

    def query(self, adj, cost, s, t):
        """
        Driver function that uses the bidirectional dijkstra function to find
        the shortest distance from s to t.
        """
        if s == t:
            return 0
        self.clear()
        self.dist[s] = 0
        self.dist_r[t] = 0
        self.q = [(0, s)]
        self.q_r = [(0, t)]
        heapq.heapify(self.q)
        heapq.heapify(self.q_r)
        while self.q and self.q_r:
            v = heapq.heappop(self.q)
            v_d, v_id = v
            if not self.proc.get(v_id, False):
                self.process(self.q, v_id, adj[0][v_id],
                             cost[0][v_id], self.dist)
                self.proc[v_id] = True
            if self.proc_r.get(v_id, False):
                return self.shortest_distance(v_id)
            v_r = heapq.heappop(self.q_r)
            vr_d, vr_id = v_r
            if not self.proc_r.get(vr_id, False):
                self.process(self.q_r, vr_id, adj[1][vr_id],
                             cost[1][vr_id], self.dist_r)
                self.proc_r[vr_id] = True
            if self.proc.get(vr_id, False):
                return self.shortest_distance(vr_id)
        return -1

def readl():
    return map(int, sys.stdin.readline().split())

if __name__ == '__main__':
    n, m = readl()
    adj = [[[] for _ in range(n)], [[] for _ in range(n)]]
    cost = [[[] for _ in range(n)], [[] for _ in range(n)]]
    for e in range(m):
        u, v, c = readl()
        adj[0][u-1].append(v-1)
        cost[0][u-1].append(c)
        adj[1][v-1].append(u-1)
        cost[1][v-1].append(c)
    t, = readl()
    bidij = BiDij(n)
    for i in range(t):
        s, t = readl()
        print(bidij.query(adj, cost, s-1, t-1))


# uses htmldiff and jsTransforms functions to run this repo's transforms and diff outputs
#   against known-good files
# see README in this dir for more info
import sys, os
import subprocess
import inspect
import time
import shutil

import jsTransforms as jst
import htmldiff as hdiff

# key dirs
transform_testfiles_dir = os.path.join(sys.path[0], 'files_for_test', 'test_docx_files')
validfiles_basedir = os.path.join(sys.path[0], 'files_for_test', 'validated_output')
valid_htmlmaker_output = os.path.join(validfiles_basedir, 'htmlmaker')
valid_htmltohtmlbook_output = os.path.join(validfiles_basedir, 'htmltohtmlbook')
valid_generateTOC_output = os.path.join(validfiles_basedir, 'generateTOC')
tmpdir_base = os.path.join(sys.path[0], 'files_for_test', 'tmp')
diff_outputdir = os.path.join(tmpdir_base, 'diff_outputs_{}'.format(time.strftime("%y%m%d%H%M%S")))

# dict for running transforms
transforms_dict = {
    '1': {
        'input_dir':transform_testfiles_dir,
        'input_file_ext':'.docx',
        'outputdir_name':'test_1_htmlbook_only',
        'output_compare_dir':valid_htmlmaker_output,
        'xform_function':jst.runHtmlmaker
    },
    '2': {
        'input_dir':valid_htmlmaker_output,
        'input_file_ext':'.html',
        'outputdir_name':'test_2_html2htmlbook_only',
        'output_compare_dir':valid_htmltohtmlbook_output,
        'xform_function':jst.setupAndRunHtmltohtmlbook
    },
    '3': {
        'input_dir':valid_htmltohtmlbook_output,
        'input_file_ext':'.html',
        'outputdir_name':'test_3_generateTOC_only',
        'output_compare_dir':valid_generateTOC_output,
        'xform_function':jst.setupAndGenerateTOC
    },
    'all': {
        'input_dir':transform_testfiles_dir,
        'input_file_ext':'.docx',
        'outputdir_name':'test_4_testALL',
        'output_compare_dir':valid_generateTOC_output,
        'xform_function':jst.runAllTransforms
    },
}

# # # # # # # # # # #   TRANSFORM FUNCTIONS   # # # # # # # # # # #
def recreateOutputDir(dirname):
    hdiff.rmExistingFSObject(dirname)
    os.makedirs(dirname)

def transformFilesInDir(transform_selection, solo_file=None):
    try:
        # (rm & re)create output dir
        outputdir = os.path.join(tmpdir_base, transforms_dict[transform_selection]['outputdir_name'])
        recreateOutputDir(outputdir)
        # run for single file as requested
        if solo_file is not None:
            filepath = os.path.join(transforms_dict[transform_selection]['input_dir'], solo_file)
            # run xform_function
            transforms_dict[transform_selection]['xform_function'](filepath, outputdir)
        else:
            for file in os.listdir(transforms_dict[transform_selection]['input_dir']):
                # screen for files with expected file ext, also not including '_pretty', "_fixed" working files
                if file.endswith(transforms_dict[transform_selection]['input_file_ext']) and hdiff.pretty_label not in file and hdiff.fixed_label not in file:
                    filepath = os.path.join(transforms_dict[transform_selection]['input_dir'], file)
                    # run xform_function
                    transforms_dict[transform_selection]['xform_function'](filepath, outputdir)
        return outputdir, transforms_dict[transform_selection]['output_compare_dir']
    except Exception as e:
        errstring = 'Error during "{}", exiting'.format(inspect.stack()[0][3])
        print(errstring, e.message, e.args)
        sys.exit(1)

def addValidFiles(new_validHtmlFiles, valid_output_dir, tmp_output_dir):
    if new_validHtmlFiles:
        for newfile in new_validHtmlFiles:
            src_filepath = os.path.join(tmp_output_dir, newfile)
            dest_filepath = os.path.join(valid_output_dir, newfile)
            shutil.copyfile(src_filepath, dest_filepath)
        print("\n(( Added missing valid files for the following testfile(s), they will be available for the next test: ))\n  {}\n".format(new_validHtmlFiles))

if __name__ == '__main__':
    # accept parameters for which transform you want to test, or all transforms (no param defaults to 'all')
    if len(sys.argv) > 1:
        test_id = sys.argv[1]
        if test_id != '1' and test_id != '2' and test_id != '3' and test_id != 'all':
            print("second parameter must indicate what test you want to run: 1, 2, 3 or 'all'.")
    else:
        test_id = 'all'
    if len(sys.argv) == 3:
        solo_file = sys.argv[2]
    else:
        solo_file = None

    # transform files
    tmp_output_dir, valid_output_dir = transformFilesInDir(test_id, solo_file)
    # run diffs
    new_validHtmlFiles = hdiff.runHtmlDiff(valid_output_dir, tmp_output_dir, diff_outputdir)
    # add new tmp files as valid files where valid files are not present
    addValidFiles(new_validHtmlFiles, valid_output_dir, tmp_output_dir)


import math
import numpy as np
"""
     Distance Between Functions
------------------------------------------------------------------------------------------------------------

     - Find Specific Counter
     - Distance between all Neighbours
     - Distance between closer neighbours
     - Closest neighbours

"""

"""
Find Specific Counter
------------------------------------------------------------------------------------------------------------
     Function:   Finds the specific grid within the grid_data

     Inputs:       grid_data, specific_string
     Outputs:    List positions of specific grid
"""

def find_specific_counter(grid_data, grid_specific):
     counter = len(grid_data)
     string = grid_specific
     counter_list = []
     i = 0
     while i != counter:
          if grid_data[i][6] == string:
               counter_list.append(i)
          i = i + 1
     return counter_list

"""
Distance between All Neighbours
----------------------------------------------------------------------------------------------------------
     Function:     Finds the distance between the atoms within the molecule
                              Interaction between all neighbours

     Inputs:         grid_ data, specific_int
     Outputs:      [[molecule_r, molecule_phi], [Atom_1_r, Atom_1_phi], [Atom_2_r, Atom_2_phi]]

     Note -
          When editing the code this is not true the output is in cart coordinates
"""

def dis_between_all_unit(unit_data, counter):
     """
     distance between molecules in untis

     """
     i = 0
     mol_pos = []
     atom_1_pos = []
     atom_2_pos = []
     while i != len(unit_data):
          mol_pos.append([np.float_(unit_data[i][0][0]),
                          np.float_(unit_data[i][0][1])])
          atom_1_pos.append([np.float_(unit_data[i][1][0][0]),
                             np.float_(unit_data[i][1][0][1])])
          atom_2_pos.append([np.float_(unit_data[i][1][1][0]),
                             np.float_(unit_data[i][1][1][1])])
          i += 1
     #    Calculate the Distance between units
     ii = 0

     dist_b_mol =[]
     dist_b_a1 = []
     dist_b_a2 = []
     while ii != len(unit_data):
          if ii != counter:
               dist_b_mol.append([np.float_(mol_pos[counter][0]) - np.float_(mol_pos[ii][0]),
                                  np.float_(mol_pos[counter][1]) - np.float_(mol_pos[ii][1])])
               dist_b_a1.append([np.float_(atom_1_pos[counter][0]) - np.float_(atom_1_pos[ii][0]),
                                 np.float_(atom_1_pos[counter][1]) - np.float_(atom_1_pos[ii][1])])
               dist_b_a2.append([np.float_(atom_2_pos[counter][0]) - np.float_(atom_2_pos[ii][0]),
                                 np.float_(atom_2_pos[counter][1]) - np.float_(atom_2_pos[ii][1])])
          ii += 1

     iii = 0
     while iii != len(unit_data):
          if iii != counter:
               dist_b_mol.append([np.float_(mol_pos[counter][0]) - np.float_(mol_pos[iii][0]),
                                  np.float_(mol_pos[counter][1]) - np.float_(mol_pos[iii][1])])
               dist_b_a1.append([np.float_(atom_1_pos[counter][0]) -
                                 np.float_(atom_2_pos[iii][0]),
                                 np.float_(atom_1_pos[counter][1]) -
                                 np.float_(atom_2_pos[iii][1])])
               dist_b_a1.append([np.float_(atom_2_pos[counter][0]) -
                                 np.float_(atom_1_pos[iii][0]),
                                 np.float_(atom_2_pos[counter][1]) -
                                 np.float_(atom_1_pos[iii][1])])
          iii += 1

     #    Return Function

     return [[dist_b_mol], [dist_b_a1], [dist_b_a2]]

def distance_between_all_neighbours(grid_data, specific_int):
     i = 0
     mol_positions = []
     atom_1_positions = []
     atom_2_positions = []
     while i != len(grid_data):
          mol_positions.append([np.float_(grid_data[i][0][0]),np.float_(grid_data[i][0][1])])
          atom_1_positions.append([np.float_(grid_data[i][1][0][0]),np.float_(grid_data[i][1][0][1])])
          atom_2_positions.append([np.float_(grid_data[i][1][1][0]),np.float_(grid_data[i][1][1][1])])
          i = i + 1
     i = 0
     dist_between_mol = []
     dist_between_atom_1 = []
     dist_between_atom_2 = []
     while i != len(grid_data):       #       change in position
          if i != specific_int:
               dist_between_mol.append([np.float_(mol_positions[specific_int][0]) -
                                        np.float_(mol_positions[i][0]),
                                        np.float_(mol_positions[specific_int][1]) -
                                        np.float_(mol_positions[i][1])])
               dist_between_atom_1.append([np.float_(atom_1_positions[specific_int][0]) -
                                           np.float_(atom_1_positions[i][0]),
                                           np.float_(atom_1_positions[specific_int][1]) -
                                           np.float_(atom_1_positions[i][1])])
               dist_between_atom_2.append([np.float_(atom_2_positions[specific_int][0]) -
                                           np.float_(atom_2_positions[i][0]),
                                           np.float_(atom_2_positions[specific_int][1]) -
                                           np.float_(atom_2_positions[i][1])])
          i = i + 1
     i = 0
     while i != len(grid_data):
          if i != specific_int:
               dist_between_atom_1.append([np.float_(atom_1_positions[specific_int][0]) -
                                           np.float_(atom_2_positions[i][0]),
                                           np.float_(atom_1_positions[specific_int][1]) -
                                           np.float_(atom_2_positions[i][1])])
               dist_between_atom_2.append([np.float_(atom_2_positions[specific_int][0]) -
                                           np.float_(atom_1_positions[i][0]),
                                           np.float_(atom_2_positions[specific_int][1]) -
                                           np.float_(atom_1_positions[i][1])])
          i = i + 1
     mol_r = []
     mol_phi = []
     atom_1_r = []
     atom_1_phi = []
     atom_2_r = []
     atom_2_phi= []
     i = 0
     while i < (len(grid_data) - 1):
          mol_r.append((np.float_(dist_between_mol[i][0]) ** 2 +
                        np.float_(dist_between_mol[i][1]) ** 2) ** 0.5)
          mol_phi.append(math.atan2(np.float_(dist_between_mol[i][1]),
                                    np.float_(dist_between_mol[i][0])))

          atom_1_r.append((np.float_(dist_between_atom_1[i][0]) ** 2 +
                           np.float_(dist_between_atom_1[i][1]) ** 2) ** 0.5)
          atom_1_phi.append(math.atan2(np.float_(dist_between_atom_1[i][1]),
                                       np.float_(dist_between_atom_1[i][0])))

          atom_2_r.append((np.float_(dist_between_atom_2[i][0]) ** 2 +
                           np.float_(dist_between_atom_2[i][1]) ** 2) ** 0.5)
          atom_2_phi.append(math.atan2(np.float_(dist_between_atom_2[i][1]),
                                       np.float_(dist_between_atom_2[i][0])))

          i = i + 1

     return [[mol_r, mol_phi], [atom_1_r, atom_1_phi], [atom_2_r, atom_2_phi]]

"""
Distance between Nearest Neighbours
----------------------------------------------------------------------------------------------------------
     Function:     Finds the distance between the nearest atoms within the molecule
                              Interaction between the nearest neighbours

     Inputs:         grid_ data, specific_int, max_range
     Outputs:      [[molecule_r, molecule_phi], [Atom_1_r, Atom_1_phi], [Atom_2_r, Atom_2_phi]]
"""

##def distance_between_nearest_neighbours(grid_data, specific_int, max_range):
##     i = 0
##     mol_positions = []
##     atom_1_positions = []
##     atom_2_positions = []
##
##     while i != len(grid_data):
##          mol_positions.append([np.float_(grid_data[i][0][0]),np.float_(grid_data[i][0][1])])
##          atom_1_positions.append([np.float_(grid_data[i][1][0][0]),np.float_(grid_data[i][1][0][1])])
##          atom_2_positions.append([np.float_(grid_data[i][1][1][0]),np.float_(grid_data[i][1][1][1])])
##          i = i + 1
##
##     i = 0
##     dist_between_mol = []
##     dist_between_atom_1 = []
##     dist_between_atom_2 = []
##     while i < len(grid_data):
##          if i != specific_int:
##               if abs(mol_positions[specific_int][0] - mol_positions[i][0]) <= max_range:
##                    dist_between_mol.append([mol_positions[specific_int][0] - mol_positions[i][0],
##                                             mol_positions[specific_int][1] - mol_positions[i][1]])
##                    dist_between_atom_1.append([atom_1_position[specific_int][0] - atom_1_position[i][0],
##                                                atom_1_position[specific_int][1] - atom_1_position[i][1]])
##                    dist_between_atom_2.append([atom_2_position[specific_int][0] - atom_2_position[i][0],
##                                                atom_2_position[specific_int][1] - atom_2_position[i][1]])
##          i = i + 1
##     i = 0
##     while i < len(grid_data):
##          if i != specific_int:
##               if abs(mol_positions[specific_int][0] - mol_positions[i][0]) <= max_range:
##                    dist_between_atom_1.append([atom_1_positions[specific_int][0] - atom_2_positions[i][0],
##                                                atom_1_positions[specific_int][1] - atom_2_positions[i][1]])
##                    dist_between_atom_1.append([atom_2_positions[specific_int][0] - atom_1_positions[i][0],
##                                                atom_2_positions[specific_int][1] - atom_1_positions[i][1]])
##          i = i + 1
##     i = 0
##     mol_r = []
##     mol_alpha = []
##     atom_1_r = []
##     atom_1_alpha = []
##     atom_2_r = []
##     atom_2_alpha = []
##     while i <= len(grid_data):
##          mol_r.append(dist_between_mol[i][0])
##          mol_alpha.append(dist_between_mol[i][1])
##          atom_1_r.append(dist_between_atom_1[i][0])
##          atom_1_alpha.append(dist_between_atom_1[i][1])
##          atom_2_r.append(dist_between_atom_2[i][0])
##          atom_2_alpha.append(dist_between_atom_2[i][1])
##          i = i + 1
##
##     sum_mol = [sum(mol_r), sum(mol_alpha)]
##
##     sum_atom_1 = [sum(atom_1_r), sum(atom_1_alpha)]
##
##     sum_atom_2 = [sum(atom_2_r), sum(atom_2_alpha)]
##
##     return [sum_mol, sum_atom_1, sum_atom_2]
##
##"""
##Closest Neighbours Int
##----------------------------------------------------------------------------------------------------------
##     Function:     Function returns with the number of near neighbours near the molecule
##
##     Inputs:         grid_ data, specific_int, max_range
##     Outputs:      Number of neighbours near
##"""

def near_neighbours_int(grid_data, specific_int, max_range):
     i = 0
     counter_neighbours = 0
     mol_positions = grid_data
     while i < len(grid_data):
          if 1 != specific_int:
               if abs(np.float_(mol_positions[specific_int][0][0]) -
                      np.float_(mol_positions[i][0][0])) <= max_range and abs(
                           np.float_(mol_positions[specific_int][0][1]) -
                           np.float_(mol_positions[i][0][1])) <= np.float_(max_range):
                    counter_neighbours = counter_neighbours + 1
          i = i + 1
     return counter_neighbours

"""

"""

def distance_between_unit_molecules(unit_data):
     i = 0
     mol_positions = []

     while i != len(unit_data):
          mol_positions.append([np.float_(unit_data[i][0][0]), np.float_(unit_data[i][0][1])])

          i = i + 1
     i = 0
     dist_between_mol = []

     while i != len(unit_data):       #       change in position
          ii = 0
          while ii != len(unit_data):

               if i != ii:
                    dist_between_mol.append([mol_positions[ii][0] - mol_positions[i][0],
                                             mol_positions[ii][1] - mol_positions[i][1]])
               ii = ii + 1
          i = i + 1

     return dist_between_mol


from encode.common import (
    ALPHANUMERIC_CHARS,
    CORRECTION_LEVELS
)
from encode.data_encoder import (
    AlphanumericEncoder,
    BytesEncoder,
    NumericEncoder,
    QREncoder
)

def select_encoding(msg: str) -> str:
    """
    Determines which type of text encoding will be used for the message.

    If msg is strictly decimal, specifies numeric encoding. If msg is composed
    of numbers, uppercase letters, and characters in
    (' ', '$', '%', '*', '+', '-', '.', '/', ':'), specifies alphanumeric
    encoding. Otherwise, specifies byte encoding.

    Parameters
    ----------
    msg : str
        Text to be encoded as a QR code.

    Returns
    -------
    str
        Specified encoding mode.

    Raises
    ------
    ValueError
        Input is too long to be encoded.
    """
    if len(msg) > 7089:
        raise ValueError('Input exceeds maximum encoding length.')

    if msg.isdecimal():
        return 'numeric'

    for char in msg:
        if (char.isalpha() and char.islower()) or \
            (not char.isalpha() and not char.isdecimal()
             and char not in ALPHANUMERIC_CHARS):
            return 'byte'

    return 'alphanumeric'

def select_encoder(msg: str, correction_level: str) -> QREncoder:
    """
    Selects an appropriate QR encoder for the message input.

    Parameters
    ----------
    msg: str
        Text to be encoded as a QR code.
    correction_level : str
        Specified error correction level.

    Returns
    -------
    qr_encoder
        qr_encoder object for the message.

    Raises
    ------
    TypeError
        Input is not a string.
    ValueError
        Correction level not in ('L', 'M', 'Q', 'H')
    """
    if not isinstance(msg, str):
        raise TypeError(f'Message is not a string: {msg}.')
    if correction_level.upper() not in CORRECTION_LEVELS:
        raise ValueError(f'Unrecognized correction level: {correction_level}.')

    encoding = select_encoding(msg)
    if encoding == 'numeric':
        return NumericEncoder(msg, correction_level.upper())
    if encoding == 'alphanumeric':
        return AlphanumericEncoder(msg, correction_level.upper())
    else:
        return BytesEncoder(msg, correction_level.upper())


# raw_to_evoked
# simple utility to plot_joint from file name

import sys

raw_file=sys.argv[1]
event_id=1

import mne

Raw=mne.io.read_raw_fif(raw_file)
Events=mne.find_events(Raw)
reject = dict(grad=4e-10, mag=4e-12, eog=150e-6)
Epochs=mne.Epochs(Raw, Events, event_id=event_id, tmin=-0.1, tmax=0.8,
        baseline=(None, 0), reject=reject, proj=True)
Evoked=Epochs.average()
Evoked.plot_joint()


import math

from tensorflow import keras

from morphzero.ai.algorithms.hash_policy import HashPolicy
from morphzero.ai.base import Evaluator
from morphzero.common import board_to_string
from morphzero.games.genericgomoku.ai.tic_tac_toe import TicTacToeKeras, TicTacToeKerasConfig
from morphzero.games.genericgomoku.game import GenericGomokuRules

def load_keras_evaluator(path: str) -> Evaluator:
    evaluator = TicTacToeKeras(
        TicTacToeKerasConfig(
            training=True,
            verbose=1,
            learning_rate=0.001,
            epochs=500,
            filters=10,
            mid_layer_size=100,
        )
    )
    evaluator.model = keras.models.load_model(path)
    return evaluator

def compare(min_max: HashPolicy, evaluator: Evaluator) -> None:
    for state in min_max.policy:
        if state.is_game_over:
            continue
        min_max_evaluation_result = min_max.evaluate(state)
        evaluator_evaluation_result = evaluator.evaluate(state)

        win_rate_difference = math.fabs(min_max_evaluation_result.win_rate - evaluator_evaluation_result.win_rate)

        evaluator_best_move_policy = max(evaluator_evaluation_result.move_policy)
        evaluator_best_move = next(
            i
            for i, policy in enumerate(evaluator_evaluation_result.move_policy)
            if policy >= evaluator_best_move_policy
        )
        min_max_best_move_policy = max(min_max_evaluation_result.move_policy)
        found_best_move = min_max_evaluation_result.move_policy[evaluator_best_move] >= min_max_best_move_policy

        if (win_rate_difference > 0.25) or not found_best_move:
            print()
            print(state.current_player)
            print(board_to_string(state.board))
            print("min_max")
            print(min_max_evaluation_result)
            print("evaluator")
            print(evaluator_evaluation_result)
            # print("WINRATE:")
            # print(f"min_max: {min_max_evaluation_result.win_rate:.4f}")
            # print(f"evaluator: {evaluator_evaluation_result.win_rate:.4f}")
            # print("MOVE POLICY")
            # print(" ".join(f"{p:.5f}" for p in min_max_evaluation_result.move_policy))
            # print(" ".join(f"{p:.5f}" for p in evaluator_evaluation_result.move_policy))

def load_and_compare() -> None:
    rules = GenericGomokuRules.create_tic_tac_toe_rules()
    min_max = HashPolicy.factory("./../models/tic_tac_toe/hash_policy_min_max")(rules)
    evaluator = load_keras_evaluator("./../models/tic_tac_toe/based_on_min_max")
    compare(min_max, evaluator)

if __name__ == "__main__":
    load_and_compare()


# def bfs(graph, start, end):
#     queue = []
#     queue.append([start])

#     while queue:

#         path = queue.pop(0)
#         # print(path)
#         node = path[-1]

#         if node == end:
#             print(path)
#         if node in graph:
#             for adj in graph[node]:
#                 new_path = list(path)
#                 new_path.append(adj)
#                 queue.append(new_path)

def bfsLocalVisited(graph, start, end):
    queue = []
    queue.append(([start], set({start})))

    while queue:

        path, local_set = queue.pop(0)
        #print(path, local_set)

        node = path[-1]

        if node == end:
            print(path)

        if node in graph:
            for adj in graph[node]:
                if adj not in local_set:
                    new_local = set(local_set)
                    new_path = list(path)

                    new_local.add(adj)
                    new_path.append(adj)

                    queue.append(( new_path, new_local))

def bfsGlobalVisited(graph, start, end):
    queue = []
    visited = set()
    visited.add(start)
    queue.append([start])

    while queue:

        path = queue.pop(0)
        # print(path)
        node = path[-1]

        if node == end:
            print(path)
        if node in graph:
            for adj in graph[node]:
                if adj not in visited:
                    new_path = list(path)
                    new_path.append(adj)
                    visited.add(adj)
                    queue.append(new_path)

def dfsVisited(graph,start,end):
    path = [start]
    visited =set()
    visited.add(start)

    dfsUtil(start,end,graph,path,visited)

def dfsUtil(source,dest,graph,path,visited):
    if path[-1] == dest:
        print(path)
        return
    if source in graph:
        for edge in graph[source]:
            if edge not in visited:
                path.append(edge)
                visited.add(edge)
                dfsUtil(edge,dest,graph,path,visited)
                path.pop()
                visited.remove(edge)

# #Handles cycles as well using visited set()
# def fetchPaths(self,graph, source, destination):

#     visited = set()
#     visited.add(source)

#     path_so_far = [source]

#     self.fetchPathsUtil(source, destination,graph, path_so_far, visited)

# def fetchPathsUtil(self, source, destination, path_so_far, visited):

#     if path_so_far[-1] == destination:
#         print("->".join(path_so_far))
#         return

#     for city in self.flights[source]:
#         if city not in visited:
#             path_so_far.append(city)
#             visited.add(city)
#             self.fetchPathsUtil(city, destination, path_so_far, visited)

#             visited.remove(city)
#             path_so_far.pop(-1)

graph = {
    "a" : ["b", "c"],
    "b" : ["c", "g"],
    "c" : ["d", "e"],
    "d" : ["h", "f"],
    "e" : ["f"],
    "g" : ["f"],
}

graph2 = {
    "a" : ["b"],
    "b" : ["c"],
    "c" : ["d"],
    "d" : ["a"],
}

# print(bfs(graph2, "a", "f"))

print(bfs1(graph, "a", "f"))

print(bfs2(graph, "a", "f"))

print(dfs(graph, "a", "f"))


import config

from datetime import timedelta, datetime

import covid_data
import plot
import spain_data

AGE_GROUPS = {
    "0-9": ["0-9"],
    "10-19": ["10-19"],
    "20-39": ["20-29", "30-39"],
    "40-59": ["40-49", "50-59"],
    "60-69": ["60-69"],
    "70+": ["70-79", "80+"],
}

AGE_GROUP_COLORS = {
    "0-9": "#FF69B4",
    "10-19": "#BA55D3",
    "20-39": "#00BFFF",
    "40-59": "#228B22",
    "60-69": "#778899",
    "70+": "#000000",
}

def _calculate_relative_to_cases(evolutions):
    num_cases = evolutions[config.ORIG_CASES_COL].values
    evolutions = evolutions.div(num_cases, axis="index")
    del evolutions[config.ORIG_CASES_COL]
    return evolutions

def plot_age_evolution(
    plot_path,
    sex=None,
    date_range=None,
    rate_by_100k=False,
    by_week=False,
    age_ranges=None,
    community=None,
    title=None,
):

    params_to_plot = config.ORIG_COUNT_COLS

    fig = plot.SharedXFigure(
        num_axes=len(params_to_plot), fig_size=config.FOR_PANEL_EVOLUTION_FIG_SIZE
    )

    for idx, (age_group_name, ages) in enumerate(age_ranges.items()):
        if community is None:
            evolutions = covid_data.get_evolutions_for_spain(
                sex=sex,
                date_range=date_range,
                rate_by_100k=rate_by_100k,
                by_week=by_week,
                age_ranges=ages,
            )
        else:
            evolutions = covid_data.get_evolutions_per_param(
                by=config.COMMUNITY,
                sex=sex,
                date_range=date_range,
                rate_by_100k=rate_by_100k,
                by_week=by_week,
                age_ranges=ages,
            )
            evolutions = {
                param: evolution.loc[:, community]
                for param, evolution in evolutions.items()
            }

        res = _plot_evolution_for_age_group(
            fig,
            evolutions,
            rate_by_100k,
            age_group_name,
            by_week,
            date_range,
            params_to_plot,
        )

    axes = fig.get_axes(0)
    axes.legend()

    if title:
        axes.set_title(title)

    fig.save_fig(plot_path)

def _plot_evolution_for_age_group(
    fig, evolutions, rate_by_100k, age_group_name, by_week, date_range, params_to_plot
):
    for idx, param in enumerate(params_to_plot):
        axes = fig.get_axes(idx)
        evolution = evolutions[param]
        if date_range is not None:
            evolution = evolution.loc[date_range[0] : date_range[1]]
        axes.plot(
            evolution.index,
            evolution.values,
            color=AGE_GROUP_COLORS[age_group_name],
            label=age_group_name,
        )

        ylabel = config.PLOT_PARAM_DESCRIPTIONS[param]
        if rate_by_100k:
            ylabel = f"{ylabel} (por 1e5 hab.)"
        if by_week:
            ylabel = f"{ylabel}\n(semanal)"
        plot.set_y_label(axes, ylabel)
        plot.set_x_ticks_format(axes, 45, ha="right")
    return {"axes": axes}

if __name__ == "__main__":

    last_date = covid_data.get_last_date_in_dframe()
    one_week = timedelta(days=7)
    last_date = last_date - one_week
    first_date = datetime(2022, 2, 1)
    DATE_RANGE = (first_date, last_date)

    date_rage_str = f"{first_date.date().day}-{first_date.date().month} al {last_date.date().day}-{last_date.date().month}"

    out_dir = config.AGE_COMMUNITY_GROUP_PLOT_DIR
    out_dir.mkdir(exist_ok=True)

    region_names_per_iso_code = spain_data.CA_NAMES_PER_ISO_CODE
    for region_iso, region_name in region_names_per_iso_code.items():
        if region_iso == "nd":
            continue
        plot_path = (
            out_dir / f"evolution_per_age_range.{region_name}.{date_rage_str}.png"
        )
        plot_age_evolution(
            plot_path,
            by_week=True,
            date_range=DATE_RANGE,
            age_ranges=AGE_GROUPS,
            rate_by_100k=True,
            community=region_iso,
            title=region_name,
        )

        if False:
            plot_path = out_dir / f"evolution_per_age_range.{region_name}.png"
            plot_age_evolution(
                plot_path,
                by_week=True,
                date_range=None,
                age_ranges=AGE_GROUPS,
                rate_by_100k=True,
                community=region_iso,
                title=region_name,
            )

    out_dir = config.AGE_GROUP_PLOT_DIR
    out_dir.mkdir(exist_ok=True)

    plot_path = out_dir / f"evolution_per_age_range.{date_rage_str}.png"
    plot_age_evolution(
        plot_path,
        by_week=True,
        date_range=DATE_RANGE,
        age_ranges=AGE_GROUPS,
        rate_by_100k=True,
    )

    plot_path = out_dir / "evolution_per_age_range.png"
    plot_age_evolution(
        plot_path,
        by_week=True,
        date_range=None,
        age_ranges=AGE_GROUPS,
        rate_by_100k=True,
    )


from odoo import api, models, fields, _

class StockPicking(models.Model):
    _inherit = 'stock.picking'

    @api.one
    def _count_tds(self):
        self.delivery_count = len(self.ddt_ids)

    delivery_count = fields.Integer("Deliveries", compute=_count_tds)

    def show_transport_documents(self):
        """
            Shows TD for each sale order line.
        """
        ret = {}
        tdEntity = 'stock.picking.package.preparation'
        tdEntity_type = self.env[tdEntity]
        transport_document_ids = tdEntity_type
        for picking_id in self:
            for ddt_id in picking_id.ddt_ids:
                transport_document_ids += ddt_id
        if transport_document_ids:
            ret = {
                'type': 'ir.actions.act_window',
                'name': _(tdEntity_type._description),
                'res_model': tdEntity,
                'view_mode': 'tree,form',
                'view_type': 'form',
                'domain': [('id', 'in', transport_document_ids.ids)],
                'target': 'current',
            }
        return ret

    @api.multi
    def prepare_validation(self):
        picking_edit = self.env['stock.picking.edit']
        picking_edit_line = self.env['stock.picking.edit.line']
        values = {}
        picking_edit_id = picking_edit.create({})
        for move in self.move_lines:
            values.update({
                'product_id': move.product_id.id,
                'product_uom_qty': move.product_uom_qty,
                'reserved_availability': move.reserved_availability,
                'quantity_done': move.reserved_availability,
                'product_uom': move.product_uom.id,
                'picking_edit_id': picking_edit_id.id,
                'move_id': move.id
            })
            picking_edit_line.create(values)

        action = self.env.ref('enhance_picking.action_stock_picking_edit_form').read()[0]
        action['res_id'] = picking_edit_id.id
        return action

    @api.model
    def check_availability(self):
        """
            Re-evaluates ram materials availability on stock.picking
        """
        criteria = [('state', 'in', ['confirmed','waiting'])]
        picking_ids = self.search(criteria)
        for picking_id in picking_ids:
            picking_id.action_assign()


# 리스트에 값을 반복문을 활용하여 대입할 수 있다. => 내포
a = [2, 4, 5, 3, 1]
b = a * 2
print("요소의 수가 두 배 확장", b)
c = [i * 2 for i in a]      # 요소의 값이 두배로
print("요소의 값이 두 배로 : ", c)

l = []
for k in a :
    l.append(k*2)
print("요소의 값이 두 배로 : ", l)

even = [i for i in range(0, 11) if i % 2 == 0]
print("0~10 에서의 짝수 리스트 : ", even)


from   TAMO.MotifTools import Motif, print_motifs,save_motifs
import sys,os,re
inp=sys.argv[1]
os.system("rm %s.tm" % inp)
class MyWriter:

    def __init__(self, stdout, filename):
        self.stdout = stdout
        self.logfile = file(filename, 'a')

    def write(self, text):
        self.stdout.write(text)
        self.logfile.write(text)

    def close(self):
        self.stdout.close()
        self.logfile.close()
    def flush(self):
        self.stdout.flush()

def Meme_out(file):
        'Parse MEME file'
        motifs=[]
        inp=open(file,"r")
        lines=inp.readlines()
        fastafile=''
        probes=[]
        i = 0
        num = 0
        background = {}
        for i in range(len(lines)):
            toks = lines[i].split()
            #print toks
            for tok in toks: tok.strip()
            if len(toks) == 2 and not fastafile and toks[0] == 'DATAFILE=':
                fastafile = toks[1]
            if len(toks) < 4: continue
            if toks[0] == 'Background' and toks[2] == 'frequencies':
                toks = lines[i+1].split()
                for j in [0,2,4,6]:
                    background[toks[j]] = float(toks[j+1])
            #print lines[i],
            if toks[0] == "MOTIF":
                m = Motif([],background)
                num    = int(toks[1])
                m.evalue = float(toks[13])
            elif (toks[0] == 'Motif' and int(toks[1]) == num and
                  toks[3] == 'BLOCKS'):
                offset = 3
                j      = 0
                while lines[i+offset+j][0:2] != '//':
                    #print lines[i+offset+j],
                    _toks = lines[i+offset+j].split()
                    seq = _toks[-2]
                    seq = re.sub('X','N',seq)
                    m.seqs.append(seq)
                    j = j + 1
            elif (toks[0] == 'Motif' and int(toks[1]) == num and
                  toks[3] == 'probability'):
                offset = 3
                j      = 0
                counts = []
                while lines[i+offset+j][0:10] != '------------'[0:10]:
                    probs = lines[i+offset+j].split()
                    _d = {}
                    for key,val in zip(['A', 'C', 'G', 'T'], probs):
                        _d[key] = float(val)
                    counts.append(_d)
                    j = j + 1
                #for c in counts:
                    #print c
                m.compute_from_counts(counts,0.00001)
                motifs.append(m)
            elif (toks[0] == 'Sequence' and toks[1] == 'name' and
                  toks[2] == 'Weight'):
                offset = 2
                j      = 0
                while lines[i+offset+j][0:5] != '*****':
                    _toks = lines[i+offset+j].split()
                    probes.append(_toks[0])
                    if len(_toks) > 5:
                        probes.append(_toks[3])
                    j = j + 1
        #writer = MyWriter(sys.stdout, '%s.tm' % file)
        #sys.stdout = writer
        save_motifs(motifs,'%s.tm' % file)
if __name__=="__main__":
	file=sys.argv[1]
	Meme_out(file)


#-*- coding: utf-8 -*-

from datetime import date, timedelta
from django.db import connection, models
from django.utils.translation import ugettext_lazy as _
from twa.utils import DEFAULT_MAX_LENGTH, AbstractModel

class RequestManager( models.Manager ):
    def get_query_set( self ):
        return super( RequestManager, self ).get_query_set()

    def get_user_agents_top_10( self ):
        fmt = '%Y-%m-%d'
        enddate = date.today()
        startdate = enddate - timedelta( 90 )
        SQL = 'SELECT COUNT(*) AS c, user_agent'
        SQL += ' FROM requests_request'
        SQL += " WHERE last_modified BETWEEN '%s' AND '%s'" % ( startdate.strftime( fmt ), enddate.strftime( fmt ) )
        SQL += ' GROUP BY user_agent'
        SQL += ' ORDER BY c DESC'
        SQL += ' LIMIT 10'
        cursor = connection.cursor()
        cursor.execute( SQL )
        agents = []
        for i in range( cursor.rowcount ):
            row = cursor.fetchone()
            agents.append( { 'count': row[0], 'user_agent': row[1] } )
        cursor.close()
        return agents

#        Django 1.1
#        from django.db.models import Count
#        return self.get_query_set().values( 'user_agent' ).annotate( agent_count = Count( 'user_agent' ) ).order_by( '-agent_count' )[:10]

class Request( AbstractModel ):
    user = models.CharField( _( 'User' ), max_length = DEFAULT_MAX_LENGTH, blank = True )
    user_agent = models.CharField( _( 'User Agent' ), max_length = 500, blank = True )
    path = models.CharField( _( 'Path' ), max_length = DEFAULT_MAX_LENGTH, blank = True )
    remote = models.CharField( _( 'Remote' ), max_length = DEFAULT_MAX_LENGTH, blank = True )

    objects = RequestManager()

    def __unicode__( self ):
        return self.user_agent


from UI.editEmployeeWin import Ui_Dialog
from PyQt5.QtWidgets import QDialog, QLineEdit
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtCore import QRegExp

class EditEmployeeWin(QDialog, Ui_Dialog):

    def __init__(self, parent, roles, empData = None) -> None:
        super().__init__(parent)
        Ui_Dialog.__init__(self)
        self.setupUi(self)
        self.empData = empData
        self.isEdit = empData != None
        selectedIndex = None
        self.editPassword.setEchoMode(QLineEdit.EchoMode.Password)
        self.editPassword_2.setEchoMode(QLineEdit.EchoMode.Password)
        self.prevLogin = None

        #self.editPassword.setValidator(QRegExpValidator(QRegExp(r"^(?=.*[0-9])(?=.*[a-z])([a-z0-9_-]+)$"), self.editPassword))
        #self.editPassword.keyPressed.connect(self.on_line_edit_key_pressed)

        #validator = QRegExpValidator(QRegExp(r"[\.]+"))
        self.pushButton.setEnabled(self.isEdit)

        for lineEdit in self.findChildren(QLineEdit):
            #lineEdit.setValidator(validator)
            lineEdit.textChanged.connect(self.on_line_edit_key_pressed)

        for index, role in enumerate(roles):
            self.cmRoles.addItem(str(role[1]), role[0])
            if selectedIndex == None and self.isEdit and empData[6] == role[0]:
                selectedIndex = index
                self.cmRoles.setCurrentIndex(selectedIndex)
        self.empGuid = None
        if self.isEdit:
            self.prevLogin = empData[4]
            self.empGuid = empData[0]
            self.toggle_boxes(False)
            self.cbChangeLoginPsw.setChecked(False)
            self.cbChangeLoginPsw.stateChanged.connect(self.state_changed)
            self.editName.setText(empData[1])
            self.editSurname.setText(empData[2])
            self.editMidname.setText(empData[3])
            self.editLogin.setText(empData[4])
        else:
            self.cbChangeLoginPsw.hide()

    def on_line_edit_key_pressed(self, event):
        sender = self.sender()
        #validator = sender.validator()
        validator = QRegExpValidator(QRegExp(r'.+'))
        state = validator.validate(event, 0)[0]

        if state != 2:
            sender.setStyleSheet('QLineEdit { border: 1px solid red }')
        else:
            sender.setStyleSheet('')

        childsEmpData = self.frameEmpData.findChildren(QLineEdit)
        childsUserData = self.frameUserData.findChildren(QLineEdit)
        empCorrect = all([validator.validate(line.text(), 0)[0] == 2 for line in childsEmpData])
        userCorrect = all([validator.validate(line.text(), 0)[0] == 2 for line in childsUserData])

        self.pushButton.setEnabled(empCorrect and (userCorrect or self.isEdit and not self.cbChangeLoginPsw.isChecked()))

    def state_changed(self, checked):
        self.toggle_boxes(checked)

    def toggle_boxes(self, isVisible):

        if isVisible:
           self.boxLogin_2.show()
           self.boxPsw_2.show()
           self.boxPswElse_2.show()
        else:
           self.boxLogin_2.hide()
           self.boxPsw_2.hide()
           self.boxPswElse_2.hide()


from nltk.corpus import stopwords

from settings.common import word_tf_df
from preprocessing_pipeline.NextGen import NextGen
from preprocessing_pipeline import (Preprocess, RemovePunctuation, Capitalization, RemoveStopWords,
                                    RemoveShortWords, TwitterCleaner, RemoveUrls)

def load_flat_dataset(path):
    dataset = []
    with open(path, 'r') as f:
        for line in f:
            dataset.append(line.strip().split(' '))
    return dataset

def load_dataset_with_dates(path):
    dataset = []
    with open(path, 'r') as f:
        for line in f:
            dataset.append(line.strip().split('\t')[1].split(' '))
    return dataset

if __name__ == '__main__':
    dataset_names = ['sample_tweets']
    forbidden_words = []  # list of words to be blacklisted [amp, rt, ...]
    syn_file = None  # synonym file containing line for each set of synonyms: [word], [synonym1], [synonym2], ...
    extra_ngrams = []  # list of $-separated ngrams: [new$york$city, joe$biden, donald$trump, no$new$taxes]

    for j in range(0, len(dataset_names)):
        ds = dataset_names[j]

        stopwords_list = stopwords.words('english')
        stopwords_list.append(['rt', 'amp'])

        pipeline = Preprocess()
        rp = RemovePunctuation(keep_hashtags=False)
        ru = RemoveUrls()
        cap = Capitalization()
        short_words = RemoveShortWords()
        tc = TwitterCleaner()
        rsw = RemoveStopWords(extra_sw=stopwords_list)

        pipeline.document_methods = [(tc.remove_deleted_tweets, str(tc),),
                                     (tc.remove_users, str(tc),),
                                     (ru.remove_urls, str(ru),),
                                     (rp.remove_punctuation, str(rp),),
                                     (cap.lowercase, str(cap),),
                                     (tc.remove_rt, str(tc),),
                                     (rsw.remove_stopwords, str(rsw),),
                                     (short_words.remove_short_words, str(short_words),)
                                     ]

        ng = NextGen()
        path = 'data/{}.csv'.format(ds)
        dataset = load_dataset_with_dates(path)
        processed_dataset = ng.full_preprocess(dataset, pipeline, ngram_min_freq=10, extra_bigrams=None, extra_ngrams=extra_ngrams)

        with open('data/{}_lightweight.csv'.format(ds), 'w') as f:
            for i in range(0, len(processed_dataset)):
                doc = processed_dataset[i]
                f.write('{}\n'.format(' '.join(doc)))

        freq = {}
        freq = word_tf_df(freq, processed_dataset)
        processed_dataset = ng.filter_by_tfidf(dataset=processed_dataset, freq=freq, threshold=0.25)

        with open('data/{}_lightweight_tdidf.csv'.format(ds), 'w') as f:
            for i in range(0, len(processed_dataset)):
                doc = processed_dataset[i]
                f.write('{}\n'.format(' '.join(doc)))


"""feedback URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path

from django.contrib import admin
from django.urls import path
from django.urls import path
from webapp.views import IndexView, ProductView, ProductCreateView, \
    ProductUpdateView, ProductDeleteView, ReviewCreateView, ReviewForProductCreateView, \
    ReviewListView, ReviewUpdateView, ReviewDeleteView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', IndexView.as_view(), name='index'),
    path('product/<int:pk>/', ProductView.as_view(), name='product_view'),
    path('product/add/', ProductCreateView.as_view(), name='product_add'),
    path('product/<int:pk>/edit/', ProductUpdateView.as_view(), name='product_update'),
    path('product/<int:pk>/delete/', ProductDeleteView.as_view(), name='product_delete'),
    path('comments/', ReviewListView.as_view(), name='comment_list'),
    path('comment/add/', ReviewCreateView.as_view(), name='comment_add'),
    path('comment/<int:pk>/edit/', ReviewUpdateView.as_view(), name='comment_update'),
    path('comment/<int:pk>/delete/', ReviewDeleteView.as_view(), name='comment_delete'),
    path('product/<int:pk>/add-comment/', ReviewForProductCreateView.as_view(), name='article_comment_create'),
]


"""
Written by: Jonas Vander Vennet
on: 2019/12/02
Answer: xpysnnkqrbuhefmcajodplyzw
"""

def neighbouring_words(wordlist):
    for word1 in wordlist:
        for word2 in wordlist:
            if len(word1) == len(word2):
                diff = 0
                for i in range(len(word1)):
                    if word1[i] != word2[i]:
                        diff += 1
                        if diff > 1:
                            break
                if diff == 1:
                    return word1, word2

def common_letters(word1, word2):
    common = ''
    for i in range(len(word1)):
        if word1[i] == word2[i]:
            common += word1[i]
    return common

def main():
    test_values = [
        ([
            'abcde',
            'fghij',
            'klmno',
            'pqrst',
            'fguij',
            'axcye',
            'wvxyz',
        ], 'fgij'),
    ]
    for test_words, desired_output in test_values:
        neighbours = neighbouring_words(test_words)
        assert(desired_output == common_letters(*neighbours))

    with open('../input.txt') as ifp:
        inputs = ifp.readlines()

    neighbours = neighbouring_words(inputs)
    common = common_letters(*neighbours)

    print(f'Common letters of neighbours: {common}')

if __name__ == '__main__':
    main()


# coding: utf-8
""" This file implements all notions of fitness. """
import numpy as np
from matador.utils.cursor_utils import get_array_from_cursor
from matador.utils.chem_utils import get_concentration, get_formation_energy

class FitnessCalculator:
    """ This class calculates the fitnesses of generations,
    by some global definition of generation-agnostic fitness.

    Parameters:
        fitness_metric (str): either 'dummy', 'hull' or 'hull_test'.
        fitness_function (callable): function to operate on numpy array of raw fitness values,
        hull (QueryConvexHull): matador hull from which to calculate metastability,
        sandbagging (bool): whether or not to "sandbag" particular compositions, i.e. lower
            a structure's fitness based on the number of nearby phases

    """

    def __init__(
        self,
        fitness_metric="dummy",
        fitness_function=None,
        hull=None,
        sandbagging=False,
        debug=False,
    ):
        """ Initialise fitness calculator, if from hull then
        extract chemical potentials.

        """
        self.testing = False
        self.debug = debug
        self.fitness_metric = fitness_metric
        if self.fitness_metric == "hull":
            self._get_raw = self._get_hull_distance
            if hull is None:
                raise RuntimeError("Cannot calculate hull distance without a hull!")
            self.hull = hull
            self.chempots = hull.chempot_cursor
        elif self.fitness_metric == "dummy":
            self._get_raw = self._get_dummy_fitness
        elif self.fitness_metric == "hull_test":
            self.testing = True
            self._get_raw = self._get_hull_distance
            self.hull = hull
            self.chempots = hull.chempot_cursor
        else:
            raise RuntimeError("No recognised fitness metric given.")

        self.sandbagging = False
        if sandbagging:
            self.sandbagging = True
            self.sandbag_multipliers = dict()

        if fitness_function is None:
            self.fitness_function = default_fitness_function
        else:
            self.fitness_function = fitness_function

    def evaluate(self, generation):
        """ Assign normalised fitnesses to an entire generation.
        Normalisation uses the logistic function such that

        `fitness = 1 - tanh(2*distance_from_hull)`,

        Parameters:
            generation (Generation/list): list/iterator over optimised structures,

        """

        raw = self._get_raw(generation)
        fitnesses = self.fitness_function(raw)

        for ind, _ in enumerate(generation):
            generation[ind]["raw_fitness"] = raw[ind]
            generation[ind]["fitness"] = fitnesses[ind]

        if self.sandbagging:
            self.update_sandbag_multipliers(generation)
            self.apply_sandbag_multipliers(generation)

    def update_sandbag_multipliers(self, generation, modifier=0.95):
        """ Assign composition penalty based on number of nearby structures.
        Updates fitness.sandbag_multipliers to a dictionary with chemical concentration as keys
        and values of fitness penalty.

        Parameters:
            generation (Generation): list of optimised structures.

        """
        for structure in generation:
            if tuple(structure["concentration"]) in self.sandbag_multipliers:
                self.sandbag_multipliers[tuple(structure["concentration"])] *= modifier
            else:
                self.sandbag_multipliers[tuple(structure["concentration"])] = modifier

    def apply_sandbag_multipliers(self, generation, locality=0.05):
        """ Scale the generation's fitness by the sandbag modifier. This
        updates the 'fitness' key and the 'modifier' key (total scaling) of each document
        in the generation.

        Parameters:
            generation (Generation): list of optimised structures.

        Keyword Arguments:
            locality (float): tolerance by which two structures are "nearby"

        """
        for ind, structure in enumerate(generation):
            generation[ind]["modifier"] = 1
            for concentration in self.sandbag_multipliers:
                if (
                    np.sqrt(
                        np.sum(
                            np.abs(
                                np.asarray(structure["concentration"])
                                - np.asarray(list(concentration))
                            )
                            ** 2
                        )
                    )
                    <= locality
                ):
                    generation[ind]["modifier"] *= self.sandbag_multipliers[
                        concentration
                    ]
            generation[ind]["fitness"] *= generation[ind]["modifier"]

    def _get_hull_distance(self, generation):
        """ Assign distance from the hull from hull for generation,
        assigning it.

        Parameters:
            generation (Generation): list of optimised structures.

        Returns:
            hull_dist (list(float)): list of distances to the hull.

        """
        for ind, populum in enumerate(generation):
            generation[ind]["concentration"] = get_concentration(
                populum, self.hull.elements
            )
            generation[ind]["formation_enthalpy_per_atom"] = get_formation_energy(
                self.chempots, populum
            )
            if self.debug:
                print(
                    generation[ind]["concentration"],
                    generation[ind]["formation_enthalpy_per_atom"],
                )
        if self.testing:
            for ind, populum in enumerate(generation):
                generation[ind]["formation_enthalpy_per_atom"] = np.random.rand() - 0.5
        structures = np.hstack(
            (
                get_array_from_cursor(generation, "concentration"),
                get_array_from_cursor(
                    generation, "formation_enthalpy_per_atom"
                ).reshape(len(generation), 1),
            )
        )
        if self.debug:
            print(structures)
        hull_dist = self.hull.get_hull_distances(structures, precompute=False)
        for ind, populum in enumerate(generation):
            generation[ind]["hull_distance"] = hull_dist[ind]
        return hull_dist

    def _get_dummy_fitness(self, generation):
        """ Generate dummy hull distances from -0.01 to 0.05.

        Parameters:
            generation (Generation): list of optimised structures.

        Returns:
            list(float): dummy list of hull distances.

        """
        return (0.05 * np.random.rand(len(generation)) - 0.01).tolist()

def default_fitness_function(raw, c=50, offset=0.075):
    """ Default fitness function: logistic function.

    Parameters:
        raw (ndarray): 1D array of raw fitness values.

    Returns:
        ndarray: 1D array of rescaled fitnesses.

    """
    fitnesses = 1 / (1 + np.exp(c * (raw - offset)))
    if isinstance(fitnesses, np.float64):
        fitnesses = min(1, fitnesses)
    else:
        fitnesses[fitnesses > 1.0] = 1.0
    return fitnesses


from django_cron import CronJobBase, Schedule
from django.db.models import Q
from .models import Device

class UpdateDeviceStatuses(CronJobBase):
    devices = []

    RUN_EVERY_MINS = 1

    schedule = Schedule(run_every_mins=RUN_EVERY_MINS)
    code = 'ARM.update_device_statuses'

    def do(self):
        devices = Device.objects.filter(
            ~(Q(status=Device.send) | Q(status=Device.in_progress)),
            stock__isnull=True,
            next_check_date__isnull=False,
        )

        for device in devices:
            if device.next_check_date:
                device.status = device.get_status()

        Device.objects.bulk_update(devices, fields=["status"])


##################################################### Import system libraries ######################################################
import matplotlib as mpl
mpl.rcdefaults()
mpl.rcParams.update(mpl.rc_params_from_file('meine-matplotlibrc'))
import matplotlib.pyplot as plt
import numpy as np
import scipy.constants as const
import uncertainties.unumpy as unp
from uncertainties import ufloat
from uncertainties.unumpy import (
    nominal_values as noms,
    std_devs as stds,
)
################################################ Finish importing system libraries #################################################

################################################ Adding subfolder to system's path #################################################
import os, sys, inspect
# realpath() will make your script run, even if you symlink it :)
cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
if cmd_folder not in sys.path:
    sys.path.insert(0, cmd_folder)

 # use this if you want to include modules from a subfolder
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"python_custom_scripts")))
if cmd_subfolder not in sys.path:
    sys.path.insert(0, cmd_subfolder)
############################################# Finish adding subfolder to system's path #############################################

##################################################### Import custom libraries ######################################################
from curve_fit import ucurve_fit
from table import (
    make_table,
    make_full_table,
    make_composed_table,
    make_SI,
    write,
)
from regression import (
    reg_linear,
    reg_quadratic,
    reg_cubic
)
from error_calculation import(
    MeanError
)
################################################ Finish importing custom libraries #################################################

################################ FREQUENTLY USED CODE ################################
#
########## IMPORT ##########
# t, U, U_err = np.genfromtxt('data.txt', unpack=True)
# t *= 1e-3

########## ERRORS ##########
# R_unc = ufloat(R[0],R[2])
# U = 1e3 * unp.uarray(U, U_err)
# Rx_mean = np.mean(Rx)                 # Mittelwert und syst. Fehler
# Rx_mean_err = MeanError(noms(Rx))     # Fehler des Mittelwertes
#
## Relative Fehler zum späteren Vergleich in der Diskussion
# RelFehler_G = (G_mess - G_lit) / G_lit
# RelFehler_B = (B_mess - B_lit) / B_lit
# write('build/RelFehler_G.tex', make_SI(RelFehler_G*100, r'\percent', figures=1))
# write('build/RelFehler_B.tex', make_SI(RelFehler_B*100, r'\percent', figures=1))

########## CURVE FIT ##########
# def f(t, a, b, c, d):
#     return a * np.sin(b * t + c) + d
#
# params = ucurve_fit(f, t, U, p0=[1, 1e3, 0, 0])   # p0 bezeichnet die Startwerte der zu fittenden Parameter
# params = ucurve_fit(reg_linear, x, y)             # linearer Fit
# params = ucurve_fit(reg_quadratic, x, y)          # quadratischer Fit
# params = ucurve_fit(reg_cubic, x, y)              # kubischer Fit
# a, b = params
# write('build/parameter_a.tex', make_SI(a * 1e-3, r'\kilo\volt', figures=1))       # type in Anz. signifikanter Stellen
# write('build/parameter_b.tex', make_SI(b * 1e-3, r'\kilo\hertz', figures=2))      # type in Anz. signifikanter Stellen

########## PLOTTING ##########
# plt.clf                   # clear actual plot before generating a new one
#
## automatically choosing limits with existing array T1
# t_plot = np.linspace(np.amin(T1), np.amax(T1), 100)
# plt.xlim(t_plot[0]-1/np.size(T1)*(t_plot[-1]-t_plot[0]), t_plot[-1]+1/np.size(T1)*(t_plot[-1]-t_plot[0]))
#
## hard coded limits
# t_plot = np.linspace(-0.5, 2 * np.pi + 0.5, 1000) * 1e-3
#
## standard plotting
# plt.plot(t_plot * 1e3, f(t_plot, *noms(params)) * 1e-3, 'b-', label='Fit')
# plt.plot(t * 1e3, U * 1e3, 'rx', label='Messdaten')
## plt.errorbar(B * 1e3, noms(y) * 1e5, fmt='rx', yerr=stds(y) * 1e5, label='Messdaten')        # mit Fehlerbalken
## plt.xscale('log')                                                                            # logarithmische x-Achse
# plt.xlim(t_plot[0] * 1e3, t_plot[-1] * 1e3)
# plt.xlabel(r'$t \:/\: \si{\milli\second}$')
# plt.ylabel(r'$U \:/\: \si{\kilo\volt}$')
# plt.legend(loc='best')
# plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
# plt.savefig('build/aufgabenteil_a_plot.pdf')

########## WRITING TABLES ##########
### IF THERE IS ONLY ONE COLUMN IN A TABLE (workaround):
## a=np.array([Wert_d[0]])
## b=np.array([Rx_mean])
## c=np.array([Rx_mean_err])
## d=np.array([Lx_mean*1e3])
## e=np.array([Lx_mean_err*1e3])
#
# write('build/Tabelle_b.tex', make_table([a,b,c,d,e],[0, 1, 0, 1, 1]))     # Jeder fehlerbehaftete Wert bekommt zwei Spalten
# write('build/Tabelle_b_texformat.tex', make_full_table(
#     'Messdaten Kapazitätsmessbrücke.',
#     'table:A2',
#     'build/Tabelle_b.tex',
#     [1,2,3,4,5],              # Hier aufpassen: diese Zahlen bezeichnen diejenigen resultierenden Spaltennummern,
#                               # die Multicolumns sein sollen
#     ['Wert',
#     r'$C_2 \:/\: \si{\nano\farad}$',
#     r'$R_2 \:/\: \si{\ohm}$',
#     r'$R_3 / R_4$', '$R_x \:/\: \si{\ohm}$',
#     r'$C_x \:/\: \si{\nano\farad}$']))
#
## Aufsplitten von Tabellen, falls sie zu lang sind
# t1, t2 = np.array_split(t * 1e3, 2)
# U1, U2 = np.array_split(U * 1e-3, 2)
# write('build/loesung-table.tex', make_table([t1, U1, t2, U2], [3, None, 3, None]))  # type in Nachkommastellen
#
## Verschmelzen von Tabellen (nur Rohdaten, Anzahl der Zeilen muss gleich sein)
# write('build/Tabelle_b_composed.tex', make_composed_table(['build/Tabelle_b_teil1.tex','build/Tabelle_b_teil2.tex']))

########## ARRAY FUNCTIONS ##########
# np.arange(2,10)                   # Erzeugt aufwärts zählendes Array von 2 bis 10
# np.zeros(15)                      # Erzeugt Array mit 15 Nullen
# np.ones(15)                       # Erzeugt Array mit 15 Einsen
#
# np.amin(array)                    # Liefert den kleinsten Wert innerhalb eines Arrays
# np.argmin(array)                  # Gibt mir den Index des Minimums eines Arrays zurück
# np.amax(array)                    # Liefert den größten Wert innerhalb eines Arrays
# np.argmax(array)                  # Gibt mir den Index des Maximums eines Arrays zurück
#
# a1,a2 = np.array_split(array, 2)  # Array in zwei Hälften teilen
# np.size(array)                    # Anzahl der Elemente eines Arrays ermitteln

########## ARRAY INDEXING ##########
# y[n - 1::n]                       # liefert aus einem Array jeden n-ten Wert als Array

########## DIFFERENT STUFF ##########
# R = const.physical_constants["molar gas constant"]      # Array of value, unit, error

# E-Feld Teilaufgabe a)

D_lang, U_1, U_2, U_3 = np.genfromtxt('messdaten/messung_E_lang.txt', unpack=True)
D_kurz, U_4, U_5 = np.genfromtxt('messdaten/messung_E_kurz.txt', unpack=True)
D_lang = D_lang * 0.0254
D_kurz = D_kurz * 0.0254 # in meter umrechnen

print("Die folgenden Plots werden Ihnen präsentiert von: Micra Tours!")
# U_b,1 = 200 V
params1 = ucurve_fit(reg_linear, U_1, D_lang)             # linearer Fit
m1, b1 = params1
write('build/parameter_m1.tex', make_SI(m1, r'\metre\per\volt', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b1.tex', make_SI(b1, r'\volt', figures=2))      # type in Anz. signifikanter Stellen
t_plot1 = np.linspace(np.amin(U_1)-0.5, np.amax(U_1)+0.5, 100)
plt.plot(t_plot1, (m1.n*t_plot1+b1.n)*100, 'b-', label='Linearer Fit')
plt.plot(U_1, D_lang*100, 'rx', label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$D \:/\: \si{\centi\metre}$')
plt.xlabel(r'$U_1 \:/\: \si{\volt}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a1.pdf')

print("In Kooperation mit: Sassi Vacation!")
print("Starring Amba-Lamb-Guy (https://www.youtube.com/watch?v=fLQWKOB5se0)")
# U_b,2 = 250 V
plt.clf()
params2 = ucurve_fit(reg_linear, U_2, D_lang)             # linearer Fit
m2, b2 = params2
write('build/parameter_m2.tex', make_SI(m2, r'\metre\per\volt', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b2.tex', make_SI(b2, r'\volt', figures=2))      # type in Anz. signifikanter Stellen
t_plot2 = np.linspace(np.amin(U_2)-0.5, np.amax(U_2)+0.5, 100)
plt.plot(t_plot2, (m2.n*t_plot2+b2.n)*100, 'b-', label='Linearer Fit')
plt.plot(U_2, D_lang*100, 'rx', label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$D \:/\: \si{\centi\metre}$')
plt.xlabel(r'$U_2 \:/\: \si{\volt}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a2.pdf')

print("... das maken dauert heute aber echt lang...")
# U_b,3 = 300 V
plt.clf()
params3 = ucurve_fit(reg_linear, U_3, D_lang)             # linearer Fit
m3, b3 = params3
write('build/parameter_m3.tex', make_SI(m3, r'\metre\per\volt', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b3.tex', make_SI(b3, r'\volt', figures=2))      # type in Anz. signifikanter Stellen
t_plot3 = np.linspace(np.amin(U_3)-0.5, np.amax(U_3)+0.5, 100)
plt.plot(t_plot3, (m3.n*t_plot3+b3.n)*100, 'b-', label='Linearer Fit')
plt.plot(U_3, D_lang*100, 'rx', label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$D \:/\: \si{\centi\metre}$')
plt.xlabel(r'$U_3 \:/\: \si{\volt}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a3.pdf')

print("Wer lässt auch gefühlt 34 Funktionen in einem Protokoll fitten?!")
# U_b,4 = 350 V
plt.clf()
params4 = ucurve_fit(reg_linear, U_4, D_kurz)             # linearer Fit
m4, b4 = params4
write('build/parameter_m4.tex', make_SI(m4, r'\metre\per\volt', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b4.tex', make_SI(b4, r'\volt', figures=2))      # type in Anz. signifikanter Stellen
t_plot4 = np.linspace(np.amin(U_4)-0.5, np.amax(U_4)+0.5, 100)
plt.plot(t_plot4, (m4.n*t_plot4+b4.n)*100, 'b-', label='Linearer Fit')
plt.plot(U_4, D_kurz*100, 'rx', label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$D \:/\: \si{\centi\metre}$')
plt.xlabel(r'$U_4 \:/\: \si{\volt}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a4.pdf')

print("Der isst auch kleine Kinder...")
# U_b,5 = 400 V
plt.clf()
params5 = ucurve_fit(reg_linear, U_5, D_kurz)             # linearer Fit
m5, b5 = params5
write('build/parameter_m5.tex', make_SI(m5, r'\metre\per\volt', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b5.tex', make_SI(b5, r'\volt', figures=2))      # type in Anz. signifikanter Stellen
t_plot5 = np.linspace(np.amin(U_5)-0.5, np.amax(U_5)+0.5, 100)
plt.plot(t_plot5, (m5.n*t_plot5+b5.n)*100, 'b-', label='Linearer Fit')
plt.plot(U_5, D_kurz*100, 'rx', label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$D \:/\: \si{\centi\metre}$')
plt.xlabel(r'$U_5 \:/\: \si{\volt}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a5.pdf')

# E-Feld a), Teil 2

die_bs = np.array([b1.n, b2.n, b3.n, b4.n, b5.n])
die_bs_err = np.array([b1.s, b2.s, b3.s, b4.s, b5.s])
die_ms = np.array([m1.n, m2.n, m3.n, m4.n, m5.n])
die_ms_err = np.array([m1.s, m2.s, m3.s, m4.s, m5.s])
print("Übrigens: Das ist unser letztes Protkoll aus dem AP!")
U_b = np.array([200, 250, 300, 350, 400])
empf = unp.uarray([m1.n, m2.n, m3.n, m4.n, m5.n], [m1.s, m2.s, m3.s, m4.s, m5.s])
plt.clf()

write('Tabelle_c.tex', make_table([U_b, die_ms*10**4, die_ms_err*10**4, die_bs*10**3, die_bs_err*10**3],[0, 2, 2, 2, 2]))     # Jeder fehlerbehaftete Wert bekommt zwei Spalten
write('Tabelle_c_texformat.tex', make_full_table(
    'Fitparameter: Steigung $m$ und y-Achsenabschnitt $b$.',
    'tab:c',
    'Tabelle_c.tex',
    [],              # Hier aufpassen: diese Zahlen bezeichnen diejenigen resultierenden Spaltennummern,
                              # die Multicolumns sein sollen
    [
    r'$U_b \:/\: \si{\volt}$',
    r'$m \:/\: 10^{-4}\si{\metre\per\volt}$',
    r'$\increment{m} \:/\: 10^{-4}\si{\metre\per\volt}$',
    r'$b \:/\: 10^{-3}\si{\volt}$',
    r'$\increment{b} \:/\: 10^{-3}\si{\volt}$']))

params6 = ucurve_fit(reg_linear, 1/U_b, noms(empf))             # linearer Fit
m6, b6 = params6
write('build/parameter_m6.tex', make_SI(m6, r'\metre', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b6.tex', make_SI(b6, r'\metre\per\volt', figures=2))      # type in Anz. signifikanter Stellen
t_plot6 = np.linspace(np.amin(1/U_b*100)-0.001*20, np.amax(1/U_b*100)+0.001*20, 10)
plt.plot(t_plot6, (m6.n*t_plot6+b6.n*100), 'b-', label='Linearer Fit')
plt.errorbar(1/U_b*100, noms(empf)*100, fmt='rx', yerr=stds(empf)*100, label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$\frac{D}{U_d} \:/\: 10^{-2}\si{\metre\per\volt}$')
plt.xlabel(r'$\frac{1}{U_\text{B}} \:/\: 10^{-2}\si{\volt\tothe{-1}}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a6.pdf')

d = 0.38 * 0.01
p = 1.9 * 0.01
L = 14.3*0.01
m6_lit = (p*L)/(2*d)

write('build/parameter_m6_lit.tex', make_SI(m6_lit, r'\metre', figures=3))       # type in Anz. signifikanter Stellen
err_m6 = (m6 - m6_lit) / m6_lit
write('build/parameter_m6_rel.tex', make_SI(err_m6.n*100, r'\percent', figures=2))

# E-Feld b)

v, A = np.genfromtxt('messdaten/frequenzen.txt', unpack=True)

U_b = 400 #(???)
D_amp = A[1] * 0.0254 # habe nicht ganz verstanden welchen Amplitudenwert wir nehmen sollen
U_amp = 1/m6 * U_b * D_amp # Formel umgestellt und eingesetzt
write('build/U_amp.tex', make_SI(U_amp, r'\volt', figures=2))
write('build/v0.tex', make_SI(v[0], r'\kilo\hertz', figures=1))
write('build/v1.tex', make_SI(v[1], r'\kilo\hertz', figures=1))
write('build/v2.tex', make_SI(v[2], r'\kilo\hertz', figures=1))
write('build/v3.tex', make_SI(v[3], r'\kilo\hertz', figures=1))

write('build/v0_mal_2.tex', make_SI(v[0]*2, r'\kilo\hertz', figures=1))
write('build/v3_durch_2.tex', make_SI(v[3]/2, r'\kilo\hertz', figures=1))

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

# B-Feld a)

D_lang, I_1, I_2, I_3 = np.genfromtxt('messdaten/messung_B_lang.txt', unpack=True)
D_kurz, I_4, I_5 = np.genfromtxt('messdaten/messung_B_kurz.txt', unpack=True)
D_lang = D_lang * 0.0254
D_kurz = D_kurz * 0.0254 # in meter umrechnen
U_b_B = np.array([250, 300, 350, 400, 450])

mu_0 = 4*np.pi*10**(-7)
N = 20 #? geraten
R = 0.282 # ? geraten
L = 17.5*0.01
B_1 = mu_0 * 8/np.sqrt(125) * N/R * I_1
B_2 = mu_0 * 8/np.sqrt(125) * N/R * I_2
B_3 = mu_0 * 8/np.sqrt(125) * N/R * I_3
B_4 = mu_0 * 8/np.sqrt(125) * N/R * I_4
B_5 = mu_0 * 8/np.sqrt(125) * N/R * I_5

# U_b,1 = 250 V
plt.clf()
params7 = ucurve_fit(reg_linear, B_1, D_lang/(L**2+D_lang**2))             # linearer Fit
m7, b7 = params7
write('build/parameter_m7.tex', make_SI(m7, r'\per\metre\per\tesla', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b7.tex', make_SI(b7, r'\per\metre', figures=2))      # type in Anz. signifikanter Stellen
t_plot7 = np.linspace(np.amin(B_1), np.amax(B_1), 100)
plt.plot(t_plot7*10**6, (m7.n*t_plot7+b7.n), 'b-', label='Linearer Fit')
plt.plot(B_1*10**(6), D_lang/(L**2+D_lang**2), 'rx', label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$\frac{D}{L^2 + D^2} \:/\: \si{\per\metre} $')
plt.xlabel(r'$B_1 \:/\: \si{\micro\tesla}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a7.pdf')

# U_b,2 = 300 V
plt.clf()
params8 = ucurve_fit(reg_linear, B_2, D_lang/(L**2+D_lang**2))             # linearer Fit
m8, b8 = params8
print("https://www.youtube.com/watch?v=Mdi534Q1Zsg")
write('build/parameter_m8.tex', make_SI(m8, r'\per\metre\per\tesla', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b8.tex', make_SI(b8, r'\per\metre', figures=2))      # type in Anz. signifikanter Stellen
t_plot8 = np.linspace(np.amin(B_2), np.amax(B_2), 100)
plt.plot(t_plot8*10**(6), (m8.n*t_plot8+b8.n), 'b-', label='Linearer Fit')
plt.plot(B_2*10**(6), D_lang/(L**2+D_lang**2), 'rx', label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$\frac{D}{L^2 + D^2} \:/\: \si{\per\metre} $')
plt.xlabel(r'$B_2 \:/\: \si{\micro\tesla}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a8.pdf')

# U_b,2 = 350 V
plt.clf()
params9 = ucurve_fit(reg_linear, B_3, D_lang/(L**2+D_lang**2))             # linearer Fit
m9, b9 = params9
write('build/parameter_m9.tex', make_SI(m9, r'\per\metre\per\tesla', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b9.tex', make_SI(b9, r'\per\metre', figures=2))      # type in Anz. signifikanter Stellen
t_plot9 = np.linspace(np.amin(B_3), np.amax(B_3), 100)
plt.plot(t_plot9*10**(6), (m9.n*t_plot9+b9.n), 'b-', label='Linearer Fit')
plt.plot(B_3*10**(6), D_lang/(L**2+D_lang**2), 'rx', label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$\frac{D}{L^2 + D^2} \:/\: \si{\per\metre} $')
plt.xlabel(r'$B_3 \:/\: \si{\micro\tesla}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a9.pdf')

# U_b,2 = 400 V
plt.clf()
params10 = ucurve_fit(reg_linear, B_4, D_kurz/(L**2+D_kurz**2))             # linearer Fit
m10, b10 = params10
write('build/parameter_m10.tex', make_SI(m10, r'\per\metre\per\tesla', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b10.tex', make_SI(b10, r'\per\metre', figures=2))      # type in Anz. signifikanter Stellen
t_plot10 = np.linspace(np.amin(B_4), np.amax(B_4), 100)
plt.plot(t_plot10*10**(6), (m10.n*t_plot10+b10.n), 'b-', label='Linearer Fit')
plt.plot(B_4*10**(6), D_kurz/(L**2+D_kurz**2), 'rx', label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$\frac{D}{L^2 + D^2} \:/\: \si{\per\metre} $')
plt.xlabel(r'$B_4 \:/\: \si{\micro\tesla}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a10.pdf')

# U_b,2 = 450 V
plt.clf()
params11 = ucurve_fit(reg_linear, B_5, D_kurz/(L**2+D_kurz**2))             # linearer Fit
m11, b11 = params11
write('build/parameter_m11.tex', make_SI(m11, r'\per\metre\per\tesla', figures=1))       # type in Anz. signifikanter Stellen
write('build/parameter_b11.tex', make_SI(b11, r'\per\metre', figures=2))      # type in Anz. signifikanter Stellen
t_plot11 = np.linspace(np.amin(B_5), np.amax(B_5), 100)
plt.plot(t_plot11*10**(6), (m11.n*t_plot11+b11.n), 'b-', label='Linearer Fit')
plt.plot(B_5*10**(6), D_kurz/(L**2+D_kurz**2), 'rx', label='Messdaten')
#plt.xlim(t_plot1[0], t_plot1[-1])
plt.ylabel(r'$\frac{D}{L^2 + D^2} \:/\: \si{\per\metre} $')
plt.xlabel(r'$B_5 \:/\: \si{\micro\tesla}$')
plt.legend(loc='best')
plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08)
plt.savefig('build/plot_a11.pdf')

die_bs_b = np.array([b7.n, b8.n, b9.n, b10.n, b11.n])
die_bs_err_b = np.array([b7.s, b8.s, b9.s, b10.s, b11.s])
die_ms_b = np.array([m7.n, m8.n, m9.n, m10.n, m11.n])
die_ms_err_b = np.array([m7.s, m8.s, m9.s, m10.s, m11.s])

write('Tabelle_e.tex', make_table([U_b_B, die_ms_b, die_ms_err_b, die_bs_b, die_bs_err_b],[0, 2, 2, 2, 2]))     # Jeder fehlerbehaftete Wert bekommt zwei Spalten
write('Tabelle_e_texformat.tex', make_full_table(
    'Fitparameter: Steigung $m$ und y-Achsenabschnitt $b$.',
    'tab:e',
    'Tabelle_e.tex',
    [],              # Hier aufpassen: diese Zahlen bezeichnen diejenigen resultierenden Spaltennummern,
                              # die Multicolumns sein sollen
    [
    r'$U_b \:/\: \si{\volt}$',
    r'$m \:/\:\si{\per\metre\per\tesla}$',
    r'$\increment{m} \:/\:\si{\per\metre\per\tesla}$',
    r'$b \:/\: \si{\per\metre}$',
    r'$\increment{b} \:/\:\si{\per\metre}$']))

steigungen = unp.uarray(die_ms_b, die_ms_err_b)
konstante = 8*U_b_B*steigungen**2
write('build/konstante_0.tex', make_SI(konstante[0]*10**(-11), r'\coulomb\per\kilogram','e11', figures=2))      # type in Anz. signifikanter Stellen
write('build/konstante_1.tex', make_SI(konstante[1]*10**(-11), r'\coulomb\per\kilogram','e11', figures=2))      # type in Anz. signifikanter Stellen
write('build/konstante_2.tex', make_SI(konstante[2]*10**(-11), r'\coulomb\per\kilogram','e11', figures=2))      # type in Anz. signifikanter Stellen
write('build/konstante_3.tex', make_SI(konstante[3]*10**(-11), r'\coulomb\per\kilogram','e11', figures=2))      # type in Anz. signifikanter Stellen
write('build/konstante_4.tex', make_SI(konstante[4]*10**(-11), r'\coulomb\per\kilogram','e11', figures=2))      # type in Anz. signifikanter Stellen

mean_k = np.mean(noms(konstante))
std_k = np.std(noms(konstante))
k = ufloat(mean_k, std_k)
write('build/konstante_mean.tex', make_SI(k*10**(-11), r'\coulomb\per\kilogram','e11', figures=2))      # type in Anz. signifikanter Stellen

k_lit = 1.758820024*10**11
write('build/lit.tex', make_SI(k_lit*10**(-11), r'\coulomb\per\kilogram','e11', figures=4))
k_rel = (mean_k - k_lit) / k_lit
write('build/rel.tex', make_SI(k_rel*100, r'\percent', figures=1))
#

## Errrdmagnetfeld

I_erd = 0.26 # Kompensationsstrom in Ampere
U_erd = 200 # Beschleunigungsspannung
phi = 70/360 * 2*np.pi #grad inklinationswinkel

B_erd = mu_0 * 8/np.sqrt(125) * N/R * I_erd
write('build/erdmagnetfeld.tex', make_SI(B_erd*10**6, r'\micro\tesla', figures=2))

B_erd_korrigiert = B_erd / np.sin(phi)
write('build/erdmagnetfeld_korrigiert.tex', make_SI(B_erd_korrigiert*10**6, r'\micro\tesla', figures=2))

B_erd_lit = 19.3221

write('build/erdmagnetfeld_korrigiert_lit.tex', make_SI(B_erd_lit, r'\micro\tesla', figures=2))