text:
from __future__ import absolute_import
from __future__ import print_function
from __future__ import division

import numpy as np
import scipy.stats
import math

def _logsumexp(x):
    """
    Sum in the log space.

    Args:
        x: array-like.

    Returns:
        A scalar.
    """
    x = np.array(x)
    m = max(x)  # for numerical stability
    return m + math.log(sum(np.exp(x - m)))

def _log1mexp(x):
    """
    Numerically stable computation of log(1-exp(x)).

    Args:
        x: a scalar.

    Returns:
        A scalar.
    """
    assert x <= 0, "Argument must be non-positive!"
    if x < -1:
        return math.log1p(-math.exp(x))
    elif x < 0:
        return math.log(-math.expm1(x))
    else:
        return -np.inf

def rdp_to_dp(orders, rdp_eps, delta):
    """
    Conversion from (lambda, eps)-RDP to conventional (eps, delta)-DP.

    Args:
        orders: an array-like list of RDP orders.
        rdp_eps: an array-like list of RDP guarantees (of the same length as orders).
        delta: target delta (a scalar).

    Returns:
        A pair of (dp_eps, optimal_order).
    """
    assert not np.isscalar(orders) and not np.isscalar(rdp_eps) and len(orders) == len(
        rdp_eps), "'orders' and 'rdp_eps' must be array-like and of the same length!"
    dp_eps = np.array(rdp_eps) - math.log(delta) / (np.array(orders) - 1)
    idx_opt = np.argmin(dp_eps)
    return dp_eps[idx_opt], orders[idx_opt]

###############################
# RDP FOR THE GNMAX MECHANISM #
###############################

def compute_logq_gnmax(votes, sigma):
    """
    Computes an upper bound on log(Pr[outcome != argmax]) for the GNMax mechanism.

    Args:
        votes: a 1-D numpy array of raw ensemble votes for a given query.
        sigma: std of the Gaussian noise in the GNMax mechanism.

    Returns:
        A scalar upper bound on log(Pr[outcome != argmax]) where log denotes natural logarithm.
    """
    num_classes = len(votes)
    variance = sigma ** 2
    idx_max = np.argmax(votes)
    votes_gap = votes[idx_max] - votes
    votes_gap = votes_gap[np.arange(num_classes) != idx_max]  # exclude argmax
    # Upper bound log(q) via a union bound.
    logq = _logsumexp(scipy.stats.norm.logsf(votes_gap, scale=math.sqrt(2 * variance)))
    return min(logq, math.log(1 - (1 / num_classes)))  # another obvious upper bound

def compute_rdp_data_independent_gnmax(sigma, orders):
    """
    Computes data-independent RDP gurantees for the GNMax mechanism.

    Args:
        sigma: std of the Gaussian noise in the GNMax mechanism.
        orders: an array-like list of RDP orders.

    Returns:
        A numpy array of upper bounds on RDP for all orders.

    Raises:
        ValueError: if the inputs are invalid.
    """
    if sigma < 0 or np.isscalar(orders) or np.any(orders <= 1):
        raise ValueError("'sigma' must be non-negative, 'orders' must be array-like, and all elements in 'orders' must be greater than 1!")
    variance = sigma ** 2
    return np.array(orders) / variance

def compute_rdp_data_dependent_gnmax(logq, sigma, orders):
    """
    Computes data-dependent RDP gurantees for the GNMax mechanism.

    Args:
        logq: a union bound on log(Pr[outcome != argmax]) for the GNMax mechanism.
        sigma: std of the Gaussian noise in the GNMax mechanism.
        orders: an array-like list of RDP orders.

    Returns:
        A numpy array of upper bounds on RDP for all orders.

    Raises:
        ValueError: if the inputs are invalid.
    """
    if logq > 0 or sigma < 0 or np.isscalar(orders) or np.any(orders <= 1):
        raise ValueError(
            "'logq' must be non-positive, 'sigma' must be non-negative, 'orders' must be array-like, and all elements in 'orders' must be greater than 1!")

    if np.isneginf(logq):  # deterministic mechanism with sigma == 0
        return np.full_like(orders, 0., dtype=np.float)

    variance = sigma ** 2
    orders = np.array(orders)
    rdp_eps = orders / variance  # data-independent bound as baseline

    # Two different higher orders computed according to Proposition 10.
    rdp_order2 = math.sqrt(variance * -logq)
    rdp_order1 = rdp_order2 + 1

    # Filter out entries to which data-dependent bound does not apply.
    mask = np.logical_and(rdp_order1 > orders, rdp_order2 > 1)

    # Corresponding RDP guarantees for the two higher orders.
    rdp_eps1 = rdp_order1 / variance
    rdp_eps2 = rdp_order2 / variance

    log_a2 = (rdp_order2 - 1) * rdp_eps2

    # Make sure that logq lies in the increasing range and that A is positive.
    if (np.any(mask) and -logq > rdp_eps2 and logq <= log_a2 - rdp_order2 *
            (math.log(1 + 1 / (rdp_order1 - 1)) + math.log(1 + 1 / (rdp_order2 - 1)))):

        # Use log1p(x) = log(1 + x) to avoid catastrophic cancellations when x ~ 0.
        log1mq = _log1mexp(logq)  # log1mq = log(1-q)
        log_a = (orders - 1) * (
            log1mq - _log1mexp((logq + rdp_eps2) * (1 - 1 / rdp_order2)))
        log_b = (orders - 1) * (rdp_eps1 - logq / (rdp_order1 - 1))

        # Use logaddexp(x, y) = log(e^x + e^y) to avoid overflow for large x, y.
        log_s = np.logaddexp(log1mq + log_a, logq + log_b)
        rdp_eps[mask] = np.minimum(rdp_eps, log_s / (orders - 1))[mask]

    assert np.all(rdp_eps >= 0)
    return rdp_eps

def is_data_independent_rdp_always_opt_gnmax(num_teachers, num_classes, sigma, orders):
    """
    Tests whether data-independent bound is always optimal for the GNMax mechanism.

    Args:
        num_teachers: number of teachers.
        num_classes: number of classes.
        sigma: std of the Gaussian noise in the GNMax mechanism.
        orders: an array-like list of RDP orders.

    Returns:
        A boolean array of the same length as orders.
    """
    unanimous_votes = np.array([num_teachers] + [0] * (num_classes - 1))
    logq = compute_logq_gnmax(unanimous_votes, sigma)

    rdp_eps_dep = compute_rdp_data_dependent_gnmax(logq, sigma, orders)
    rdp_eps_ind = compute_rdp_data_independent_gnmax(sigma, orders)
    return np.isclose(rdp_eps_dep, rdp_eps_ind)

###################################
# RDP FOR THE THRESHOLD MECHANISM #
###################################

def compute_logpr_answered(t, sigma, votes):
    """
    Computes log(Pr[answered]) for the threshold mechanism.

    Args:
        t: the threshold (a scalar).
        sigma: std of the Gaussian noise in the threshold mechanism.
        votes: a 1-D numpy array of raw ensemble votes for a given query.

    Returns:
        The value of log(Pr[answered]) where log denotes natural logarithm.
    """
    return scipy.stats.norm.logsf(t - round(max(votes)), scale=sigma)

def compute_rdp_data_independent_threshold(sigma, orders):
    """
    Computes data-independent RDP gurantees for the threshold mechanism.

    Args:
        sigma: std of the Gaussian noise in the threshold mechanism.
        orders: an array-like list of RDP orders.

    Returns:
        A numpy array of upper bounds on RDP for all orders.

    Raises:
        ValueError: if the inputs are invalid.
    """
    # The input to the threshold mechanism has sensitivity 1 rather than 2 as
    # compared to the GNMax mechanism, hence the sqrt(2) factor below.
    return compute_rdp_data_independent_gnmax(2 ** .5 * sigma, orders)

def compute_rdp_data_dependent_threshold(logpr, sigma, orders):
    """
    Computes data-dependent RDP gurantees for the threshold mechanism.

    Args:
        logpr: the value of log(Pr[answered]) for the threshold mechanism.
        sigma: std of the Gaussian noise in the threshold mechanism.
        orders: an array-like list of RDP orders.

    Returns:
        A numpy array of upper bounds on RDP for all orders.

    Raises:
        ValueError: if the inputs are invalid.
    """
    logq = min(logpr, _log1mexp(logpr))
    # The input to the threshold mechanism has sensitivity 1 rather than 2 as
    # compared to the GNMax mechanism, hence the sqrt(2) factor below.
    return compute_rdp_data_dependent_gnmax(logq, 2 ** .5 * sigma, orders)

def is_data_independent_rdp_always_opt_threshold(num_teachers, t, sigma, orders):
    """
    Tests whether data-independent bound is always optimal for the threshold mechanism.

    Args:
        num_teachers: number of teachers.
        t: the threshold (a scalar).
        sigma: std of the Gaussian noise in the threshold mechanism.
        orders: an array-like list of RDP orders.

    Returns:
        A boolean array of the same length as orders.
    """
    # Since the data-dependent bound depends only on max(votes), it suffices to
    # check whether the data-dependent bounds are better than the data-independent
    # bounds in the extreme cases where max(votes) is minimal or maximal.
    # For both Confident GNMax and Interactive GNMax it holds that
    #   0 <= max(votes) <= num_teachers.
    logpr1 = compute_logpr_answered(t, sigma, np.array([0]))
    logpr2 = compute_logpr_answered(t, sigma, np.array([num_teachers]))

    rdp_eps_dep1 = compute_rdp_data_dependent_threshold(logpr1, sigma, orders)
    rdp_eps_dep2 = compute_rdp_data_dependent_threshold(logpr2, sigma, orders)

    rdp_eps_ind = compute_rdp_data_independent_threshold(sigma, orders)
    return np.logical_and(np.isclose(rdp_eps_dep1, rdp_eps_ind), np.isclose(rdp_eps_dep2, rdp_eps_ind))

# if __name__ == "__main__":
#     num_teachers = 250
#     num_classes = 10
#     sigma_threshold = 200
#     sigma_gnmax = 40
#     t = 300
#     delta = 1e-6
#     orders = np.concatenate((np.arange(2, 100, .5), np.logspace(np.log10(100), np.log10(1000), num=200)))
#
#     unanimous_votes = np.array([num_teachers] + [0] * (num_classes - 1))
#     logq = compute_logq_gnmax(unanimous_votes, sigma_gnmax)
#     rdp_eps_dep = compute_rdp_data_dependent_gnmax(logq, sigma_gnmax, orders)
#     rdp_eps_ind = compute_rdp_data_independent_gnmax(sigma_gnmax, orders)
#     dp_eps_dep = rdp_to_dp(orders, rdp_eps_dep, delta)
#     dp_eps_ind = rdp_to_dp(orders, rdp_eps_ind, delta)
#     print("dp_eps_dep:", dp_eps_dep)
#     print("dp_eps_ind:", dp_eps_ind)

max_stars_repo_name: cleverhans-lab/capc-iclr

max_issues_repo_name: cleverhans-lab/capc-iclr

max_forks_repo_name: cleverhans-lab/capc-iclr


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

import numpy as np
import cv2

def preprocess(image, img_size=(224,224)):
    """
    # Args
        image : rgb-ordered array
    """
    image = np.expand_dims(cv2.resize(image.astype(np.float32), img_size), axis=0)
    return image

def get_params(t7_file):
    import torchfile
    t7 = torchfile.load(t7_file, force_8bytes_long=True)
    weights = []
    biases = []
    for idx, module in enumerate(t7.modules):
        weight = module.weight
        bias = module.bias
        if idx == 0:
            print(bias)
        elif weight is not None:
            weight = weight.transpose([2,3,1,0])
            weights.append(weight)
            biases.append(bias)
    return weights, biases

def set_params(model, weights, biases):
    i = 0
    for layer in model.layers:
        # assign params
        if len(layer.get_weights()) > 0:
            layer.set_weights([weights[i], biases[i]])
            i += 1

def plot(imgs):
    import matplotlib.pyplot as plt
    fig, ax = plt.subplots()
    plt.subplot(1, 3, 1)
    plt.axis('off')
    plt.title("content image")
    plt.imshow(imgs[0])
    plt.subplot(1, 3, 2)
    plt.axis('off')
    plt.title("style image")
    plt.imshow(imgs[1])
    plt.subplot(1, 3, 3)
    plt.axis('off')
    plt.title("stylized image")
    plt.imshow(imgs[2])
    plt.show()

def print_t7_graph(t7_file):
    import torchfile
    t7 = torchfile.load(t7_file, force_8bytes_long=True)
    for idx, module in enumerate(t7.modules):
        print("{}, {}".format(idx, module._typename))

        weight = module.weight
        bias = module.bias
        if weight is not None:
            weight = weight.transpose([2,3,1,0])
            print("    ", weight.shape, bias.shape)

if __name__ == '__main__':
    from adain import PROJECT_ROOT
    import os
    # print_t7_graph(os.path.join(PROJECT_ROOT, "pretrained", "vgg_normalised.t7"))
    print_t7_graph(os.path.join(PROJECT_ROOT, "pretrained", "decoder.t7"))

ext: py

reason: import numpy


text:
import unittest
import numpy as np
from prml import nn

class TestSoftmax(unittest.TestCase):

    def test_softmax(self):
        self.assertTrue(np.allclose(nn.softmax(np.ones(4)).value, 0.25))

if __name__ == '__main__':
    unittest.main()

max_stars_repo_name: iamfaith/DeepLearning


text:
import gensim.models
from gensim.test.utils import datapath
import os
import numpy as np
import joblib
import pandas as pd

class Swem(object):
    """
    Swemを取得するクラス
    """

    def __init__(self, file_path: str = None, is_train: bool = True):
        """
        file_pathにchiveのpathを指定する
        指定しない場合，新たに学習する
        is_trainがTrueの場合，追加学習を行う
        :param file_path: chiveのpath
        :param is_train: 追加学習を行うかどうか
        """
        self.file_path = file_path
        self.is_train = is_train
        self.model: gensim.models.Word2Vec = \
            gensim.models.KeyedVectors.load_word2vec_format(file_path, binary=False) if file_path else None
        self.vocab = set(self.model.vocab.keys()) if file_path else None
        self.vector_size = self.model.vector_size if file_path else None

    def _train(self, sentences) -> None:
        """
        追加学習を行う
        :param sentences: 単語に分割されたリスト
        """
        self.model.build_vocab(sentences, update=True)
        self.model.train(sentences, total_examples=self.model.corpus_count, epochs=self.model.iter)
        self.vocab = set(self.model.vocab.keys())

    def save_model(self, file_path: str) -> None:
        """
        モデルを保存する
        :param file_path: 保存先
        """
        assert file_path, "file_path is None"

        dir_path = os.path.dirname(file_path)
        if not os.path.exists(dir_path):
            os.mkdir(dir_path)

        # self.model.save(file_path)

        os.makedirs(os.path.dirname(file_path), exist_ok=True)
        joblib.dump(self.model, file_path, compress=True)

    def load_model(self, file_path: str) -> None:
        """
        モデルのロード
        :param file_path:
        :return:
        """
        assert os.path.exists(file_path), "file_path is not exists"
        # self.model = gensim.models.Word2Vec.load(file_path)
        self.model = joblib.load(file_path)
        self.vocab = set(self.model.vocab.keys())
        self.vector_size = self.model.vector_size

    def _get_word_embeddings(self, word_list) -> np.array:
        """
        word_embeddingのリストを取得する
        :param word_list: 単語リスト
        :return: np.array, shape(len(word_list), self.vector_size)
        """
        np.random.seed(abs(hash(" ".join(word_list))) % (10 ** 8))
        vectors = []
        for word in word_list:
            if word in self.vocab:
                vectors.append(self.model[word])
            else:
                vectors.append(np.random.uniform(-0.01, 0.01, self.vector_size))

        return np.array(vectors)

    def get_swem(self, sentences) -> np.array:
        """
        swemの構築
        :param sentences: 単語に分割されたリスト
        :return:
        """
        if self.file_path and self.is_train:
            self._train(sentences)

        swems = []
        for word_list in sentences:
            word_embeddings = self._get_word_embeddings(word_list)
            swems.append(np.r_[np.mean(word_embeddings, axis=0), np.max(word_embeddings, axis=0)])

        return np.array(swems)

def main():
    swem = Swem(file_path="./data/model/chive-1.1-mc5-20200318/chive-1.1-mc5-20200318.txt", is_train=True)
    df = pd.read_csv("./data/tweets_wakati_hinshi.csv")

max_stars_repo_name: Lain-progressivehouse/TweetCollection

max_issues_repo_name: Lain-progressivehouse/TweetCollection

max_forks_repo_name: Lain-progressivehouse/TweetCollection


text:
import re

import numpy as np
import numpy.testing as npt
import pytest

from cara import models
from cara.monte_carlo.data import expiration_distribution

def test_multiple_wrong_weight_size():
    weights = (1., 2., 3.)
    e_base = models.Expiration(2.5)
    with pytest.raises(
            ValueError,
            match=re.escape("expirations and weigths must contain the"
                            "same number of elements")
    ):
        e = models.MultipleExpiration([e_base, e_base], weights)

def test_multiple_wrong_diameters():
    weights = (1., 2., 3.)
    e1 = models.Expiration(np.array([1., 1.]))
    e2 = models.Expiration(1.)
    e3 = models.Expiration(2.)
    with pytest.raises(
            ValueError,
            match=re.escape("diameters must all be scalars")
    ):
        e = models.MultipleExpiration([e1, e2, e3], weights)

def test_multiple():
    weights = (1., 1.)
    mask = models.Mask.types['Type I']
    e1 = models.Expiration.types['Breathing']
    e2 = models.Expiration.types['Singing']
    aerosol_expected = (e1.aerosols(mask) + e2.aerosols(mask))/2.
    e = models.MultipleExpiration([e1, e2], weights)
    npt.assert_almost_equal(aerosol_expected, e.aerosols(mask))

# expected values obtained from analytical formulas
@pytest.mark.parametrize(
    "BLO_weights, expected_aerosols",
    [
        [(1.,0.,0.), 8.33551e-13],
        [(1.,1.,1.), 2.20071e-11],
        [(1.,5.,5.), 1.06701e-10],
    ],
)
def test_expiration_aerosols(BLO_weights, expected_aerosols):
    mask = models.Mask.types['No mask']
    e = expiration_distribution(BLO_weights)
    npt.assert_allclose(e.build_model(100000).aerosols(mask).mean(),
                        expected_aerosols, rtol=1e-2)

max_stars_repo_name: pk-scs/cara

max_issues_repo_name: pk-scs/cara

max_forks_repo_name: pk-scs/cara


text:
# -*- coding: utf-8 -*-
"""
Created on Fri Dec 20 08:52:01 2019

@author: Malte Fritz
"""

from tespy.networks import network
from tespy.components import (sink, source, turbine, condenser,
                              pump, heat_exchanger_simple, cycle_closer)
from tespy.connections import connection, bus, ref
from tespy.tools.characteristics import char_line
from matplotlib import pyplot as plt
import numpy as np
from tespy.tools import logger
import logging
mypath = logger.define_logging(
log_path=True, log_version=True, timed_rotating={'backupCount': 4},
screen_level=logging.WARNING, screen_datefmt = "no_date")

# %% calculation of thermal efficiency (for this specific process)

def thermal_efficiency(sg, cond, turb, pump):

    # carnot efficiency

    T_m_in = sg.Q.val / sg.SQ1.val
    T_m_out = cond.Q.val / cond.SQ1.val
    eta_c = 1 - (T_m_out / T_m_in)

    # irreversibility elements

    f = T_m_out / sg.Q.val
    d_eta_t = turb.Sirr.val * f
    d_eta_p = pump.Sirr.val * f

    # thermal efficiency

    eta_th = abs(turb.P.val + pu.P.val) / sg.Q.val
    print('Thermal efficiency by definition:', round(eta_th, 4))
    print('Thermal efficiency by entropy analysis:',
          round(eta_c - (d_eta_t + d_eta_p), 4))

    # plot
    fig, ax = plt.subplots()

    x = [0, 1, 2, 3]
    eta = [eta_c, d_eta_t, d_eta_p, eta_th]
    plt.bar(x, eta, Color='#00395b', zorder=3)

    ax.set_ylabel('efficiency')
    ax.set_xticks(x)
    ax.set_xticklabels(['$\eta_c$', '$\Delta \eta_t$', '$\Delta \eta_p$',
                        '$\eta_{th}$'])
    plt.title('thermal efficiency')
    ax.grid(axis='y', zorder=0)

    rects, labels = ax.patches, [round(val, 4) for val in eta]

    for rect, label in zip(rects, labels):
        height = rect.get_height()
        ax.text(rect.get_x() + rect.get_width() / 2, height, label,
                ha='center', va='bottom')

    plt.show()

    fig.savefig('efficiency.svg')

# %% network

fluids = ['water']

nw = network(fluids=fluids)
nw.set_attr(p_unit='bar', T_unit='C', h_unit='kJ / kg',
            p_range=[0.01, 150], T_range=[5, 800], h_range=[10, 5000])

# %% components

# main components
turb = turbine('turbine')
con = condenser('condenser')
pu = pump('pump')
steam_generator = heat_exchanger_simple('steam generator')
closer = cycle_closer('cycle closer')

# cooling water
so_cw = source('cooling water inlet')
si_cw = sink('cooling water outlet')

# %% connections

# main cycle
fs_in = connection(closer, 'out1', turb, 'in1')
ws = connection(turb, 'out1', con, 'in1')
cond = connection(con, 'out1', pu, 'in1')
fw = connection(pu, 'out1', steam_generator, 'in1')
fs_out = connection(steam_generator, 'out1', closer, 'in1')
nw.add_conns(fs_in, ws, cond, fw, fs_out)

# cooling water
cw_in = connection(so_cw, 'out1', con, 'in2')
cw_out = connection(con, 'out2', si_cw, 'in1')
nw.add_conns(cw_in, cw_out)

# %% busses

# characteristic function for generator efficiency
x = np.array([0, 0.2, 0.4, 0.6, 0.8, 1, 1.2])
y = np.array([0, 0.86, 0.9, 0.93, 0.95, 0.96, 0.95])

gen = char_line(x=x, y=y)

# motor of pump has a constant efficiency
power = bus('total output power')
power.add_comps({'comp': turb, 'param': 'P', 'char': gen},
                {'comp': pu, 'char': 1 / 0.95})
nw.add_busses(power)

# %% parametrization of components

turb.set_attr(eta_s=0.9, design=['eta_s'], offdesign=['eta_s_char', 'cone'])
con.set_attr(pr1=0.5, pr2=0.98, ttd_u=5, design=['pr2', 'ttd_u'],
             offdesign=['zeta2', 'kA_char'])
pu.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char'])
steam_generator.set_attr(pr=0.95)

# %% parametrization of connections

# offdesign calculation: use parameter design for auto deactivation
# turbine inlet pressure is deriven by stodolas law, outlet pressure by
# characteristic of condenser
fs_in.set_attr(p=100, T=500, fluid={'water': 1}, design=['p'])

cw_in.set_attr(T=20, p=5, fluid={'water': 1})
cw_out.set_attr(T=30)

# total output power as input parameter
power.set_attr(P=-10e6)

# %% solving

mode = 'design'

file = 'cr'

# solve the network, print the results to prompt and save
nw.solve(mode=mode)
nw.print_results()
nw.save(file)

thermal_efficiency(steam_generator, con, turb, pu)
# change to offdesign mode
mode = 'offdesign'

# reset power input
power.set_attr(P=-9e6)

# the design file holds the information on the design case
# initialisation from previously design process
nw.solve(mode=mode, design_path='cr')
nw.print_results()

thermal_efficiency(steam_generator, con, turb, pu)

max_stars_repo_name: andresgm/oemof-examples

max_issues_repo_name: andresgm/oemof-examples

max_forks_repo_name: andresgm/oemof-examples


text:
"""
Copyright (c) 2015 SONATA-NFV and Paderborn University
ALL RIGHTS RESERVED.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Neither the name of the SONATA-NFV, Paderborn University
nor the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.

This work has been performed in the framework of the SONATA project,
funded by the European Commission under Grant number 671517 through
the Horizon 2020 and 5G-PPP programmes. The authors would like to
acknowledge the contributions of their colleagues of the SONATA
partner consortium (www.sonata-nfv.eu).
"""
import logging

import site
import time
from subprocess import Popen
import re
import requests
import os
import json

from mininet.net import Containernet
from mininet.node import Controller, DefaultController, OVSSwitch, OVSKernelSwitch, Docker, RemoteController
from mininet.cli import CLI
from mininet.link import TCLink
from mininet.clean import cleanup
import networkx as nx
from emuvim.dcemulator.monitoring import DCNetworkMonitor
from emuvim.dcemulator.node import Datacenter, EmulatorCompute, EmulatorExtSAP
from emuvim.dcemulator.resourcemodel import ResourceModelRegistrar

LOG = logging.getLogger("dcemulator.net")
LOG.setLevel(logging.DEBUG)

# default CPU period used for cpu percentage-based cfs values (microseconds)
CPU_PERIOD = 1000000

# default priority setting for added flow-rules
DEFAULT_PRIORITY = 1000
# default cookie number for new flow-rules
DEFAULT_COOKIE = 10

class DCNetwork(Containernet):
    """
    Wraps the original Mininet/Containernet class and provides
    methods to add data centers, switches, etc.

    This class is used by topology definition scripts.
    """

    def __init__(self, controller=RemoteController, monitor=False,
                 enable_learning=False, # learning switch behavior of the default ovs switches icw Ryu controller can be turned off/on, needed for E-LAN functionality
                 dc_emulation_max_cpu=1.0,  # fraction of overall CPU time for emulation
                 dc_emulation_max_mem=512,  # emulation max mem in MB
                 **kwargs):
        """
        Create an extended version of a Containernet network
        :param dc_emulation_max_cpu: max. CPU time used by containers in data centers
        :param kwargs: path through for Mininet parameters
        :return:
        """
        # members
        self.dcs = {}
        self.ryu_process = None
        #list of deployed nsds.E_Lines and E_LANs (uploaded from the dummy gatekeeper)
        self.deployed_nsds = []
        self.deployed_elines = []
        self.deployed_elans = []
        self.installed_chains = []

        # always cleanup environment before we start the emulator
        self.killRyu()
        cleanup()

        # call original Docker.__init__ and setup default controller
        Containernet.__init__(
            self, switch=OVSKernelSwitch, controller=controller, **kwargs)

        # default switch configuration
        enable_ryu_learning = False
        if enable_learning :
            self.failMode = 'standalone'
            enable_ryu_learning = True
        else:
            self.failMode = 'secure'

        # Ryu management
        if controller == RemoteController:
            # start Ryu controller
            self.startRyu(learning_switch=enable_ryu_learning)

        # add the specified controller
        self.addController('c0', controller=controller)

        # graph of the complete DC network
        self.DCNetwork_graph = nx.MultiDiGraph()

        # initialize pool of vlan tags to setup the SDN paths
        self.vlans = range(1, 4095)[::-1]

        # link to Ryu REST_API
        ryu_ip = 'localhost'
        ryu_port = '8080'
        self.ryu_REST_api = 'http://{0}:{1}'.format(ryu_ip, ryu_port)
        self.RyuSession = requests.Session()

        # monitoring agent
        if monitor:
            self.monitor_agent = DCNetworkMonitor(self)
        else:
            self.monitor_agent = None

        # initialize resource model registrar
        self.rm_registrar = ResourceModelRegistrar(
            dc_emulation_max_cpu, dc_emulation_max_mem)
        self.cpu_period = CPU_PERIOD

    def addDatacenter(self, label, metadata={}, resource_log_path=None):
        """
        Create and add a logical cloud data center to the network.
        """
        if label in self.dcs:
            raise Exception("Data center label already exists: %s" % label)
        dc = Datacenter(label, metadata=metadata, resource_log_path=resource_log_path)
        dc.net = self  # set reference to network
        self.dcs[label] = dc
        dc.create()  # finally create the data center in our Mininet instance
        LOG.info("added data center: %s" % label)
        return dc

    def addLink(self, node1, node2, **params):
        """
        Able to handle Datacenter objects as link
        end points.
        """
        assert node1 is not None
        assert node2 is not None

        # ensure type of node1
        if isinstance( node1, basestring ):
            if node1 in self.dcs:
                node1 = self.dcs[node1].switch
        if isinstance( node1, Datacenter ):
            node1 = node1.switch
        # ensure type of node2
        if isinstance( node2, basestring ):
            if node2 in self.dcs:
                node2 = self.dcs[node2].switch
        if isinstance( node2, Datacenter ):
            node2 = node2.switch
        # try to give containers a default IP
        if isinstance( node1, Docker ):
            if "params1" not in params:
                params["params1"] = {}
            if "ip" not in params["params1"]:
                params["params1"]["ip"] = self.getNextIp()
        if isinstance( node2, Docker ):
            if "params2" not in params:
                params["params2"] = {}
            if "ip" not in params["params2"]:
                params["params2"]["ip"] = self.getNextIp()
        # ensure that we allow TCLinks between data centers
        # TODO this is not optimal, we use cls=Link for containers and TCLink for data centers
        # see Containernet issue: https://github.com/mpeuster/containernet/issues/3
        if "cls" not in params:
            params["cls"] = TCLink

        link = Containernet.addLink(self, node1, node2, **params)

        # try to give container interfaces a default id
        node1_port_id = node1.ports[link.intf1]
        if isinstance(node1, Docker):
            if "id" in params["params1"]:
                node1_port_id = params["params1"]["id"]
        node1_port_name = link.intf1.name

        node2_port_id = node2.ports[link.intf2]
        if isinstance(node2, Docker):
            if "id" in params["params2"]:
                node2_port_id = params["params2"]["id"]
        node2_port_name = link.intf2.name

        # add edge and assigned port number to graph in both directions between node1 and node2
        # port_id: id given in descriptor (if available, otherwise same as port)
        # port: portnumber assigned by Containernet

        attr_dict = {}
        # possible weight metrics allowed by TClink class:
        weight_metrics = ['bw', 'delay', 'jitter', 'loss']
        edge_attributes = [p for p in params if p in weight_metrics]
        for attr in edge_attributes:
            # if delay: strip ms (need number as weight in graph)
            match = re.search('([0-9]*\.?[0-9]+)', str(params[attr]))
            if match:
                attr_number = match.group(1)
            else:
                attr_number = None
            attr_dict[attr] = attr_number

        attr_dict2 = {'src_port_id': node1_port_id, 'src_port_nr': node1.ports[link.intf1],
                      'src_port_name': node1_port_name,
                     'dst_port_id': node2_port_id, 'dst_port_nr': node2.ports[link.intf2],
                      'dst_port_name': node2_port_name}
        attr_dict2.update(attr_dict)
        self.DCNetwork_graph.add_edge(node1.name, node2.name, attr_dict=attr_dict2)

        attr_dict2 = {'src_port_id': node2_port_id, 'src_port_nr': node2.ports[link.intf2],
                      'src_port_name': node2_port_name,
                     'dst_port_id': node1_port_id, 'dst_port_nr': node1.ports[link.intf1],
                      'dst_port_name': node1_port_name}
        attr_dict2.update(attr_dict)
        self.DCNetwork_graph.add_edge(node2.name, node1.name, attr_dict=attr_dict2)

        LOG.debug("addLink: n1={0} intf1={1} -- n2={2} intf2={3}".format(
            str(node1),node1_port_name, str(node2), node2_port_name))

        return link

    def removeLink(self, link=None, node1=None, node2=None):
        """
        Remove the link from the Containernet and the networkx graph
        """
        if link is not None:
            node1 = link.intf1.node
            node2 = link.intf2.node
        assert node1 is not None
        assert node2 is not None
        Containernet.removeLink(self, link=link, node1=node1, node2=node2)
        # TODO we might decrease the loglevel to debug:
        try:
            self.DCNetwork_graph.remove_edge(node2.name, node1.name)
        except:
            LOG.warning("%s, %s not found in DCNetwork_graph." % ((node2.name, node1.name)))
        try:
            self.DCNetwork_graph.remove_edge(node1.name, node2.name)
        except:
            LOG.warning("%s, %s not found in DCNetwork_graph." % ((node1.name, node2.name)))

    def addDocker( self, label, **params ):
        """
        Wrapper for addDocker method to use custom container class.
        """
        self.DCNetwork_graph.add_node(label, type=params.get('type', 'docker'))
        return Containernet.addDocker(self, label, cls=EmulatorCompute, **params)

    def removeDocker( self, label, **params):
        """
        Wrapper for removeDocker method to update graph.
        """
        self.DCNetwork_graph.remove_node(label)
        return Containernet.removeDocker(self, label, **params)

    def addExtSAP(self, sap_name, sap_ip, **params):
        """
        Wrapper for addExtSAP method to store SAP  also in graph.
        """
        # make sure that 'type' is set
        params['type'] = params.get('type','sap_ext')
        self.DCNetwork_graph.add_node(sap_name, type=params['type'])
        return Containernet.addExtSAP(self, sap_name, sap_ip, **params)

    def removeExtSAP(self, sap_name, **params):
        """
        Wrapper for removeExtSAP method to remove SAP  also from graph.
        """
        self.DCNetwork_graph.remove_node(sap_name)
        return Containernet.removeExtSAP(self, sap_name)

    def addSwitch( self, name, add_to_graph=True, **params ):
        """
        Wrapper for addSwitch method to store switch also in graph.
        """

        # add this switch to the global topology overview
        if add_to_graph:
            self.DCNetwork_graph.add_node(name, type=params.get('type','switch'))

        # set the learning switch behavior
        if 'failMode' in params :
            failMode = params['failMode']
        else :
            failMode = self.failMode

        s = Containernet.addSwitch(self, name, protocols='OpenFlow10,OpenFlow12,OpenFlow13', failMode=failMode, **params)

        return s

    def getAllContainers(self):
        """
        Returns a list with all containers within all data centers.
        """
        all_containers = []
        for dc in self.dcs.itervalues():
            all_containers += dc.listCompute()
        return all_containers

    def start(self):
        # start
        for dc in self.dcs.itervalues():
            dc.start()
        Containernet.start(self)

    def stop(self):

        # stop the monitor agent
        if self.monitor_agent is not None:
            self.monitor_agent.stop()

        # stop emulator net
        Containernet.stop(self)

        # stop Ryu controller
        self.killRyu()

    def CLI(self):
        CLI(self)

    def setLAN(self, vnf_list):
        """
        setup an E-LAN network by assigning the same VLAN tag to each DC interface of the VNFs in the E-LAN

        :param vnf_list: names of the VNFs in this E-LAN  [{name:,interface:},...]
        :return:
        """
        src_sw = None
        src_sw_inport_nr = 0
        src_sw_inport_name = None

        # get a vlan tag for this E-LAN
        vlan = self.vlans.pop()

        for vnf in vnf_list:
            vnf_src_name = vnf['name']
            vnf_src_interface = vnf['interface']

            # check if port is specified (vnf:port)
            if vnf_src_interface is None:
                # take first interface by default
                connected_sw = self.DCNetwork_graph.neighbors(vnf_src_name)[0]
                link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
                vnf_src_interface = link_dict[0]['src_port_id']

            for connected_sw in self.DCNetwork_graph.neighbors(vnf_src_name):
                link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
                for link in link_dict:
                    if (link_dict[link]['src_port_id'] == vnf_src_interface or
                                link_dict[link]['src_port_name'] == vnf_src_interface):  # Fix: we might also get interface names, e.g, from a son-emu-cli call
                        # found the right link and connected switch
                        src_sw = connected_sw
                        src_sw_inport_nr = link_dict[link]['dst_port_nr']
                        src_sw_inport_name = link_dict[link]['dst_port_name']
                        break

            # set the tag on the dc switch interface
            LOG.debug('set E-LAN: vnf name: {0} interface: {1} tag: {2}'.format(vnf_src_name, vnf_src_interface,vlan))
            switch_node = self.getNodeByName(src_sw)
            self._set_vlan_tag(switch_node, src_sw_inport_name, vlan)

    def _addMonitorFlow(self, vnf_src_name, vnf_dst_name, vnf_src_interface=None, vnf_dst_interface=None,
                       tag=None, **kwargs):
        """
        Add a monitoring flow entry that adds a special flowentry/counter at the begin or end of a chain.
        So this monitoring flowrule exists on top of a previously defined chain rule and uses the same vlan tag/routing.
        :param vnf_src_name:
        :param vnf_dst_name:
        :param vnf_src_interface:
        :param vnf_dst_interface:
        :param tag: vlan tag to be used for this chain (same tag as existing chain)
        :param monitor_placement: 'tx' or 'rx' indicating to place the extra flowentry resp. at the beginning or end of the chain
        :return:
        """

        src_sw = None
        src_sw_inport_nr = 0
        src_sw_inport_name = None
        dst_sw = None
        dst_sw_outport_nr = 0
        dst_sw_outport_name = None

        LOG.debug("call AddMonitorFlow vnf_src_name=%r, vnf_src_interface=%r, vnf_dst_name=%r, vnf_dst_interface=%r",
                  vnf_src_name, vnf_src_interface, vnf_dst_name, vnf_dst_interface)

        #check if port is specified (vnf:port)
        if vnf_src_interface is None:
            # take first interface by default
            connected_sw = self.DCNetwork_graph.neighbors(vnf_src_name)[0]
            link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
            vnf_src_interface = link_dict[0]['src_port_id']

        for connected_sw in self.DCNetwork_graph.neighbors(vnf_src_name):
            link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
            for link in link_dict:
                if (link_dict[link]['src_port_id'] == vnf_src_interface or
                        link_dict[link]['src_port_name'] == vnf_src_interface):  # Fix: we might also get interface names, e.g, from a son-emu-cli call
                    # found the right link and connected switch
                    src_sw = connected_sw
                    src_sw_inport_nr = link_dict[link]['dst_port_nr']
                    src_sw_inport_name = link_dict[link]['dst_port_name']
                    break

        if vnf_dst_interface is None:
            # take first interface by default
            connected_sw = self.DCNetwork_graph.neighbors(vnf_dst_name)[0]
            link_dict = self.DCNetwork_graph[connected_sw][vnf_dst_name]
            vnf_dst_interface = link_dict[0]['dst_port_id']

        vnf_dst_name = vnf_dst_name.split(':')[0]
        for connected_sw in self.DCNetwork_graph.neighbors(vnf_dst_name):
            link_dict = self.DCNetwork_graph[connected_sw][vnf_dst_name]
            for link in link_dict:
                if link_dict[link]['dst_port_id'] == vnf_dst_interface or \
                        link_dict[link]['dst_port_name'] == vnf_dst_interface:  # Fix: we might also get interface names, e.g, from a son-emu-cli call
                    # found the right link and connected switch
                    dst_sw = connected_sw
                    dst_sw_outport_nr = link_dict[link]['src_port_nr']
                    dst_sw_outport_name = link_dict[link]['src_port_name']
                    break

        if not tag >= 0:
            LOG.exception('tag not valid: {0}'.format(tag))

        # get shortest path
        try:
            # returns the first found shortest path
            # if all shortest paths are wanted, use: all_shortest_paths
            path = nx.shortest_path(self.DCNetwork_graph, src_sw, dst_sw, weight=kwargs.get('weight'))
        except:
            LOG.exception("No path could be found between {0} and {1} using src_sw={2} and dst_sw={3}".format(
                vnf_src_name, vnf_dst_name, src_sw, dst_sw))
            LOG.debug("Graph nodes: %r" % self.DCNetwork_graph.nodes())
            LOG.debug("Graph edges: %r" % self.DCNetwork_graph.edges())
            for e, v in self.DCNetwork_graph.edges():
                LOG.debug("%r" % self.DCNetwork_graph[e][v])
            return "No path could be found between {0} and {1}".format(vnf_src_name, vnf_dst_name)

        LOG.info("Path between {0} and {1}: {2}".format(vnf_src_name, vnf_dst_name, path))

        current_hop = src_sw
        switch_inport_nr = src_sw_inport_nr

        cmd = kwargs.get('cmd')

        #iterate through the path to install the flow-entries
        for i in range(0,len(path)):
            current_node = self.getNodeByName(current_hop)

            if path.index(current_hop) < len(path)-1:
                next_hop = path[path.index(current_hop)+1]
            else:
                #last switch reached
                next_hop = vnf_dst_name

            next_node = self.getNodeByName(next_hop)

            if next_hop == vnf_dst_name:
                switch_outport_nr = dst_sw_outport_nr
                LOG.info("end node reached: {0}".format(vnf_dst_name))
            elif not isinstance( next_node, OVSSwitch ):
                LOG.info("Next node: {0} is not a switch".format(next_hop))
                return "Next node: {0} is not a switch".format(next_hop)
            else:
                # take first link between switches by default
                index_edge_out = 0
                switch_outport_nr = self.DCNetwork_graph[current_hop][next_hop][index_edge_out]['src_port_nr']

           # set of entry via ovs-ofctl
            if isinstance( current_node, OVSSwitch ):
                kwargs['vlan'] = tag
                kwargs['path'] = path
                kwargs['current_hop'] = current_hop
                kwargs['switch_inport_name'] = src_sw_inport_name
                kwargs['switch_outport_name'] = dst_sw_outport_name
                kwargs['skip_vlan_tag'] = True
                kwargs['pathindex'] = i

                monitor_placement = kwargs.get('monitor_placement').strip()
                # put monitor flow at the dst switch
                insert_flow = False
                if monitor_placement == 'tx' and path.index(current_hop) == 0:  # first node:
                    insert_flow = True
                # put monitoring flow at the src switch
                elif monitor_placement == 'rx' and path.index(current_hop) == len(path) - 1:  # last node:
                    insert_flow = True
                elif monitor_placement not in ['rx', 'tx']:
                    LOG.exception('invalid monitor command: {0}'.format(monitor_placement))

                if self.controller == RemoteController and insert_flow:
                    ## set flow entry via ryu rest api
                    self._set_flow_entry_ryu_rest(current_node, switch_inport_nr, switch_outport_nr, **kwargs)
                    break
                elif insert_flow:
                    ## set flow entry via ovs-ofctl
                    self._set_flow_entry_dpctl(current_node, switch_inport_nr, switch_outport_nr, **kwargs)
                    break

            # take first link between switches by default
            if isinstance( next_node, OVSSwitch ):
                switch_inport_nr = self.DCNetwork_graph[current_hop][next_hop][0]['dst_port_nr']
                current_hop = next_hop

        return "path {2} between {0} and {1}".format(vnf_src_name, vnf_dst_name, cmd)

    def setChain(self, vnf_src_name, vnf_dst_name, vnf_src_interface=None, vnf_dst_interface=None, **kwargs):
        """
        Chain 2 vnf interfaces together by installing the flowrules in the switches along their path.
        Currently the path is found using the default networkx shortest path function.
        Each chain gets a unique vlan id , so different chains wil not interfere.

        :param vnf_src_name: vnf name (string)
        :param vnf_dst_name: vnf name (string)
        :param vnf_src_interface: source interface name  (string)
        :param vnf_dst_interface: destination interface name  (string)
        :param cmd: 'add-flow' (default) to add a chain, 'del-flows' to remove a chain
        :param cookie: cookie for the installed flowrules (can be used later as identifier for a set of installed chains)
        :param match: custom match entry to be added to the flowrules (default: only in_port and vlan tag)
        :param priority: custom flowrule priority
        :param monitor: boolean to indicate whether this chain is a monitoring chain
        :param tag: vlan tag to be used for this chain (pre-defined or new one if none is specified)
        :param skip_vlan_tag: boolean to indicate if a vlan tag should be appointed to this flow or not
        :param path: custom path between the two VNFs (list of switches)
        :return: output log string
        """

        # special procedure for monitoring flows
        if kwargs.get('monitor'):

            # check if chain already exists
            found_chains = [chain_dict for chain_dict in self.installed_chains if
             (chain_dict['vnf_src_name'] == vnf_src_name and chain_dict['vnf_src_interface'] == vnf_src_interface
             and chain_dict['vnf_dst_name'] == vnf_dst_name and chain_dict['vnf_dst_interface'] == vnf_dst_interface)]

            if len(found_chains) > 0:
                # this chain exists, so need an extra monitoring flow
                # assume only 1 chain per vnf/interface pair
                LOG.debug('*** installing monitoring chain on top of pre-defined chain from {0}:{1} -> {2}:{3}'.
                            format(vnf_src_name, vnf_src_interface, vnf_dst_name, vnf_dst_interface))
                tag = found_chains[0]['tag']
                ret = self._addMonitorFlow(vnf_src_name, vnf_dst_name, vnf_src_interface, vnf_dst_interface,
                                     tag=tag, table_id=0, **kwargs)
                return ret
            else:
                # no chain existing (or E-LAN) -> install normal chain
                LOG.warning('*** installing monitoring chain without pre-defined NSD chain from {0}:{1} -> {2}:{3}'.
                            format(vnf_src_name, vnf_src_interface, vnf_dst_name, vnf_dst_interface))
                pass

        cmd = kwargs.get('cmd', 'add-flow')
        if cmd == 'add-flow' or cmd == 'del-flows':
            ret = self._chainAddFlow(vnf_src_name, vnf_dst_name, vnf_src_interface, vnf_dst_interface, **kwargs)
            if kwargs.get('bidirectional'):
                if kwargs.get('path') is not None:
                    kwargs['path'] = list(reversed(kwargs.get('path')))
                ret = ret +'\n' + self._chainAddFlow(vnf_dst_name, vnf_src_name, vnf_dst_interface, vnf_src_interface, **kwargs)

        else:
            ret = "Command unknown"

        return ret

    def _chainAddFlow(self, vnf_src_name, vnf_dst_name, vnf_src_interface=None, vnf_dst_interface=None, **kwargs):

        src_sw = None
        src_sw_inport_nr = 0
        src_sw_inport_name = None
        dst_sw = None
        dst_sw_outport_nr = 0
        dst_sw_outport_name = None

        LOG.debug("call chainAddFlow vnf_src_name=%r, vnf_src_interface=%r, vnf_dst_name=%r, vnf_dst_interface=%r",
                  vnf_src_name, vnf_src_interface, vnf_dst_name, vnf_dst_interface)

        #check if port is specified (vnf:port)
        if vnf_src_interface is None:
            # take first interface by default
            connected_sw = self.DCNetwork_graph.neighbors(vnf_src_name)[0]
            link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
            vnf_src_interface = link_dict[0]['src_port_id']

        for connected_sw in self.DCNetwork_graph.neighbors(vnf_src_name):
            link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
            for link in link_dict:
                if (link_dict[link]['src_port_id'] == vnf_src_interface or
                        link_dict[link]['src_port_name'] == vnf_src_interface):  # Fix: we might also get interface names, e.g, from a son-emu-cli call
                    # found the right link and connected switch
                    src_sw = connected_sw
                    src_sw_inport_nr = link_dict[link]['dst_port_nr']
                    src_sw_inport_name = link_dict[link]['dst_port_name']
                    break

        if vnf_dst_interface is None:
            # take first interface by default
            connected_sw = self.DCNetwork_graph.neighbors(vnf_dst_name)[0]
            link_dict = self.DCNetwork_graph[connected_sw][vnf_dst_name]
            vnf_dst_interface = link_dict[0]['dst_port_id']

        vnf_dst_name = vnf_dst_name.split(':')[0]
        for connected_sw in self.DCNetwork_graph.neighbors(vnf_dst_name):
            link_dict = self.DCNetwork_graph[connected_sw][vnf_dst_name]
            for link in link_dict:
                if link_dict[link]['dst_port_id'] == vnf_dst_interface or \
                        link_dict[link]['dst_port_name'] == vnf_dst_interface:  # Fix: we might also get interface names, e.g, from a son-emu-cli call
                    # found the right link and connected switch
                    dst_sw = connected_sw
                    dst_sw_outport_nr = link_dict[link]['src_port_nr']
                    dst_sw_outport_name = link_dict[link]['src_port_name']
                    break

        path = kwargs.get('path')

        if path is None:
            # get shortest path
            try:
                # returns the first found shortest path
                # if all shortest paths are wanted, use: all_shortest_paths
                # path = nx.shortest_path(self.DCNetwork_graph, src_sw, dst_sw, weight=kwargs.get('weight'))

                # adjustment: transform delays to int (on copied graph) and use them for computing shortest paths
                g = self.DCNetwork_graph.copy()
                edge_delays = nx.get_edge_attributes(g, 'delay')
                int_delays = {k: int(v) for (k, v) in edge_delays.items()}
                nx.set_edge_attributes(g, 'delay', int_delays)
                path = nx.shortest_path(g, src_sw, dst_sw, weight='delay')
                print('Calculated shortest path (for delay): {}'.format(path))
            except:
                LOG.exception("No path could be found between {0} and {1} using src_sw={2} and dst_sw={3}".format(
                    vnf_src_name, vnf_dst_name, src_sw, dst_sw))
                LOG.debug("Graph nodes: %r" % self.DCNetwork_graph.nodes())
                LOG.debug("Graph edges: %r" % self.DCNetwork_graph.edges())
                for e, v in self.DCNetwork_graph.edges():
                    LOG.debug("%r" % self.DCNetwork_graph[e][v])
                return "No path could be found between {0} and {1}".format(vnf_src_name, vnf_dst_name)

        LOG.info("Path between {0} and {1}: {2}".format(vnf_src_name, vnf_dst_name, path))

        current_hop = src_sw
        switch_inport_nr = src_sw_inport_nr

        # choose free vlan
        cmd = kwargs.get('cmd')
        vlan = None
        if cmd == 'add-flow':
            if kwargs.get('tag'):
                # use pre-defined tag
                vlan = kwargs.get('tag')
            else:
                vlan = self.vlans.pop()

        # store the used vlan tag to identify this chain
        if not kwargs.get('monitor'):
            chain_dict = {}
            chain_dict['vnf_src_name'] = vnf_src_name
            chain_dict['vnf_dst_name'] = vnf_dst_name
            chain_dict['vnf_src_interface'] = vnf_src_interface
            chain_dict['vnf_dst_interface'] = vnf_dst_interface
            chain_dict['tag'] = vlan
            self.installed_chains.append(chain_dict)

        #iterate through the path to install the flow-entries
        for i in range(0,len(path)):
            current_node = self.getNodeByName(current_hop)

            if i < len(path) - 1:
                next_hop = path[i + 1]
            else:
                # last switch reached
                next_hop = vnf_dst_name

            next_node = self.getNodeByName(next_hop)

            if next_hop == vnf_dst_name:
                switch_outport_nr = dst_sw_outport_nr
                LOG.info("end node reached: {0}".format(vnf_dst_name))
            elif not isinstance( next_node, OVSSwitch ):
                LOG.info("Next node: {0} is not a switch".format(next_hop))
                return "Next node: {0} is not a switch".format(next_hop)
            else:
                # take first link between switches by default
                index_edge_out = 0
                switch_outport_nr = self.DCNetwork_graph[current_hop][next_hop][index_edge_out]['src_port_nr']

           # set OpenFlow entry
            if isinstance( current_node, OVSSwitch ):
                kwargs['vlan'] = vlan
                kwargs['path'] = path
                kwargs['current_hop'] = current_hop
                kwargs['switch_inport_name'] = src_sw_inport_name
                kwargs['switch_outport_name'] = dst_sw_outport_name
                kwargs['pathindex'] = i

                if self.controller == RemoteController:
                    ## set flow entry via ryu rest api
                    self._set_flow_entry_ryu_rest(current_node, switch_inport_nr, switch_outport_nr, **kwargs)
                else:
                    ## set flow entry via ovs-ofctl
                    self._set_flow_entry_dpctl(current_node, switch_inport_nr, switch_outport_nr, **kwargs)

            # take first link between switches by default
            if isinstance( next_node, OVSSwitch ):
                switch_inport_nr = self.DCNetwork_graph[current_hop][next_hop][0]['dst_port_nr']
                current_hop = next_hop

        flow_options = {
            'priority':kwargs.get('priority', DEFAULT_PRIORITY),
            'cookie':kwargs.get('cookie', DEFAULT_COOKIE),
            'vlan':kwargs['vlan'],
            'path':kwargs['path'],
            'match_input':kwargs.get('match')
        }
        flow_options_str = json.dumps(flow_options, indent=1)
        return "success: {2} between {0} and {1} with options: {3}".format(vnf_src_name, vnf_dst_name, cmd, flow_options_str)

    def _set_flow_entry_ryu_rest(self, node, switch_inport_nr, switch_outport_nr, **kwargs):
        match = 'in_port=%s' % switch_inport_nr

        cookie = kwargs.get('cookie')
        match_input = kwargs.get('match')
        cmd = kwargs.get('cmd')
        path = kwargs.get('path')
        index = kwargs.get('pathindex')

        vlan = kwargs.get('vlan')
        priority = kwargs.get('priority', DEFAULT_PRIORITY)
        # flag to not set the ovs port vlan tag
        skip_vlan_tag = kwargs.get('skip_vlan_tag')
        # table id to put this flowentry
        table_id = kwargs.get('table_id')
        if not table_id:
            table_id = 0

        s = ','
        if match_input:
            match = s.join([match, match_input])

        flow = {}
        flow['dpid'] = int(node.dpid, 16)

        if cookie:
            flow['cookie'] = int(cookie)
        if priority:
            flow['priority'] = int(priority)

        flow['table_id'] = table_id

        flow['actions'] = []

        # possible Ryu actions, match fields:
        # http://ryu.readthedocs.io/en/latest/app/ofctl_rest.html#add-a-flow-entry
        if cmd == 'add-flow':
            prefix = 'stats/flowentry/add'
            if vlan != None:
                if index == 0:  # first node
                    # set vlan tag in ovs instance (to isolate E-LANs)
                    if not skip_vlan_tag:
                        in_port_name = kwargs.get('switch_inport_name')
                        self._set_vlan_tag(node, in_port_name, vlan)
                    # set vlan push action if more than 1 switch in the path
                    if len(path) > 1:
                        action = {}
                        action['type'] = 'PUSH_VLAN'  # Push a new VLAN tag if a input frame is non-VLAN-tagged
                        action['ethertype'] = 33024   # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame
                        flow['actions'].append(action)
                        action = {}
                        action['type'] = 'SET_FIELD'
                        action['field'] = 'vlan_vid'
                        # ryu expects the field to be masked
                        action['value'] = vlan | 0x1000
                        flow['actions'].append(action)

                elif index == len(path) - 1:  # last node
                    # set vlan tag in ovs instance (to isolate E-LANs)
                    if not skip_vlan_tag:
                        out_port_name = kwargs.get('switch_outport_name')
                        self._set_vlan_tag(node, out_port_name, vlan)
                    # set vlan pop action if more than 1 switch in the path
                    if len(path) > 1:
                        match += ',dl_vlan=%s' % vlan
                        action = {}
                        action['type'] = 'POP_VLAN'
                        flow['actions'].append(action)

                else:  # middle nodes
                    match += ',dl_vlan=%s' % vlan

            # output action must come last
            action = {}
            action['type'] = 'OUTPUT'
            action['port'] = switch_outport_nr
            flow['actions'].append(action)

        elif cmd == 'del-flows':
            prefix = 'stats/flowentry/delete'

            if cookie:
                # TODO: add cookie_mask as argument
                flow['cookie_mask'] = int('0xffffffffffffffff', 16)  # need full mask to match complete cookie

            action = {}
            action['type'] = 'OUTPUT'
            action['port'] = switch_outport_nr
            flow['actions'].append(action)

        flow['match'] = self._parse_match(match)
        self.ryu_REST(prefix, data=flow)

    def _set_vlan_tag(self, node, switch_port, tag):
        node.vsctl('set', 'port {0} tag={1}'.format(switch_port,tag))
        LOG.debug("set vlan in switch: {0} in_port: {1} vlan tag: {2}".format(node.name, switch_port, tag))

    def _set_flow_entry_dpctl(self, node, switch_inport_nr, switch_outport_nr, **kwargs):

        match = 'in_port=%s' % switch_inport_nr

        cookie = kwargs.get('cookie')
        match_input = kwargs.get('match')
        cmd = kwargs.get('cmd')
        path = kwargs.get('path')
        index = kwargs.get('pathindex')
        vlan = kwargs.get('vlan')

        s = ','
        if cookie:
            cookie = 'cookie=%s' % cookie
            match = s.join([cookie, match])
        if match_input:
            match = s.join([match, match_input])
        if cmd == 'add-flow':
            action = 'action=%s' % switch_outport_nr
            if vlan != None:
                if index == 0: # first node
                    action = ('action=mod_vlan_vid:%s' % vlan) + (',output=%s' % switch_outport_nr)
                    match = '-O OpenFlow13 ' + match
                elif index == len(path) - 1:  # last node
                    match += ',dl_vlan=%s' % vlan
                    action = 'action=strip_vlan,output=%s' % switch_outport_nr
                else:  # middle nodes
                    match += ',dl_vlan=%s' % vlan
            ofcmd = s.join([match, action])
        elif cmd == 'del-flows':
            ofcmd = match
        else:
            ofcmd = ''

        node.dpctl(cmd, ofcmd)
        LOG.info("{3} in switch: {0} in_port: {1} out_port: {2}".format(node.name, switch_inport_nr,
                                                                                switch_outport_nr, cmd))

    # start Ryu Openflow controller as Remote Controller for the DCNetwork
    def startRyu(self, learning_switch=True):
        # start Ryu controller with rest-API
        python_install_path = site.getsitepackages()[0]
        # ryu default learning switch
        #ryu_path = python_install_path + '/ryu/app/simple_switch_13.py'
        #custom learning switch that installs a default NORMAL action in the ovs switches
        dir_path = os.path.dirname(os.path.realpath(__file__))
        ryu_path = dir_path + '/son_emu_simple_switch_13.py'
        ryu_path2 = python_install_path + '/ryu/app/ofctl_rest.py'
        # change the default Openflow controller port to 6653 (official IANA-assigned port number), as used by Mininet
        # Ryu still uses 6633 as default
        ryu_option = '--ofp-tcp-listen-port'
        ryu_of_port = '6653'
        ryu_cmd = 'ryu-manager'
        FNULL = open("/tmp/ryu.log", 'w')
        if learning_switch:
            self.ryu_process = Popen([ryu_cmd, ryu_path, ryu_path2, ryu_option, ryu_of_port], stdout=FNULL, stderr=FNULL)
            LOG.debug('starting ryu-controller with {0}'.format(ryu_path))
            LOG.debug('starting ryu-controller with {0}'.format(ryu_path2))
        else:
            # no learning switch, but with rest api
            self.ryu_process = Popen([ryu_cmd, ryu_path2, ryu_option, ryu_of_port], stdout=FNULL, stderr=FNULL)
            LOG.debug('starting ryu-controller with {0}'.format(ryu_path2))
        time.sleep(1)

    def killRyu(self):
        """
        Stop the Ryu controller that might be started by son-emu.
        :return:
        """
        # try it nicely
        if self.ryu_process is not None:
            self.ryu_process.terminate()
            self.ryu_process.kill()
        # ensure its death ;-)
        Popen(['pkill', '-f', 'ryu-manager'])

    def ryu_REST(self, prefix, dpid=None, data=None):

        if dpid:
            url = self.ryu_REST_api + '/' + str(prefix) + '/' + str(dpid)
        else:
            url = self.ryu_REST_api + '/' + str(prefix)
        if data:
            req = self.RyuSession.post(url, json=data)
        else:
            req = self.RyuSession.get(url)

        # do extra logging if status code is not 200 (OK)
        if req.status_code is not requests.codes.ok:
            logging.info(
                'type {0}  encoding: {1} text: {2} headers: {3} history: {4}'.format(req.headers['content-type'],
                                                                                req.encoding, req.text,
                                                                                req.headers, req.history))
            LOG.info('url: {0}'.format(str(url)))
            if data: LOG.info('POST: {0}'.format(str(data)))
            LOG.info('status: {0} reason: {1}'.format(req.status_code, req.reason))

        if 'json' in req.headers['content-type']:
            ret = req.json()
            return ret

        ret = req.text.rstrip()
        return ret

    # need to respect that some match fields must be integers
    # http://ryu.readthedocs.io/en/latest/app/ofctl_rest.html#description-of-match-and-actions
    def _parse_match(self, match):
        matches = match.split(',')
        dict = {}
        for m in matches:
            match = m.split('=')
            if len(match) == 2:
                try:
                    m2 = int(match[1], 0)
                except:
                    m2 = match[1]

                dict.update({match[0]:m2})
        return dict

    def find_connected_dc_interface(self, vnf_src_name, vnf_src_interface=None):

        if vnf_src_interface is None:
            # take first interface by default
            connected_sw = self.DCNetwork_graph.neighbors(vnf_src_name)[0]
            link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
            vnf_src_interface = link_dict[0]['src_port_id']

        for connected_sw in self.DCNetwork_graph.neighbors(vnf_src_name):
            link_dict = self.DCNetwork_graph[vnf_src_name][connected_sw]
            for link in link_dict:
                if (link_dict[link]['src_port_id'] == vnf_src_interface or
                        link_dict[link]['src_port_name'] == vnf_src_interface):  # Fix: we might also get interface names, e.g, from a son-emu-cli call
                    # found the right link and connected switch
                    src_sw = connected_sw
                    src_sw_inport_nr = link_dict[link]['dst_port_nr']
                    src_sw_inport_name = link_dict[link]['dst_port_name']
                    return src_sw_inport_name

max_stars_repo_name: StefanUPB/vim-emu

max_issues_repo_name: StefanUPB/vim-emu

max_forks_repo_name: StefanUPB/vim-emu

reason: import networkx


text:
""" Measures for polygon meshes """

__copyright__ = "Copyright 2011, UniDesign Development Team"
__license__ = "BSD"
__authors__ = ["Stephan Gerhard <connectome@unidesign.ch>"]

import numpy as np

from ..geometry import polygonmesh

def surface_area(polygon_mesh):
    """ Computes the surface area for a polygon mesh.

    Parameters
    ----------
    polygon_mesh : ``PolygonMesh`` object

    Returns
    -------
    result : surface area

    """
    if isinstance(polygon_mesh, polygonmesh.FaceVertexMesh):
        print("A FaceVertex Mesh")
        result = 0.0
        for face in polygon_mesh.faces:
            v1, v2, v3 = face
            result += 0.5 * abs(np.linalg.norm(
                np.cross(
                    polygon_mesh.vertices[v2]-polygon_mesh.vertices[v1],
                    polygon_mesh.vertices[v3]-polygon_mesh.vertices[v1] )))
        return result

    return None

max_stars_repo_name: unidesigner/unidesign

max_issues_repo_name: unidesigner/unidesign

max_forks_repo_name: unidesigner/unidesign


text:
import cv2
import numpy as np
import numpy
import imutils
from math import sqrt
import os
from time import gmtime , strftime
def minimum_value(pair, dictionary={}):  # intentional dangerous default value
    if pair not in dictionary:
        #dictionary[pair] = pair[0] ** 2 + pair[1] ** 2
        dictionary[pair]=sqrt(pow(pair[0], 2) + pow(pair[1], 2))
        # if np.array_equal(mask, blue_mask):
        #     print ('Robot', (int(XX), int(YY)))
    else :
        pass
        #print "Waiting..."
    return dictionary[pair]
#
# def dist(tuple):
#     return sqrt(pow(tuple[0], 2) + pow(tuple[1], 2))
#
# def sorting_func(first, second):
#     import pdb
#     pdb.set_trace()
#     if dist(first) < dist(second):
#         return 1
#     elif dist(second) < dist(first):
#         return -1
#     else:
#         return 0
counter =0
cap = cv2.VideoCapture(0)
while cap.isOpened():
    ret, frame = cap.read()
    #################################____________________Converting the Image to HSV and MASKING the image ______________________#####################################
    ORANGE_MIN = np.array([40, 40, 60], np.uint8)
    ORANGE_MAX = np.array([50, 70, 80], np.uint8)
    hsv_img = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    Conv_hsv_Gray = cv2.cvtColor(hsv_img, cv2.COLOR_BGR2GRAY)
    mask_inv = cv2.bitwise_not(Conv_hsv_Gray)
    # define range of blue color in HSV
    lower_blue = np.array([100, 70, 50])
    upper_blue = np.array([130, 255, 255])
    lower_green = np.array([50, 50, 140])
    upper_green = np.array([100, 255, 255])
    Lower_black = np.array([0, 0, 0])
    # upper_black= np.array([180, 255, 40])
    # upper_black= np.array([140, 140, 150])
    # upper_black= np.array([140, 140, 140])
    upper_black = np.array([140, 140, 140])
    Lower_RED=np.array([10,255,255])
    Upper_RED=np.array([179,255,255])
    # lower_white = np.array([0,0,0])
    # upper_white = np.array([0,0,200])

    sensitivity = 20
    lower_white = np.array([0, 0, 255 - sensitivity])
    upper_white = np.array([255, sensitivity, 255])
    black_mask = cv2.inRange(hsv_img, Lower_black, upper_black)
    blue_mask = cv2.inRange(hsv_img, lower_blue, upper_blue)
    green_mask = cv2.inRange(hsv_img, lower_green, upper_green) # I have the Green threshold image.
    red_mask = cv2.inRange(hsv_img, Lower_RED, Upper_RED) # I have the Green threshold image.
    #mask = blue_mask + black_mask
    mask = blue_mask
    # if ( counter<400):
    #     mask = green_mask
    # else :
    #     mask= blue_mask
    # find contours in the thresholded image
    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if imutils.is_cv2() else cnts[1]
    obj_list = []
    obj_list2 = []

    dict = []
    dict2 = []

    bla=[]
    bla2=[]

    L=[]
    L2=[]

    Robot=[]
    Robot2=[]

    # loop over the contours
    for c in cnts:
        # compute the center of the contour
        M = cv2.moments(c)
        if M["m00"] != 0:
            cX = int(M["m10"] / M["m00"])
            cY = int(M["m01"] / M["m00"])
        else:
            cX, cY = 0, 0
        ((x, y), radius) = cv2.minEnclosingCircle(c)
        XX = int(x) / 6.2
        YY = int(y) / 4.8
        w = int(XX), int(YY)
        L=[(int(XX),int(YY))]
        # draw the contour and center of the shape on the image
        # if cX >10 and cY>10:
        if radius >60 and radius < 100:
            ((x, y), radius) = cv2.minEnclosingCircle(c)

            aTargetDictionary = {}
            List10 = [(radius)]
            # List11 = ['obj1','obj2','obj3','obj4','obj5','obj6','obj7','obj8','obj9','obj10','obj11','obj12','obj13','obj14','obj15','obj16','obj17','obj18','obj19','obj20' \
            #          ' obj21','obj22','obj23','obj24','obj25','obj26','obj27','obj28','obj29','obj30','obj31','obj32','obj33',
            #           'obj34','obj35','obj36','obj37','obj38','obj39','obj40']
            List11 = ['obj1', 'obj2', 'obj3', 'obj4', 'obj5']

            obj_list.append((int(x), int(y)))
            dict.append((int(XX),int(YY)))
            Mines_locations=dict
            yarab = {k: v for k, v in zip(List11, obj_list)}
            #yarab = {k: v for k, v in zip(List11, dict)}

            #########################                    Applying the Minmum Path Sorting               #####################################################################
            bla = sorted(dict, key=minimum_value)

            print "BLUE", bla
            cv2.circle(frame, (int(x), int(y)), int(radius),
                       (0, 0, 255), 2)
            cv2.circle(frame, (cX, cY), 2, (255, 255, 255), -1)

            cv2.putText(frame, (str(w)), (cX - 20, cY - 20),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
    cv2.imshow('frame', frame)

            # cv2.putText(frame, "center x,y".format(cX, cY), (cX - 20, cY - 20),
            #                       cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

    dodo = frame
    cnts2 = cv2.findContours(green_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts2 = cnts2[0] if imutils.is_cv2() else cnts2[1]

            #cv2.imshow('dodo', dodo)
            ################################################_____Ya_rab####################################
    for c2 in cnts2:
                # compute the center of the contour
                M2 = cv2.moments(c2)
                if M2["m00"] != 0:
                    cX2 = int(M2["m10"] / M2["m00"])
                    cY2 = int(M2["m01"] / M2["m00"])
                else:
                    cX2, cY2 = 0, 0
                ((x2, y2), radius2) = cv2.minEnclosingCircle(c2)
                XX2 = int(x2) / 6.2
                YY2 = int(y2) / 4.8
                w2 = int(XX2), int(YY2)
                L2 = [(int(XX2), int(YY2))]
                # draw the contour and center of the shape on the image
                # if cX >10 and cY>10:
                if radius2 > 60 and radius2< 100:
                    ((x2, y2), radius2) = cv2.minEnclosingCircle(c2)
                    #print x2,y2

                    aTargetDictionary2 = {}
                    List102 = [(radius2)]
                    # List11 = ['obj1','obj2','obj3','obj4','obj5','obj6','obj7','obj8','obj9','obj10','obj11','obj12','obj13','obj14','obj15','obj16','obj17','obj18','obj19','obj20' \
                    #          ' obj21','obj22','obj23','obj24','obj25','obj26','obj27','obj28','obj29','obj30','obj31','obj32','obj33',
                    #           'obj34','obj35','obj36','obj37','obj38','obj39','obj40']
                    List112 = ['obj1', 'obj2', 'obj3', 'obj4', 'obj5']

                    obj_list2.append((int(x2), int(y2)))
                    #dict2.append((int(XX2), int(YY2)))
                    dict2.append((int(XX2), int(YY2)))
                    Mines_locations2 = dict2
                    yarab2 = {k: v for k, v in zip(List112, obj_list2)}
                    # yarab = {k: v for k, v in zip(List11, dict)}

                    #########################                    Applying the Minmum Path Sorting               #####################################################################
                    bla2 = sorted(dict2, key=minimum_value)
                    print "GREEEN", dict2

                    cv2.circle(dodo, (int(x2), int(y2)), int(radius2),
                               (0, 0, 255), 2)
                    cv2.circle(dodo, (cX2, cY2), 2, (255, 255, 255), -1)

                    cv2.putText(dodo, (str(w2)), (cX2 - 20, cY2 - 20),
                                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

    cv2.imshow('dodo', dodo)

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

#cv2.imshow('frame', frame)
    #counter=counter+1
    #print counter

    # cv2.imshow('mask', mask)
    # cv2.imshow('result', res)

    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

cap.release()


text:
from datetime import date, timedelta
import json
import os
import dirtyjson
import requests
import numpy as np

"""
Example
-------

from dividend_chaser.workers.stock_universe_worker import StockUniverseWorker
StockUniverseWorker.dump()

"""

class StockUniverseWorker:
  data_dir = 'data/'
  filename = f"{data_dir}/stocks.json"
  url = 'https://www.thestreet.com/util/divs.jsp'
  """ Worker responsible for analyzing the whole universe of stocks with dividends
  """

  @classmethod
  def loadStocks(cls):
    with open(StockUniverseWorker.filename) as file:
      obj = json.load(file)
      return obj

  @classmethod
  def dump(cls, start_date="2019-01-01", end_date="2019-12-31"):
    """
    Returns
    -------
    List of all stocks written to file
    """
    print(f"Writing to {StockUniverseWorker.filename}")
    stocks = StockUniverseWorker().get_all_dividends(start_date, end_date)
    stocks = list(np.unique(stocks))
    if not os.path.exists(StockUniverseWorker.data_dir):
      os.makedirs(StockUniverseWorker.data_dir)
    with open(StockUniverseWorker.filename, 'w') as fp:
      json.dump(stocks, fp)

    return stocks

  def get_all_dividends(self, start, end):
    start_date = date.fromisoformat(start)
    end_date = date.fromisoformat(end)

    d = start_date
    stocks = []
    while d < end_date:
      stocks = stocks + self._get_dividend_stocks_for_date(d)
      d = d + timedelta(days=1)

    return stocks

  def _get_dividend_stocks_for_date(self, target_date: date):
    date_str = target_date.strftime("%m_%d_%Y")
    url = f"{StockUniverseWorker.url}?date={date_str}"
    r = requests.get(url=url)
    content = r.content.decode("utf-8")

    stocks = []
    print(f"Date: {date_str}")
    if(content == ""):
      print("No dividends")
    else:
      parsed = dirtyjson.loads(content)
      results = parsed.get("results")
      for obj in results:
        symbol = obj.get("symbol")
        if(symbol.find(".") < 0):
          stocks.append(symbol)

    return stocks


text:
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np

from src.heat_pump import HeatPumpConstCOP

def plot():
    d = {
        "cop": 3.0,
        "fluid": {
            "fluid-name": "PG",
            "concentration": 20
        },
    }

    hp = HeatPumpConstCOP(d)

    x = np.arange(-3000, 3000, 100)
    y_a = [hp.simulate(m, 0.1, 15) for m in x]
    y_b = [hp.simulate(m, 0.25, 15) for m in x]
    y_c = [hp.simulate(m, 1.0, 15) for m in x]
    fig, ax = plt.subplots()
    ax.plot([-3000, 3000], [15, 15], label=r"$T_{in,src}$")
    ax.plot(x, y_a, label=r"$T_{out,src}$ $\dot{m}=0.10$ [kg/s]")
    ax.plot(x, y_b, label=r"$T_{out,src}$ $\dot{m}=0.25$ [kg/s]", linestyle="--")
    ax.plot(x, y_c, label=r"$T_{out,src}$ $\dot{m}=1.00$ [kg/s]", linestyle=":")

    ax.set_xlabel(r"$\dot{q}_{zone}$ [W]")
    ax.set_ylabel(r"$T_{out,src}$ [C]")
    ax.legend()
    ax.grid()
    f_name = Path(__file__).parent / "_heat_pump_const_cop.png"
    plt.savefig(f_name, bbox_inches="tight")

if __name__ == "__main__":
    plot()

max_stars_repo_name: mitchute/SWHE

max_issues_repo_name: mitchute/SWHE

max_forks_repo_name: mitchute/SWHE