text:
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px

from rdkit import Chem
from rdkit.Chem import Draw
from rdkit.Chem import inchi
from rdkit import DataStructs

our_color_discrete_map={
                  "unknown": "rgba(180, 180, 180, 0.24)",
                  "low": "rgba(5, 192, 5, 0.74)",
                  "medium": "rgba(255, 112, 0, 0.74)",
                  "high": "rgba(224, 19, 19, 0.74)",
                  "watching": "blue"
                  }

def user_input_features(bees):
    pesticides = ["{} - {}".format(a_, b_) for a_, b_ in zip(bees.index.map(str).values , bees['name'].values)]
    pesticide_selection = st.sidebar.selectbox('Which pesticide would you like to know more about?',  pesticides)
    n_neighbours = st.sidebar.slider('Neighbours', 1, 10, 3)

    data = {'n_neighbours': n_neighbours,
            'pesticide_selection': pesticide_selection}
    features = pd.DataFrame(data, index=[0])
    return features

def give_nearest_n(proj_3d, point, k):
    n = proj_3d.shape[0]
    data = proj_3d.copy()

    dist_matrix = np.zeros((n, n))
    for i in range(1,n):
        dist = np.linalg.norm(data[:i,:]-data[i,:] , axis=1)
        for id, d in enumerate(dist):
            dist_matrix[i,id] = d

    dist_matrix = dist_matrix + dist_matrix.T

    nearest_n = np.zeros_like(dist_matrix, dtype=int)
    for id, row in enumerate(dist_matrix):
        nearest_n[id] = np.argsort(row)
    nearest_n = nearest_n[:,1:]
    return nearest_n[point, 0:k]

def show_atom_number(mol, label):
    for atom in mol.GetAtoms():
        atom.SetProp(label, str(atom.GetIdx()+1))
    return mol

def get_labels(bees, slected_pesticide_idx):
    y_full = bees['honeybees_contact_kill_risk'].values
    y_full = y_full.add_categories('watching')
    y_full[slected_pesticide_idx] = 'watching' # What point do you want to watch?

    return y_full

def plot_2d(proj_2d, bees, slected_pesticide_idx):
  y_full = get_labels(bees, slected_pesticide_idx)

  fig_2d = px.scatter(
      proj_2d, x=0, y=1,
          hover_data=[bees.index.map(str).values, bees['name'].values],
          color=y_full, labels={'color': 'risk'},
          color_discrete_map=our_color_discrete_map,
  )
  return fig_2d

def plot_3d(proj_3d, bees, slected_pesticide_idx):
  y_full = get_labels(bees, slected_pesticide_idx)

  fig_3d = px.scatter_3d(
      proj_3d, x=0, y=1, z=2,
        hover_data=[bees.index.map(str).values, bees['name'].values],
          color=y_full, labels={'color': 'risk'},
          color_discrete_map=our_color_discrete_map,
  )
  fig_3d.update_traces(marker_size=5)

  fig_3d.show()

  return fig_3d

def streamlit_stuff():

  st.write("""
  # Bee-Friendly Pesticide Classifier

  This app lets you choose one pesticide from a collection of pesticides and predicts the risk of death for a bee if she encounters that specific pesticide.
  We infer the risk by looking at the risk-rating of similar pesticides (from a chemical molecule structure perspective).
  """)

  st.sidebar.header('User Input Parameters')

  bees = pd.read_pickle('scraped_molecules_honeybees_working.pickle')
  bees['honeybees_contact_kill_risk'] = bees['honeybees_contact_kill_risk'].cat.add_categories('unknown').fillna("unknown")
  df = user_input_features(bees)

  st.subheader('User Input Parameters')
  st.write(df)

  slected_pesticide = df['pesticide_selection'].values[0]
  slected_pesticide_idx = int(slected_pesticide.split("-")[0][:-1])
  st.write(slected_pesticide, slected_pesticide_idx)

  proj_2d = np.load("2317_proj_2d.npy")
  st.header("2D UMAP")
  st.plotly_chart(plot_2d(proj_2d, bees, slected_pesticide_idx))

  proj_3d = np.load("2317_proj_3d.npy")
  st.header("3D UMAP")
  st.plotly_chart(plot_3d(proj_3d, bees, slected_pesticide_idx))

  slected_pesticide_row = bees.iloc[slected_pesticide_idx, :]
  st.header("Info about " + slected_pesticide_row['name'])
  st.write(f"This one is currently classified as {str(slected_pesticide_row['honeybees_contact_kill_risk'])}.")

  m = inchi.MolFromInchi(slected_pesticide_row['inchi'])
  fig = Draw.MolToMPL(m)
  st.pyplot(fig)

  # K-NN
  st.subheader('Nearest Neighbours')

  k = int(df['n_neighbours'].values[0])
  nn = give_nearest_n(proj_3d, slected_pesticide_idx, k)
  st.write(nn)

  df_nn = bees.iloc[nn]
  st.write(df_nn)

  for n in nn:
      # st.write(df_nn.loc[n])
      st.subheader('Neighbour ' + df_nn.loc[n, 'name'] + ': ' + str(df_nn.loc[n, 'honeybees_contact_kill_risk']))
      nn_mol = inchi.MolFromInchi(df_nn.loc[n, 'inchi'])
      fig = Draw.MolToMPL(nn_mol)
      st.pyplot(fig)

  # st.subheader('Class labels and their corresponding index number')
  # st.write(iris.target_names)

  # st.subheader('Prediction')
  # st.write(iris.target_names[prediction])

  # st.subheader('Prediction Probability')
  # st.write(prediction_proba)

streamlit_stuff()

max_stars_repo_name: ScholliYT/bee-friendly

max_issues_repo_name: ScholliYT/bee-friendly

max_forks_repo_name: ScholliYT/bee-friendly


text:
# This code was based on https://github.com/Octavian-ai/english2cypher
# Octavian.ai developed.

import tensorflow as tf
import os.path
import numpy as np
import traceback
import yaml
from collections import Counter
import logging

logger = logging.getLogger(__name__)

from .input import gen_input_fn, EOS
from .model import model_fn
from .args import get_args
from .util import *
from .build_data import *

def train(args):
    """
    Main function to train the data.
    """
    tf.logging.set_verbosity(tf.logging.DEBUG)

    estimator = tf.estimator.Estimator(
        model_fn,
        model_dir=args["model_dir"],
        warm_start_from=args["warm_start_dir"],
        params=args)

    eval_spec = tf.estimator.EvalSpec(input_fn=lambda:gen_input_fn(args, "eval"))
    steps_per_cycle = int(args["max_steps"]/args["predict_freq"])

    def do_train(max_steps):
        """
        Perform the actural training.
        """
        # max_steps is a bit awkward, but hey, this is tensorflow
        train_spec = tf.estimator.TrainSpec(input_fn=lambda:gen_input_fn(args, "train"), max_steps=max_steps)
        tf.estimator.train_and_evaluate(
            estimator,
            train_spec,
            eval_spec
        )

    def do_predict(max_steps):
        """ Perform predictions."""
        print("-----------------------")
        print("Predictions")

        stats = Counter()

        def get_formatted_predictions():
            predictions = estimator.predict(input_fn=lambda:gen_input_fn(args, "predict"))

            for prediction in predictions:
                o = {}
                for k, v in prediction.items():
                    if k == "input":
                        o[k] = prediction_to_english(v)
                    elif k in ["guided", "target"]:
                        o[k] = [prediction_to_cypher(v)]
                    elif k == "beam":
                        o[k] = [prediction_to_cypher(i) for i in v]

                for i in o["beam"]:
                    if i == o["target"]:
                        stats["correct"] += 1
                    else:
                        stats["incorrect"] += 1

                logger.debug(o)
                yield o

            print(stats)

        with tf.gfile.GFile(os.path.join(args["output_dir"], f"predictions-{max_steps}.yaml"), 'w') as file:
            yaml.dump_all(
                get_formatted_predictions(),
                file,
                default_flow_style=False,
                width=999)

    for i in range(args["predict_freq"]):
        max_steps = steps_per_cycle * (i+1)

        if not args["skip_training"]:
            do_train(max_steps)

        try:
            do_predict(max_steps)

            if args["skip_training"]:
                break

        except Exception:
            traceback.print_exc()
            pass

if __name__ == "__main__":

    def extend(parser):
        parser.add_argument('--skip-training',
                action='store_true',
                help="Whether to skip the training part of not. If yes, then do not perform the training and only perform one prediction.")
        parser.add_argument('--tokenize-data',
                action='store_true',
                help="Whether to perform the tokenize data process or not.")

    args = get_args(extend)

    if args["tokenize_data"]:
        expand_unknowns_and_partition(args)

    train(args)

ext: py

max_stars_repo_name: yuzhiliu/graphqa

reason: import numpy


text:
#!/usr/bin/env python3
"""Transformer model tests."""

import numpy as np
import tensorflow as tf

from lm_human_preferences.utils import core as utils
from lm_human_preferences.language import model

def test_incremental():
    hparams = model.HParams()
    hparams.override_from_dict(dict(
        n_vocab=10,
        n_ctx=5,
        n_embd=9,
        n_head=3,
        n_layer=2,
    ))
    batch_size = 2
    steps = 5
    np.random.seed(7)
    tf.set_random_seed(7)

    # Transformer model
    m = model.Model(hparams=hparams)
    X = tf.placeholder(shape=[batch_size, None], dtype=tf.int32)
    logits = m(X=X)['lm_logits']
    past_p = tf.placeholder(shape=model.past_shape(hparams=hparams, batch_size=batch_size), dtype=tf.float32)
    # Test reusing it in a different variable scope
    with tf.variable_scope('other_scope'):
        past_lm = m(X=X[:,-1:], past=past_p)
    past_logits = past_lm['lm_logits']
    future = tf.concat([past_p, past_lm['present']], axis=-2)

    # Data
    ids = np.random.randint(hparams.n_vocab, size=[batch_size, steps]).astype(np.int32)
    past = np.zeros(model.past_shape(hparams=hparams, batch_size=batch_size, sequence=0), dtype=np.float32)

    # Evaluate
    with tf.Session() as sess:
        tf.global_variables_initializer().run()
        for step in range(steps):
            logits_v, past_logits_v, past = sess.run([logits, past_logits, future],
                                                      feed_dict={X: ids[:,:step+1], past_p: past})
            assert np.allclose(logits_v[:,-1:], past_logits_v, atol=1e-3, rtol=1e-3)

def test_mask():
    np.random.seed(7)
    tf.set_random_seed(7)

    # Make a transformer
    hparams = model.HParams()
    hparams.override_from_dict(dict(
        n_vocab=10,
        n_ctx=8,
        n_embd=3,
        n_head=3,
        n_layer=2,
    ))
    batch_size = 4# 64
    policy = model.Model(hparams=hparams)

    # Random pasts and tokens
    past_length = 4
    length = 3
    past = np.random.randn(*model.past_shape(
        hparams=hparams, batch_size=batch_size, sequence=past_length)).astype(np.float32)
    X = np.random.randint(hparams.n_vocab, size=[batch_size, length])

    # Run model without gaps
    logits = policy(past=past, X=X)['lm_logits']

    # Run the same thing, but with gaps randomly inserted
    gap_past_length = 7
    gap_length = 5
    def random_subsequence(*, n, size):
        # Always make the first token be present, since the model tries to fill gaps with the previous states
        sub = [
            np.concatenate(([0], np.random.choice(np.arange(1,n), size=size-1, replace=False)))
            for _ in range(batch_size)
        ]
        return np.sort(sub, axis=-1)
    past_sub = random_subsequence(n=gap_past_length, size=past_length)
    X_sub = random_subsequence(n=gap_length, size=length)
    past_gap = np.random.randn(*model.past_shape(
        hparams=hparams, batch_size=batch_size, sequence=gap_past_length)).astype(np.float32)
    X_gap = np.random.randint(hparams.n_vocab, size=[batch_size, gap_length])
    mask = np.zeros([batch_size, gap_past_length + gap_length], dtype=np.bool)
    for b in range(batch_size):
        for i in range(past_length):
            past_gap[b,:,:,:,past_sub[b,i]] = past[b,:,:,:,i]
        for i in range(length):
            X_gap[b,X_sub[b,i]] = X[b,i]
        mask[b, past_sub[b]] = mask[b, gap_past_length + X_sub[b]] = 1
    gap_logits = policy(past=past_gap, X=X_gap, mask=mask)['lm_logits']
    sub_logits = utils.index_each(gap_logits, X_sub)

    # Compare
    with tf.Session() as sess:
        tf.global_variables_initializer().run()
        logits, sub_logits = sess.run([logits, sub_logits])
        assert logits.shape == sub_logits.shape
        assert np.allclose(logits, sub_logits, atol=1e-5)

def test_attention_mask():
    with tf.Session() as sess:
        for nd in 1, 2, 3:
            for ns in range(nd, 4):
                ours = model.attention_mask(nd, ns, dtype=tf.int32)
                theirs = tf.matrix_band_part(tf.ones([nd, ns], dtype=tf.int32), tf.cast(-1, tf.int32), ns-nd)
                ours, theirs = sess.run([ours, theirs])
                print(ours)
                print(theirs)
                assert np.all(ours == theirs)

if __name__ == '__main__':
    test_mask()
    test_attention_mask()
    test_incremental()


text:
"""
A module for multi turn dialog.
"""
import csv
from collections import Counter
from itertools import chain
import json

import numpy as np

from .._utils.unordered_hash import UnorderedSha256
from .dataloader import BasicLanguageGeneration
from ..metric import MetricChain, MultiTurnPerplexityMetric, MultiTurnBleuCorpusMetric, \
	MultiTurnDialogRecorder, HashValueRecorder
from ..metric import BleuPrecisionRecallMetric, EmbSimilarityPrecisionRecallMetric

# pylint: disable=W0223
class MultiTurnDialog(BasicLanguageGeneration):
	r"""Base class for multi-turn dialog datasets. This is an abstract class.

	Arguments:{ARGUMENTS}

	Attributes:{ATTRIBUTES}
	"""

	ARGUMENTS = BasicLanguageGeneration.ARGUMENTS
	ATTRIBUTES = BasicLanguageGeneration.ATTRIBUTES

	def __init__(self, \
				 ext_vocab=None, \
				 key_name=None,	\
		):
		ext_vocab = ext_vocab or ["<pad>", "<unk>", "<go>", "<eos>"]
		super().__init__(ext_vocab, key_name)

	def get_batch(self, key, index, needhash=False):
		'''Get a batch of specified `index`.

		Arguments:
			key (str): must be contained in `key_name`
			index (list): a list of specified index

		Returns:
			(dict): A dict at least contains:

				* turn_length(list): A 1-d list, the number of turns in sessions.
					Size: `[batch_size]`
				* sent_length(list): A 2-d non-padded list, the length of sentence in turns.
					The second dimension is various in different session.
					Length of outer list: `[batch_size]`
				* sent(:class:`numpy.array`): A 3-d padding array containing id of words.
					Only provide valid words. `unk_id` will be used if a word is not valid.
					Size: `[batch_size, max(turn_length[i]), max(sent_length)]`
				* sent_allvocabs(:class:`numpy.array`): A 3-d padding array containing id of words.
					Provide both valid and invalid vocabs.
					Size: `[batch_size, max(turn_length[i]), max(sent_length)]`

			See the example belows.

		Examples:
			>>> dataloader.get_batch('train', 1)
			>>>

		Todo:
			* fix the missing example
		'''
		if key not in self.key_name:
			raise ValueError("No set named %s." % key)
		res = {}
		res["turn_length"] = [len(self.data[key]['session'][i]) for i in index]
		res["sent_length"] = []
		for i in index:
			sent_length = [len(sent) for sent in self.data[key]['session'][i]]
			res["sent_length"].append(sent_length)
		res_sent = res["sent"] = np.zeros((len(index), np.max(res['turn_length']), \
			np.max(list(chain(*res['sent_length'])))), dtype=int)
		for i, index_i in enumerate(index):
			for j, sent in enumerate(self.data[key]['session'][index_i]):
				res_sent[i, j, :len(sent)] = sent

		if needhash:
			unordered_hash = UnorderedSha256()
			for j in index:
				unordered_hash.update_data(repr((self.data[key]['session'][j], self.valid_vocab_len)).encode())
			res["hashvalue"] = unordered_hash.digest()
			# hashvalue must be unique for representing the whole batch

		res["sent_allvocabs"] = res_sent.copy()
		res_sent[res_sent >= self.valid_vocab_len] = self.unk_id
		return res

	def multi_turn_trim_index(self, index, turn_length=None, ignore_first_token=False):
		'''Trim indexes for multi turn dialog. There will be 3 steps:
			* For every turn, if there is an `<eos>`, \
				find first `<eos>` and abondon words after it (included the `<eos>`).
			* Ignore `<pad>` s at the end of every turn.
			* When `turn_length` is None, discard the first empty turn and the turn after it. \
				Otherwise, discard the turn according to turn_length.

		Arguments:
			index (list or :class:`numpy.array`): a 2-d array of int.
				Size: `[turn_length, max_sent_length]`
			turn_length (int): Default: None
			ignore_first_token (bool): if True, ignore first token of each turn (must be `<go>`).

		Examples:

		Todo:
			* fix the missing example
		'''
		res = []
		for i, turn_index in enumerate(index):
			if turn_length and i >= turn_length:
				break
			turn_trim = self.trim_index(turn_index)
			if turn_trim and ignore_first_token:
				turn_trim = turn_trim[1:]
			if turn_length is None and (not turn_trim):
				break
			res.append(turn_trim)
		return res

	def multi_turn_sen_to_index(self, session, invalid_vocab=False):
		'''Convert a session from string to index representation.

		Arguments:
			sen (list): a 2-d list of str, representing each token of the session.
			invalid_vocab (bool): whether to provide invalid vocabs.
					If ``False``, invalid vocabs will be trasfered to `unk_id`.
					If ``True``, invalid vocabs will using their own id.
					Default: False

		Examples:

		Todo:
			* fix the missing example
		'''
		if invalid_vocab:
			return list(map(lambda sent: list(map( \
				lambda word: self.word2id.get(word, self.unk_id), sent)), \
			session))
		else:
			return list(map(lambda sent: list(map( \
				self._valid_word2id, sent)), \
			session))

	def multi_turn_index_to_sen(self, index, trim=True, turn_length=None, ignore_first_token=False):
		'''Convert a session from index to string representation

		Arguments:
			index (list or :class:`numpy.array`): a 2-d array of int.
				Size: [turn_length, max_sent_length]
			trim (bool): if True, call :func:`multi_turn_trim_index` before convertion.
			turn_length (int): Only works when trim=True.
				If True, the session is trimmed according the turn_length. Default: None
			ignore_first_token (bool): Only works when trim=True.
				If True, ignore first token of each turn (must be `<go>`).

		Examples:

		Todo:
			* fix the missing example
		'''
		if trim:
			index = self.multi_turn_trim_index(index, turn_length=turn_length, \
				ignore_first_token=ignore_first_token)
		return list(map(lambda sent: \
			list(map(lambda word: self.all_vocab_list[word], sent)), \
			index))

	def get_teacher_forcing_metric(self, gen_log_prob_key="gen_log_prob"):
		'''Get metric for teacher-forcing mode.

		It contains:

		* :class:`.metric.MultiTurnPerplexityMetric`

		Arguments:
			gen_prob_key (str): default: `gen_prob`. Refer to :class:`.metric.PerplexityMetric`
		'''
		metric = MetricChain()
		metric.add_metric(HashValueRecorder(hash_key="teacher_forcing_hashvalue"))
		metric.add_metric(MultiTurnPerplexityMetric(self, gen_log_prob_key=gen_log_prob_key))
		return metric

	def get_inference_metric(self, gen_key="gen"):
		'''Get metric for inference.

		It contains:

		* :class:`.metric.BleuCorpusMetric`
		* :class:`.metric.MultiTurnDialogRecorder`

		Arguments:
			gen_key (str): default: "gen". Refer to :class:`.metric.BleuCorpusMetric` or
					   :class:`.metric.MultiTurnDialogRecorder`
		'''
		metric = MetricChain()
		metric.add_metric(HashValueRecorder(hash_key="inference_hashvalue"))
		metric.add_metric(MultiTurnBleuCorpusMetric(self, gen_key=gen_key))
		metric.add_metric(MultiTurnDialogRecorder(self, gen_key=gen_key))
		return metric

class UbuntuCorpus(MultiTurnDialog):

	'''A dataloder for Ubuntu dataset.

	Arguments:{ARGUMENTS}

	Refer to :class:`.MultiTurnDialog` for attributes and methods.

	Todo:
		* add references
	'''

	ARGUMENTS = r'''
			file_path (str): a str indicates the dir of OpenSubtitles dataset.
			min_vocab_times (int): A cut-off threshold of `UNK` tokens. All tokens appear
				less than `min_vocab_times`	will be replaced by `<unk>`. Default: 10.
			max_sen_length (int): All sentences longer than `max_sen_length` will be shortened
				to first `max_sen_length` tokens. Default: 50.
			max_turn_length (int): All sessions longer than `max_turn_length` will be shortened
				to first `max_turn_length` sentences. Default: 20.
			invalid_vocab_times (int):  A cut-off threshold of invalid tokens. All tokens appear
				not less than `invalid_vocab_times` in the **whole dataset** (except valid words) will be
				marked as invalid words. Otherwise, they are unknown words, both in training or
				testing stages. Default: 0 (No unknown words).
	'''

	def __init__(self, file_path, min_vocab_times=10, max_sen_length=50, max_turn_length=20, \
			invalid_vocab_times=0):
		self._file_path = file_path
		self._min_vocab_times = min_vocab_times
		self._max_sen_length = max_sen_length
		self._max_turn_length = max_turn_length
		self._invalid_vocab_times = invalid_vocab_times
		super(UbuntuCorpus, self).__init__()

	def _load_data(self):
		r'''Loading dataset, invoked by `MultiTurnDialog.__init__`
		'''
		origin_data = {}
		for key in self.key_name:
			with open('%s/ubuntu_corpus_%s.csv' % (self._file_path, key)) as data_file:
				raw_data = list(csv.reader(data_file))
				head = raw_data[0]
				if head[2] == 'Label':
					raw_data = [d[0] + d[1] for d in raw_data[1:] if d[2] == '1.0']
				else:
					raw_data = [d[0] + d[1] for d in raw_data[1:]]

				raw2line = lambda raw: [sent.strip().split() \
						for sent in raw.strip().replace('__eou__', '').split('__eot__')]
				origin_data[key] = {'session': list(map(raw2line, raw_data))}

		raw_vocab_list = list(chain(*chain(*(origin_data['train']['session']))))
		# Important: Sort the words preventing the index changes between different runs
		vocab = sorted(Counter(raw_vocab_list).most_common(), key=lambda pair: (-pair[1], pair[0]))
		left_vocab = list(filter(lambda x: x[1] >= self._min_vocab_times, vocab))
		left_vocab = list(map(lambda x: x[0], left_vocab))
		vocab_list = self.ext_vocab + left_vocab
		valid_vocab_len = len(vocab_list)
		valid_vocab_set = set(vocab_list)

		for key in self.key_name:
			if key == 'train':
				continue
			raw_vocab_list.extend(list(chain(*chain(*(origin_data[key]['session'])))))
		vocab = sorted(Counter(raw_vocab_list).most_common(), \
					   key=lambda pair: (-pair[1], pair[0]))
		left_vocab = list( \
			filter( \
				lambda x: x[1] >= self._invalid_vocab_times and x[0] not in valid_vocab_set, \
				vocab))
		left_vocab = list(map(lambda x: x[0], left_vocab))
		vocab_list.extend(left_vocab)

		print("valid vocab list length = %d" % valid_vocab_len)
		print("vocab list length = %d" % len(vocab_list))

		word2id = {w: i for i, w in enumerate(vocab_list)}
		line2id = lambda line: ([self.go_id] + list(\
					map(lambda word: word2id.get(word, self.unk_id), line)) + \
					[self.eos_id])[:self._max_sen_length]

		data = {}
		data_size = {}
		for key in self.key_name:
			data[key] = {}
			data[key]['session'] = [list(map(line2id, session[:self._max_turn_length])) \
					for session in origin_data[key]['session']]
			data_size[key] = len(data[key]['session'])
			vocab = list(chain(*chain(*(origin_data[key]['session']))))
			vocab_num = len(vocab)
			oov_num = len(list(filter(lambda word: word not in word2id, vocab)))
			invalid_num = len(list(filter(lambda word: word not in valid_vocab_set, vocab))) - oov_num
			sent_length = list(map(len, chain(*origin_data[key]['session'])))
			cut_word_num = np.sum(np.maximum(np.array(sent_length) - self._max_sen_length + 2, 0))
			turn_length = list(map(len, origin_data[key]['session']))
			sent_num = np.sum(turn_length)
			cut_sent_num = np.sum(np.maximum(np.array(turn_length) - self._max_turn_length, 0))
			print(("%s set. invalid rate: %f, unknown rate: %f, max sentence length before cut: %d, " + \
					"cut word rate: %f\n\tmax turn length before cut: %d, cut sentence rate: %f") % \
					(key, invalid_num / vocab_num, oov_num / vocab_num, max(sent_length), \
					cut_word_num / vocab_num, max(turn_length), cut_sent_num / sent_num))
		return vocab_list, valid_vocab_len, data, data_size

class SwitchboardCorpus(MultiTurnDialog):
	'''A dataloder for Switchboard dataset.

	Arguments: {ARGUMENTS}

	Refer to :class:`.MultiTurnDialog` for attributes and methods.

	Todo:
		* add references
	'''

	ARGUMENTS = UbuntuCorpus.ARGUMENTS

	def __init__(self, file_path, min_vocab_times=5, max_sen_length=50, max_turn_length=1000, \
				 invalid_vocab_times=0):
		self._file_path = file_path
		self._min_vocab_times = min_vocab_times
		self._max_sen_length = max_sen_length
		self._max_turn_length = max_turn_length
		self._invalid_vocab_times = invalid_vocab_times

		self.word2id = {}
		super().__init__()

	def _convert2ids(self, origin_data):
		'''Convert topic, da, word to ids, invoked by ^SwitchboardCorpus._load_data^
		and ^SwitchboardCorpus._load_multi_ref_data^

		Arguments:
			origin_data (dict): Contains at least:

				* session (list): A 3-d list, utterances in words.
				  Size of the outermost list: num_data.
				  Size of the second innermost list: num of utterances in a session.
				  Size of the innermost list: num of words in a utterance.

		Returns:
			(dict): Contains:

			* session (list): utterances in ids. Size: same as input
		'''
		data = {}
		sess2id = lambda sess: [([self.go_id] + \
								 list(map(lambda word: self.word2id.get(word, self.unk_id), utt)) + \
								 [self.eos_id])[:self._max_sen_length] for utt in sess]
		data['session'] = list(map(sess2id, origin_data['session']))
		return data

	def _read_file(self, filepath, add_pre_turn=True, add_suf_turn=False):
		'''Reading data from file, invoked by ^SwitchboardCorpus._load_data^
			and ^SwitchboardCorpus._load_multi_ref_data^

		Arguments:
			* filepath (str): Name of the file to read from
			* add_pre_turn (bool): Whether to add turn ^<d>^ ahead of each session
		'''
		origin_data = {'session': []}
		with open(filepath, "r") as data_file:
			for line in data_file:
				line = json.loads(line)
				prefix_utts = [['X', '<d>']] + line['utts']
				# pylint: disable=cell-var-from-loop
				suffix_utts = list(map(lambda utt: utt[1][1].strip() + ' ' \
							if prefix_utts[utt[0]][0] == utt[1][0] \
							else '<eos> ' + utt[1][1].strip() + ' ', enumerate(line['utts'])))
				utts = ('<d> ' + "".join(suffix_utts).strip()).split("<eos>")
				sess = list(map(lambda utt: utt.strip().split(), utts))
				if not add_pre_turn:
					sess = sess[1:]
				if add_suf_turn:
					sess += [['<d>']]
				origin_data['session'].append(sess[:self._max_turn_length])
		return origin_data

	def _build_vocab(self, origin_data):
		r'''Building vocabulary(words, topics, da), invoked by `SwitchboardCorpus._load_data`
		'''
		raw_vocab = list(chain(*chain(*origin_data['train']['session'])))
		vocab = sorted(Counter(raw_vocab).most_common(), key=lambda pair: (-pair[1], pair[0]))
		left_vocab = list(filter(lambda x: x[1] >= self._min_vocab_times, vocab))
		left_vocab = list(map(lambda x: x[0], left_vocab))
		vocab_list = self.ext_vocab + left_vocab
		self.valid_vocab_len = len(vocab_list)
		valid_vocab_set = set(vocab_list)

		for key in self.key_name:
			if key == 'train':
				continue
			raw_vocab.extend(list(chain(*chain(*(origin_data[key]['session'])))))
		vocab = sorted(Counter(raw_vocab).most_common(), key=lambda pair: (-pair[1], pair[0]))
		left_vocab = list(filter(lambda x: \
				x[1] >= self._invalid_vocab_times and x[0] not in valid_vocab_set, vocab))
		left_vocab = list(map(lambda x: x[0], left_vocab))
		vocab_list.extend(left_vocab)

		self.word2id = {w: i for i, w in enumerate(vocab_list)}

		print("valid vocab list length = %d" % self.valid_vocab_len)
		print("vocab list length = %d" % len(vocab_list))
		return vocab_list, valid_vocab_set

	def _load_multi_ref_data(self):
		r'''Loading dataset, invoked by `SwitchboardCorpus._load_data`
		'''
		filename = '%s/switchboard_corpus_multi_ref.jsonl' % self._file_path
		candidate = []
		with open(filename, "r") as data_file:
			idx = 0
			for line in data_file:
				line = json.loads(line)
				utt2id = lambda utt: list(map(lambda w: \
										self.word2id.get(w, self.unk_id), utt[1].strip().split()))
				candidate.append(list(map(utt2id, line['responses'])))
				idx += 1
		return candidate

	def _load_data(self):
		r'''Loading dataset, invoked by `MultiTurnDialog.__init__`
		'''
		origin_data = {}
		self.key_name.append('multi_ref')
		for key in self.key_name:
			origin_data[key] = self._read_file('%s/switchboard_corpus_%s.jsonl' % (self._file_path, key), \
											   add_pre_turn=(key != 'multi_ref'), \
											   add_suf_turn=(key == 'multi_ref'))

		vocab_list, valid_vocab_set = self._build_vocab(origin_data)

		data = {}
		data_size = {s: 0 for s in self.key_name}
		for key in self.key_name:
			data[key] = self._convert2ids(origin_data[key])
			data_size[key] = len(data[key]['session'])

			vocab = list(chain(*chain(*(origin_data[key]['session']))))
			vocab_num = len(vocab)
			oov_num = len(list(filter(lambda word: word not in self.word2id, vocab)))
			invalid_vocab_num = len(list(filter(lambda word: \
											word not in valid_vocab_set, vocab))) - oov_num
			sent_lens = list(map(len, chain(*origin_data[key]['session'])))
			cut_word_num = np.sum(np.maximum(np.array(sent_lens) - self._max_sen_length + 2, 0))
			turn_lens = list(map(len, origin_data[key]['session']))
			cut_sent_num = np.sum(np.maximum(np.array(turn_lens) - self._max_turn_length, 0))
			print(("%s set. invalid rate: %f, unknown rate: %f, max sentence length before cut: %d, " + \
				   "cut word rate: %f\n\tmax turn length before cut: %d, cut sentence rate: %f") % \
				  (key, invalid_vocab_num / vocab_num, oov_num / vocab_num, max(sent_lens), \
				   cut_word_num / vocab_num, max(turn_lens), cut_sent_num / np.sum(turn_lens)))
		data['multi_ref']['candidate'] = self._load_multi_ref_data()
		return vocab_list, len(valid_vocab_set), data, data_size

	def get_batch(self, key, index, needhash=False):
		'''Get a batch of specified `index`.

		Arguments:
			key (str): must be contained in `key_name`
			index (list): a list of specified index
			needhash (bool): whether to return a hashvalue
			  representing this batch of data. Default: False.

		Returns:
			(dict): A dict contains what is in the return of MultiTurnDialog.get_batch.
			  It additionally contains:

				* candidates (list): A 3-d list, multiple responses for reference
				  Size of outermost list: batch_size
				  Size of second innermost list: varying num of references
				  Size of innermost list: varying num of words in a reference

			See the example belows.

		Examples:
			>>> dataloader.get_batch('train', [1])
			>>>

		Todo:
			* fix the missing example
		'''
		res = super().get_batch(key, index)
		gather = lambda sub_key: [self.data[key][sub_key][i] for i in index]
		for sub_key in self.data[key]:
			if sub_key not in res:
				res[sub_key] = gather(sub_key)
		#TODO: add hashvalue for SwitchBoard
		return res

	#TODO: move to inference metric. embedding have to be a property of dataloader
	def get_precision_recall_metric(self, embed):
		'''Get metrics for precision and recall in terms of BLEU, cosine similarity.

		It contains:

		* :class:`.metric.PrecisionRecallMetric`

		Arguments:
			embed (:class:`numpy.array`): Glove word embedding
		'''
		metric = MetricChain()
		for ngram in range(1, 5):
			metric.add_metric(BleuPrecisionRecallMetric(self, ngram))
		metric.add_metric(EmbSimilarityPrecisionRecallMetric(self, embed, 'avg'))
		metric.add_metric(EmbSimilarityPrecisionRecallMetric(self, embed, 'extrema'))
		return metric


text:
import sys
import cv2
import numpy as np
import pytesseract
from textblob import Word
from PIL import Image,ImageEnhance,ImageFilter

#Capturing the image from camera
cam = cv2.VideoCapture(0)

while True:
        ret, frame = cam.read()
        #Converting image to gray
        gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        #Applying Threshold
        thresh = cv2.threshold(gray,100,200,cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
        #Setting the kernel
        kernel = np.ones((5,5),np.uint8)
        #Dilating
        thresh_dilated = cv2.dilate(thresh, kernel, iterations=0)
        #Displaying the window for camera
        cv2.imshow('window',thresh_dilated)
        #Saving the image
        cv2.imwrite(r'/home/vatsalbabel/Desktop/capture.png',thresh_dilated)
        #Reading the image
        im=Image.open(r'/home/vatsalbabel/Desktop/capture.png')
        #Filtering the noise and enhancing the image
        im=im.filter(ImageFilter.MedianFilter())
        enhancer=ImageEnhance.Contrast(im)
        im=enhancer.enhance(5)
        im=im.convert('1')
        #Saving the image
        im.save(r'/home/vatsalbabel/Desktop/final.jpg')
        #Reading the image
        toString_image = Image.open(r'/home/vatsalbabel/Desktop/final.jpg')
        #Getting the text from the image using pytesseract
        recogs = pytesseract.image_to_string(toString_image)

        #Showing the confidence percentage and suggestion
        if len(str(recogs))!=0:
            recogs = recogs.lower()
            recogs = recogs.strip()
            recogs = recogs.replace('\\',' ')

            #Suggestion module
            try:
                list_sugg = []
                list_of_words = recogs.split()
                for i in list_of_words:
                    word = Word(i)
                    list_sugg.append(str(word.spellcheck()[0][0]))
                recogs = " ".join(list_sugg)
            except:
                pass
            sys.stdout.write(recogs)

            #Confidence module
            recogs = recogs.strip()
            recogs = recogs.replace('\\',' ')
            list_of_words = str(recogs).split()
            confidence_per = 0
            count = 0
            for i in list_of_words:
                try:
                    word = Word(str(i))
                    confidence_per += float(word.spellcheck()[0][1])
                    count += 1
                    confidence_per /= count
                except:
                    pass

            #sys.stdout.write("\tConfidence Level: "+str(confidence_per*100))
            print
        #'q' for exit
        if cv2.waitKey(1) &0xFF == ord('q'):
            break

#Exiting
cam.release()
cv2.destroyAllWindows()


text:
import os  # isort: skip

from time import time

import cv2
import numpy as np
import torch
import matplotlib.pyplot as plt

from tqdm import tqdm
from torch.utils.data import DataLoader

import segmentation_models_pytorch as smp

from utils import configuration
from utils.dataset import SegmDataset
from utils.build_model import build_model
from utils.augmentations import get_preprocessing, apply_validation_augmentation  # apply_preprocessing,

def setup_system(system_config: configuration.System) -> None:
    torch.manual_seed(system_config.seed)

def denormalize(x):
    """Scale image to range 0..1 for correct plot"""
    x_max = np.percentile(x, 98)
    x_min = np.percentile(x, 2)
    x = (x - x_min) / (x_max - x_min)
    x = x.clip(0, 1)
    return x

def main(system_config=configuration.System):

    os.environ['CUDA_VISIBLE_DEVICES'] = '0, 1'
    setup_system(system_config)

    img_dir = os.path.join(configuration.DataSet.root_dir, configuration.DataSet.img_val_dir)
    gt_dir = os.path.join(configuration.DataSet.root_dir, configuration.DataSet.mask_val_dir)

    net = build_model(configuration)

    net.load_state_dict(
        torch.load('./outputs/mobilenet_v2+deeplab_v3+_2020-05-25-22-18/best_model.pth')['model_state_dict']
    )
    net.to(configuration.Trainer.device)
    print(net)
    preprocessing_fn = smp.encoders.get_preprocessing_fn(
        configuration.Model.encoder, configuration.Model.encoder_weights
    )
    val_dataset = SegmDataset(
        img_dir,
        gt_dir,
        classes=configuration.DataSet.classes,
        augmentations=apply_validation_augmentation(),
        preprocessing=get_preprocessing(preprocessing_fn)
    )

    dataloaders = DataLoader(
        val_dataset, batch_size=1, shuffle=True, num_workers=configuration.DataLoader.num_workers
    )
    count = 0
    possible_classes = (
        'sky', 'building', 'pole', 'road', 'pavement', 'tree', 'signsymbol', 'fence', 'car', 'pedestrian',
        'bicyclist', 'unlabelled'
    )
    start = time()
    for image, gt_mask in tqdm(dataloaders):
        count += 1
        image = image.to(configuration.Trainer.device)
        pr_masks = net.predict(image)
        image = image.squeeze(0).permute(1, 2, 0).detach().cpu().numpy()
        pr_masks = pr_masks.squeeze(0).permute(1, 2, 0).detach().cpu()
        pr_masks = pr_masks.softmax(dim=-1)
        gt_mask = gt_mask.squeeze(0).permute(1, 2, 0).detach().cpu()
        pr_masks = pr_masks.argmax(dim=-1)
        gt_mask = gt_mask.argmax(dim=-1)
        plt.subplot(131)
        plt.imshow(denormalize(image))
        plt.grid(False)
        plt.xticks([])
        plt.yticks([])
        plt.title('Image')
        plt.subplot(132)
        plt.imshow(gt_mask.numpy())
        plt.grid(False)
        plt.xticks([])
        plt.yticks([])
        plt.title('GT Mask')
        plt.subplot(133)
        plt.imshow(pr_masks.numpy())
        plt.grid(False)
        plt.xticks([])
        plt.yticks([])
        plt.title('Predicted')
        plt.savefig(f'./vis_images/inference/{count}.png')
    #     i = 0
    #     plt.figure(figsize=(30, 70))
    #     for j in range(12):
    #         plt.subplot(7, 2, j + 1)
    #         if j % 2 == 0:
    #             plt.title(f'GT {possible_classes[i]}', fontsize=48)
    #             plt.xticks([])
    #             plt.yticks([])
    #             plt.imshow(gt_mask[..., i])
    #         else:
    #             plt.title(f'Predicted {possible_classes[i]}', fontsize=48)
    #             plt.xticks([])
    #             plt.yticks([])
    #             pr_masks[..., i][pr_masks[..., i] >= 0.5] = 1
    #             pr_masks[..., i][pr_masks[..., i] < 0.5] = 0
    #             plt.imshow(pr_masks[..., i])
    #             i += 1
    #     plt.savefig(f'./vis_images/inference/{count}_1.png')
    #     plt.figure(figsize=(30, 70))
    #     for j in range(12):
    #         plt.subplot(7, 2, j + 1)
    #         if j % 2 == 0:
    #             plt.title(f'GT {possible_classes[i]}', fontsize=48)
    #             plt.xticks([])
    #             plt.yticks([])
    #             plt.imshow(gt_mask[..., i])
    #         else:
    #             plt.title(f'Predicted {possible_classes[i]}', fontsize=48)
    #             plt.xticks([])
    #             plt.yticks([])
    #             pr_masks[..., i][pr_masks[..., i] >= 0.5] = 1
    #             pr_masks[..., i][pr_masks[..., i] < 0.5] = 0
    #             plt.imshow(pr_masks[..., i])
    #             i += 1
    #     plt.savefig(f'./vis_images/inference/{count}_2.png')
    # print('FPS: ', (time() - start) / len(dataloaders))

if __name__ == '__main__':
    main()


text:
import numpy as np
import pandas as pd
from pandas import concat
import matplotlib
import seaborn as sns
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')

sma30 = []
sma100 = []

for i, bank in enumerate(ib_bank_list, 1):
    plt.subplot(2, 2, i)

    avg30day = pd.DataFrame()
    avg30day['close'] = bank['close'].rolling(window = 30).mean()
    sma30.append(avg30day)

    avg100day = pd.DataFrame()
    avg100day['close'] = bank['close'].rolling(window = 100).mean()
    sma100.append(avg100day)

max_stars_repo_name: nialky/stock-signal

max_issues_repo_name: nialky/stock-signal

max_forks_repo_name: nialky/stock-signal


text:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Collects the feature values from many different feature extractors.

Created on Wed Sep 29 12:36:01 2021

@author: lbechberger
"""

import pdb
import numpy as np
from code.feature_extraction.feature_extractor import FeatureExtractor

# extend FeatureExtractor for the sake of simplicity
class FeatureCollector(FeatureExtractor):

    # constructor
    def __init__(self, features):

        # store features
        self._features = features

        # collect input columns
        input_columns = []
        for feature in self._features:
            input_columns += feature.get_input_columns()

        # remove duplicate columns
        input_colums = list(set(input_columns))

        # call constructor of super class
        super().__init__(input_columns, "FeatureCollector")

    # overwrite fit: instead of calling _set_variables(), we forward the call to the features
    def fit(self, df):

        for feature in self._features:
            feature.fit(df)

    # overwrite transform: instead of calling _get_values(), we forward the call to the features
    def transform(self, df):

        all_feature_values = []

        for feature in self._features:
            # loop over each dimension and append it:
            # multi dimension feature -> create multiple columns
            for col in feature.transform(df).T:
                all_feature_values.append(col)

        result = np.array(all_feature_values).T
        return result

    def get_feature_names(self, df):
        feature_names = []
        for feature in self._features:
            dim = feature.transform(df).shape
            # append the name of a feature
            # one dimension feature
            if dim[1] == 1:
                feature_names.append(feature.get_feature_name())
            # multi dimension feature -> create multiple columns
            else:
                feature_names += [
                    feature.get_feature_name() + "_{0}".format(ind + 1)
                    for ind in range(dim[1])
                ]

        return feature_names

max_stars_repo_name: avocardio/MLinPractice

max_issues_repo_name: avocardio/MLinPractice

max_forks_repo_name: avocardio/MLinPractice


text:
"""

Cyro電子顕微鏡で撮影したデータをするソフトウェア｡
主に､画像上のタンパク質の座標を抽出し､データベースと比較するときに使う｡
下の3つの機能がある｡

* 基準点のxyz座標から､指定されたパターンの点を生成する
* 生成された点ごとに､y軸を中心として始点からの距離に応じて回転させる
* 基準点の並びを直線と考え､y軸と並行に向けるためのオイラー角を計算する

Todo:
    * 回転角度/Åを自動で計算させる
    * docstringを充実させる

"""
import PySimpleGUI as sg
from typing import Optional, Any
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import pandas as pd
import math
import os
from scipy.spatial.transform import Rotation as Rot
from scipy import interpolate

class Calculator:
    """演算とファイル入出力を担当するclass"""

    def __init__(self):
        # 座標ファイルのPath
        self.input_file_path: str = ""
        # ファイルから読み込んだ基準点
        self.df_base_coordinates: Optional[pd.DataFrame] = None
        # 生成された点
        self.df_generated_coordinates: Optional[pd.DataFrame] = None
        # 生成されたオイラー角
        self.df_euler_degree: Optional[pd.DataFrame] = None
        # y軸並行にするためのRot
        self.rot2y: Optional[Rot] = None

    def load_text_file(self, path: str):
        self.input_file_path = path
        coordinates = []
        with open(path) as f:
            print("opened file: " + self.input_file_path)
            for line in f:
                coordinates.append(list(map(float, line.split())))
        print("reading file is completed")
        self.df_base_coordinates = pd.DataFrame(coordinates, columns=["x", "y", "z"])
        self.df_generated_coordinates = None
        print("converting read data is completed")

    def _save_df(self, df: pd.DataFrame, file_name: str):
        print("writing into " + file_name)
        with open(file_name, "w") as f:
            for _, row in df.iterrows():
                f.write(str(row[0]) + " " + str(row[1]) + " " + str(row[2]) + "\n")
        print("writing completed")

    def _add_suffix2path(self, file_path, suffix):
        dir_name = os.path.dirname(file_path)
        base_name = os.path.basename(file_path.split(".", 1)[0])
        ext = os.path.splitext(file_path)[1]
        return dir_name + os.sep + base_name + suffix + ext

    def save_positions(self):
        if self.df_generated_coordinates is not None:
            position_file_path = self._add_suffix2path(
                self.input_file_path, "_position"
            )
            self._save_df(self.df_generated_coordinates, position_file_path)

    def save_rotations(self):
        if self.df_euler_degree is not None:
            rotation_file_path = self._add_suffix2path(
                self.input_file_path, "_rotation"
            )
            self._save_df(self.df_euler_degree, rotation_file_path)

    def plot(self, ax):
        assert self.df_base_coordinates is not None
        ax.clear()
        ax.set_xlabel("x")
        ax.set_ylabel("y")
        ax.set_zlabel("z")

        ax.scatter3D(self.df_base_coordinates["x"].values, self.df_base_coordinates["y"].values, self.df_base_coordinates["z"].values, color="r")  # type: ignore

        # グラフに表示するデータ。軸のスケールを揃えるのに使う
        df_all = self.df_base_coordinates.copy(deep=True)

        # 点が生成されている場合
        if self.df_generated_coordinates is not None:
            ax.scatter3D(self.df_generated_coordinates["x"].values, self.df_generated_coordinates["y"].values, self.df_generated_coordinates["z"].values, color="b", alpha=0.2)  # type: ignore
            ax.legend(["Original", "Generated"])

            df_all = pd.concat([df_all, self.df_generated_coordinates])

        else:
            ax.legend(["Original"])

        # 角軸のスケールを揃える
        x_max, y_max, z_max = df_all.max()
        x_min, y_min, z_min = df_all.min()
        max_range = max([x_max - x_min, y_max - y_min, z_max - z_min]) / 2

        x_mid = (x_min + x_max) / 2
        y_mid = (y_min + y_max) / 2
        z_mid = (z_min + z_max) / 2

        ax.set_xlim(x_mid - max_range, x_mid + max_range)
        ax.set_ylim(y_mid - max_range, y_mid + max_range)
        ax.set_zlim(z_mid - max_range, z_mid + max_range)

    def calculate_rot2y(self):
        """self.df_base_coordinatesの直線をy軸に並行にするRotを返す

        self.df_base_coordinatesには､複数の基準点が入っている｡
        基準点を直線と考え､y軸に並行な向きにするためにどう回転させるかを計算する｡

        raises:
            AssertionError: self.df_base_coordinatesがNoneの場合
        """
        assert self.df_base_coordinates is not None

        df_arrows: pd.DataFrame = self.df_base_coordinates.copy(deep=True)

        # 点同士を結ぶ直線のベクトルを計算する
        df_arrows = df_arrows.diff()
        df_arrows.drop(0, inplace=True)

        # ベクトルのx,y,z成分をそれぞれ抽出
        x: np.ndarray = df_arrows["x"].values  # type: ignore
        y: np.ndarray = df_arrows["y"].values  # type: ignore
        z: np.ndarray = df_arrows["z"].values  # type: ignore

        x = x.mean()
        y = y.mean()
        z = z.mean()

        # (x,y,z)の順番に回転角を計算
        radians = [
            -math.atan2(z, y),
            0,  # y軸に向けるので0
            math.atan2(x, math.sqrt(y ** 2 + z ** 2)),
        ]

        # 回転軸を設定
        axes = [np.array([1, 0, 0]), np.array([0, 1, 0]), np.array([0, 0, 1])]

        # 回転ベクトル
        vectors = [radians[i] * axes[i] for i in range(len(radians))]

        # Rotオブジェクト
        rots = [Rot.from_rotvec(vec) for vec in vectors]

        # Rotオブジェクト(x,y,zの順番に掛け合わせている)
        self.rot2y = rots[2] * rots[1] * rots[0]

        # 計算結果を保存
        rot_x, rot_y, rot_z = self.rot2y.as_euler('zxz',degrees=True)
        self.df_euler_degree = pd.DataFrame(
            [[math.degrees(rot_x), math.degrees(rot_y), math.degrees(rot_z)]],
            columns=["x", "y", "z"],
        )

    def _calc_spline(self):
        assert self.df_base_coordinates is not None
        base_x: np.ndarray = self.df_base_coordinates["x"].values  # type: ignore
        base_y: np.ndarray = self.df_base_coordinates["y"].values  # type: ignore
        base_z: np.ndarray = self.df_base_coordinates["z"].values  # type: ignore

        spline_tck, _ = interpolate.splprep([base_x, base_y, base_z])  # type: ignore

        # スプライン曲線の長さを計算する
        t = np.linspace(0, 1, 1000)

        x, y, z = interpolate.splev(t, spline_tck)
        x = np.diff(x)
        y = np.diff(y)
        z = np.diff(z)

        spline_length = np.sum(np.sqrt(x ** 2 + y ** 2 + z ** 2))
        return spline_tck, spline_length

    def _calculate_pitch_rotation(
        self,
        t: np.ndarray,
        spline_length: float,
        angstrom_per_pixel: float,
        pitch_degree: float,
        pitch_nm: float,
    ):
        try:
            pitch_radian_per_angstrom = math.radians(pitch_degree) / (pitch_nm * 10)
        except OverflowError:
            return
        except ZeroDivisionError:
            return

        # 始点からの距離に対して, pitchを適用する

        # 生成点ごとの回転角を計算する
        radians = t * spline_length * angstrom_per_pixel * pitch_radian_per_angstrom

        # y軸を中心としてradianだけ回転させるRotオブジェクト
        rot_y_axis: Rot = Rot.from_rotvec(
            np.array(
                [np.zeros(radians.shape[0]), radians, np.zeros(radians.shape[0])]
            ).T
        )

        assert self.rot2y is not None
        # 全体のRotオブジェクト
        rot_whole = rot_y_axis * self.rot2y

        # 全体の回転ベクトル
        rot_whole_vectors = rot_whole.as_euler('zxz', degrees=True)  # type: ignore

        self.df_euler_degree = pd.DataFrame()
        self.df_euler_degree["x"] = rot_whole_vectors[:, 0]
        self.df_euler_degree["y"] = rot_whole_vectors[:, 1]
        self.df_euler_degree["z"] = rot_whole_vectors[:, 2]

    def generate_along_line(
        self,
        angstrom_per_pixel: float,
        distance_nm: float,
        pitch_degree: Optional[float] = None,
        pitch_nm: Optional[float] = None,
    ):
        spline_tck, spline_length = self._calc_spline()

        distance_angstrom = distance_nm * 10

        try:
            if distance_angstrom == 0:
                raise OverflowError
            num = int(spline_length * angstrom_per_pixel / distance_angstrom)
        except OverflowError:
            # 値をユーザーが入力中
            self.reset_calculation()
            return

        if num == 0:
            return

        # 媒介変数t. 0<=t<=1でスプライン曲線の始点から終点までをカバーできる
        t = np.linspace(0, 1, num)
        x, y, z = interpolate.splev(t, spline_tck)
        self.df_generated_coordinates = pd.DataFrame()
        self.df_generated_coordinates["x"] = x
        self.df_generated_coordinates["y"] = y
        self.df_generated_coordinates["z"] = z

        if pitch_degree is not None and pitch_nm is not None:
            self._calculate_pitch_rotation(
                t, spline_length, angstrom_per_pixel, pitch_degree, pitch_nm
            )
        else:
            self.df_euler_degree = None

    def generate_in_column(
        self,
        angstrom_per_pixel: float,
        radius_nm: float,
        point_number: int,
        pitch_degree: Optional[float] = None,
        pitch_nm: Optional[float] = None,
    ):
        """スプライン曲線を中心とした円柱の中で、ランダムに点を生成する

        数学的な計算方法:
            目標: スプライン曲線の方向と垂直な平面でthetaとrを指定したい

            (以下の処理は、生成された点ごとにそれぞれ別の原点を用意する)
            スプライン曲線上に生成された点をある原点とし、
            生データのデカルト座標系を平行移動させた座標系で議論する

            スプライン曲線を微分し、スプライン曲線の方向を示す単位ベクトル(dx, dy, dz)を計算する
            点(dx, dy, 0)と原点を結ぶ直線と垂直で、かつ原点を通る直線をxy平面上で求める
            その直線の単位ベクトルを、vertical_vector とする

            xy平面上のvertical_vectorを3次元座標系に変換する(z=0を付け加えるだけ)
            vertical_vector を回転ベクトル(dx * theta, dy * theta, dz * theta)で回転させ、r倍すると、求めたい座標を得られる

            theta,rを計算する平面とその軸は(dx, dy, dz)に依存するが、r,thetaともに乱数で、ランダムな座標が得られれば良いので、問題ないと考えた
        """

        try:
            radius_pixel = radius_nm * 10 / angstrom_per_pixel
        except (OverflowError, ZeroDivisionError):
            # 値をユーザーが入力中
            self.reset_calculation()
            return

        if point_number <= 0:
            return

        spline_tck, spline_length = self._calc_spline()

        theta = np.random.uniform(0, math.pi * 2, point_number)
        r = np.sqrt(np.random.uniform(0, radius_pixel ** 2, point_number))
        # 媒介変数t(0<=t<=1)でスプライン曲線上での位置を指定する
        t = np.linspace(0, 1, point_number)

        # スプライン曲線上でのある位置のベクトルを求めるために使う
        dt = 1 / point_number / 10

        x, y, z = interpolate.splev(t, spline_tck)
        x_plus_dx, y_plus_dy, z_plus_dz = interpolate.splev(t + dt, spline_tck)

        dx = x_plus_dx - x
        dy = y_plus_dy - y
        dz = z_plus_dz - z

        abs_delta = np.sqrt(dx ** 2 + dy ** 2 + dz ** 2)
        dx /= abs_delta
        dy /= abs_delta
        dz /= abs_delta

        # xy平面上の、ベクトル(dx, dy, dz)と垂直な単位ベクトル
        vertical_vector = np.array(
            [
                dy / np.sqrt(dx ** 2 + dy ** 2),
                -dx / np.sqrt(dx ** 2 + dy ** 2),
                np.zeros(point_number),
            ]
        ).T

        rot_vector = Rot.from_rotvec(np.array([dx * theta, dy * theta, dz * theta]).T)
        rotated_vector = rot_vector.apply(vertical_vector)

        self.df_generated_coordinates = pd.DataFrame(columns=["x", "y", "z"])
        self.df_generated_coordinates["x"] = rotated_vector[:, 0] * r + x
        self.df_generated_coordinates["y"] = rotated_vector[:, 1] * r + y
        self.df_generated_coordinates["z"] = rotated_vector[:, 2] * r + z

        if pitch_degree is not None and pitch_nm is not None:
            self._calculate_pitch_rotation(
                t, spline_length, angstrom_per_pixel, pitch_degree, pitch_nm
            )

    def reset_calculation(self):
        """ファイルをロードした時点まで戻る"""
        self.df_generated_coordinates = None
        self.df_euler_degree = None
        self.calculate_rot2y()

class GUI:
    """表示部分を担当するclass

    表示する画面のデザイン・管理を担当する

    """

    def __init__(self):
        self.calculator = Calculator()
        self.font = "Calibri"
        self.fontsize = {
            "title": 50,
            "default": 30,
            "detail": 15,
        }
        self.colors = {
            "default_button": ("#FFFFFF", "#283b5b"),
            "special_button": "royalblue",
            "special_title": "royalblue",
        }
        # 1~3のみ
        self.step: int = 1

        self.window = None
        # window の位置
        self.window_location = None

        # グラフ描画用
        self.figure = plt.figure()
        self.ax = self.figure.add_subplot(111, projection="3d")

        # ユーザーが入力したデータを保存する｡(Backボタン用)
        self.parameters = {
            "STEP1": {
                "-PATH POSITION FILE-": "",
                "-PATH MRC FILE-": "",
            },
            "STEP2": {
                "-ALONG LINE-": False,
                "-IN COLUMN-": False,
                "-ROTATION FOR Y AXIS-": False,
                "-ROTATION FOR ROTATING PROTAIN-": False,
            },
            "STEP3": {
                "-ANGSTROM PER PIXEL-": "",
                "-POINT DISTANCE-": "",
                "-MAX RADIUS-": "",
                "-POINT NUMBER-": "",
                "-PITCH DEGREE-": "",
                "-PITCH DISTANCE-": "",
            },
        }

    def _create_layout(self):
        def _layout_header():
            padding = 30
            return sg.Column(
                [
                    [
                        sg.Text(
                            "Choose File",
                            font=(self.font, self.fontsize["title"]),
                            pad=(padding, 0),
                            justification="center",
                            key="-STEP1 TITLE-",
                        ),
                        sg.Text(
                            "->",
                            font=(self.font, self.fontsize["default"]),
                            justification="center",
                        ),
                        sg.Text(
                            "Select type",
                            font=(self.font, self.fontsize["title"]),
                            pad=(padding, 0),
                            justification="center",
                            key="-STEP2 TITLE-",
                        ),
                        sg.Text(
                            "->",
                            font=(self.font, self.fontsize["default"]),
                            justification="center",
                        ),
                        sg.Text(
                            "Set parameter",
                            font=(self.font, self.fontsize["title"]),
                            pad=(padding, 0),
                            justification="center",
                            key="-STEP3 TITLE-",
                        ),
                    ]
                ],
                pad=((0, 0), (0, 50)),
            )

        def _layout_foot():
            padding_center = 30

            back_button = sg.Button(
                "Back",
                font=(self.font, self.fontsize["default"]),
                pad=(padding_center, 0),
                key="-BACK-",
            )

            next_button = sg.Button(
                "Next",
                font=(self.font, self.fontsize["default"]),
                tooltip="You can return to this display later",
                pad=(padding_center, 0),
                key="-NEXT-",
            )

            save_button = sg.Button(
                "Save",
                font=(self.font, self.fontsize["default"]),
                pad=(padding_center, 0),
                key="-SAVE-",
            )

            return sg.Column(
                [[back_button, next_button, save_button]], justification="center"
            )

        def _layout_step1():
            padding_center = 40
            padding_top = 60
            padding_bottom = 60
            input_text_size = 40

            position_title = sg.Text(
                "Position File",
                font=(self.font, self.fontsize["default"]),
                justification="center",
                expand_x=True,
            )
            position_file = [
                sg.InputText(
                    size=input_text_size,
                    font=(self.font, self.fontsize["detail"]),
                    key="-PATH POSITION FILE-",
                ),
                sg.FileBrowse(
                    "Open",
                    font=(self.font, self.fontsize["default"]),
                    file_types=(
                        ("Text files", "*.txt"),
                        ("All files", "*"),
                    ),
                ),
            ]
            column_position = sg.Column(
                [[position_title], position_file],
                pad=((0, padding_center), (padding_top, padding_bottom)),
            )

            mrc_title = sg.Text(
                "MRC File",
                font=(self.font, self.fontsize["default"]),
                justification="center",
                expand_x=True,
            )
            mrc_file = [
                sg.InputText(
                    size=input_text_size,
                    key="-PATH MRC FILE-",
                    font=(self.font, self.fontsize["detail"]),
                ),
                sg.FileBrowse(
                    "Open",
                    font=(self.font, self.fontsize["default"]),
                    file_types=(
                        ("MRC files", "*.mrc"),
                        ("All files", "*"),
                    ),
                ),
            ]
            column_mrc = sg.Column(
                [[mrc_title], mrc_file],
                pad=((padding_center, 0), (padding_top, padding_bottom)),
            )

            return sg.Column([[column_position, column_mrc]], justification="center")

        def _layout_step2():
            padding = 20
            line_button = sg.Button(
                "Along Line",
                tooltip="入力ファイルから読み取った基準点からスプライン曲線もどきを生成します。\n"
                + "その後、スプライン曲線上に指定の間隔で点を生成・出力できます。",
                font=(self.font, self.fontsize["default"]),
                pad=padding,
                key="-ALONG LINE-",
            )
            column_button = sg.Button(
                "In Column",
                font=(self.font, self.fontsize["default"]),
                tooltip="入力ファイルから読み取った基準点からスプライン曲線もどきを生成します。\n"
                + "その後、スプライン曲線を中心とした円柱を生成し、円柱内でランダムに点を生成・出力できます。",
                pad=padding,
                key="-IN COLUMN-",
            )
            rot2y_button = sg.Button(
                "Rotation for y axis",
                font=(self.font, self.fontsize["default"]),
                tooltip="入力ファイルから読み取った基準点を直線に近似し、\n" + "その直線をy軸に平行にできる回転ベクトルを出力します。",
                pad=padding,
                key="-ROTATION FOR Y AXIS-",
            )
            pitch_button = sg.Button(
                "Rotation for rotating protain",
                font=(self.font, self.fontsize["default"]),
                tooltip="入力ファイルから読み取った基準点からスプライン曲線もどきを生成します。\n"
                + "その後、スプライン曲線の周りでらせんを描く構造があると仮定し、\n"
                + "らせんをy軸に平行にできる回転ベクトルを出力します。\n"
                + "この回転ベクトルは、Rotation for y axisの回転ベクトルと合成されています。",
                pad=padding,
                key="-ROTATION FOR ROTATING PROTAIN-",
            )
            frame_generation = sg.Frame(
                "Position Generation",
                [[line_button], [column_button]],
                font=(self.font, self.fontsize["default"]),
                element_justification="center",
                pad=padding,
            )
            frame_calc = sg.Frame(
                "Rotation Calculation",
                [[rot2y_button], [pitch_button]],
                font=(self.font, self.fontsize["default"]),
                element_justification="center",
                pad=padding,
            )
            return sg.Column([[frame_generation, frame_calc]], justification="center")

        def _layout_step3():
            input_text_size = 10
            padding = 20
            column_name = sg.Column(
                [
                    [
                        sg.Text(
                            "Angstrom / pixel",
                            font=(self.font, self.fontsize["default"]),
                        ),
                    ],
                    [
                        sg.Text(
                            "Point Distance (nm)",
                            font=(self.font, self.fontsize["default"]),
                        ),
                    ],
                    [
                        sg.Text(
                            "Max Radius (nm)",
                            font=(self.font, self.fontsize["default"]),
                        )
                    ],
                    [
                        sg.Text(
                            "Point Number",
                            font=(self.font, self.fontsize["default"]),
                        ),
                    ],
                    [
                        sg.Text(
                            "Pitch Degree", font=(self.font, self.fontsize["default"])
                        ),
                    ],
                    [
                        sg.Text(
                            "Pitch Distance (nm)",
                            font=(self.font, self.fontsize["default"]),
                        ),
                    ],
                ],
            )
            column_input_text = sg.Column(
                [
                    [
                        sg.InputText(
                            key="-ANGSTROM PER PIXEL-",
                            size=input_text_size,
                            font=(self.font, self.fontsize["default"]),
                            enable_events=True,
                        ),
                    ],
                    [
                        sg.InputText(
                            key="-POINT DISTANCE-",
                            size=input_text_size,
                            font=(self.font, self.fontsize["default"]),
                            enable_events=True,
                        ),
                    ],
                    [
                        sg.InputText(
                            key="-MAX RADIUS-",
                            size=input_text_size,
                            font=(self.font, self.fontsize["default"]),
                            enable_events=True,
                        )
                    ],
                    [
                        sg.InputText(
                            key="-POINT NUMBER-",
                            size=input_text_size,
                            font=(self.font, self.fontsize["default"]),
                            enable_events=True,
                        ),
                    ],
                    [
                        sg.InputText(
                            key="-PITCH DEGREE-",
                            size=input_text_size,
                            font=(self.font, self.fontsize["default"]),
                            enable_events=True,
                        ),
                    ],
                    [
                        sg.InputText(
                            key="-PITCH DISTANCE-",
                            size=input_text_size,
                            font=(self.font, self.fontsize["default"]),
                            enable_events=True,
                        ),
                    ],
                ],
                pad=padding,
            )
            canvas_plot = sg.Canvas(key="-PLOT CANVAS-")

            return sg.Column(
                [[column_name, column_input_text, canvas_plot]], justification="center"
            )

        def _layout_main():
            if self.step == 1:
                return _layout_step1()
            elif self.step == 2:
                return _layout_step2()
            elif self.step == 3:
                return _layout_step3()
            else:
                raise ValueError("self.step is " + str(self.step))

        layout = [
            [_layout_header()],
            [_layout_main()],
            [_layout_foot()],
        ]

        if self.window is not None:
            self.window_location = self.window.CurrentLocation()
            self.window.close()
            self.window: Any = sg.Window(
                "Hikaru's Magic Software",
                layout,
                finalize=True,
                location=self.window_location,
            )
        else:
            self.window: Any = sg.Window(
                "Hikaru's Magic Software",
                layout,
                finalize=True,
            )

        # 状況に応じた調整
        self.window["-STEP" + str(self.step) + " TITLE-"].update(
            background_color=self.colors["special_title"]
        )

        if self.step == 1:
            self.window["-BACK-"].update(visible=False)
            self.window["-SAVE-"].update(visible=False)
            for key in self.parameters["STEP1"].keys():
                self.window[key].update(self.parameters["STEP1"][key])
        elif self.step == 2:
            self.window["-SAVE-"].update(visible=False)
            for key in self.parameters["STEP2"].keys():
                if self.parameters["STEP2"][key] is True:
                    self.window[key].update(button_color=self.colors["special_button"])
        elif self.step == 3:
            self.window["-NEXT-"].update(visible=False)

            # 保存されていた値を画面上に表示
            for key in self.parameters["STEP3"].keys():
                self.window[key].update(self.parameters["STEP3"][key])

            # オプションに合わせていらない入力ができないようにする
            if self.parameters["STEP2"]["-ALONG LINE-"] is False:
                self.window["-POINT DISTANCE-"].update(visible=False)
            if self.parameters["STEP2"]["-IN COLUMN-"] is False:
                self.window["-MAX RADIUS-"].update(visible=False)
                self.window["-POINT NUMBER-"].update(visible=False)
            if self.parameters["STEP2"]["-ROTATION FOR ROTATING PROTAIN-"] is False:
                self.window["-PITCH DEGREE-"].update(visible=False)
                self.window["-PITCH DISTANCE-"].update(visible=False)

            if (
                self.parameters["STEP2"]["-ALONG LINE-"] is False
                and self.parameters["STEP2"]["-IN COLUMN-"] is False
                and self.parameters["STEP2"]["-ROTATION FOR ROTATING PROTAIN-"] is False
            ):
                self.window["-ANGSTROM PER PIXEL-"].update(visible=False)

            # figure と canvas を紐付ける
            self.figure_canvas = FigureCanvasTkAgg(
                self.figure, self.window["-PLOT CANVAS-"].TKCanvas
            )
            self.figure_canvas.draw()
            self.figure_canvas.get_tk_widget().pack(side="top", fill="both", expand=1)

            self._calculate_graph()
            self._plot()

        else:
            assert ValueError("self.step is " + str(self.step))

        return

    def _calculate_graph(self):
        """条件にしたがって、self.calculatorで演算を行う

        STEP2で入力したパラメーターと、STEP3で入力中のパラメーターを用いて計算する

        * 考慮するSTEP2のパラメーターと必要なSTEP3のパラメーター
        STEP2パラメーター
            * 必要なSTEP3のパラメーター
        -ALONG LINE-
            * -ANGSTROM PER PIXEL-
            * -POINT DISTANCE-
        -IN COLUMN-
            * -ANGSTROM PER PIXEL-
            * -POINT NUMBER-
            * -MAX RADIUS-
        -ROTATION FOR ROTATING PROTAIN-
            * -ANGSTROM PER PIXEL-
            * -PITCH DEGREE-
            * -PITCH DISTANCE-

        * 考慮しないSTEP2のパラメーター
        -ROTATION FOR Y AXIS-
            calculatorがファイルの読み込みを行った時点で、計算されているため

        Notes:
            -ROTATION FOR ROTATING PROTAIN-は-ALONG LINE-または-IN COLUMN-と共存必須
            画面が変わってもパラメーターを保持しているため、
            画面に表示されていなくても数値が入っている可能性がある

        """

        try:
            pitch_degree = float(self.parameters["STEP3"]["-PITCH DEGREE-"])
            pitch_distance = float(self.parameters["STEP3"]["-PITCH DISTANCE-"])
        except ValueError:
            # float に変換できない場合
            pitch_degree = None
            pitch_distance = None

        if self.parameters["STEP2"]["-ROTATION FOR ROTATING PROTAIN-"] is False:
            pitch_degree = None
            pitch_distance = None

        # angstrom_per_pixel は未選択以外どのパラメーターでも必要
        try:
            angstrom_per_pixel = float(self.parameters["STEP3"]["-ANGSTROM PER PIXEL-"])
        except ValueError:
            # float に変換できない場合
            # angstrom_per_pixel は必須情報
            self.calculator.reset_calculation()
            return

        if self.parameters["STEP2"]["-IN COLUMN-"] is True:
            try:
                point_number = int(self.parameters["STEP3"]["-POINT NUMBER-"])
                max_radius = float(self.parameters["STEP3"]["-MAX RADIUS-"])
            except ValueError:
                # 必須情報が足りない
                return
            self.calculator.generate_in_column(
                angstrom_per_pixel,
                max_radius,
                point_number,
                pitch_degree,
                pitch_distance,
            )
        elif self.parameters["STEP2"]["-ALONG LINE-"] is True:
            try:
                point_distance = float(self.parameters["STEP3"]["-POINT DISTANCE-"])
            except ValueError:
                # 必須条件が足りない
                return

            self.calculator.generate_along_line(
                angstrom_per_pixel,
                point_distance,
                pitch_distance,
                pitch_distance,
            )
        else:
            # 無選択
            self.calculator.reset_calculation()
            return

    def _plot(self):
        self.calculator.plot(self.ax)
        self.figure_canvas.draw()

    def run(self):
        def _save_parameters():
            """self.parametersに保存する"""
            for key in self.parameters["STEP" + str(self.step)].keys():
                self.parameters["STEP" + str(self.step)][key] = values[key]

        def _on_click_back_button():
            if self.step == 2:
                # 実装するべきことなし
                pass
            elif self.step == 3:
                _save_parameters()
            else:
                # 実行されることなし
                raise RuntimeError(
                    "GUI._on_click_back_button() called when self.step == 1"
                )

            self.step -= 1
            self._create_layout()

        def _on_click_next_button():
            """NEXT ボタンが押されたときの処理を行う"""
            if self.step == 1:
                _save_parameters()
                try:
                    self.calculator.load_text_file(values["-PATH POSITION FILE-"])
                    self.calculator.calculate_rot2y()
                except FileNotFoundError as e:
                    sg.popup_error("Sorry. We could not find the file you entered.")
                    print(e)
                    return
            elif self.step == 2:
                pass
            else:
                # 実行されることなし
                raise RuntimeError(
                    "GUI._on_click_next_button() called when self.step == 3"
                )

            self.step += 1
            self._create_layout()
            print("re-created layout")

        def _on_click_save_button():
            try:
                flag_saved = False
                if (
                    self.parameters["STEP2"]["-ALONG LINE-"] is True
                    or self.parameters["STEP2"]["-IN COLUMN-"] is True
                ):
                    self.calculator.save_positions()
                    flag_saved = True
                if (
                    self.parameters["STEP2"]["-ROTATION FOR Y AXIS-"] is True
                    or self.parameters["STEP2"]["-ROTATION FOR ROTATING PROTAIN-"]
                    is True
                ):
                    flag_saved = True
                    self.calculator.save_rotations()
                if flag_saved is False:
                    sg.popup("Nothing saved according to the options you selected")
            except AssertionError:
                sg.popup_error("Internal Error: self.calculator.save() failed")

        def _update_step2_button(key: str, toggle: bool):
            self.parameters["STEP2"][key] = toggle
            if toggle is True:
                self.window[key].update(button_color=self.colors["special_button"])
            else:
                self.window[key].update(button_color=self.colors["default_button"])

        self._create_layout()

        while True:
            event, values = self.window.read()

            if event is None:
                break
            elif event == "-BACK-":
                _on_click_back_button()
                continue
            elif event == "-NEXT-":
                _on_click_next_button()
                continue
            elif event == "-SAVE-":
                _on_click_save_button()
                continue

            if self.step == 1:
                # 実装するべきことなし
                pass
            elif self.step == 2:
                # TrueをFalseに､FalseをTrueに
                self.parameters["STEP2"][event] = (
                    self.parameters["STEP2"][event] is False
                )

                # 変更したボタンの色を変更する
                if self.parameters["STEP2"][event] is True:
                    self.window[event].update(
                        button_color=self.colors["special_button"]
                    )
                else:
                    self.window[event].update(
                        button_color=self.colors["default_button"]
                    )

                # 依存関係に対応
                if self.parameters["STEP2"][event] is True:
                    if event == "-ALONG LINE-":
                        # -IN COLUMN- と共存不可
                        _update_step2_button("-IN COLUMN-", False)
                    elif event == "-IN COLUMN-":
                        # -ALONG LINE- と共存不可
                        _update_step2_button("-ALONG LINE-", False)
                    elif event == "-ROTATION FOR ROTATING PROTAIN-":
                        # -IN COLUMN- または -ALONG LINE- を選択する必要がある
                        if (
                            self.parameters["STEP2"]["-ALONG LINE-"] is False
                            and self.parameters["STEP2"]["-IN COLUMN-"] is False
                        ):
                            # どちらでも良いが、デフォルトで -ALONG LINE- を自動で選択するように
                            _update_step2_button("-ALONG LINE-", True)
                        # -ROTATION FOR Y AXIS- を選択する必要がある
                        _update_step2_button("-ROTATION FOR Y AXIS-", True)
                else:
                    if (
                        event == "-ROTATION FOR Y AXIS-"
                        or event == "-IN COLUMN-"
                        or event == "-ALONG LINE-"
                    ):
                        # -ROTATION FOR ROTATING PROTAIN- を解除
                        _update_step2_button("-ROTATION FOR ROTATING PROTAIN-", False)
            elif self.step == 3:
                _save_parameters()
                self._calculate_graph()
                self._plot()
                pass

        self.window.close()

def main():
    gui = GUI()
    gui.run()

def tester():
    df = pd.DataFrame()
    for _ in range(1000):
        calculator = Calculator()
        calculator.load_text_file("./data.txt")
        calculator.calculate_rot2y()

        calculator.generate_in_column(1, 10, 1, 1)

if __name__ == "__main__":
    main()
    # tester()

reason: import numpy,from scipy


text:
import numpy as np
from mathipy.math import calculus

class NRoot(calculus.Function):
    """
    f(x) = a * root_n(kx + p) + b
    """

    function_type = 'Nth Root'

    def __init__(self, n: int = 2, **kwargs):
        self.a: float = kwargs.get('a', 1)
        self.n = n
        self.k: float = kwargs.get('k', 1)
        self.p: float = kwargs.get('p', 0)
        self.b: float = kwargs.get('b', 0)

        if n == 0:
            raise ValueError('Root index cannot be 0')

    def get_yint(self) -> float:
        return self(0)

    def find_roots(self):
        r = ((-self.b / self.a) ** self.n - self.p) / self.k
        return r if self(r) == 0 else np.nan

    def calculate_values(self, x):
        return self.a * ((self.k * x + self.p) ** (1. / self.n)) + self.b

    def plot_func(self, ax):
        ax.scatter(0, self.get_yint(), color=calculus.Function.function_part['y-intercept'])
        ax.scatter(self.find_roots(), 0, color=calculus.Function.function_part['roots'])

    def __str__(self):
        representation = ''
        if self.a != 1:
            representation += f'{self.a} · '
        if self.n != 2:
            representation += f'Root{self.n}('
        else:
            representation += 'Sqrt('
        if self.k != 1:
            representation += f'{self.k}x'
        else:
            representation += 'x'
        if self.p != 0:
            representation += f' + {self.p})'
        else:
            representation += f')'
        if self.b != 0:
            representation += f' + {self.b}'
        return representation

max_stars_repo_name: BatiDyDx/maths-tools-python

max_issues_repo_name: BatiDyDx/maths-tools-python

max_forks_repo_name: BatiDyDx/maths-tools-python