#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@File    ：issue.py
@Author  ：Zeno
@Email   ：zhangyongjun@ones.ai
@Date    ：2022/1/5
@Desc    ：工作项测试用例数据模块
"""
from falcons.helper import mocks
from falcons.ops import generate_param

from main.params.const import ACCOUNT

def add_standard_issue():
    """添加标准工作项"""
    return generate_param({
        'issue_type': {
            'name': f'Std{mocks.serial_no()}'[:30],
            'icon': 3,
            'type': 0
        }
    })

def add_sub_issue():
    """添加子工作项"""
    return generate_param({
        'issue_type': {
            'name': f'子Sub{mocks.serial_no()}'[:30],
            'icon': 15,
            'type': 1
        }
    })

def show_issue_list():
    """显示工作项列表"""
    return generate_param({
        'issue_type': 0,
        # 'issue_type_config': 0
    })

def issue_check():
    """用于工作项检查"""
    return generate_param({
        'issue_type': 0,
        'field': 0
    })

def delete_issue():
    """删除工作项"""
    return generate_param({}, **{'issue_uuid': ''})

def copy_issue():
    """复制工作项"""
    return generate_param({
        "issue_type": {
            "name": f'CpyIssue{mocks.ones_uuid()}',
            "icon": 2,
            "type": 0
        },
        "copy_from": ''  # 原工作项UUID
    })

def add_project_issue():
    """添加工作项到项目"""
    return generate_param({
        'issue_type_uuids': [
            ''  # 工作项uuid
        ]
    }, is_project=True)

def delete_project_issue():
    """删除项目工作项"""
    return generate_param({}, is_project=True, **{'issue_uuid': ''})

def add_issue_field():
    """添加属性到工作项"""
    return generate_param({
        'field_config': {
            'field_uuid': '',  # 工作项属性UUID
            'required': False
        }
    })

def update_issue_field(issue_uuid, field_uuid, time):
    """更新工作项开始，结束时间字段"""
    return generate_param({"tasks": [
        {
            "uuid": issue_uuid,
            "field_values": [
                {
                    "field_uuid": field_uuid,
                    "type": 5,
                    "value": time
                }
            ],
            "only_edit_alone_permission_fields": True
        }
    ]})

def issue_field_config():
    """获取工作项属性配置"""
    return generate_param({}, **{'issue_uuid': ''})

def get_task_progress(task_uuid):
    return generate_param({
        "query": "\n    query TASK($key: Key) {\n      task(key: $key) {\n        \n    planStartDate\nplanEndDate\nprogress\n\n    subTaskCount\n  \n\n        issueType {\n          uuid\n        }\n        subIssueType {\n          uuid\n        }\n        project {\n          uuid\n        }\n        issueTypeScope {\n          uuid\n        }\n      }\n    }\n  ",
        "variables": {
            "key": "task-" + task_uuid
        }
    })

def copy_issue_type_config(issue_uuid: list):
    """从已有项目中复制工作项"""
    return generate_param({
        "copy_from": {
            ACCOUNT.project_uuid: issue_uuid  # 工作项类型uuid
        }
    })

# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
# 工作项类型-属性与视图-模块标签页

def tab_config_update():
    """更新模块标签页"""
    p = {"configs": []}

    for num in range(1, 10):
        p['configs'].append(
            {
                "type": num,
                "is_show": True,
                "can_hide": True
            }
        )

    return generate_param(p)

def tab_config_update1():
    return generate_param({"configs": []})

# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
# 工作项类型-工作项工作流

def issue_workflow_set_init():
    """工作项工作流设置初始状态"""
    return generate_param({
        "task_status_config": {
            "default": True
        }
    }, is_project=True)

def issue_workflow_status_add():
    """添加工作项工作流状态"""
    return generate_param({"task_status_configs": []}, is_project=True)

def issue_workflow_status_delete():
    """删除工作项工作流状态"""
    return generate_param({}, is_project=True)

def issue_workflow_transition_add():
    """添加工作项工作流步骤"""
    return generate_param({
        "transitions": [
            {
                "project_uuid": ACCOUNT.project_uuid,
                "issue_type_uuid": "JbqewS6U",
                "start_status_uuid": "LyKDyvu3",
                "end_status_uuid": "LyKDyvu3",
                "name": "进行中"
            }
        ]
    }, is_project=True)

def sort_issue_type(issue_type_uuids: list):
    """项目内工作项类型排序"""
    return generate_param({
        "issue_type_uuids": issue_type_uuids
    }, is_project=True)

def task_sort(positions: list):
    """工作项状态排序"""
    return generate_param({
        "positions": positions
    }, is_project=True)

def add_task_field(fields: list, issue_types: list):
    """添加属性到工作项类型"""
    return generate_param({
        "fields": fields,
        "global_view_config": [],
        "team_issue_types": [],
        "project_issue_types": [
            {
                "project_uuid": ACCOUNT.project_uuid,
                "issue_types": issue_types
            }
        ]
    })

def notice_rules():
    return generate_param({}, is_project=True)

def add_notice_rules():
    """新增，编辑工作项提醒"""
    return generate_param({
        "field_uuid": '',
        "action": '',
        "notice_time": '',
        "notice_types": [
            "notice_center"
        ],
        "notice_user_domains": '',
        "filter_condition": '',
        "condition": ''
    }, is_project=True)

def notice_config():
    """工作项通知参数"""
    return generate_param({
        "roles": [],
        "single_user_uuids": [],
        "role_uuids": [],
        "group_uuids": [],
        "department_uuids": [],
        "field_uuids": []
    })

def update_notice_center():
    """工作项通知 通知方式配置"""
    return generate_param({
        "notice_center": False,
        "effect_notice_center": False,
        "email": False,
        "effect_email": True,
        "wechat": False,
        "effect_wechat": False
    })

def field_sort():
    """关键属性排序"""
    return generate_param({
        "fields": [
            ''
        ]
    })

def post_action():
    """后置动作参数"""
    return generate_param({
        "transition": {
            "uuid": '',
            "issue_type_uuid": '',
            "project_uuid": ACCOUNT.project_uuid,
            "post_function": ''
        }
    }, is_project=True)

def global_post_action():
    """配置中心-后置动作参数"""
    return generate_param({
        "transition": {
            "post_function": [
                ''
            ]
        }
    })

def update_step_field(step_uuid: str, it_uuid: str, prj_uuid: str, fields: [dict]):
    """更新步骤属性"""
    return generate_param({
        "transition": {
            "uuid": step_uuid,
            "issue_type_uuid": it_uuid,
            "project_uuid": prj_uuid,
            "fields": fields
        }
    }, is_project=True)

def add_issue_permission():
    """add 工作项权限"""
    return generate_param({
        "permission_rule": {
            "context_type": "issue_type",
            "context_param": {
                "project_uuid": ACCOUNT.project_uuid,
                "issue_type_uuid": ''
            },
            "permission": '',
            "user_domain_type": '',
            "user_domain_param": ''
        }
    })

# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
# 全局配置-工作项类型
def issue_type_create(typ=0, icon=3):
    """
    参数：全局配置-新建工作项类型
    :param typ: 0 标准工作项 1 子工作项
    :param icon: 1～15
    :return:
    """
    return generate_param({
        "issue_type": {
            "name": f'it-{mocks.ones_uuid()}',
            "icon": icon,
            "type": typ
        }
    })

# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
# 全局配置-工作项-优先级

def priori_update():
    """优先级变更"""

    return generate_param({'field': ''})


import os

this_dir = os.path.dirname(os.path.abspath(__file__))

import numpy as np
import torch as T
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from gymnasium.utils.save_video import save_video
from utils.plotting import plot_learning_curve

class DQN(nn.Module):
    def __init__(self, env, lr, fc1_dims, fc2_dims, fc3_dims):
        super(DQN,self).__init__()
        self.input_dims = [env.observation_space.shape[0]]
        self.fc1_dims = fc1_dims
        self.fc2_dims = fc2_dims
        self.fc3_dims = fc3_dims
        self.n_actions = env.action_space.n
        self.fc1 = nn.Linear(*self.input_dims,self.fc1_dims)
        self.fc2 = nn.Linear(self.fc1_dims,self.fc2_dims)
        self.fc3 = nn.Linear(self.fc2_dims,self.fc3_dims)
        self.fc4 = nn.Linear(self.fc3_dims,self.n_actions)
        self.optimizer = optim.Adam(self.parameters(), lr=lr)
        self.loss = nn.HuberLoss(delta=0.8)
        self.device = T.device('cuda:0' if T.cuda.is_available() else 'cpu')
        self.to(self.device)

    def forward(self,state):
        x = F.tanh(self.fc1(state))
        x = F.tanh(self.fc2(x))
        x = F.tanh(self.fc3(x))
        actions = self.fc4(x)
        return actions

class DQNAgent():
    def __init__(self, env, n_episodes=100, gamma=0.99, epsilon=1.0, lr=1e-3, batch_size=100, buffer_size=100000, max_steps=700, eps_end=0.01, eps_dec=5e-4):
        # Setup agent
        self.env = env
        self.n_episodes = n_episodes
        self.gamma = gamma
        self.epsilon = epsilon
        self.lr = lr
        self.eps_min = eps_end
        self.eps_dec = eps_dec
        self.action_space = list(range(env.action_space.n))
        self.buffer_size = buffer_size
        self.batch_size = batch_size
        self.max_steps = max_steps
        self.mem_cnter = 0
        self.Q_eval = DQN(env, lr, fc1_dims=200, fc2_dims=200, fc3_dims=200)

        #build memory holders
        self.state_memory = np.zeros((self.buffer_size, *[env.observation_space.shape[0]]), dtype=np.float32) # build memory holder
        self.new_state_memory = np.zeros((self.buffer_size, *[env.observation_space.shape[0]]), dtype=np.float32) # build memory holder
        self.action_memory = np.zeros(self.buffer_size, dtype=np.int32)
        self.reward_memory =np.zeros(self.buffer_size, dtype=np.float32)
        self.terminal_memory = np.zeros(self.buffer_size, dtype = np.bool_)

        # Stuff for data, plots, and videos
        self.step_starting_index = 0
        self.dqn_data_path = os.path.abspath(os.path.join(this_dir, '..', '..', 'data', 'dqn'))
        self.video_path = os.path.abspath(os.path.join(self.dqn_data_path, 'videos'))
        self.plots_path = os.path.abspath(os.path.join(self.dqn_data_path, 'plots'))

    def reset_memory(self):
        self.mem_cnter = 0
        self.state_memory = np.zeros((self.buffer_size, *[self.env.observation_space.shape[0]]), dtype=np.float32)
        self.new_state_memory = np.zeros((self.buffer_size, *[self.env.observation_space.shape[0]]), dtype=np.float32)
        self.action_memory = np.zeros(self.buffer_size, dtype=np.int32)
        self.reward_memory = np.zeros(self.buffer_size, dtype=np.float32)
        self.terminal_memory = np.zeros(self.buffer_size, dtype=np.bool_)

    # Store experience into buffer
    def store_transition(self,state,action,reward,state_,terminated):
        index = self.mem_cnter % self.buffer_size # can overwrite oldest memories
        self.state_memory[index] = state
        self.new_state_memory[index] = state_
        self.reward_memory[index]=  reward
        self.terminal_memory[index] = terminated
        self.action_memory[index] = action
        self.mem_cnter += 1

    # Epsilon-Greedy Policy
    def select_action(self,observation):
        if np.random.random() > self.epsilon:
            state = T.Tensor(np.array(observation)).to(self.Q_eval.device)
            actions = self.Q_eval.forward(state)
            action = T.argmax(actions).item() # convert from tensor
        else:
            action = np.random.choice(self.action_space)
        return action

    def learn(self):

        # Just explore until the batch is full
        if self.mem_cnter < self.batch_size:
            return 0.0

        self.Q_eval.optimizer.zero_grad()

        max_mem = min(self.mem_cnter, self.buffer_size) # take the less full one
        batch = np.random.choice(max_mem, self.batch_size, replace=False) # get rid of duplicate memories for learning

        batch_index = np.arange(self.batch_size, dtype=np.int32)

        state_batch = T.tensor(self.state_memory[batch]).to(self.Q_eval.device) # turn a subset of memory into a pytorch tensor
        new_state_batch = T.tensor(self.new_state_memory[batch]).to(self.Q_eval.device)
        reward_batch = T.tensor(self.reward_memory[batch]).to(self.Q_eval.device)
        terminal_batch = T.tensor(self.terminal_memory[batch]).to(self.Q_eval.device)
        action_batch = self.action_memory[batch]

        # drive agent to max action
        q_eval = self.Q_eval.forward(state_batch)[batch_index,action_batch] # grab actions you took
        q_next = self.Q_eval.forward(new_state_batch)# get next actions
        q_next[terminal_batch] = 0.0
        q_target = reward_batch+self.gamma*T.max(q_next,dim=1)[0] # grab value not index

        loss = self.Q_eval.loss(q_target,q_eval).to(self.Q_eval.device)
        loss.backward() # back propagate

        self.Q_eval.optimizer.step()

        # decay epsilon
        self.epsilon = self.epsilon - self.eps_dec if self.epsilon > self.eps_min \
            else self.eps_min

        return loss.item()

    def train(self, msim=None):
        # Initialize metrics
        scores, losses, stds, avg_scores, avg_losses, eps_history = [], [], [], [], [], []
        best_score = float('-inf')

        # Loop over the range of the number of episodes
        for ep_index in range(self.n_episodes):
            # Initialize the experience for this episode
            score = 0
            terminated = False
            truncated = False
            obs = self.env.reset()
            s = obs[0]
            env_step = 0

            while not terminated and not truncated and env_step < self.max_steps:
                action = self.select_action(s)

                # Gather experience
                sp, r, terminated, truncated, _ = self.env.step(action)

                # Increment score
                score += r

                # Store experience into buffer
                self.store_transition(s, action, r, sp, terminated)
                loss = self.learn()

                # Setup for next iteration
                s = sp
                env_step += 1

                # Save environment rendering
                if (terminated or truncated or env_step==self.max_steps) and msim is None:
                    env_render = self.env.render()
                    save_video(
                        env_render,
                        video_folder=self.video_path,
                        fps=self.env.metadata["render_fps"],
                        name_prefix="dqn_video",
                        step_starting_index=self.step_starting_index,
                        episode_index=ep_index
                    )
                    self.step_starting_index += env_step
                    env_step = 0
                    if ep_index==self.n_episodes-1:
                        save_video(
                            env_render,
                            video_folder=self.video_path,
                            fps=self.env.metadata["render_fps"],
                            name_prefix="final_dqn_video",
                        )

            if score > best_score and msim is None:
                best_score = score
                if best_score > 100.0:
                    save_video(
                        env_render,
                        video_folder=self.video_path,
                        name_prefix=f'best_dqn_score{best_score:.2f}',
                        fps=self.env.metadata["render_fps"],
                    )

            # Store the score for this episode
            scores.append(score)
            losses.append(loss)
            eps_history.append(self.epsilon)

            # Compute average score and std over the last 25 episodes
            avg_loss = np.mean(losses[-25:])
            avg_score = np.mean(scores[-25:])
            avg_scores.append(avg_score)
            avg_losses.append(avg_loss)
            std = np.std(scores[-25:])
            stds.append(std)

            print('episode', ep_index, 'score %.2f' % score,'avg score %.2f' % avg_score)

        if msim is not None:
            plot_learning_curve(list(range(1, self.n_episodes+1)), losses, avg_losses, self.plots_path + f'/loss_learning_curve_mc_{msim+1}.png', 'loss')
            plot_learning_curve(list(range(1, self.n_episodes+1)), scores, avg_scores, self.plots_path + f'/score_learning_curve_mc_{msim+1}.png', 'score')
        else:
            plot_learning_curve(list(range(1, self.n_episodes+1)), losses, avg_losses, self.plots_path + f'/loss_learning_curve.png', 'loss')
            plot_learning_curve(list(range(1, self.n_episodes+1)), scores, avg_scores, self.plots_path + f'/score_learning_curve.png', 'score')

        return scores, avg_score, std


from krita import *
from krita_stable_diffusion.interface.interfaces.horizontal_interface import HorizontalInterface
from krita_stable_diffusion.interface.interfaces.vertical_interface import VerticalInterface

class LayoutBase:
    def __init__(self, **kwargs):
        interface_kwargs = {
            "widgets": kwargs.get("widgets", []),
            "interfaces": kwargs.get("interfaces", []),
        }
        if kwargs.get("orientation", "vertical") == "vertical":
            self.layout = VerticalInterface(**interface_kwargs)
        else:
            self.layout = HorizontalInterface(**interface_kwargs)


from django.conf.urls import patterns, url

from . import views

urlpatterns = patterns('',

    url(r'^register/$',
        view=views.RegisterView.as_view(),
        name="register",
    ),

    url(r'^(?P<profile_id>[0-9]+)/$',
        view=views.ProfileDetailView.as_view(),
        name="detail",
    ),

    url(r'^(?P<profile_id>[0-9]+)/edit$',
        view=views.ProfileEditView.as_view(),
        name="edit",
    ),

)


import random

S = 'I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .'

S_split = S.split(' ')

out = []

for s in S_split:
    if len(s) > 4:
        f = s[0]
        b = s[-1]
        m = list(s[1:-1])
        random.shuffle(m)
        m = ''.join(m)
        s = f + m + b
    out.append(s)

print(' '.join(out))


def build_data_pkg(mac_rx,ip_rx,mac_sx,ip_sx,data):
    chunks = 0
    leftover = 0
    if len(data) % 4 == 0:
        chunks = len(data) // 4
    else:
        chunks = len(data) // 4
        leftover = len(data) % 4
    output = []
    for i in range(chunks):
        target = data[i*4:(i+1)*4]
        output.append(f"{mac_rx}|{ip_rx}|{mac_sx}|{ip_sx}|{i}|{target}")
    if leftover:
        target = data[-leftover:]
        output.append(f"{mac_rx}|{ip_rx}|{mac_sx}|{ip_sx}|{chunks}|{target}")
    return output

print(build_data_pkg("80:90:00:00:00:00","192.168.3.3","80:90:00:00:00:01","192.168.4.5","Hello World"))


import json

from requests import RequestException
from urllib3.exceptions import NewConnectionError

from healthchecktest import settings
import requests
import unittest

PROTOCOL = 'https' if settings.TARGET_USE_HTTPS else 'http'
PORT = settings.TARGET_PORT
HOST = settings.TARGET_HOST
PATH = settings.TARGET_PATH
TIMEOUT = settings.TARGET_TIMEOUT

class HealthCheckTestCase(unittest.TestCase):

    def setUp(self):
        self.url = '{scheme}://{host}:{port}{path}'.format(
            scheme=PROTOCOL,
            host=HOST,
            port=PORT,
            path=PATH)

    def test__healthcheck_returns_http_response(self):

        try:
            response = requests.get(self.url, timeout=TIMEOUT)
            json.dumps(response.content.decode())
            self.assertEqual(200, response.status_code, response.content.decode())
        except (RequestException, NewConnectionError) as e:
            self.fail("Could not fetch response from url %s: %s" % (self.url, e))
        except ValueError:
            self.fail('Should have received a JSON response.')


def solution(n):
    num1 = n
    num2 = 0
    str1 = str(n)
    str2 = ""
    arr1 = []
    for i in str1:
        arr1.append(i)
    arr1.sort(reverse = True)
    for i in arr1:
        str2 = str2 + i
    return int(str2)

print(solution(14328))

"""
문제 설명
함수 solution은 정수 n을 매개변수로 입력받습니다. n의 각 자릿수를 큰것부터 작은 순으로 정렬한 새로운 정수를 리턴해주세요. 예를들어 n이 118372면 873211을 리턴하면 됩니다.

제한 조건
n은 1이상 8000000000 이하인 자연수입니다.
"""


from transliterate import translit
import re

def slugify(string: str) -> str:
    return re.sub(
        r'^-+|-+$', '', re.sub(
            r'[\s_-]+', '-', re.sub(
                r'[^\w\s-]', '', translit(
                    u"" + string, "ru", reversed=True
                )
                .lower()
                .strip())))


__revision__ = "$Id: UnreliableHandicapper.py,v 1.9 2003/02/09 17:52:13 zooko Exp $"

# pyutil modules
from pyutil.humanreadable import hr

# egtp modules
from egtp import idlib

# The most reliable broker is still handicapped this much.
TUNING_FACTOR=float(2**8)

# Extra boost for publication: we want to publish to more reliable servers!!
PUB_TUNING_FACTOR=float(8)

# The least reliable broker is handicapped as much as the furthest-away broker.
MIN_RELIABILITY=TUNING_FACTOR / idlib.Largest_Distance_NativeId_Int_Space

class UnreliableHandicapper:
    def __init__(self, counterparties, our_id):
        self.counterparties = counterparties
        self.our_id = our_id

    def __call__(self, counterparty_id, metainfo, message_type, message_body, TUNING_FACTOR=TUNING_FACTOR):
        """
        for all msgtypes
        """
        if idlib.equal(counterparty_id, self.our_id):
            return 0.0  # no handicap for us, we have high self esteem
        else:
            cpty = self.counterparties.get_counterparty_object(counterparty_id)
            reliability = cpty.get_custom_stat("reliability", 1.0)
            if reliability < MIN_RELIABILITY:
                reliability = MIN_RELIABILITY
                cpty.set_reliability(reliability)

        if message_type in ('pub block', 'put blob'): # "put block" is the way it will be spelled in the future, "put blob" is the way it was spelled in the past
            return (TUNING_FACTOR * PUB_TUNING_FACTOR) / reliability
        else:
            return TUNING_FACTOR / reliability


# -*- coding: utf-8 -*-
"""
Created on Thu Jul  1 09:33:36 2021

@author: Artur Ruppel
"""
import os
import pickle
import numpy as np
import matplotlib.image as mpimg

def rgb2gray(rgb):
    return np.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140])
import matplotlib.pyplot as plt
import matplotlib.patches as patches
# from lmfit import minimize, Parameters, Model

def analyse_tfm_data(folder, stressmappixelsize):
    Dx = np.load(folder + "/Dx.npy")
    Dy = np.load(folder + "/Dy.npy")
    Tx = np.load(folder + "/Tx.npy")
    Ty = np.load(folder + "/Ty.npy")

    # calculate force amplitude
    T = np.sqrt(Tx ** 2 + Ty ** 2)

    x_end = np.shape(Dx)[1]
    y_end = np.shape(Dx)[0]
    t_end = np.shape(Dx)[2]
    cell_end = np.shape(Dx)[3]
    y_half = np.rint(y_end / 2).astype(int)
    x_half = np.rint(x_end / 2).astype(int)

    Es_density = 0.5 * (stressmappixelsize ** 2) * (Tx * Dx + Ty * Dy)

    # average over whole cell and then over left and right half
    Es = np.nansum(Es_density, axis=(0, 1))  # maps are coming from matlab calculations where x and y-axes are inverted
    Es_left = np.nansum(Es_density[:, 0:x_half, :, :], axis=(0, 1))
    Es_right = np.nansum(Es_density[:, x_half:x_end, :, :], axis=(0, 1))

    # average over first twenty frames before photoactivation
    Es_baseline = np.nanmean(Es[0:20, :], axis=0)

    # normalize strain energy by first substracting the baseline for each cell and then dividing by the average baseline
    relEs = (Es - np.nanmean(Es[0:20], axis=0)) / np.nanmean(Es[0:20], axis=(0, 1))
    relEs_left = (Es_left - np.nanmean(Es_left[0:20], axis=0)) / np.nanmean(Es_left[0:20], axis=(0, 1))
    relEs_right = (Es_right - np.nanmean(Es_right[0:20], axis=0)) / np.nanmean(Es_right[0:20], axis=(0, 1))

    # calculate total force in x- and y-direction
    Fx = np.nansum(abs(Tx), axis=(0, 1)) * (stressmappixelsize ** 2)
    Fy = np.nansum(abs(Ty), axis=(0, 1)) * (stressmappixelsize ** 2)

    # calculate force angle
    force_angle = np.arctan(np.divide(Fy, Fx)) * 360 / (2 * np.pi)
    force_angle_baseline = np.nanmean(force_angle[0:20, :], axis=0)

    # calculate cell-cell force
    Fx_left = np.nansum(Tx[:, 0:x_half, :, :], axis=(0, 1)) * (stressmappixelsize ** 2)
    Fx_right = np.nansum(Tx[:, x_half:x_end, :, :], axis=(0, 1)) * (stressmappixelsize ** 2)
    F_cellcell = Fx_left - Fx_right

    # calculate sigma_x for contour model by integrating the x-forces in the center of the TFM map and dividing by the height of the window
    sigmawindow = 24  # The x componenent of the force is calculated on a window of this width in pixel in the center of the TFM map
    # The x component of the force is summed up on a window from the edge minus sigmadistance_from_border to the center minus sigmadistance_from_center
    sigmadistance_from_center = 18
    sigmadistance_from_border = 18
    x_window = x_half - sigmadistance_from_center - sigmadistance_from_border

    # the other aspect ratios require different window parameters
    if "1to2" in folder:
        sigmawindow = 12  # The x componenent of the force is calculated on a window of this width in pixel in the center of the TFM map
        # The x component of the force is summed up on a window from the edge minus sigmadistance_from_border to the center minus sigmadistance_from_center
        sigmadistance_from_center = 20
        sigmadistance_from_border = 4
        x_window = x_half - sigmadistance_from_center - sigmadistance_from_border

    if "2to1" in folder:
        sigmawindow = 36  # The x componenent of the force is calculated on a window of this width in pixel in the center of the TFM map
        # The x component of the force is summed up on a window from the edge minus sigmadistance_from_border to the center minus sigmadistance_from_center
        sigmadistance_from_center = 8
        sigmadistance_from_border = 24
        x_window = x_half - sigmadistance_from_center - sigmadistance_from_border

    # plop = Tx[:,:,0,0]
    # plop[y_half - int(sigmawindow / 2):y_half + int(sigmawindow / 2), sigmadistance_from_border:x_half - sigmadistance_from_center] = 10
    # plt.imshow(plop)
    # plt.show()

    sigma_x_left = \
        np.nanmean(
            Tx[y_half - int(sigmawindow / 2):y_half + int(sigmawindow / 2), sigmadistance_from_border:x_half - sigmadistance_from_center, :,
            :], axis=(0, 1)) / x_window * stressmappixelsize
    sigma_x_right = \
        np.nansum(Tx[y_half - int(sigmawindow / 2):y_half + int(sigmawindow / 2),
                  x_half + sigmadistance_from_center:x_end - sigmadistance_from_border, :, :],
                  axis=(0, 1)) / x_window * stressmappixelsize

    sigma_x = (sigma_x_left - sigma_x_right) / 2

    # in some rare cases the surface tension value is negative due to high noise in the TFM map. This messes up further analysis so I set it to a small, positive value
    for c in range(sigma_x.shape[0]):
        for t in range(sigma_x.shape[1]):
            if sigma_x[c, t] < 0:
                sigma_x[c, t] = 0.1e-3

    # average over first twenty frames before photoactivation
    sigma_x_baseline = np.nanmean(sigma_x[0:20, :], axis=0)

    # calculate relative energy increase
    REI = relEs[32, :] - relEs[20, :]
    REI_left = relEs_left[32, :] - relEs_left[20, :]
    REI_right = relEs_right[32, :] - relEs_right[20, :]

    # calculate corner averages
    Fx_topleft = np.zeros((t_end, cell_end))
    Fx_topright = np.zeros((t_end, cell_end))
    Fx_bottomright = np.zeros((t_end, cell_end))
    Fx_bottomleft = np.zeros((t_end, cell_end))
    Fy_topleft = np.zeros((t_end, cell_end))
    Fy_topright = np.zeros((t_end, cell_end))
    Fy_bottomright = np.zeros((t_end, cell_end))
    Fy_bottomleft = np.zeros((t_end, cell_end))

    # find force peak and sum up all values within radius r
    r = 12  # ~10 µM
    x = np.arange(0, x_half)
    y = np.arange(0, y_half)
    for cell in np.arange(cell_end):
        # find peak in first frame
        T_topleft = T[0:y_half, 0:x_half, 0, cell]
        T_topleft_max = np.where(T_topleft == np.amax(T_topleft))

        T_topright = T[0:y_half, x_half:x_end, 0, cell]
        T_topright_max = np.where(T_topright == np.amax(T_topright))

        T_bottomleft = T[y_half:y_end, 0:x_half, 0, cell]
        T_bottomleft_max = np.where(T_bottomleft == np.amax(T_bottomleft))

        T_bottomright = T[y_half:y_end, x_half:x_end, 0, cell]
        T_bottomright_max = np.where(T_bottomright == np.amax(T_bottomright))
        for t in np.arange(t_end):
            mask_topleft = (x[np.newaxis, :] - T_topleft_max[1]) ** 2 + (
                    y[:, np.newaxis] - T_topleft_max[0]) ** 2 < r ** 2
            Fx_topleft[t, cell] = np.nansum(Tx[0:y_half, 0:x_half, t, cell] * mask_topleft) * stressmappixelsize ** 2 \
                                  - sigma_x[t, cell] * r * stressmappixelsize  # correcting for the contribution of the surface tension
            Fy_topleft[t, cell] = np.nansum(Ty[0:y_half, 0:x_half, t, cell] * mask_topleft) * stressmappixelsize ** 2

            mask_topright = (x[np.newaxis, :] - T_topright_max[1]) ** 2 + (
                    y[:, np.newaxis] - T_topright_max[0]) ** 2 < r ** 2
            Fx_topright[t, cell] = np.nansum(
                Tx[0:y_half, x_half:x_end, t, cell] * mask_topright) * stressmappixelsize ** 2 \
                                   - sigma_x[t, cell] * r * stressmappixelsize  # correcting for the contribution of the surface tension
            Fy_topright[t, cell] = np.nansum(
                Ty[0:y_half, x_half:x_end, t, cell] * mask_topright) * stressmappixelsize ** 2

            mask_bottomleft = (x[np.newaxis, :] - T_bottomleft_max[1]) ** 2 + (
                    y[:, np.newaxis] - T_bottomleft_max[0]) ** 2 < r ** 2
            Fx_bottomleft[t, cell] = np.nansum(
                Tx[y_half:y_end, 0:x_half, t, cell] * mask_bottomleft) * stressmappixelsize ** 2 \
                                     - sigma_x[t, cell] * r * stressmappixelsize  # correcting for the contribution of the surface tension
            Fy_bottomleft[t, cell] = np.nansum(
                Ty[y_half:y_end, 0:x_half, t, cell] * mask_bottomleft) * stressmappixelsize ** 2

            mask_bottomright = (x[np.newaxis, :] - T_bottomright_max[1]) ** 2 + (
                    y[:, np.newaxis] - T_bottomright_max[0]) ** 2 < r ** 2
            Fx_bottomright[t, cell] = np.nansum(
                Tx[y_half:y_end, x_half:x_end, t, cell] * mask_bottomright) * stressmappixelsize ** 2 \
                                      - sigma_x[t, cell] * r * stressmappixelsize  # correcting for the contribution of the surface tension
            Fy_bottomright[t, cell] = np.nansum(
                Ty[y_half:y_end, x_half:x_end, t, cell] * mask_bottomright) * stressmappixelsize ** 2

    data = {"Dx": Dx, "Dy": Dy, "Tx": Tx, "Ty": Ty, "sigma_x": sigma_x, "sigma_x_baseline": sigma_x_baseline,
            "Fx_topleft": Fx_topleft, "Fx_topright": Fx_topright, "Fx_bottomright": Fx_bottomright,
            "Fx_bottomleft": Fx_bottomleft,
            "Fy_topleft": Fy_topleft, "Fy_topright": Fy_topright, "Fy_bottomright": Fy_bottomright,
            "Fy_bottomleft": Fy_bottomleft,
            "Es": Es, "Es_left": Es_left, "Es_right": Es_right, "Es_baseline": Es_baseline,
            "relEs": relEs, "relEs_left": relEs_left, "relEs_right": relEs_right,
            "REI": REI, "REI_left": REI_left, "REI_right": REI_right,
            "Fx": Fx, "Fy": Fy, "force_angle": force_angle, "force_angle_baseline": force_angle_baseline,
            "F_cellcell": F_cellcell}

    return data

def analyse_msm_data(folder):
    sigma_xx = np.load(folder + "/sigma_xx.npy")
    sigma_yy = np.load(folder + "/sigma_yy.npy")
    sigma_xy = np.load(folder + "/sigma_xy.npy")
    sigma_yx = np.load(folder + "/sigma_yx.npy")
    masks = np.load(folder + "/mask.npy")

    # replace 0 with NaN to not mess up average calculations
    sigma_xx[sigma_xx == 0] = 'nan'
    sigma_yy[sigma_yy == 0] = 'nan'
    sigma_xy[sigma_xy == 0] = 'nan'
    sigma_yx[sigma_yx == 0] = 'nan'

    # calculate normal stress
    sigma_max = (sigma_xx + sigma_yy) / 2 + np.sqrt(((sigma_xx - sigma_yy) / 2) ** 2 + sigma_xy ** 2)
    sigma_min = (sigma_xx + sigma_yy) / 2 - np.sqrt(((sigma_xx - sigma_yy) / 2) ** 2 + sigma_xy ** 2)

    sigma_avg_normal = (sigma_max + sigma_min) / 2

    # calculate stress profile along x-axis.
    # I cut out the borders by multiplying with masks that describes the cell contour exactly to mitigate boundary effects
    sigma_xx_x_profile = np.nanmean(sigma_xx * masks, axis=0)
    sigma_yy_x_profile = np.nanmean(sigma_yy * masks, axis=0)
    sigma_avg_normal_x_profile = np.nanmean(sigma_avg_normal * masks, axis=0)

    x_end = np.shape(sigma_xx)[1]
    x_half = np.rint(x_end / 2).astype(int)

    # average over whole cell and then over left and right half
    sigma_xx_average = np.nanmean(sigma_xx, axis=(0, 1))  # maps are coming from matlab calculations where x and y-axes are inverted
    sigma_xx_left_average = np.nanmean(sigma_xx[:, 0:x_half, :, :], axis=(0, 1))
    sigma_xx_right_average = np.nanmean(sigma_xx[:, x_half:x_end, :, :], axis=(0, 1))
    sigma_yy_average = np.nanmean(sigma_yy, axis=(0, 1))
    sigma_yy_left_average = np.nanmean(sigma_yy[:, 0:x_half, :, :], axis=(0, 1))
    sigma_yy_right_average = np.nanmean(sigma_yy[:, x_half:x_end, :, :], axis=(0, 1))
    sigma_avg_normal_average = np.nanmean(sigma_avg_normal,
                                          axis=(0, 1))  # maps are coming from matlab calculations where x and y-axes are inverted
    sigma_avg_normal_left_average = np.nanmean(sigma_avg_normal[:, 0:x_half, :, :], axis=(0, 1))
    sigma_avg_normal_right_average = np.nanmean(sigma_avg_normal[:, x_half:x_end, :, :], axis=(0, 1))

    # average over first twenty frames before photoactivation
    sigma_xx_baseline = np.nanmean(sigma_xx_average[0:20, :], axis=0)
    sigma_yy_baseline = np.nanmean(sigma_yy_average[0:20, :], axis=0)

    sigma_xx_x_profile_baseline = np.nanmean(sigma_xx_x_profile[:, 0:20, :], axis=1)
    sigma_yy_x_profile_baseline = np.nanmean(sigma_yy_x_profile[:, 0:20, :], axis=1)
    sigma_avg_normal_x_profile_baseline = np.nanmean(sigma_avg_normal_x_profile[:, 0:20, :], axis=1)

    # normalize stesses by first substracting the baseline for each cell and then dividing by the average baseline
    relsigma_xx = (sigma_xx_average - np.nanmean(sigma_xx_average[0:20], axis=0)) / np.nanmean(sigma_xx_average[0:20], axis=(0, 1))
    relsigma_xx_left = \
        (sigma_xx_left_average - np.nanmean(sigma_xx_left_average[0:20], axis=0)) / np.nanmean(sigma_xx_left_average[0:20], axis=(0, 1))
    relsigma_xx_right = \
        (sigma_xx_right_average - np.nanmean(sigma_xx_right_average[0:20], axis=0)) / np.nanmean(sigma_xx_right_average[0:20], axis=(0, 1))

    relsigma_yy = (sigma_yy_average - np.nanmean(sigma_yy_average[0:20], axis=0)) / np.nanmean(sigma_yy_average[0:20], axis=(0, 1))
    relsigma_yy_left = \
        (sigma_yy_left_average - np.nanmean(sigma_yy_left_average[0:20], axis=0)) / np.nanmean(sigma_yy_left_average[0:20], axis=(0, 1))
    relsigma_yy_right = \
        (sigma_yy_right_average - np.nanmean(sigma_yy_right_average[0:20], axis=0)) / np.nanmean(sigma_yy_right_average[0:20], axis=(0, 1))

    relsigma_avg_normal = (sigma_avg_normal_average - np.nanmean(sigma_avg_normal_average[0:20], axis=0)) / np.nanmean(
        sigma_avg_normal_average[0:20], axis=(0, 1))
    relsigma_avg_normal_left = \
        (sigma_avg_normal_left_average - np.nanmean(sigma_avg_normal_left_average[0:20], axis=0)) / np.nanmean(
            sigma_avg_normal_left_average[0:20], axis=(0, 1))
    relsigma_avg_normal_right = \
        (sigma_avg_normal_right_average - np.nanmean(sigma_avg_normal_right_average[0:20], axis=0)) / np.nanmean(
            sigma_avg_normal_right_average[0:20], axis=(0, 1))

    # calculate anisotropy coefficient
    AIC = (sigma_xx_average - sigma_yy_average) / (sigma_xx_average + sigma_yy_average)
    AIC_baseline = np.nanmean(AIC[0:20, :], axis=0)

    # calculate relative stress increase
    RSI_xx = relsigma_xx[32, :] - relsigma_xx[20, :]
    RSI_xx_left = relsigma_xx_left[32, :] - relsigma_xx_left[20, :]
    RSI_xx_right = relsigma_xx_right[32, :] - relsigma_xx_right[20, :]

    RSI_yy = relsigma_yy[32, :] - relsigma_yy[20, :]
    RSI_yy_left = relsigma_yy_left[32, :] - relsigma_yy_left[20, :]
    RSI_yy_right = relsigma_yy_right[32, :] - relsigma_yy_right[20, :]

    RSI_normal = relsigma_avg_normal[32, :] - relsigma_avg_normal[20, :]
    RSI_normal_left = relsigma_avg_normal_left[32, :] - relsigma_avg_normal_left[20, :]
    RSI_normal_right = relsigma_avg_normal_right[32, :] - relsigma_avg_normal_right[20, :]

    # calculate relative stress profile along x-axis after photoactivation
    sigma_xx_x_profile_increase = (np.median(sigma_xx_x_profile[:, 30:33, :], axis=1) - np.median(sigma_xx_x_profile[:, 0:20, :], axis=1))  # take median to mitigate outliers
    sigma_yy_x_profile_increase = (np.median(sigma_yy_x_profile[:, 30:33, :], axis=1) - np.median(sigma_yy_x_profile[:, 0:20, :], axis=1))
    sigma_avg_normal_x_profile_increase = (np.median(sigma_avg_normal_x_profile[:, 30:33, :], axis=1) - np.median(sigma_avg_normal_x_profile[:, 0:20, :], axis=1))
    # sigma_avg_normal_x_profile_increase = (sigma_avg_normal_x_profile[:, 32, :] - sigma_avg_normal_x_profile[:, 20, :])

    # SI_normal_left = np.nansum(sigma_avg_normal_x_profile_increase[0:int(sigma_avg_normal_x_profile_increase.shape[0] / 2)], axis=0)
    # SI_normal_right = np.nansum(sigma_avg_normal_x_profile_increase[int(sigma_avg_normal_x_profile_increase.shape[0] / 2):-1], axis=0)

    # replace 0 with NaN to not mess up smoothing
    sigma_avg_normal_x_profile_increase[sigma_avg_normal_x_profile_increase == 0] = 'nan'

    # quantify degree of asymmetry of the strain
    # rel_sigma_curve = sigma_avg_normal_x_profile_increase / np.nansum(np.abs(sigma_avg_normal_x_profile_increase), axis=0)

    # sigma_avg_normal_x_profile_increase_asymmetry_curve = (rel_sigma_curve - np.flipud(rel_sigma_curve))
    # sigma_increase_asymmetry_coefficient = np.nansum(sigma_avg_normal_x_profile_increase_asymmetry_curve[0:int(sigma_avg_normal_x_profile_increase_asymmetry_curve.shape[0] / 2)], axis=0)
    # sigma_increase_asymmetry_coefficient = SI_normal_right / SI_normal_left

    # find position at which stress attenuates through sigmoid fit
    # def find_stress_attenuation_position(stresscurve):
    #     def sigmoid(x, left_asymptote, right_asymptote, x0, l0):
    #         return (left_asymptote - right_asymptote) / (1 + np.exp((x - x0) / l0)) + right_asymptote
    #
    #     left_asymptote_all = np.zeros(stresscurve.shape[1])
    #     right_asymptote_all = np.zeros(stresscurve.shape[1])
    #     x0_all = np.zeros(stresscurve.shape[1])
    #     l0_all = np.zeros(stresscurve.shape[1])
    #
    #     for c in range(stresscurve.shape[1]):
    #         x = np.linspace(-40, 40, stresscurve.shape[0])  # in µm
    #         y_current = stresscurve[:, c]
    #
    #         # remove nans from the curve
    #         x1 = np.delete(x, np.argwhere(np.isnan(y_current)))
    #         y1 = np.delete(y_current, np.argwhere(np.isnan(y_current)))
    #
    #         gmodel = Model(sigmoid)
    #         result = gmodel.fit(y1, x=x1, left_asymptote=0, right_asymptote=1e-3, x0=0, l0=1)
    #
    #         left_asymptote_all[c] = result.params.valuesdict()['left_asymptote']
    #         right_asymptote_all[c] = result.params.valuesdict()['right_asymptote']
    #         x0_all[c] = result.params.valuesdict()['x0']
    #         l0_all[c] = result.params.valuesdict()['l0']
    #     return left_asymptote_all, right_asymptote_all, x0_all, l0_all

    # left_asymptote, right_asymptote, x0, l0 = find_stress_attenuation_position(sigma_avg_normal_x_profile_increase)

    # def fit_double_gaussian(stresscurve):
    #     def double_gaussian(x, peak_left, peak_right, center_left, center_right, width_left, width_right):
    #         return peak_left * np.exp(-(x - center_left) ** 2 / width_left) + peak_right * np.exp(-(x - center_right) ** 2 / width_right)
    #
    #     peak_left_all = np.zeros(stresscurve.shape[1])
    #     peak_right_all = np.zeros(stresscurve.shape[1])
    #
    #     for c in range(stresscurve.shape[1]):
    #         x = np.linspace(-40, 40, stresscurve.shape[0])  # in µm
    #         y_current = stresscurve[:, c]
    #
    #         # remove nans from the curve
    #         x1 = np.delete(x, np.argwhere(np.isnan(y_current)))
    #         y1 = np.delete(y_current, np.argwhere(np.isnan(y_current)))
    #
    #         gmodel = Model(double_gaussian)
    #         params = Parameters()
    #         params.add('peak_left', value=0.0005)
    #         params.add('peak_right', value=0.0005)
    #         params.add('center_left', value=-20, max=0, min=-40)
    #         params.add('center_right', value=20, max=40, min=0)
    #         params.add('width_left', value=50, min=1)
    #         params.add('width_right', value=50, min=1)
    #         result = gmodel.fit(y1, params, x=x1)
    #
    #         # y_fit = double_gaussian(x1, 0.0005, 0, -10, 10, 50, 50)
    #         plt.plot(x1, result.best_fit)
    #         plt.plot(x1, y1)
    #         plt.show()
    #
    #         peak_left_all[c] = result.params.valuesdict()['peak_left']
    #         peak_right_all[c] = result.params.valuesdict()['peak_right']
    #     return peak_left_all, peak_right_all
    #
    # sigma_peak_left, sigma_peak_right = fit_double_gaussian(sigma_avg_normal_x_profile_increase)
    #
    # relative_sigma_peak_right = sigma_peak_right / (np.abs(sigma_peak_left) + np.abs(sigma_peak_right))

    data = {"sigma_xx": sigma_xx, "sigma_yy": sigma_yy, "sigma_avg_normal": sigma_avg_normal,
            "sigma_xx_average": sigma_xx_average, "sigma_yy_average": sigma_yy_average,
            "sigma_xx_left_average": sigma_xx_left_average,
            "sigma_yy_left_average": sigma_yy_left_average,
            "sigma_xx_right_average": sigma_xx_right_average,
            "sigma_yy_right_average": sigma_yy_right_average,
            "sigma_xx_baseline": sigma_xx_baseline, "sigma_yy_baseline": sigma_yy_baseline,
            "sigma_xx_x_profile_baseline": sigma_xx_x_profile_baseline,
            "sigma_yy_x_profile_baseline": sigma_yy_x_profile_baseline,
            "sigma_avg_normal_x_profile_baseline": sigma_avg_normal_x_profile_baseline,
            "relsigma_xx": relsigma_xx, "relsigma_yy": relsigma_yy,
            "relsigma_xx_left": relsigma_xx_left, "relsigma_yy_left": relsigma_yy_left,
            "relsigma_avg_normal_left": relsigma_avg_normal_left,
            "relsigma_xx_right": relsigma_xx_right, "relsigma_yy_right": relsigma_yy_right,
            "relsigma_avg_normal_right": relsigma_avg_normal_right,
            "AIC_baseline": AIC_baseline, "AIC": AIC,
            "RSI_xx": RSI_xx, "RSI_xx_left": RSI_xx_left, "RSI_xx_right": RSI_xx_right,
            "RSI_yy": RSI_yy, "RSI_yy_left": RSI_yy_left, "RSI_yy_right": RSI_yy_right,
            "RSI_normal": RSI_normal, "RSI_normal_left": RSI_normal_left, "RSI_normal_right": RSI_normal_right,
            "sigma_xx_x_profile_increase": sigma_xx_x_profile_increase,
            "sigma_yy_x_profile_increase": sigma_yy_x_profile_increase,
            "sigma_avg_normal_x_profile_increase": sigma_avg_normal_x_profile_increase,
            }
    return data

def analyse_shape_data(folder, stressmappixelsize):
    Xtop = np.load(folder + "/Xtop.npy")
    Xbottom = np.load(folder + "/Xbottom.npy")

    Ytop = np.load(folder + "/Ytop.npy")
    Ybottom = np.load(folder + "/Ybottom.npy")

    noFrames = Xtop.shape[1]
    noCells = Xtop.shape[2]

    # I want to calculate the deformation of the contour, but the fibertracks have varying lengths, so to calculate the strain
    # I first need to interpolate them to a grid so that all tracks have the same shape
    nb_points_interpl = 50
    Xtop_interpl = np.zeros((nb_points_interpl, noFrames, noCells))
    Xbottom_interpl = np.zeros((nb_points_interpl, noFrames, noCells))

    Ytop_interpl = np.zeros((nb_points_interpl, noFrames, noCells))
    Ybottom_interpl = np.zeros((nb_points_interpl, noFrames, noCells))

    for cell in range(noCells):
        Xtop_current = Xtop[:, :, cell]
        Xbottom_current = Xbottom[:, :, cell]

        Ytop_current = Ytop[:, :, cell]
        Ybottom_current = Ybottom[:, :, cell]

        # remove zero lines
        Xtop_current = Xtop_current[~np.all(Xtop_current == 0, axis=1)]
        Xbottom_current = Xbottom_current[~np.all(Xbottom_current == 0, axis=1)]

        Ytop_current = Ytop_current[~np.all(Ytop_current == 0, axis=1)]
        Ybottom_current = Ybottom_current[~np.all(Ybottom_current == 0, axis=1)]

        # apply interpolation
        for frame in range(noFrames):
            Xtop_interpl[:, frame, cell] = np.linspace(Xtop_current[0, frame], Xtop_current[-1, frame], nb_points_interpl)
            Xbottom_interpl[:, frame, cell] = np.linspace(Xbottom_current[0, frame], Xbottom_current[-1, frame], nb_points_interpl)

            Ytop_interpl[:, frame, cell] = np.interp(Xtop_interpl[:, frame, cell], Xtop_current[:, frame], Ytop_current[:, frame])
            Ybottom_interpl[:, frame, cell] = np.interp(Xbottom_interpl[:, frame, cell], Xbottom_current[:, frame],
                                                        Ybottom_current[:, frame])

    # calculate width of the cell as function of x and t
    W = Ybottom_interpl - Ytop_interpl

    # calculate width of the cell center (where the junction is in the doublets) as function of t
    windowlength = 2
    center_left = int(nb_points_interpl / 2 - windowlength)
    center_right = int(nb_points_interpl / 2 + windowlength)
    W_center = np.nanmean(W[center_left:center_right, :, :], axis=0)
    relW_center = (W_center - np.nanmean(W_center[0:20], axis=0)) / np.nanmean(W_center[0:20])
    relW_center_end = relW_center[-1, :]

    W_center_baseline = np.nanmean(W_center[0:20, :], axis=0)

    # calculate contour strain at peak contraction
    epsilon = 1 - np.nanmean(W[:, 1:20, :], axis=1) / np.nanmean(W[:, 30:33, :], axis=1)
    rel_epsilon = epsilon / np.nansum(np.abs(epsilon), axis=0)

    # quantify degree of asymmetry of the strain
    epsilon_asymmetry_curve = (rel_epsilon - np.flipud(rel_epsilon))
    epsilon_asymmetry_coefficient = -np.nansum(epsilon_asymmetry_curve[0:int(epsilon_asymmetry_curve.shape[0] / 2)], axis=0)

    masks = np.load(folder + "/mask.npy")

    # calculate spreadingsizes with masks
    spreadingsize = (stressmappixelsize ** 2) * np.nansum(masks, axis=(0, 1))
    spreadingsize_baseline = np.nanmean(spreadingsize[0:20, :], axis=0)

    # load average actin angles
    actin_anisotropy_coefficient = np.load(folder + "/actin_anisotropy.npy").squeeze(axis=0)

    cortex_intensity_left = np.load(folder + "/cortex_intensity_left.npy")
    cortex_intensity_right = np.load(folder + "/cortex_intensity_right.npy")
    cortex_intensity = cortex_intensity_left + cortex_intensity_right

    # normalize cortex intensities by first substracting the baseline for each cell and then dividing by the average baseline
    relcortex_intensity_left = (cortex_intensity_left - np.nanmean(cortex_intensity_left[0:20, :], axis=0)) / np.nanmean(
        cortex_intensity_left[0:20, :], axis=(0, 1))
    relcortex_intensity_right = (cortex_intensity_right - np.nanmean(cortex_intensity_right[0:20, :], axis=0)) / np.nanmean(
        cortex_intensity_right[0:20, :], axis=(0, 1))
    relcortex_intensity = (cortex_intensity - np.nanmean(cortex_intensity[0:20, :], axis=0)) / np.nanmean(
        cortex_intensity[0:20, :], axis=(0, 1))

    RAI_cortex_left = relcortex_intensity_left[32, :] - relcortex_intensity_left[20, :]
    RAI_cortex_right = relcortex_intensity_right[32, :] - relcortex_intensity_right[20, :]
    RAI_cortex = relcortex_intensity[32, :] - relcortex_intensity[20, :]

    SF_intensity_left = np.load(folder + "/SF_intensity_left.npy")
    SF_intensity_right = np.load(folder + "/SF_intensity_right.npy")
    SF_intensity = SF_intensity_left + SF_intensity_right

    # normalize SF intensities by first substracting the baseline for each cell and then dividing by the average baseline
    relSF_intensity_left = (SF_intensity_left - np.nanmean(SF_intensity_left[0:20, :], axis=0)) / np.nanmean(
        SF_intensity_left[0:20, :], axis=(0, 1))
    relSF_intensity_right = (SF_intensity_right - np.nanmean(SF_intensity_right[0:20, :], axis=0)) / np.nanmean(
        SF_intensity_right[0:20, :], axis=(0, 1))
    relSF_intensity = (SF_intensity - np.nanmean(SF_intensity[0:20, :], axis=0)) / np.nanmean(
        SF_intensity[0:20, :], axis=(0, 1))

    RAI_SF_left = relSF_intensity_left[32, :] - relSF_intensity_left[20, :]
    RAI_SF_right = relSF_intensity_right[32, :] - relSF_intensity_right[20, :]
    RAI_SF = relSF_intensity[32, :] - relSF_intensity[20, :]

    data = {"Xtop": Xtop, "Xbottom": Xbottom, "Ytop": Ytop, "Ybottom": Ybottom,
            "masks": masks, "cell_width_center_baseline": W_center_baseline, "cell_width_center": W_center, "relcell_width_center": relW_center, "relcell_width_center_end": relW_center_end,
            "contour_strain": epsilon, "ASC": epsilon_asymmetry_coefficient,
            "spreadingsize": spreadingsize, "spreadingsize_baseline": spreadingsize_baseline,
            "actin_anisotropy_coefficient": actin_anisotropy_coefficient,
            "cortex_intensity": cortex_intensity, "cortex_intensity_left": cortex_intensity_left, "cortex_intensity_right": cortex_intensity_right,
            "relcortex_intensity": relcortex_intensity, "relcortex_intensity_left": relcortex_intensity_left, "relcortex_intensity_right": relcortex_intensity_right,
            "RAI_cortex": RAI_cortex, "RAI_cortex_left": RAI_cortex_left, "RAI_cortex_right": RAI_cortex_right,
            "SF_intensity": SF_intensity, "SF_intensity_left": SF_intensity_left, "SF_intensity_right": SF_intensity_right,
            "relSF_intensity": relSF_intensity, "relSF_intensity_left": relSF_intensity_left, "relSF_intensity_right": relSF_intensity_right,
            "RAI_SF": RAI_SF, "RAI_SF_left": RAI_SF_left, "RAI_SF_right": RAI_SF_right}

    return data

def main_meta_analysis(folder, title, noFrames):
    stressmappixelsize = 0.864 * 1e-6  # in meter

    folder += title

    # calculate strain energies over all cells, normalize data to baseline values etc.
    TFM_data = analyse_tfm_data(folder, stressmappixelsize)

    # calculate averages over all cells, normalize data to baseline values etc.
    MSM_data = analyse_msm_data(folder)

    # calculate spreading area and such
    shape_data = analyse_shape_data(folder, stressmappixelsize)

    print(title + ": done!")
    alldata = {"TFM_data": TFM_data, "MSM_data": MSM_data, "shape_data": shape_data}

    return alldata

if __name__ == "__main__":
    # This is the folder where all the input data is stored
    folder = "C:/Users/aruppel/Documents/_forcetransmission_in_cell_doublets_raw/"

    AR1to1dfsl = "AR1to1_doublets_full_stim_long"
    AR1to1sfsl = "AR1to1_singlets_full_stim_long"
    AR1to1dfss = "AR1to1_doublets_full_stim_short"
    AR1to1sfss = "AR1to1_singlets_full_stim_short"
    AR1to2dhs = "AR1to2_doublets_half_stim"
    AR1to1dhs = "AR1to1_doublets_half_stim"
    AR1to1shs = "AR1to1_singlets_half_stim"
    AR2to1dhs = "AR2to1_doublets_half_stim"

    # These functions perform a series of analyses and assemble a dictionary of dictionaries containing all the data that was used for plotting
    AR1to1d_fullstim_long = main_meta_analysis(folder, AR1to1dfsl, 60)
    AR1to1s_fullstim_long = main_meta_analysis(folder, AR1to1sfsl, 60)
    AR1to1d_fullstim_short = main_meta_analysis(folder, AR1to1dfss, 50)
    AR1to1s_fullstim_short = main_meta_analysis(folder, AR1to1sfss, 50)
    AR1to2d_halfstim = main_meta_analysis(folder, AR1to2dhs, 60)
    AR1to1d_halfstim = main_meta_analysis(folder, AR1to1dhs, 60)
    AR1to1s_halfstim = main_meta_analysis(folder, AR1to1shs, 60)
    AR2to1d_halfstim = main_meta_analysis(folder, AR2to1dhs, 60)

    # save dictionaries to a file using pickle
    if not os.path.exists(folder + "analysed_data"):
        os.mkdir(folder + "analysed_data")

    with open(folder + "analysed_data/AR1to1d_fullstim_long.dat", 'wb') as outfile:
        pickle.dump(AR1to1d_fullstim_long, outfile, protocol=pickle.HIGHEST_PROTOCOL)
    with open(folder + "analysed_data/AR1to1s_fullstim_long.dat", 'wb') as outfile:
        pickle.dump(AR1to1s_fullstim_long, outfile, protocol=pickle.HIGHEST_PROTOCOL)
    with open(folder + "analysed_data/AR1to1d_fullstim_short.dat", 'wb') as outfile:
        pickle.dump(AR1to1d_fullstim_short, outfile, protocol=pickle.HIGHEST_PROTOCOL)
    with open(folder + "analysed_data/AR1to1s_fullstim_short.dat", 'wb') as outfile:
        pickle.dump(AR1to1s_fullstim_short, outfile, protocol=pickle.HIGHEST_PROTOCOL)
    with open(folder + "analysed_data/AR1to2d_halfstim.dat", 'wb') as outfile:
        pickle.dump(AR1to2d_halfstim, outfile, protocol=pickle.HIGHEST_PROTOCOL)
    with open(folder + "analysed_data/AR1to1d_halfstim.dat", 'wb') as outfile:
        pickle.dump(AR1to1d_halfstim, outfile, protocol=pickle.HIGHEST_PROTOCOL)
    with open(folder + "analysed_data/AR1to1s_halfstim.dat", 'wb') as outfile:
        pickle.dump(AR1to1s_halfstim, outfile, protocol=pickle.HIGHEST_PROTOCOL)
    with open(folder + "analysed_data/AR2to1d_halfstim.dat", 'wb') as outfile:
        pickle.dump(AR2to1d_halfstim, outfile, protocol=pickle.HIGHEST_PROTOCOL)


with open('./AoCdata/2022/day5.txt', 'r') as f:
    data = f.read().split('\n\n')
cratesList = [] # lista de cratesList
lista = data[0].split('\n')
lista.pop()
aux = data[0].split('\n')[-1]
for i, j in enumerate(aux):
    if not j.isdigit():
        continue
    j = int(j)
    crates = []
    for j in lista:
        if j[i].isalpha():
            crates.append(j[i])
    cratesList.append(crates)
steps = []
for i in data[1].split('\n'):
    aux = i.replace('move','').replace('from','').replace('to','').replace(' ','')
    steps.append((int(aux[:-2]), int(aux[-2]), int(aux[-1])))
cratesList2 = cratesList.copy()
for i in steps:
    #part 1
    blocks = cratesList[i[1] - 1][:i[0]]
    cratesList[i[1] - 1] = cratesList[i[1] - 1][i[0]:]
    cratesList[i[2] - 1] = list(reversed(blocks)) + cratesList[i[2] - 1]
    #part 2
    blocks2 = cratesList2[i[1] - 1][:i[0]]
    cratesList2[i[1] - 1] = cratesList2[i[1] - 1][i[0]:]
    cratesList2[i[2] - 1] = blocks + cratesList2[i[2] - 1]
print('Problema 1:', ''.join([i[0] if i != [] else '' for i in cratesList]))
print('Problema 2:', ''.join([i[0] if i != [] else '' for i in cratesList2]))


import App
import Custom.CrazyShipAbilities.Cooldowns
import Custom.CrazyShipAbilities.Utils

MAX_NUKES_PER_PERIOD = 3
NUKE_COOLDOWN_PERIOD = 24
NUKE_PREFIX = '42km Nuke'

def Initialize(OverrideExisting):
	global Cooldown, NukeNames
	if 'Cooldown' in globals().keys() and not OverrideExisting:
		return
	Cooldown = Custom.CrazyShipAbilities.Cooldowns.ParallelCooldown(NUKE_COOLDOWN_PERIOD, MAX_NUKES_PER_PERIOD)
	NukeNames = []

def GetTitle():
	return 'Nuke'

def GetCooldownS():
	return Cooldown.GetCooldownS()

def GetNReady():
	return Cooldown.GetNReady()

def GetNCooldowns():
	return Cooldown.GetNCooldowns()

def UseAbility(pPlayer):
	if not Cooldown.IsReady():
		return

	Cooldown.Trigger()

	shipName = Custom.CrazyShipAbilities.Utils.GenChildShipName(NUKE_PREFIX, len(NukeNames), pPlayer)
	NukeNames.append(shipName)

	import MissionLib
	nuke = Custom.CrazyShipAbilities.Utils.SpawnDroneShip(
		'Probe',
		shipName,
		0,
		pPlayer,
		group = MissionLib.GetMission().GetNeutralGroup()
	)
	nuke.EnableCollisionsWith(pPlayer, 0)
	nuke.SetScale(200)

	# Allow the ship to drift
	nuke.GetImpulseEngineSubsystem().SetPowerPercentageWanted(0)
	nuke.GetShields().SetPowerPercentageWanted(0)

	originalPlayerVelocity = pPlayer.GetVelocityTG()

	nukeVelocity = Custom.CrazyShipAbilities.Utils.Unitized(pPlayer.GetWorldForwardTG())
	nukeVelocity.Scale(Custom.CrazyShipAbilities.Utils.KphToInternalGameSpeed(8000))

	playerVelocityKnockback = Custom.CrazyShipAbilities.Utils.Unitized(nukeVelocity)
	playerVelocityKnockback.Scale(-150)

	newPlayerVelocity = Custom.CrazyShipAbilities.Utils.CloneVector(playerVelocityKnockback)
	newPlayerVelocity.Add(originalPlayerVelocity)
	pPlayer.SetVelocity(newPlayerVelocity)

	nuke.SetVelocity(nukeVelocity)
	nuke.AlignToVectors(pPlayer.GetWorldForwardTG(), pPlayer.GetWorldUpTG())


############################################################
#
#dataAnalyser.py
#
############################################################
#
# Author: romano <sromanos@cern.ch>
#
# May 2013
#
# Goal:
# - Produce the evolution plots for: LV, temp, reference voltage, HV, HVset and DeltaHV
#
# Input parameters are:
#
# -> Period for data recovery
#
#
#
#############################################################

from src.ReadGenericCalibration import *
from src.oscalls import *
from src.run import *
import datetime
import time
import sys

#from ROOT import *
import ROOT

# insert HV tools
from src.HV.hvtools import *

class dataAnalyser(GenericWorker):
	"Evolution plots for all the variables stored in DCS"

	def __init__(self, ini_Date, fin_Date, mode, do_extraPlots):

		self.fin_Date = fin_Date
		self.ini_Date = ini_Date
		self.HVTool = hvtools()
		self.mode = mode
		self.do_extraPlots = do_extraPlots

	def ProcessStart(self):

		# definition of loops limits
		print('The analysis start at', datetime.datetime.now())

		max_partitions, max_modules, max_channels = 4, 64, 48

		#for the plots

		ini_volt  = 450
		end_volt = 1000
		binning_volt = (end_volt-ini_volt)*2

		ini_low_volt = 0
		end_low_volt = 20
		binning_low_volt = (end_low_volt-ini_low_volt)*2

		ini_Dvolt     = -400.5
		end_Dvolt     = 200.5
		binning_Dvolt = abs(end_Dvolt-ini_Dvolt)
		binning_Dvolt = 5*int(binning_Dvolt)

		ini_ref_volt   = 1180
		end_ref_volt   = 1280
		binning_ref_volt = (end_ref_volt-ini_ref_volt)*4

		ini_temp  = 15
		end_temp  = 40
		binning_temp = (end_temp-ini_temp)*4

		period = 1 #number of points per day

		if self.mode=='RegularJob':
			inDir = os.path.join(getResultDirectory(),'HV/files/mergefile/RegularJob')
			outDir = os.path.join(getResultDirectory(),'HV/files/results/RegularJob')
			inFile_name = 'HV_RegularJob_Merged.root'

		else:
			inDir = os.path.join(getResultDirectory(),'HV/files/mergefile/' + str(ini_Date))
			outDir = os.path.join(getResultDirectory(),'HV/files/results/'+ str(ini_Date))
			inFile_name = 'HV_' + str(ini_Date) + '_Merged.root'

		mergedFile = TFile(inDir + '/' + inFile_name,'READ')
		tree = mergedFile.Get('ZeTree')

		tree.Print()
		#print tree.GetMinimun("Date")

		n_entries = tree.GetEntries()

		# output file tree: branches definitions
		Measure     = array('f',[ 0 ])
		Reference   = array('f',[ 0 ])
		Date        = array('i',[ 0 ])

		MeasureType = array('i',[ 0 ])
		Channel     = array('i',[ 0 ])
		Module      = array('i',[ 0 ])
		Partition   = array('i',[ 0 ])

		tree.SetBranchAddress('Measure', Measure)
		tree.SetBranchAddress('Reference', Reference)
		tree.SetBranchAddress('Date', Date)

		tree.SetBranchAddress('MeasureType', MeasureType)
		tree.SetBranchAddress('Channel', Channel)
		tree.SetBranchAddress('Module', Module)
		tree.SetBranchAddress('Partition', Partition)

		# For the evolution plots

		ini_day = tree.GetMinimum("Date")
		end_day = tree.GetMaximum("Date")
		binning_day = (end_day-ini_day) / (86400 * period)
		binning_day = int(round(binning_day))

		self.HVTool.mkdir(outDir)
		outFile = TFile(outDir + '/A_histograms.root', 'RECREATE')

		outFile.mkdir('DHV')
		outFile.mkdir('HV')
		outFile.mkdir('HVset')
		outFile.mkdir('T')
		outFile.mkdir('Ref')
		outFile.mkdir('LV')
		outFile.mkdir('Time')
		outFile.cd()

		# Lists of histograms and TProfiles:

		h_means, h_sigmas, h_DHV_part, h_final_DHV_part, max_diff_part, h_HV_vs_t_part, h_DHV_vs_t_part, h_T_vs_t_part, h2_map = [], [], [], [], [], [], [], [], []
		h_HV_vs_t_mod, h_DHV_vs_t_mod, h_T_vs_t_mod = [], [], []
		h_HV, h_HV_vs_t, h_HVset, h_HVset_vs_t, h_DHV, h_DHV_vs_t, h_T, h_T_vs_t, h_LV, h_LV_vs_t, h_ref, h_ref_vs_t = [], [], [], [], [], [], [], [], [], [], [], []

		difference_date, h_intertime, h_intertime_long = [], [], [] # To study the time

		# Histrograms declaration
		for ipart in range(4): # loop in all the partitions

			part_name = self.HVTool.get_partition_name(ipart)

			# histos of means
			h_means.append(TH1F("h_means_"+part_name,"All means in partition "+part_name+";#mu_{i}; #events",150,-15,15))
			h_means[ipart].SetDirectory(0)

			# histos of sigmas
			h_sigmas.append(TH1F("h_sigmas_"+part_name,"All sigmas in partition "+part_name+";#sigma_{i}; #events",500,0,5))
			h_sigmas[ipart].SetDirectory(0)

			# histos of DHV
			h_DHV_part.append(TH1F("h_DHV_"+part_name,"#DeltaHV ("+part_name+");#DeltaHV (V); #events",binning_Dvolt,ini_Dvolt,end_Dvolt))
			h_DHV_part[ipart].SetDirectory(0)

			# histos of DHV for good channels
			h_final_DHV_part.append(TH1F("h_final_DHV_"+part_name,"#DeltaHV ("+part_name+") for Good Channels;#DeltaHV (V); #events",binning_Dvolt,ini_Dvolt,end_Dvolt))
			h_final_DHV_part[ipart].SetDirectory(0)

			# histos of Max diff
			max_diff_part.append(TH1F("h_max_diff_"+part_name,"Max diff ("+part_name+");Max diff; #events",1000,0,100))
			max_diff_part[ipart].SetDirectory(0)

			# TProfiles of HV
			h_HV_vs_t_part.append(TProfile("HV_vs_t_"+part_name,"High Voltage ("+part_name+") vs Time; Day; HV (V)",binning_day ,ini_day,end_day,ini_volt,end_volt))
			h_HV_vs_t_part[ipart].GetXaxis().SetTimeDisplay(1)
			h_HV_vs_t_part[ipart].SetDirectory(0)

			# TProfiles of DHV
			h_DHV_vs_t_part.append(TProfile("DHV_vs_t_"+part_name,"#DeltaHV ("+part_name+") vs Time; Day; #DeltaHV (V)",binning_day,ini_day,end_day,ini_Dvolt,end_Dvolt))
			h_DHV_vs_t_part[ipart].GetXaxis().SetTimeDisplay(1)
			h_DHV_vs_t_part[ipart].SetDirectory(0)

			# TProfiles of Temperatures
			h_T_vs_t_part.append(TProfile("T_vs_t_"+part_name,"T ("+part_name+") vs Time; Day; T (*C)",binning_day,ini_day,end_day,ini_temp,end_temp))
			h_T_vs_t_part[ipart].GetXaxis().SetTimeDisplay(1)
			h_T_vs_t_part[ipart].SetDirectory(0)

			# maps for good and bad channels
			h2_map.append(TH2F("Map_"+part_name,"Mapping of channels for partition "+part_name+";Module;Channel",max_modules+2,0,max_modules+2,max_channels+2,0,max_channels+2))
			h2_map[ipart].SetDirectory(0)

			h_HV_vs_t_mod.append([])
			h_DHV_vs_t_mod.append([])
			h_T_vs_t_mod.append([])

			h_HV.append([])
			h_HVset.append([])
			h_DHV.append([])
			h_T.append([])
			h_LV.append([])
			h_ref.append([])
			h_intertime.append([])
			h_intertime_long.append([])

			h_HV_vs_t.append([])
			h_HVset_vs_t.append([])
			h_DHV_vs_t.append([])
			h_T_vs_t.append([])
			h_LV_vs_t.append([])
			h_ref_vs_t.append([])

			difference_date.append([])
			for imod in range(64): # loop in all the modules

				mod_name = part_name + str(imod+1).zfill(2)

				# TProfiles of HV
				h_HV_vs_t_mod[ipart].append(TProfile("HV_vs_t_"+mod_name,"High Voltage ("+mod_name+") vs Time; Day; HV (V)",binning_day ,ini_day,end_day,ini_volt,end_volt))
				h_HV_vs_t_mod[ipart][imod].GetXaxis().SetTimeDisplay(1)
				h_HV_vs_t_mod[ipart][imod].SetDirectory(0)

				# TProfiles of DHV
				h_DHV_vs_t_mod[ipart].append(TProfile("DHV_vs_t_"+mod_name,"#DeltaHV ("+mod_name+") vs Time; Day; #DeltaHV (V)",binning_day,ini_day,end_day,ini_Dvolt,end_Dvolt))
				h_DHV_vs_t_mod[ipart][imod].GetXaxis().SetTimeDisplay(1)
				h_DHV_vs_t_mod[ipart][imod].SetDirectory(0)

				# TProfiles of Temperatures
				h_T_vs_t_mod[ipart].append(TProfile("T_vs_t_"+mod_name,"T ("+mod_name+") vs Time; Day; T (*C)",binning_day,ini_day,end_day,ini_temp,end_temp))
				h_T_vs_t_mod[ipart][imod].GetXaxis().SetTimeDisplay(1)
				h_T_vs_t_mod[ipart][imod].SetDirectory(0)

				h_HV[ipart].append([])
				h_HVset[ipart].append([])
				h_DHV[ipart].append([])
				h_T[ipart].append([])
				h_LV[ipart].append([])
				h_ref[ipart].append([])
				h_intertime[ipart].append([])
				h_intertime_long[ipart].append([])

				h_HV_vs_t[ipart].append([])
				h_HVset_vs_t[ipart].append([])
				h_DHV_vs_t[ipart].append([])
				h_T_vs_t[ipart].append([])
				h_LV_vs_t[ipart].append([])
				h_ref_vs_t[ipart].append([])

				difference_date[ipart].append([])
				for ichan in range(48): # loop in all the channels

					chan_name = mod_name + '_' + str(ichan+1).zfill(2)

					if self.HVTool.IsThisChannelInstrumented(ipart,imod+1,ichan+1):

						# HV
						h_HV[ipart][imod].append(TH1F("h_HV_"+chan_name,"High Voltage ("+chan_name+"); HV (V); #events", binning_volt, ini_volt, end_volt))
						h_HV[ipart][imod][ichan].SetDirectory(0)

						h_HV_vs_t[ipart][imod].append(TProfile("HV_vs_t_"+chan_name,"High Voltage ("+chan_name+") vs Time; Day; HV (V)", binning_day, ini_day,end_day, ini_volt,end_volt))
						h_HV_vs_t[ipart][imod][ichan].GetXaxis().SetTimeDisplay(1)
						h_HV_vs_t[ipart][imod][ichan].SetDirectory(0)

						# DHV
						h_DHV[ipart][imod].append(TH1F("h_DHV_"+chan_name,"#DeltaHV ("+chan_name+"); #DeltaHV (V); #events", binning_Dvolt, ini_Dvolt, end_Dvolt))
						h_DHV[ipart][imod][ichan].SetDirectory(0)

						h_DHV_vs_t[ipart][imod].append(TProfile("DHV_vs_t_"+chan_name,"#DeltaHV ("+chan_name+") vs Time; Day; #DeltaHV (V)",binning_day,ini_day,end_day,ini_Dvolt,end_Dvolt))
						h_DHV_vs_t[ipart][imod][ichan].GetXaxis().SetTimeDisplay(1)
						h_DHV_vs_t[ipart][imod][ichan].SetDirectory(0)

						# Setting
						h_HVset[ipart][imod].append(TH1F("h_HVset_"+chan_name,"#Requested HV ("+chan_name+"); HVset (V); #events", binning_volt, ini_volt, end_volt))
						h_HVset[ipart][imod][ichan].SetDirectory(0)

						h_HVset_vs_t[ipart][imod].append(TProfile("HVset_vs_t_"+chan_name,"Requested HV ("+chan_name+") vs Time; Day; HVset (V)",binning_day,ini_day,end_day,ini_volt,end_volt))
						h_HVset_vs_t[ipart][imod][ichan].GetXaxis().SetTimeDisplay(1)
						h_HVset_vs_t[ipart][imod][ichan].SetDirectory(0)

					else:
						# fill with strings the channels that are not intrumented
						h_HV[ipart][imod].append('no instrumented channel')
						h_HV_vs_t[ipart][imod].append('no instrumented channel')
						h_DHV[ipart][imod].append('no instrumented channel')
						h_DHV_vs_t[ipart][imod].append('no instrumented channel')
						h_HVset[ipart][imod].append('no instrumented channel')
						h_HVset_vs_t[ipart][imod].append('no instrumented channel')

					if ichan<7:
						# There are 7 probes for the measurement of the temp
						h_T[ipart][imod].append(TH1F("h_T_"+chan_name,"T ("+chan_name+"); T (*C); #events", binning_temp, ini_temp, end_temp))
						h_T[ipart][imod][ichan].SetDirectory(0)

						h_T_vs_t[ipart][imod].append(TProfile("T_vs_t_"+chan_name,"T ("+chan_name+") vs Time; Day; T (*C)",binning_day,ini_day,end_day,ini_temp,end_temp))
						h_T_vs_t[ipart][imod][ichan].GetXaxis().SetTimeDisplay(1)
						h_T_vs_t[ipart][imod][ichan].SetDirectory(0)

						# There are 7 values of low voltage
						h_LV[ipart][imod].append(TH1F("h_LV_"+chan_name,"Low Voltage ("+chan_name+"); Low Voltage (mV); #events", binning_low_volt, ini_low_volt, end_low_volt))
						h_LV[ipart][imod][ichan].SetDirectory(0)

						h_LV_vs_t[ipart][imod].append(TProfile("LV_vs_t_"+chan_name,"Low Voltage ("+chan_name+") vs Time; Day; Low Voltage (mV)",binning_day,ini_day,end_day,ini_low_volt,end_low_volt))
						h_LV_vs_t[ipart][imod][ichan].GetXaxis().SetTimeDisplay(1)
						h_LV_vs_t[ipart][imod][ichan].SetDirectory(0)

					if ichan<2:
						# There are 2 values for the reference voltage
						h_ref[ipart][imod].append(TH1F("h_ref_"+chan_name," Reference Voltage ("+chan_name+"); Ref Voltage(mV); #events", binning_ref_volt, ini_ref_volt, end_ref_volt))
						h_ref[ipart][imod][ichan].SetDirectory(0)

						h_ref_vs_t[ipart][imod].append(TProfile("Ref_vs_t_"+chan_name,"Reference Voltage ("+chan_name+") vs Time; Day; Ref Voltage (mV)",binning_day,ini_day,end_day,ini_ref_volt,end_ref_volt))
						h_ref_vs_t[ipart][imod][ichan].GetXaxis().SetTimeDisplay(1)
						h_ref_vs_t[ipart][imod][ichan].SetDirectory(0)

					difference_date[ipart][imod].append([])
					difference_date[ipart][imod][ichan] = 0

					h_intertime[ipart][imod].append(TH1F(chan_name+"_inter_time", "Time difference between two consecutive measurements ("+chan_name+"); #Deltat (s); #events", 600,0,600))
					h_intertime[ipart][imod][ichan].SetDirectory(0)
					h_intertime_long[ipart][imod].append(TH1F(chan_name+"_inter_time_long" , "Time difference between two consecutive measurements ("+chan_name+"); #Deltat (s); Events", 588,0,84640))
					h_intertime_long[ipart][imod][ichan].SetDirectory(0)

		#Fill Histograms
		print(n_entries)

		point = n_entries/100
		increment = n_entries/20

		counter = int(0)
		while counter < n_entries:
		#while counter < 30000000:

			# progress bar

			if (counter % (5*point) == 0):
				sys.stdout.write("\r[" + "=" * (counter / increment) +  " " * ((n_entries - counter)/ increment) + "]" +  str(counter / point) + "%")
				sys.stdout.flush()
				print('\n')

			tree.GetEntry(counter)
			#print "Event", counter, "Partition = ",Partition[0], "Module = ", Module[0], "Channel = ", Channel[0], 'measureType =', MeasureType[0], 'measure = ', Measure[0], 'refe =', Reference[0]
			counter += 1

			measureType = MeasureType[0]
			partition = Partition[0]
			module = Module[0]-1
			channel = Channel[0]-1
			measure = Measure[0]
			reference = Reference[0]
			date = Date[0]

			deltaHV = Measure[0] - Reference[0]

			# Histograms concerning Temperatures
			if measureType==1:
				if channel<7:
					h_T[partition][module][channel].Fill(measure)
					h_T_vs_t[partition][module][channel].Fill(date,measure)

					if self.do_extraPlots:
						h_T_vs_t_mod[partition][module].Fill(date,measure)
						h_T_vs_t_part[partition].Fill(date,measure)

			elif measureType==2:
				if self.HVTool.IsThisChannelInstrumented(partition,module+1,channel+1):

					h_HV[partition][module][channel].Fill(measure)
					h_HV_vs_t[partition][module][channel].Fill(date,measure)

					h_HVset[partition][module][channel].Fill(reference)
					h_HVset_vs_t[partition][module][channel].Fill(date,reference)

					h_DHV[partition][module][channel].Fill(deltaHV)
					h_DHV_vs_t[partition][module][channel].Fill(date,deltaHV)

					if self.do_extraPlots:
						h_DHV_part[partition].Fill(deltaHV)
						h_DHV_vs_t_part[partition].Fill(date,deltaHV)
						h_DHV_vs_t_mod[partition][module].Fill(date,deltaHV)

						h_HV_vs_t_part[partition].Fill(date,measure)
						h_HV_vs_t_mod[partition][module].Fill(date,measure)

						if difference_date[partition][module][channel]==0:
							difference_date[partition][module][channel] = date
						else:
							h_intertime[partition][module][channel].Fill(date-difference_date[partition][module][channel])
							h_intertime_long[partition][module][channel].Fill(date-difference_date[partition][module][channel])

			elif measureType==3:
				if channel<2:
					h_ref[partition][module][channel].Fill(measure)
					h_ref_vs_t[partition][module][channel].Fill(date,measure)

			elif measureType==4:
				if channel<7:
					h_LV[partition][module][channel].Fill(measure)
					h_LV_vs_t[partition][module][channel].Fill(date,measure)

		# Analysis

		# Computing other plots
		for ipart in range(4): # loop in all the partitions

			threshold_mv_mean   = 1
			threshold_RMS_mean  =  1

			threshold_mv_sigmas = 1
			threshold_RMS_sigmas= 1

			badChan_threshold_mean  = 5
			badChan_threshold_sigma = 1

			for imod in range(64): # loop in all the modules

				for ichan in range(48): # loop in all the modules

					if self.HVTool.IsThisChannelInstrumented(ipart,imod+1,ichan+1):

						if h_DHV[ipart][imod][ichan].Integral() == 0:
							continue

						if not self.HVTool.HasThisChannelHVData(ipart, imod, ichan, h_HV_vs_t[ipart][imod][ichan]):
							continue

						isGood, imu, _, _= self.HVTool.IsThisChannelGood(h_DHV[ipart][imod][ichan],ini_Dvolt, end_Dvolt, binning_Dvolt, threshold_mv_mean, threshold_RMS_mean, badChan_threshold_mean, badChan_threshold_sigma)
						if isGood:
							h_means[ipart].Fill(imu)

		# Calculation of the thresholds

		h_means_mv = []
		h_means_rms = []

		h_sigmas_mv = []
		h_sigmas_rms = []

		for ipart in range(4): # loop in all the partitions
			imean, irms = self.HVTool.MeanAndSigmaThresholds(h_means[ipart])
			#print imean, irms
			h_means_mv.append(imean)
			h_means_rms.append(irms)

		for ipart in range(4): # loop in all the partitions
			for imod in range(64): # loop in all the modules
				for ichan in range(48): # loop in all the modules

					if self.HVTool.IsThisChannelInstrumented(ipart,imod+1,ichan+1):

						if h_DHV[ipart][imod][ichan].Integral() == 0:
							continue

						isigma = self.HVTool.SigmasThresholds(h_DHV[ipart][imod][ichan])
						#print isigma
						h_sigmas[ipart].Fill(isigma)

			fit_sigmas = TF1("f2","gaus",0,10)
			h_sigmas[ipart].Fit("f2","RSQ")

			imean = fit_sigmas.GetParameter(1)
			irms = fit_sigmas.GetParameter(2)
			h_sigmas_mv.append(imean)
			h_sigmas_rms.append(irms)

		# Separating good and bad channels
		outputFile = TFile(outDir + '/HV_HVset_plots.root', 'RECREATE')
		self.HVTool.mkdir(outDir + '/Summary')

		self.HVTool.FilesHeaderWriter(outDir + '/good_channels.txt',outDir + '/bad_channels.txt',outDir + '/for_latex.txt' , ini_Date, fin_Date)
		for ipart in range(4): # loop in all the partitions
			part_name = self.HVTool.get_partition_name(ipart)
			print('Partition ', part_name, ' proceeding ...')

			threshold_mv_mean    = h_means_mv[ipart]
			threshold_RMS_mean   = h_means_rms[ipart]

			threshold_mv_sigmas  = h_sigmas_mv[ipart]
			threshold_RMS_sigmas = h_sigmas_rms[ipart]

			self.HVTool.PartitionHeader(part_name, threshold_mv_mean, threshold_RMS_mean, threshold_mv_sigmas, threshold_RMS_sigmas, outDir + '/good_channels.txt', outDir + '/bad_channels.txt')

			for imod in range(64): # loop in all the modules
				for ichan in range(48): # loop in all the modules

					if self.HVTool.IsThisChannelInstrumented(ipart,imod+1,ichan+1):

						status = 0

						if h_DHV[ipart][imod][ichan].Integral()==0:
							status = 4
						else:
							if not self.HVTool.HasThisChannelHVData(ipart, imod, ichan, h_HV_vs_t[ipart][imod][ichan]):
								status = 4
							else:
								isGood, imu, isigma, causes = self.HVTool.IsThisChannelGood(h_DHV[ipart][imod][ichan],ini_Dvolt, end_Dvolt, binning_Dvolt, threshold_mv_mean, threshold_RMS_mean, badChan_threshold_mean, badChan_threshold_sigma)
								if isGood:

									isUnstable, causes_un, count_error = self.HVTool.IsThisChannelUnStable(h_DHV_vs_t[ipart][imod][ichan], imu)
									if isUnstable:
										# Unstable channels
										status = 3
										self.HVTool.WriteBadChannel(part_name, imod+1, ichan+1, imu, isigma, outDir + '/bad_channels.txt', causes_un)
										self.HVTool.PerformDiagnosticForBadChannel(outDir + '/bad_channels.txt', h_HV[ipart][imod][ichan], h_HVset[ipart][imod][ichan], h_T[ipart][imod][5], h_ref[ipart][imod][1])
										self.HVTool.threesholdPlots_DHV(ipart, imod+1, ichan+1, imu, outputFile, h_DHV_vs_t[ipart][imod][ichan] , h_HV_vs_t[ipart][imod][ichan], h_HVset_vs_t[ipart][imod][ichan])

										#print part_name, imod+1, ichan+1, count_error
									else:
										# Stable and without offset channel
										status = 1
										self.HVTool.WriteGoodChannel(part_name, imod+1, ichan+1, imu, isigma, outDir + '/good_channels.txt')
										self.HVTool.WriteSummary(part_name, imod+1, ichan+1, outDir + '/short_good_channels.txt')
										self.HVTool.threesholdPlots_DHV(ipart, imod+1, ichan+1, imu, outputFile, h_DHV_vs_t[ipart][imod][ichan] , h_HV_vs_t[ipart][imod][ichan], h_HVset_vs_t[ipart][imod][ichan])

										#print part_name, imod+1, ichan+1, count_error
								else:
									#  Channel with offset
									status = 2

									isUnstable, causes_un, count_error = self.HVTool.IsThisChannelUnStable(h_DHV_vs_t[ipart][imod][ichan], imu)
									if isUnstable:
										status = 3
										causes += causes_un

									self.HVTool.WriteBadChannel(part_name, imod+1, ichan+1, imu, isigma, outDir + '/bad_channels.txt', causes)
									self.HVTool.PerformDiagnosticForBadChannel(outDir + '/bad_channels.txt', h_HV[ipart][imod][ichan], h_HVset[ipart][imod][ichan], h_T[ipart][imod][5], h_ref[ipart][imod][1])
									self.HVTool.offset_forLatex(part_name, imod+1, ichan+1, outDir + '/for_latex.txt' , imu, h_HV[ipart][imod][ichan], h_HVset[ipart][imod][ichan])
									self.HVTool.threesholdPlots_DHV(ipart, imod+1, ichan+1, imu, outputFile, h_DHV_vs_t[ipart][imod][ichan] , h_HV_vs_t[ipart][imod][ichan], h_HVset_vs_t[ipart][imod][ichan])

									#print part_name, imod+1, ichan+1, count_error

						# Performing mapping for this channel
						h2_map[ipart].Fill(imod+1, ichan+1, status)

						self.HVTool.mkdir(outDir + '/LISTS')
						date_format = time.strftime("%y%m%d", fin_Date.timetuple())
						# writes summary text files
						if status==2:
							self.HVTool.WriteSummary(part_name, imod+1, ichan+1, outDir + '/LISTS/'+date_format+'_bad_list.txt')
						if status==3:
							self.HVTool.WriteSummary(part_name, imod+1, ichan+1, outDir + '/LISTS/'+date_format+'_unstable_list.txt')
						if status==4:
							self.HVTool.WriteSummary(part_name, imod+1, ichan+1, outDir + '/LISTS/'+date_format+'_noHV_list.txt')

		outputFile.Close()

		# Write
		for ipart in range(4): # loop in all the partitions
			outFile.cd()

			h_means[ipart].Write()
			h_sigmas[ipart].Write()
			h2_map[ipart].Write()

			if self.do_extraPlots:
				h_DHV_part[ipart].Write()
				h_DHV_vs_t_part[ipart].Write()
				h_HV_vs_t_part[ipart].Write()
				h_T_vs_t_part[ipart].Write()

			for imod in range(64): # loop in all the modules

				if self.do_extraPlots:
					outFile.cd('HV/')
					h_HV_vs_t_mod[ipart][imod].Write()
					outFile.cd('DHV/')
					h_DHV_vs_t_mod[ipart][imod].Write()
					outFile.cd('T/')
					h_T_vs_t_mod[ipart][imod].Write()

				for ichan in range(48): # loop in all the channels

					if self.HVTool.IsThisChannelInstrumented(ipart,imod+1,ichan+1):
						outFile.cd("HV/")
						h_HV[ipart][imod][ichan].Write()
						h_HV_vs_t[ipart][imod][ichan].Write()

						outFile.cd('DHV/')
						h_DHV[ipart][imod][ichan].Write()
						h_DHV_vs_t[ipart][imod][ichan].Write()

						outFile.cd('HVset/')
						h_HVset[ipart][imod][ichan].Write()
						h_HVset_vs_t[ipart][imod][ichan].Write()

					if ichan<7:
						outFile.cd("T/")
						h_T[ipart][imod][ichan].Write()
						h_T_vs_t[ipart][imod][ichan].Write()

					if ichan<2:
						outFile.cd('Ref/')
						h_ref[ipart][imod][ichan].Write()
						h_ref_vs_t[ipart][imod][ichan].Write()

					if ichan<7:
						outFile.cd('LV/')
						h_LV[ipart][imod][ichan].Write()
						h_LV_vs_t[ipart][imod][ichan].Write()

					outFile.cd('Time/')
					if self.do_extraPlots:
						h_intertime[ipart][imod][ichan].Write()
						h_intertime_long[ipart][imod][ichan].Write()

		outFile.Write()
		outFile.Close()

	def ProcessRegion(self, region):
		if region.GetHash() == 'TILECAL':
			print("You produced the evolutions plots for HV, HVset, DHV, T, LV and refVol. The next step is perfom the HV analysis")
			print('The analysis finished at', datetime.datetime.now())


#!/usr/bin/env python
# enccoding: utf-8
'''
@author: Yankai
@project:
'''
import xlrd,xlwt
from xlutils.copy import copy

#打开excel
readbook = xlrd.open_workbook(r'C:\Users\kmf\接口复习\test.xlsx')
#获取读入文件的sheet
sheet1 = readbook.sheet_by_index(0)
sheet2 = readbook.sheet_by_name('sheet2')
allsheetnames = readbook.sheet_names()
print(sheet1,sheet2,allsheetnames)
#获取sheet最大行数和列数
nrows = sheet1.nrows#行
ncols = sheet2.ncols#列
print(nrows,ncols)
#获取某个单元格的值
lng = sheet1.cell(1,1).value#获取1行1列的表格值，从0开始计数
print(lng)
#获取某行/某列的值
row_value = sheet1.row_values(2)#获取x行的值，从0开始计数
col_value = sheet1.col_values(3)#获取y列的值，从0开始计数
print(row_value,col_value)


import streamlit as st
import pandas as pd
import numpy as np
def gauss_jordan(matrix):
    num_rows, num_cols = matrix.shape
    pivot_row = 0

    for col in range(num_cols - 1):
        # Mencari pivot
        pivot_value = matrix[pivot_row, col]
        for row in range(pivot_row + 1, num_rows):
            if matrix[row, col] > pivot_value:
                pivot_row = row
                pivot_value = matrix[row, col]
        # Melakukan pertukaran baris jika pivot row bukan baris saat ini
        if pivot_row != col:
            matrix[[pivot_row, col]] = matrix[[col, pivot_row]]

        # Mengubah pivot menjadi 1 dengan membagi baris dengan pivot
        matrix[col] = matrix[col] / matrix[col, col]

        # Menghilangkan elemen di kolom pivot dari baris lainnya
        for row in range(num_rows):
            if row != col:
                matrix[row] = matrix[row] - matrix[row, col] * matrix[col]

        # Pindah ke baris berikutnya
        pivot_row += 1

    return matrix
#cramer rules
def cramer_rule(matrix_A, matrix_b):
    det_A = np.linalg.det(matrix_A)
    n = matrix_A.shape[0]
    results = []

    for i in range(n):
        matrix_A_copy = matrix_A.copy()
        matrix_A_copy[:, i] = matrix_b
        det_A_i = np.linalg.det(matrix_A_copy)
        result = det_A_i / det_A
        results.append(result)

    return results
#untuk title
st.title(':white[MATRIX CALCULATOR]')

#untuk sidebar
with st.sidebar:
    tipe = st.radio('pilih tipe', ['Single Matrix' , 'Double Matrix', 'Gauss Jordan']) #digunakan untuk memilih

#untuk expander (memilih ukuran)
with st.expander('Pilih Ukuran'):
    with st.form('pilih ukuran'):

        if tipe == 'Single Matrix':
            row1= st.number_input('ukuran baris dari matriks ', min_value=2)
            col1= st.number_input('ukuran kolom dari matriks ', min_value=2)
            st.form_submit_button('kirim ukuran matriks')

        elif tipe == 'Double Matrix':
            row1= st.number_input('ukuran baris dari matriks pertama', min_value=2)
            col1= st.number_input('ukuran kolom dari matriks pertama', min_value=2)
            row2= st.number_input('ukuran baris dari matriks kedua', min_value=2)
            col2= st.number_input('ukuran kolom dari matriks kedua', min_value=2)
            st.form_submit_button('kirim ukuran matriks')

        elif tipe == 'Gauss Jordan':
            row1= st.number_input('ukuran baris dari matriks ', min_value=2)
            col1= st.number_input('ukuran kolom dari matriks ', min_value=2)
            st.form_submit_button('kirim ukuran matriks')

# untuk single matriks
if tipe == 'Single Matrix':
        st.write('data untuk matriks')
        with st.form('Submit Matrix'):
            df_1 = pd.DataFrame(columns=[f'x{index}' for index in range(1, col1 + 1)], index=[f'x{index}' for index in range(1, row1 + 1)], dtype=float)
            df_1_input = st.data_editor(df_1, use_container_width=True, key=1)
            matrix1 = df_1_input.fillna(0).to_numpy()
            oprasi = st.radio('Pilih Oprasi',['Det(A)','A(INVERSE)', 'A(TRANSPOSE)','RANK'])
            if st.form_submit_button('Calculate'):
                if oprasi == 'A(INVERSE)':
                    if np.isnan(df_1_input.astype(float).values).any():
                        st.warning("Mohon isi angka terlebih dahulu.")
                    elif matrix1.shape[0] != matrix1.shape[1]:
                            st.warning("Ordo matriks harus sama jika mau menghitung inverse.")
                    else:
                        determinan = np.linalg.det(matrix1)
                        if determinan == 0:
                            st.warning("Matriks tersebut adalah matriks singular, jadi tidak bisa dihitung inverse nya. Silahkan coba lagi!")
                        else:
                            inverse = np.linalg.inv(matrix1)
                            bulat_inverse = round(inverse,3)
                            st.write('Hasil inverse nya adalah :',bulat_inverse)
                elif oprasi == 'Det(A)':
                    if np.isnan(df_1_input.astype(float).values).any():
                        st.warning("Mohon isi angka terlebih dahulu.")
                    elif matrix1.shape[0] != matrix1.shape[1]:
                        st.warning("Ordo matriks harus sama jika mau menghitung determinan.")
                    else:
                        determinan = np.linalg.det(matrix1)
                        bulat_determinan = round(determinan,3)
                        st.write('Hasil determinan nya adalah :', bulat_determinan)
                elif oprasi == 'A(TRANSPOSE)':
                    if np.isnan(df_1_input.astype(float).values).any():
                        st.warning("Mohon isi angka terlebih dahulu.")
                    else:
                        determinan = np.linalg.det(matrix1)
                        if determinan == 0:
                                st.warning("Masukkan angka yang benar!!")
                        else:
                            transpose = np.transpose(matrix1)
                            st.write('Hasil transpose nya adalah :',transpose)
                elif oprasi == ('RANK') :
                    if np.isnan(df_1_input.astype(float).values).any():
                        st.warning("Mohon isi angka terlebih dahulu.")
                    else:
                        rank = np.linalg.matrix_rank(matrix1)
                        st.write('RANK nya adalah :',rank)

# untuk double matriks
elif tipe == 'Double Matrix':
        st.write('data untuk matriks')
        with st.form('Submit Matrix'):
            df_1 = pd.DataFrame(columns=[f'x{index}' for index in range(1, col1 + 1)], index=[f'x{index}' for index in range(1, row1 + 1)], dtype=float)
            df_1_input = st.data_editor(df_1, use_container_width=True, key=1)
            df_2= pd.DataFrame(columns=[f'x{index}' for index in range(1,col2+1)], index=[f'x{index}' for index in range(1, row2+1)], dtype=float)
            df_2_input = st.data_editor(df_2, use_container_width=True, key=2)
            matrix1= df_1_input.fillna(0).to_numpy()
            matrix2= df_2_input.fillna(0).to_numpy()
            oprasi = st.radio('Pilih Oprasi',['A*B', 'A+B','A-B'])
            if st.form_submit_button('Calculate'):
                if oprasi == 'A*B':
                    if np.isnan(df_1_input.astype(float).values).any():
                        st.warning("Mohon isi angka terlebih dahulu.")
                    elif matrix1.shape[1] != matrix2.shape[0]:
                         st.warning("Jumlah kolom matriks pertama harus sama dengan jumlah baris matriks kedua.")
                        # untuk memeriksa apakah jumlah kolom dan baris
                    else :
                        kali = np.matmul(matrix1, matrix2)
                        st.write('Hasil dari perkalian matriks tersebut adalah : ',kali)
                elif oprasi == 'A+B':
                    if np.isnan(df_1_input.astype(float).values).any():
                        st.warning("Mohon isi angka terlebih dahulu.")
                    elif matrix1.shape[0] != matrix1.shape[1]:
                        st.warning("Ordo matriks harus sama jika mau menghitung penjumlahan matriks.")
                    else:
                        tambah = matrix1 + matrix2
                        st.write('Hasil dari penjumlahan matriks tersebut adalah : ',tambah)
                elif oprasi == 'A-B':
                    if np.isnan(df_1_input.astype(float).values).any():
                        st.warning("Mohon isi angka terlebih dahulu.")
                    elif matrix1.shape[0] != matrix1.shape[1]:
                        st.warning("Ordo matriks harus sama jika mau menghitung pengurangan matriks.")
                    else :
                        kurang = matrix1 - matrix2
                        st.write('Hasil dari pengurangan matriks tersebut adalah : ', kurang)
# untuk Gauss Jordan
elif tipe == 'Gauss Jordan':
        st.write('data untuk matriks')
        with st.form('Submit Matrix'):
            df_1 = pd.DataFrame(columns=[f'x{index}' for index in range(1, col1 + 1)], index=[f'x{index}' for index in range(1, row1 + 1)], dtype=float)
            df_1_input = st.data_editor(df_1, use_container_width=True, key=1)
            matrix1 = df_1_input.fillna(0).to_numpy()
            oprasi = st.radio('Pilih Oprasi',[ 'Gauss Jordan'])
            if st.form_submit_button('Calculate'):
                if oprasi == ('Gauss Jordan') :
                    if np.isnan(df_1_input.astype(float).values).any():
                        st.warning("Mohon isi angka terlebih dahulu.")
                    else:
                        gaus =  gauss_jordan(matrix1)
                        st.write('Hasil dari matriks Gauss Jordan tersebut adalah :',gaus)
                        result = gauss_jordan(matrix1)
                        num_rows, num_cols = result.shape
                        solution = result[:, num_cols-1]
                        print("Solusi:")
                        for i, value in enumerate(solution):
                            print(f"x{i+1} = {value}")


import praw
import requests
import json
from datetime import datetime
import time
import argparse
from os.path import join
from os import getcwd
from tqdm import tqdm

class Downloader:
    def __init__(self, client_id = None, client_secret = None, user_agent = None):
        if client_id is not None:
            self.reddit = praw.Reddit(client_id=client_id,
                                client_secret=client_secret,
                                user_agent=user_agent)

    def scrape_posts(self, subreddit, start_time = None, end_time = None, interval = 3600*6):
        '''With default args, downloads all posts from a subreddit
        For optimal speed, interval should be big enough that there are more post
        than the pushshift_max (currently 100) during that period.
        '''
        wait_time = 0.5
        retries = 10
        pushshift_max = 100
        if start_time is None:
            if not hasattr(self, "reddit"):
                raise Exception("Since no API keys were provided, start_time and end_time must be specified")
            start_time = int(self.reddit.subreddit(subreddit).created_utc)
        if end_time is None:
            end_time = int(datetime.now().timestamp())

        output_file = f'fetched_r_{subreddit}_{start_time}_{end_time}.json'
        with open(output_file, 'w') as f:
            print(f"Fetching data and saving it in {join(getcwd(),output_file)}...")
            f.write("[")
            tqdmbar = tqdm(total = end_time - start_time)
            while start_time < end_time:
                end_interval = min(start_time + interval, end_time)
                url = f"https://api.pushshift.io/reddit/search/submission/?after={start_time}&before={end_interval}&subreddit={subreddit}&limit=1000&score=%3E0"
                r = requests.get(url)
                for i in range(retries):
                    if r.status_code == 200:
                        break
                    else:
                        print("ERROR", str(r.status_code))
                        time.sleep(1*(2**i))
                        r = requests.get(url)
                posts = json.loads(r.text)["data"]
                if len(posts) < pushshift_max:
                    tqdmbar.update(interval)
                    start_time += interval
                else:
                    tqdmbar.update(int(posts[-1]["created_utc"]) - start_time)
                    start_time = int(posts[-1]["created_utc"])
                for post in posts:
                    json.dump(post, f)
                    f.write(",\n")
                time.sleep(wait_time)
            tqdmbar.close()
            # correcting end of file:
            f.seek(f.tell()-2)
            f.truncate()
            f.write("]")

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--subreddit', type=str, required = True)
    parser.add_argument('--client_id', type=str, default = None)
    parser.add_argument('--client_secret', type=str, default = None)
    parser.add_argument('--user_agent', type=str, default = None)
    parser.add_argument('--start_time', type=int, default = None)
    parser.add_argument('--end_time', type=int, default = None)
    parser.add_argument('--interval', type=int, default = 3600*6)

    args = parser.parse_args()

    downloader = Downloader(args.client_id, args.client_secret, args.user_agent)
    downloader.scrape_posts(args.subreddit, args.start_time, args.end_time, args.interval)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import argparse
import pickle

import hjson as json
import torch

import loader
from calc_F_score import calc_F_score  # ~/work/misc
from model.AutoNER_with_RL import AutoNER_with_RL

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='This script is BiLSTM-CRF \
        trainable imcomplete annotation')
    parser.add_argument('--model', type=str, default=None,
                        help='load a model information, please input file stem \
        without ".info"/".weight"')
    parser.add_argument('--test_file', type=str, default=None,
                        help='test corpus')
    parser.add_argument('--minibatch', type=int, default=32)
    parser.add_argument('--token_splitter', type=str, default=' ',
                        help="that's/O a/O apple-pen/PPAP -> \
        [that's/O, a/O, apple-pen/PP|AP]")
    parser.add_argument('--tag_splitter', type=str, default='/',
                        help=" -> [O, O, PP|AP]")
    args = parser.parse_args()

    test_data = open(args.test_file, 'r').read().split('\n')
    test_data = [_.split(args.token_splitter) for _ in test_data if _ != '']

    with open(args.model + '.info.hjson', mode='rb') as f:
        model_info = pickle.load(f)
    autoner = AutoNER_with_RL(model_info['prams'],
                              model_info['w2i'],
                              model_info['i2w'],
                              model_info['ch2i'],
                              model_info['i2ch'],
                              model_info['t2i'],
                              model_info['i2t'])
    autoner.load_state_dict(torch.load(args.model + '.weight',
                                       map_location=lambda storage, loc: storage))
    if 'CUDA_VISIBLE_DEVICES' in os.environ:
        gpu_id = os.environ['CUDA_VISIBLE_DEVICES']
        if int(gpu_id) >= 0:
            cuda_device = torch.device('cuda')
            autoner.to(cuda_device)
            autoner.to_gpu(cuda_device)

    dev_sents, dev_sent_labels = \
        loader.read_corpus_column(args.test_file, {}, {}, {}, {}, {}, {}, {}, {},
                                  '\n\n', '\n', ' ', None, 0, 0, None,
                                  vocab_expand=False, return_BIESO=True)
    dev_corpus = [dev_sents, dev_sent_labels]
    for i, (sent, sent_label) in enumerate(zip(dev_sents, dev_sent_labels)):
        if len(sent) == 0:
            dev_sents.remove(sent)
            dev_sent_labels.remove(sent_label)
    assert(len(dev_corpus[0]) == len(dev_corpus[1]))

    minibatch = args.minibatch
    autoner.eval()
    predict_sents = []
    dev_sents = dev_corpus[0]
    for i in range(0, len(dev_sents), minibatch):
        input_sents = []
        for r in range(i, min(i+minibatch, len(dev_corpus[0]))):
            input_sents.append(dev_sents[r])
        predicts = autoner.predict(input_sents)
        predict_sents.extend(predicts)
    prec, recall, f_score = calc_F_score(dev_corpus[1],
                                         predict_sents,
                                         ' ',
                                         '</>',
                                         'O',
                                         '-',
                                         0)
    print(prec, recall, f_score)
    # for words in test_data:
    #     predict_tags = model.predict([words])
    #     newline = ''
    #     for t, word in enumerate(words):
    #         newline += word + args.tag_splitter + predict_tags[t] + \
    #             args.token_splitter
    #     newline = newline[:-len(args.token_splitter)]
    #     print(newline)


class BSTNode:
  def __init__(self, key):
    self.key = key
    self.left = None
    self.right = None
    self.parent = None
    self.height = 1

def add(tree, key, parent=None):
  if tree is None:
    tree = BSTNode(key)
    tree.parent = parent
    tree.height = parent.height + 1
  # dodawnay klocek nachodzi od:
  # 1. prawej
  # 2. lewej
  elif (key[0] <= tree.key[1] and tree.key[0] <= key[1]) or \
       (tree.key[0] <= key[1] and key[0] <= tree.key[1]):
    tree.key = (min(tree.key[0], key[0]), max(tree.key[1], key[1]))
    tree.right = add(tree.right, key, tree)
  # nie nachodzi
  else:
    tree.left = add(tree.left, key, tree)
    tree = tree.left

  return tree

def print_node(node):
  print(f'key: {node.key}')
  print(f'height: {node.height}')

  if node.left is not None:
    print(f'left: {node.left.key}')
  else:
    print('left: None')

  if node.right is not None:
    print(f'right: {node.right.key}')
  else:
    print('right: None')

def print_nodes(tree):
  if tree is None:
    return

  print_nodes(tree.left)
  print_node(tree)
  print()
  print_nodes(tree.right)

def print_breadth_first(tree):
  if tree is None:
    print('Empty')
    return

  children = [tree]
  while len(children) > 0:
    _children = []

    for node in children:
      print(node.key, end=' ')
      if node.left is not None:
        _children.append(node.left)
      if node.right is not None:
        _children.append(node.right)

    print()
    children = _children

def get_height(tree, height=0):
  if tree is None:
    return height

  height = max(height, tree.height)

  return max(get_height(tree.left, height), get_height(tree.right, height))

def bricks(ranges):
  n = len(ranges)
  tree = BSTNode(ranges[0])
  for i in range(1, n):
    tree = add(tree, ranges[i])

  return get_height(tree)

# 3
ranges = [(1, 3), (2, 5), (0, 3), (8, 9), (4, 6)]

# 4
ranges = [(1, 3), (1, 5), (0, 5), (0, 6)]

# 4 a powinno byc 3
ranges = [(0, 1), (2, 3), (0, 3), (0, 1)]

# 6
ranges = [(1, 3), (2, 5), (0, 3), (8, 9), (4, 6), (4, 6), (4, 6), (0, 10)]

print(bricks(ranges))