text:
# Copyright 2020 Adap GmbH. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Federating: Fast and Slow."""

import math
import statistics
from logging import DEBUG, INFO
from typing import Callable, Dict, List, Optional, Tuple, cast

import numpy as np

from flwr.common import (
    EvaluateRes,
    FitIns,
    FitRes,
    Weights,
    parameters_to_weights,
    weights_to_parameters,
)
from flwr.common.logger import log
from flwr.server.client_manager import ClientManager
from flwr.server.client_proxy import ClientProxy

from .aggregate import aggregate, weighted_loss_avg
from .fedavg import FedAvg

E = 0.001
E_TIMEOUT = 0.0001
WAIT_TIMEOUT = 600

class FastAndSlow(FedAvg):
    """Strategy implementation which alternates between fast and slow rounds.

    :meta private:
    """

    # pylint: disable=too-many-arguments,too-many-instance-attributes,too-many-locals
    def __init__(
        self,
        fraction_fit: float = 0.1,
        fraction_eval: float = 0.1,
        min_fit_clients: int = 1,
        min_eval_clients: int = 1,
        min_available_clients: int = 1,
        eval_fn: Optional[Callable[[Weights], Optional[Tuple[float, float]]]] = None,
        min_completion_rate_fit: float = 0.5,
        min_completion_rate_evaluate: float = 0.5,
        on_fit_config_fn: Optional[Callable[[int], Dict[str, str]]] = None,
        on_evaluate_config_fn: Optional[Callable[[int], Dict[str, str]]] = None,
        importance_sampling: bool = True,
        dynamic_timeout: bool = True,
        dynamic_timeout_percentile: float = 0.8,
        alternating_timeout: bool = False,
        r_fast: int = 1,
        r_slow: int = 1,
        t_fast: int = 10,
        t_slow: int = 10,
    ) -> None:
        super().__init__(
            fraction_fit=fraction_fit,
            fraction_eval=fraction_eval,
            min_fit_clients=min_fit_clients,
            min_eval_clients=min_eval_clients,
            min_available_clients=min_available_clients,
            eval_fn=eval_fn,
            on_fit_config_fn=on_fit_config_fn,
            on_evaluate_config_fn=on_evaluate_config_fn,
        )
        self.min_completion_rate_fit = min_completion_rate_fit
        self.min_completion_rate_evaluate = min_completion_rate_evaluate
        self.importance_sampling = importance_sampling
        self.dynamic_timeout = dynamic_timeout
        self.dynamic_timeout_percentile = dynamic_timeout_percentile
        self.alternating_timeout = alternating_timeout
        self.r_fast = r_fast
        self.r_slow = r_slow
        self.t_fast = t_fast
        self.t_slow = t_slow
        self.contributions: Dict[str, List[Tuple[int, int, int]]] = {}
        self.durations: List[Tuple[str, float, int, int]] = []

    def __repr__(self) -> str:
        rep = f"FastAndSlow(importance_sampling={self.importance_sampling}, "
        rep += f"dynamic_timeout={self.dynamic_timeout}, "
        rep += f"dynamic_timeout_percentile={self.dynamic_timeout_percentile}, "
        rep += f"alternating_timeout={self.alternating_timeout}, "
        rep += f"r_fast={self.r_fast}, r_slow={self.r_slow}, "
        rep += f"t_fast={self.t_fast}, t_slow={self.t_slow})"
        return rep

    # pylint: disable=too-many-locals
    def on_configure_fit(
        self, rnd: int, weights: Weights, client_manager: ClientManager
    ) -> List[Tuple[ClientProxy, FitIns]]:
        """Configure the next round of training."""

        # Block until `min_num_clients` are available
        sample_size, min_num_clients = self.num_fit_clients(
            client_manager.num_available()
        )
        success = client_manager.wait_for(
            num_clients=min_num_clients, timeout=WAIT_TIMEOUT
        )
        if not success:
            # Do not continue if not enough clients are available
            log(
                INFO,
                "FedFS: not enough clients available after timeout %s",
                WAIT_TIMEOUT,
            )
            return []

        # Sample clients
        msg = "FedFS round %s, sample %s clients (based on all previous contributions)"
        if self.alternating_timeout:
            log(
                DEBUG,
                msg,
                str(rnd),
                str(sample_size),
            )
            clients = self._contribution_based_sampling(
                sample_size=sample_size, client_manager=client_manager
            )
        elif self.importance_sampling:
            if rnd == 1:
                # Sample with 1/k in the first round
                log(
                    DEBUG,
                    "FedFS round %s, sample %s clients with 1/k",
                    str(rnd),
                    str(sample_size),
                )
                clients = self._one_over_k_sampling(
                    sample_size=sample_size, client_manager=client_manager
                )
            else:
                fast_round = is_fast_round(
                    rnd - 1, r_fast=self.r_fast, r_slow=self.r_slow
                )
                log(
                    DEBUG,
                    "FedFS round %s, sample %s clients, fast_round %s",
                    str(rnd),
                    str(sample_size),
                    str(fast_round),
                )
                clients = self._fs_based_sampling(
                    sample_size=sample_size,
                    client_manager=client_manager,
                    fast_round=fast_round,
                )
        else:
            clients = self._one_over_k_sampling(
                sample_size=sample_size, client_manager=client_manager
            )

        # Prepare parameters and config
        parameters = weights_to_parameters(weights)
        config = {}
        if self.on_fit_config_fn is not None:
            # Use custom fit config function if provided
            config = self.on_fit_config_fn(rnd)

        # Set timeout for this round
        if self.dynamic_timeout:
            if self.durations:
                candidates = timeout_candidates(
                    durations=self.durations,
                    max_timeout=self.t_slow,
                )
                timeout = next_timeout(
                    candidates=candidates,
                    percentile=self.dynamic_timeout_percentile,
                )
                config["timeout"] = str(timeout)
            else:
                # Initial round has not past durations, use max_timeout
                config["timeout"] = str(self.t_slow)
        elif self.alternating_timeout:
            use_fast_timeout = is_fast_round(rnd - 1, self.r_fast, self.r_slow)
            config["timeout"] = str(self.t_fast if use_fast_timeout else self.t_slow)
        else:
            config["timeout"] = str(self.t_slow)

        # Fit instructions
        fit_ins = FitIns(parameters, config)

        # Return client/config pairs
        return [(client, fit_ins) for client in clients]

    def _one_over_k_sampling(
        self, sample_size: int, client_manager: ClientManager
    ) -> List[ClientProxy]:
        """Sample clients with probability 1/k."""
        sample_size, min_num_clients = self.num_fit_clients(
            client_manager.num_available()
        )
        clients = client_manager.sample(
            num_clients=sample_size, min_num_clients=min_num_clients
        )
        return clients

    def _contribution_based_sampling(
        self, sample_size: int, client_manager: ClientManager
    ) -> List[ClientProxy]:
        """Sample clients depending on their past contributions."""
        # Get all clients and gather their contributions
        all_clients: Dict[str, ClientProxy] = client_manager.all()
        cid_idx: Dict[int, str] = {}
        raw: List[float] = []
        for idx, (cid, _) in enumerate(all_clients.items()):
            cid_idx[idx] = cid
            penalty = 0.0
            if cid in self.contributions.keys():
                contribs: List[Tuple[int, int, int]] = self.contributions[cid]
                penalty = statistics.mean([c / m for _, c, m in contribs])
            # `p` should be:
            # - High for clients which have never been picked before
            # - Medium for clients which have contributed,
            #   but not used their entire budget
            # - Low (but not 0) for clients which have been picked and used their budget
            raw.append(1.1 - penalty)

        # Sample clients
        return normalize_and_sample(
            all_clients=all_clients,
            cid_idx=cid_idx,
            raw=np.array(raw),
            sample_size=sample_size,
            use_softmax=False,
        )

    def _fs_based_sampling(
        self, sample_size: int, client_manager: ClientManager, fast_round: bool
    ) -> List[ClientProxy]:
        """Sample clients with 1/k * c/m in fast rounds and 1 - c/m in slow rounds."""
        all_clients: Dict[str, ClientProxy] = client_manager.all()
        k = len(all_clients)
        cid_idx: Dict[int, str] = {}
        raw: List[float] = []
        for idx, (cid, _) in enumerate(all_clients.items()):
            cid_idx[idx] = cid

            if cid in self.contributions.keys():
                # Previously selected clients
                contribs: List[Tuple[int, int, int]] = self.contributions[cid]

                # pylint: disable=invalid-name
                _, c, m = contribs[-1]
                c_over_m = c / m
                # pylint: enable-msg=invalid-name

                if fast_round:
                    importance = (1 / k) * c_over_m + E
                else:
                    importance = 1 - c_over_m + E
            else:
                # Previously unselected clients
                if fast_round:
                    importance = 1 / k
                else:
                    importance = 1
            raw.append(importance)

        log(
            DEBUG,
            "FedFS _fs_based_sampling, sample %s clients, raw %s",
            str(sample_size),
            str(raw),
        )

        return normalize_and_sample(
            all_clients=all_clients,
            cid_idx=cid_idx,
            raw=np.array(raw),
            sample_size=sample_size,
            use_softmax=False,
        )

    def on_aggregate_fit(
        self,
        rnd: int,
        results: List[Tuple[ClientProxy, FitRes]],
        failures: List[BaseException],
    ) -> Optional[Weights]:
        """Aggregate fit results using weighted average."""
        if not results:
            return None

        # Check if enough results are available
        completion_rate = len(results) / (len(results) + len(failures))
        if completion_rate < self.min_completion_rate_fit:
            # Not enough results for aggregation
            return None

        # Convert results
        weights_results = [
            (parameters_to_weights(fit_res.parameters), fit_res.num_examples)
            for client, fit_res in results
        ]
        weights_prime = aggregate(weights_results)

        if self.importance_sampling:
            # Track contributions to the global model
            for client, fit_res in results:
                cid = client.cid
                contribution: Tuple[int, int, int] = (
                    rnd,
                    fit_res.num_examples,
                    fit_res.num_examples_ceil,
                )
                if cid not in self.contributions.keys():
                    self.contributions[cid] = []
                self.contributions[cid].append(contribution)

        if self.dynamic_timeout:
            self.durations = []
            for client, fit_res in results:
                cid_duration = (
                    client.cid,
                    fit_res.fit_duration,
                    fit_res.num_examples,
                    fit_res.num_examples_ceil,
                )
                self.durations.append(cid_duration)

        return weights_prime

    def on_aggregate_evaluate(
        self,
        rnd: int,
        results: List[Tuple[ClientProxy, EvaluateRes]],
        failures: List[BaseException],
    ) -> Optional[float]:
        """Aggregate evaluation losses using weighted average."""
        if not results:
            return None

        # Check if enough results are available
        completion_rate = len(results) / (len(results) + len(failures))
        if completion_rate < self.min_completion_rate_evaluate:
            # Not enough results for aggregation
            return None

        return weighted_loss_avg(
            [
                (evaluate_res.num_examples, evaluate_res.loss, evaluate_res.accuracy)
                for client, evaluate_res in results
            ]
        )

def is_fast_round(rnd: int, r_fast: int, r_slow: int) -> bool:
    """Determine if the round is fast or slow.

    :meta private:
    """
    remainder = rnd % (r_fast + r_slow)
    return remainder - r_fast < 0

def softmax(logits: np.ndarray) -> np.ndarray:
    """Compute softmax.

    :meta private:
    """
    e_x = np.exp(logits - np.max(logits))
    return cast(np.ndarray, e_x / e_x.sum(axis=0))

def normalize_and_sample(
    all_clients: Dict[str, ClientProxy],
    cid_idx: Dict[int, str],
    raw: np.ndarray,
    sample_size: int,
    use_softmax: bool = False,
) -> List[ClientProxy]:
    """Normalize the relative importance and sample clients accordingly.

    :meta private:
    """
    indices = np.arange(len(all_clients.keys()))
    if use_softmax:
        probs = softmax(np.array(raw))
    else:
        probs = raw / sum(raw)

    log(
        DEBUG,
        "FedFS normalize_and_sample, sample %s clients from %s, probs: %s",
        str(sample_size),
        str(len(indices)),
        str(probs),
    )
    sampled_indices = np.random.choice(
        indices, size=sample_size, replace=False, p=probs
    )
    clients = [all_clients[cid_idx[idx]] for idx in sampled_indices]
    return clients

def timeout_candidates(
    durations: List[Tuple[str, float, int, int]], max_timeout: int
) -> List[float]:
    """Calculate timeout candidates based on previous round training durations.

    :meta private:
    """
    scaled_timeout_candidates = [
        fit_duration * float(num_ex_ceil) / (float(num_ex) + E_TIMEOUT)
        for _, fit_duration, num_ex, num_ex_ceil in durations
    ]
    return [min(st, max_timeout) for st in scaled_timeout_candidates]

def next_timeout(candidates: List[float], percentile: float) -> int:
    """Cacluate timeout for the next round.

    :meta private:
    """
    candidates.sort()
    num_included = math.ceil(len(candidates) * percentile)
    timeout_raw = candidates[num_included - 1]
    timeout_ceil = math.ceil(timeout_raw)
    return timeout_ceil


text:
""" write a module which imports all following modules and solves the task
modul1:
- scrapes uniprot to get fasta sequences and protein name with a list input of uniprot accesion numbers
- remove everything with is not part of sequence itself
- create a dictonair for eacht uniprot ID with the corresponding [fasta sequence and protein name], check if there are dublicates, if yes remove them
- save this dict in a pickle and json file for later use
modul2
- Store each entry in a file in a given directory with the uniprot ID as filename
- check if file is already in directory, if yes pass if no then create """

# chooser working directoriy
import os

from numpy import isin
path = r"C:\Users\Kevin.Yar\Projects\biognosys-research\Kevin_Yar\_DataPrep_Simultan\menu3"
os.chdir(path)
#Get internet stuff
from urllib import request
from bs4 import BeautifulSoup as bs
import gzip
import lxml
#tocheck
import io
from datetime import datetime
from time import sleep
#to pickle / jason
import json

import pandas as pd
import numpy as np

import re

########################################################################################################
########################################################################################################
#load xml file from uniprot

def uniprotScraper(protList, save="n", path=""):
    global result
    """ this function scrapes through uniprot and gets the most important information like, proteinname, organism and AA sequence
    Just insert protList a list with uniprot ID's and select if you want to save the JSON file with save to be either n = no oder y= yes.
    Furthermore add an output FOLDER path. If you want to save the JSON file in a panda just pandas.read_json() this thing"""

    if isinstance(protList, io.IOBase):
        pro = []
        for i in protList:
            i.replace(",","")
            i.replace("\n", "")
            pro.append(i)
        protList = pro

    print(protList)
    ok = input("Passt das so?")

    if ok == "n" or ok == "no":
        return print("ok")

    if isinstance(protList, list):
        pass
    elif isinstance(protList, pd.Series) or isinstance(protList, np.ndarray):
        protList = list(protList)
    else:
        print("The input is neither a list nor a open() object")

    for el in protList:     #check dublicates
        if protList.count(el) > 1:
            print(el + " is at least a dublicate")
            protList.remove(el) #because remove only removes 1 element

    dic = {}
    name = []
    gene = []
    orga = []
    stringID = []

    seq = []
    liLen = len(protList)
    animation = ["[■□□□□□□□□□]","[■■□□□□□□□□]", "[■■■□□□□□□□]", "[■■■■□□□□□□]", "[■■■■■□□□□□]", "[■■■■■■□□□□]", "[■■■■■■■□□□]", "[■■■■■■■■□□]", "[■■■■■■■■■□]", "[■■■■■■■■■■]"]
    for nr, p in enumerate(protList):

        print(f"Process: {nr} / {len(protList)}", end='\r')
        #countdown animation

        try:
            #get url
            request_ = request.urlopen('https://www.uniprot.org/uniprot/' + p + '.xml.gz').read() #load compressed uniprot xml site
            bsRe = bs(gzip.decompress(request_),'lxml') #from binary to readably and transform to beautifulsoup format
        except:
            pass
        #get protein name
        try:
            name.append(str(bsRe.uniprot.entry.protein.fullname.string))
        except:
            print("No Protein Name found")
            name.append("-")

            #get gene
        try:
            geneString = str(bsRe.uniprot.entry.gene.select("name"))
            geneString = re.search(r'>(.*?)<', geneString).group(1)
            gene.append(geneString)
        except:
            gene.append("-")

        #get organism
        try:
            organismString = str(bsRe.uniprot.entry.organism.select("name"))
            orga.append(re.search(r'>(.*?)<',organismString).group(1))
        except:
            orga.append("-")

        #get sequence
        try:
            if not bsRe.uniprot.entry.sequence.string == None:
                seq.append(str(bsRe.uniprot.entry.sequence.string))
            else:
                raise AttributeError

        except:
            try:
                seq.append(str(bsRe.find_all("sequence")[-1].string)) #searches the last element from multiple sequence entry
            except:
                print("No Protein Sequence for  found")
                seq.append("-")

        # get STRING ID
        add_ = ""
        try:
            for i in bsRe.uniprot.entry:
                i = str(i)
                if not "STRING" in i:
                    add_ = "-"
                else:
                    add_ = i
                    break

            for i in bsRe.uniprot.entry.find_all('dbreference'):
                                if not i['type']=='STRING':
                                    add_ = "-"
                                elif i['type']=='STRING':
                                    #print(i["id"])
                                    add_ = i['id']
                                    break

            if add_ == "-":
                stringID.append("-")
            else:
                stringID.append(add_)
                #i = re.search(r'"(.*?)"', add_).group(1)
                #stringID.append(i)

        except:
            stringID.append("-")

    dic["uniprot"] = protList
    dic["proteinName"] = name
    dic["gene"] = gene
    dic["organism"] = orga
    dic["fastaSequence"] = seq
    dic["stringID"] = stringID

    if save == "y":
        try:
            saveJson(dic, path=path)
        except:
            print("saving result in variable result")
            result = dic

    result = dic

    print(""" |￣￣￣￣￣￣￣￣￣￣￣|

            Done!!

    |＿＿＿＿＿＿＿＿＿＿＿|
        \ ( •◡• ) /
           \    /
            ---
            |   | """)
    return dic

#########################################################
############  column cbinder ############################

def uniprotScraperColumnBind(df, column = None, save="n", path=""):
    """ This function is an addition to the original uniprotScraperColumnBind function. It just cbinds a missing column"""

    if column == None:
        return print("please specify which column you want to add. \n choose either name, gene, organism, sequence, stringID ")
    elif column in df.columns:
        return print("Column is already present")
    elif not isinstance(column, list):
        column = [column]

    print(df.columns)
    print(f"Add column {column}")
    input("Passt das so?")

    if not( isinstance(df, pd.Series) or isinstance(df, pd.DataFrame) or isinstance(df, np.ndarray)):
        return print("The input is neither a dataframe nor a np.array object")
    else:
        dfUniprot = list(df.uniprot)

    dic = {}
    name = []
    gene = []
    orga = []
    stringID = []
    seq = []

    liLen = len(dfUniprot)

    for nr, p in enumerate(dfUniprot):

        print(f"Process: {nr} / {len(dfUniprot)}", end='\r')
        #countdown animation

        #get url
        request_ = request.urlopen('https://www.uniprot.org/uniprot/' + p + '.xml.gz').read() #load compressed uniprot xml site
        bsRe = bs(gzip.decompress(request_),'lxml') #from binary to readably and transform to beautifulsoup format

        if "name" in column:
            #get protein name
            try:
                name.append(str(bsRe.uniprot.entry.protein.fullname.string))
                continue
            except:
                print("No Protein Name found")
                name.append("-")
                continue
        elif "gene" in column:
            #get gene
            try:
                geneString = str(bsRe.uniprot.entry.gene.select("name"))
                geneString = re.search(r'>(.*?)<', geneString).group(1)
                gene.append(geneString)
                continue
            except:
                gene.append("-")
                continue

        elif "organism" in column:
            #get organism
            try:
                organismString = bsRe.uniprot.entry.organism.select("name")
                try:
                    orga.append(organismString[0].string)
                except:
                    orga.append(re.search(r'>(.*?)<',organismString).group(1))
                continue
            except:
                orga.append("-")
                continue

        elif "sequence" in column:
            #get sequence
            try:
                if not bsRe.uniprot.entry.sequence.string == None:
                    seq.append(str(bsRe.uniprot.entry.sequence.string))
                    continue
                else:
                    raise AttributeError
                    continue

            except:
                try:
                    seq.append(str(bsRe.find_all("sequence")[-1].string)) #searches the last element from multiple sequence entry
                    continue
                except:
                    print("No Protein Sequence for  found")
                    seq.append("-")
                    continue

        elif "stringID" in column:
        # get STRING ID
            try:
                for i in bsRe.uniprot.entry.find_all('dbreference'):
                                    if i['type']=='STRING':
                                        print(i["id"])
                                        stringID.append(i['id'])
                                        continue

            except:
                stringID.append("-")

    if "proteinName" in column:
        dic["proteinName"] = name
    elif "gene" in column:
        dic["gene"] = gene
    elif "organism" in column:
        dic["organism"] = orga
    elif "sequence" in column:
        dic["fastaSequence"] = seq
    elif "stringID" in column:
        dic["stringID"] = stringID

    df_ = pd.DataFrame.from_dict(dic)
    df_new = pd.concat([df, df_], axis=1)

    print("Done")
    return df_new

def saveJson(element, path=""):
    #save json
    JSON = open(os.path.join(path, datetime.now().strftime("%Y_%m_%d__%H_%M")+"_uniprotScraperDict.json"), "w")
    json.dump(element, JSON)
    JSON.close()

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

source = r"S:\Ana\2022\821_Depletion_Panel_Designer_DPD\menu3\AHH.csv"
exit = r"S:\Ana\2022\821_Depletion_Panel_Designer_DPD\menu3"
names = pd.read_csv(source, header=0)

#get uniprot information
uniprotScraper(names.uniprot.unique(), save="y", path=exit)

a <- pd.DataFrame.from_dict(result)

for i in ["proteinName", "gene", "organism", "fastaSequence", "stringID"]:
    print(i)
    print(len(result[i]))

#read in the created json file
yeah = pd.read_json(r"S:\Ana\2022\821_Depletion_Panel_Designer_DPD\menu3\2022_03_31__12_38_uniprotScraperDict.json")
yeah.to_csv(r"S:\Ana\2022\821_Depletion_Panel_Designer_DPD\menu3\seqInfo.csv")

#add the molecular properties to each protein
os.chdir(r"S:\Big_No_Backup\Kevin\Uniprot-fastaScraper-by-xml\Ex12X")
import biopython
biopython.proteinInfos(yeah, "y")

#query=P178616&fields=accession,id,entry name,reviewed,protein names,genes,organism,length
df1 = pd.read_csv(r"S:\Ana\2022\821_Depletion_Panel_Designer_DPD\menu3\proteinSeqInfoExt.csv")

ext: py

max_stars_repo_name: cewinharhar/Uniprot-fastaScraper-by-xml

max_issues_repo_name: cewinharhar/Uniprot-fastaScraper-by-xml

max_forks_repo_name: cewinharhar/Uniprot-fastaScraper-by-xml

reason: import numpy,from numpy


text:
import numpy as np
import torch
from torch.nn.functional import softmax
import os

from utils import set_seeds
from attack import attack
from utils import show_image, to4d

def expt1(model, test_data, device, num_classes=10, figs_dir=None):
	""" See relation between ground truth and false prediction class. """

	classes_seen = set()
	norm_rs = np.zeros((num_classes, num_classes))
	probs = np.zeros((num_classes, num_classes))
	for i in range(100):
		if len(classes_seen) == num_classes: break

		X, y = test_data[i]
		if y in classes_seen: continue
		else: classes_seen.add(y)

		for false_pred in range(num_classes):
			fig_file = None
			if figs_dir:
				fig_name = f'{model.get_name()}_{y}_{false_pred}'
				fig_file = os.path.join(figs_dir, fig_name)

			norm_r, prob = attack(model, X, y, false_pred, device, fig_file)

			norm_rs[y][false_pred] = norm_r
			probs[y][false_pred] = prob

	return norm_rs, probs

def show_expt1_orig_images(test_data, num_classes=10, figs_dir=None):
	classes_seen = set()
	for i in range(100):
		if len(classes_seen) == num_classes: break

		X, y = test_data[i]
		if y in classes_seen: continue
		else: classes_seen.add(y)

		fig_file = os.path.join(figs_dir, f'{y}')
		show_image(X, fig_file)

def expt2(model, test_data, device, figs_dir=None):
	""" Compare the use of L1 and L2 penalty on the perturbation r. """
	print('L1 norm')
	for num in range(3):
		X, y = test_data[num]
		false = 10 - y
		fig_file = os.path.join(figs_dir, f'l1-{num}')
		print(attack(model, X, y, false, device, fig_file=fig_file, norm='l1'))

	print('L2 norm')
	for num in range(3):
		X, y = test_data[num]
		false = 10 - y
		fig_file = os.path.join(figs_dir, f'l2-{num}')
		print(attack(model, X, y, false, device, fig_file=fig_file, norm='l2'))

def expt3(models, X, y, device):
	f = 10 - y
	n = len(models)
	results = np.zeros((n,n,7))
	for i, m1 in enumerate(models):
		print(f'{i = }, m1 = {m1.get_name()}')
		r, p = attack(m1, X, y, f, device)
		for j, m2 in enumerate(models):
			rs = [0.8*r, r, 1.2*r, 1.5*r, 2*r, 4*r]
			ps = []
			for rr in rs:
				Xr = torch.clamp(X + r, 0, 1).to(device)
				if len(X.shape) == 3: X = to4d(X)
				logits = m2(Xr)
				p = softmax(logits, dim=1).detach().cpu().numpy()[0][f]
				ps.append(p)
			results[i][j] = np.array(p)

	return results

def expt4(model, X, y, device):
	f = 10 - y
	r, p = attack(model, X, y, f, device)
	rs = [0.5*r, 0.8*r, r, 1.2*r, 1.5*r, 2*r]
	ps = []
	for r in rs:
		Xr = torch.clamp(X + r, 0, 1).to(device)
		if len(Xr.shape) == 3: X = to4d(X)
		logits = model(Xr)
		p = softmax(logits, dim=1).detach().cpu().numpy()[0][f]
		ps.append(p)
	return ps

max_stars_repo_name: akkapakasaikiran/fooling-NNs

max_issues_repo_name: akkapakasaikiran/fooling-NNs

max_forks_repo_name: akkapakasaikiran/fooling-NNs

reason: import numpy


text:
import numpy
import theano.tensor as T
from theano import function

x = T.dscalar('x')
y = T.dscalar('y')
z = x + y
f = function([x, y], z)
f(2, 3)
numpy.allclose(f(16.3, 12.1), 28.4)

max_stars_repo_name: datmo/docker-files

max_issues_repo_name: asuprem/docker-files

max_forks_repo_name: asuprem/docker-files

reason: import numpy,import theano,from theano


text:
import logging
import random
from pathlib import Path
from typing import List

import numpy as np
import torch
from PIL import Image
from torch.utils.data import Dataset
import torchvision.transforms.functional as TF
from elastic_transform import elastic_transform, affine_elastic_transform
import cv2

class UltraSoundSingleDataset(Dataset):
    def __init__(self, dir_imgs: Path, dir_masks: Path, scale: float = 1):
        self.dir_imgs = dir_imgs
        self.dir_masks = dir_masks
        self.scale = scale
        assert 0 < scale <= 1, 'Scale must be between 0 and 1'

        self.paths_img = sorted(dir_imgs.iterdir(), key=lambda x: x.stem)
        self.paths_mask = sorted(dir_masks.iterdir(), key=lambda x: x.stem)

        self.check_img_with_mask()
        logging.info(f'Creating dataset with {len(self.paths_img)} examples')

    def __len__(self):
        return len(self.paths_img)

    def check_img_with_mask(self):
        """image and mask should have same file name."""
        len_imgs = len(self.paths_img)
        len_masks = len(self.paths_mask)
        collect_not_match = []
        assert len_imgs == len_masks, \
            f"The number of images ({len_imgs}) does not match the number of masks ({len_masks})."
        for id_img, id_mask in zip(self.paths_img, self.paths_mask):
            if id_img.stem != id_mask.stem:
                collect_not_match.append((id_img.stem, id_mask.stem))

        assert collect_not_match == [], f'Exist mismatch pairs: {collect_not_match}'

    @classmethod
    def preprocess(cls, pil_img, scale):
        w, h = pil_img.size
        new_w, new_h = int(scale * w), int(scale * h)
        assert new_w > 0 and new_h > 0, 'Scale is too small'
        pil_img = pil_img.resize((new_w, new_h))

        img_nd = np.array(pil_img)

        if len(img_nd.shape) == 2:
            img_nd = np.expand_dims(img_nd, axis=2)

        # HWC to CHW
        img_trans = img_nd.transpose((2, 0, 1))
        if img_trans.max() > 1:
            img_trans = img_trans / 255

        return img_trans

    def __getitem__(self, i):
        path_img = self.paths_img[i]
        path_mask = self.paths_mask[i]

        img = Image.open(path_img).convert('L')
        mask = Image.open(path_mask)

        assert img.size == mask.size, \
            f'Image and mask ({path_img.stem}) should be the same size, but are {img.size} and {mask.size}'

        img = self.preprocess(img, self.scale)
        mask = self.preprocess(mask, self.scale)

        return {
            'image': torch.from_numpy(img).type(torch.FloatTensor),
            'mask': torch.from_numpy(mask).type(torch.FloatTensor)
        }

class UltraSoundMultiDataset(Dataset):
    def __init__(self, dirs_img: List[Path], dirs_mask: List[Path],
                 size_expect: tuple = (500, 400), scale: float = 1, transforms: List[str] = []):
        self.dirs_img = dirs_img
        self.dirs_mask = dirs_mask
        self.scale = scale
        self.wh_expect = size_expect
        self.transforms = transforms
        self.transforms_available = ['flip', 'rotate', 'elastic', 'affine_elastic', 'gaussian']
        self._check_transforms()
        assert 0 < scale <= 1, 'Scale must be between 0 and 1'

        self.paths_img, self.paths_mask = self.load_paths_per_dataset()

    def __len__(self):
        return len(self.paths_img)

    def _check_transforms(self):
        if self.transforms not in [None, []]:
            for t in self.transforms:
                assert t in self.transforms_available, \
                    f'Operation {t} is not in {self.transforms_available}!'

    def load_paths_per_dataset(self):
        paths_img_all = []
        paths_mask_all = []
        for i, (dir_img, dir_mask) in enumerate(zip(self.dirs_img, self.dirs_mask), 1):
            paths_img = sorted(dir_img.iterdir(), key=lambda x: x.stem)
            paths_mask = sorted(dir_mask.iterdir(), key=lambda x: x.stem)
            self.check_img_with_mask(paths_img, paths_mask)
            logging.info(f'Dataset-{i: <2}:{len(paths_img)} examples')
            paths_img_all += paths_img
            paths_mask_all += paths_mask
        logging.info(f'All Datasets: {len(paths_img_all)} examples')
        return paths_img_all, paths_mask_all

    @staticmethod
    def check_img_with_mask(paths_img, paths_mask):
        """image and mask should have same file name."""
        len_imgs = len(paths_img)
        len_masks = len(paths_mask)
        collect_not_match = []
        assert len_imgs == len_masks, \
            f"The number of images ({len_imgs}) does not match the number of masks ({len_masks})."
        for id_img, id_mask in zip(paths_img, paths_mask):
            if id_img.stem != id_mask.stem:
                collect_not_match.append((id_img.stem, id_mask.stem))

        assert collect_not_match == [], f'Exist mismatch pairs: {collect_not_match}'

    @staticmethod
    def resize_with_padding(in_img: Image, size_out: tuple, pad_style: str = 'average'):
        def get_img_new_wh(old_wh: tuple):
            old_w, old_h = old_wh
            dst_w, dst_h = size_out  # include pad area

            if old_w / old_h > dst_w / dst_h:
                new_h = dst_h
                new_w = new_h * old_w / old_h
            else:
                new_w = dst_w
                new_h = new_w * old_h / old_w

            return round(new_w), round(new_h)

        # ------ choose pad color ------
        if pad_style == 'average':
            pad_color = in_img.resize((1, 1)).getpixel((0, 0))
        elif pad_style == 'black':
            if in_img.mode in ['L', 'P']:
                pad_color = 0
            elif in_img.mode == 'RGB':
                pad_color = (0, 0, 0)
            elif in_img.mode == '1':
                pad_color = False
            else:
                raise NotImplementedError
        else:
            raise NotImplementedError

        out_img = Image.new(in_img.mode, size_out, pad_color)
        in_img_scaled = in_img.resize(get_img_new_wh(in_img.size))
        upper_left_corner = ((out_img.size[0] - in_img_scaled.size[0]) // 2,
                             (out_img.size[1] - in_img_scaled.size[1]) // 2)
        out_img.paste(in_img_scaled, upper_left_corner)

        return out_img

    @classmethod
    def preprocess(cls, pil_img, scale):
        w, h = pil_img.size
        new_w, new_h = int(scale * w), int(scale * h)
        assert new_w > 0 and new_h > 0, 'Scale is too small'
        pil_img = pil_img.resize((new_w, new_h))

        img_nd = np.array(pil_img)

        if len(img_nd.shape) == 2:
            img_nd = np.expand_dims(img_nd, axis=2)

        # HWC to CHW
        img_trans = img_nd.transpose((2, 0, 1))
        if img_trans.max() > 1:
            img_trans = img_trans / 255

        return img_trans

    def show_samples(self, num=5):
        idx_random = np.random.choice(self.__len__(), num, replace=False)
        for n, idx in enumerate(idx_random):
            pair = self.__getitem__(idx)
            image = pair['image'].numpy()[0] * 255
            mask = pair['mask'].numpy()[0] * 255
            image = image.astype(np.uint8)
            mask = mask.astype(np.uint8)
            image = Image.fromarray(image)
            mask = Image.fromarray(mask)

            dst = Image.new('L', (image.width + mask.width, image.height))
            dst.paste(image, (0, 0))
            dst.paste(mask, (image.width, 0))

            dst.show(str(n))

    def show_img_with_mask_outline(self, idx):
        pair = self.__getitem__(idx)
        image = pair['image'].numpy()[0] * 255
        image = image.astype(np.uint8)
        cv2.imshow('image', image)
        mask = pair['mask'].numpy().astype(np.uint8).squeeze()
        # https://docs.opencv.org/4.5.3/d4/d73/tutorial_py_contours_begin.html
        # findContours need 0-1 image input
        contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        # -1 means draw all the contours
        cv2.drawContours(image, contours, -1, color=(255, 0, 0), thickness=1)

        cv2.imshow('image_contour', image)
        cv2.waitKey()

    def _do_transforms(self, image, mask):
        if random.random() < 0.5:
            return image, mask

        if 'flip' in self.transforms:
            image = TF.hflip(image)
            mask = TF.hflip(mask)

        if 'rotate' in self.transforms:
            degree = random.randint(0, 10)
            image = TF.rotate(image, angle=degree)
            mask = TF.rotate(mask, angle=degree)

        if 'elastic' in self.transforms:
            alpha = random.uniform(300, 400)  # 200
            sigma = random.uniform(9, 13)  # 9-13
            image, mask = elastic_transform(image, mask, alpha, sigma)

        if 'affine_elastic' in self.transforms:
            alpha = random.uniform(0, 200)
            sigma = random.uniform(9, 13)
            alpha_affine = random.uniform(0, 30)
            image, mask = affine_elastic_transform(image, mask,
                                                   alpha, sigma, alpha_affine)

        if 'gaussian' in self.transforms:
            image = np.array(image)
            assert len(image.shape) == 2
            mean = 8
            var = 10
            sigma = var ** 0.5
            gaussian = np.random.normal(mean, sigma, image.shape)  # np.zeros((224, 224), np.float32)
            noisy_image = image + gaussian
            noisy_image = np.clip(noisy_image, 0, 255)
            image = Image.fromarray(noisy_image.astype('uint8'))

        return image, mask

    def __getitem__(self, i):
        path_img = self.paths_img[i]
        path_mask = self.paths_mask[i]

        img = Image.open(path_img).convert('L')
        mask = Image.open(path_mask).convert('P')
        assert img.size == mask.size, \
            f'Image and mask ({path_img.stem}) should be the same size, but are {img.size} and {mask.size}'

        if self.transforms is not None:
            img, mask = self._do_transforms(img, mask)

        if img.size != self.wh_expect:
            img = self.resize_with_padding(img, self.wh_expect, pad_style='average')
            mask = self.resize_with_padding(mask, self.wh_expect, pad_style='black')

        img = self.preprocess(img, self.scale)
        mask = self.preprocess(mask, self.scale)

        return {
            'image': torch.from_numpy(img).type(torch.FloatTensor),
            'mask': torch.from_numpy(mask).type(torch.FloatTensor)
        }

if __name__ == '__main__':
    dir_train_img_1 = Path('C:\\Users\Administrator\Desktop\智能医疗\数据集\BUSI_split_merge\\{t}\gray')
    dir_train_mask_1 = Path('C:\\Users\Administrator\Desktop\智能医疗\数据集\BUSI_split_merge\\{t}\mask')
    dir_train_img_2 = Path('C:\\Users\Administrator\Desktop\智能医疗\数据集\BUSI_split_merge\malignant\gray')
    dir_train_mask_2 = Path('C:\\Users\Administrator\Desktop\智能医疗\数据集\BUSI_split_merge\malignant\mask')
    dirs_img = [dir_train_img_1]
    dirs_mask = [dir_train_mask_1]
    ds = UltraSoundMultiDataset(dirs_img, dirs_mask, transforms=['elastic'])
    o = ds[3]
    # ds.show_samples(1)
    for i in range(10, 20):
        ds.show_img_with_mask_outline(i)


text:
import logging
import os

import matplotlib
import matplotlib.pyplot as plt
import numpy

OVERWRITE_PHYSIO_PLOTS = False

width = 6
height = 3
dpi = 40

matplotlib.rcParams.update({'font.size': 8})

def preprocess_psychophysio_data(experiment_data):
    # split experiment data by condition
    for i, condition in enumerate(experiment_data['conditions']):
        condition_dataframe = experiment_data['dataframe'][experiment_data['dataframe']['Condition'] == condition]

        # print(condition_dataframe.head(5))

        logging.info('Preprocessing physio data for condition: %s', condition)

        # TODO check whether files already exist and whether to overwrite them
        if not OVERWRITE_PHYSIO_PLOTS:
            logging.info('--> use preprocessed files')
            continue

        # cycle through all physio data types
        condition_start_pos = condition_dataframe['Time'].iloc[0]
        condition_end_pos = condition_dataframe['Time'].iloc[-1]
        condition_dataframe.reset_index(inplace=True, drop=True)

        draw_psychophysio_data(experiment_data, 'HeartRate', condition_start_pos, condition_end_pos)
        draw_psychophysio_data(experiment_data, 'Respiration', condition_start_pos, condition_end_pos, span=600)
        draw_psychophysio_data(experiment_data, 'PupilDilation', condition_start_pos, condition_end_pos)

        # todo change code in other places to use preprocessed pngs

def draw_psychophysio_data(experiment_data, data_type, start_pos, end_pos, span=1200, highlight_span=50, full_plot=False):
    physio_data = experiment_data['dataframe'][data_type]

    plt.figure(figsize=(width, height), dpi=dpi)

    for i in range(end_pos - start_pos):
        if i % 100 != 0:
            continue

        # draw one plot per second for each frame within one condition
        plt.clf()

        current_time = i

        y_values_mask = numpy.isfinite(physio_data)
        x_axis = numpy.arange(0, len(physio_data), 1)

        minimum = start_pos + current_time - span
        maximum = start_pos + current_time + span
        if minimum < 0:
            minimum = 0

        plot_y_values = physio_data[minimum:maximum]
        y_values_mask = numpy.isfinite(plot_y_values)

        if len(plot_y_values) < (maximum - minimum):
            maximum = len(plot_y_values) + minimum

        x_axis = numpy.arange(minimum, maximum, 1)

        plt.plot(x_axis[y_values_mask], plot_y_values[y_values_mask])

        # todo add horizontal line for average condition and/or average of entire session

        # add backgrounds for condition visualization
        task_start = minimum
        if start_pos > minimum:
            task_start = start_pos

        task_end = maximum
        if maximum > end_pos:
            task_end = end_pos

        plt.axvspan(task_start, task_end, color='blue', alpha=0.05)

        # highlight current time
        plt.axvspan(start_pos + current_time - highlight_span, start_pos + current_time + highlight_span, color='red', alpha=0.2)
        plt.gca().set_ylim(min(physio_data), max(physio_data))

        # save plot as pngs
        file_name = experiment_data['participant'] + '_' + data_type + '_' + str(current_time) + '.png'
        plt.savefig(os.path.join('temp', 'physio', file_name), bbox_inches='tight')

max_stars_repo_name: brains-on-code/CodersMUSE

max_issues_repo_name: brains-on-code/CodersMUSE

max_forks_repo_name: brains-on-code/CodersMUSE


text:
from solver.perceptron import SimplePerceptron
import numpy as np

if __name__ == "__main__":
  x = np.array([[0,0,0], [0,2,1], [1,1,1], [1,-1,0]])
  t = np.array([-1,1,1,-1])

  perceptron = SimplePerceptron(t, x, bias=1)
  perceptron.train(2)
  print('Prediction', perceptron.predict(np.array([1,0,0,1])))

max_stars_repo_name: s-cortes/perceptron

max_issues_repo_name: s-cortes/perceptron

max_forks_repo_name: s-cortes/perceptron


text:
# Copyright 2020 MONAI Consortium
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import os
import sys
import tempfile
from glob import glob

import nibabel as nib
import numpy as np
import torch
from torch.utils.data import DataLoader

from monai import config
from monai.data import ImageDataset, create_test_image_3d, decollate_batch
from monai.inferers import sliding_window_inference
from monai.metrics import DiceMetric
from monai.networks.nets import UNet
from monai.transforms import Activations, AddChannel, AsDiscrete, Compose, SaveImage, ScaleIntensity, EnsureType

def main(tempdir):
    config.print_config()
    logging.basicConfig(stream=sys.stdout, level=logging.INFO)

    print(f"generating synthetic data to {tempdir} (this may take a while)")
    for i in range(5):
        im, seg = create_test_image_3d(128, 128, 128, num_seg_classes=1)

        n = nib.Nifti1Image(im, np.eye(4))
        nib.save(n, os.path.join(tempdir, f"im{i:d}.nii.gz"))

        n = nib.Nifti1Image(seg, np.eye(4))
        nib.save(n, os.path.join(tempdir, f"seg{i:d}.nii.gz"))

    images = sorted(glob(os.path.join(tempdir, "im*.nii.gz")))
    segs = sorted(glob(os.path.join(tempdir, "seg*.nii.gz")))

    # define transforms for image and segmentation
    imtrans = Compose([ScaleIntensity(), AddChannel(), EnsureType()])
    segtrans = Compose([AddChannel(), EnsureType()])
    val_ds = ImageDataset(images, segs, transform=imtrans, seg_transform=segtrans, image_only=False)
    # sliding window inference for one image at every iteration
    val_loader = DataLoader(val_ds, batch_size=1, num_workers=1, pin_memory=torch.cuda.is_available())
    dice_metric = DiceMetric(include_background=True, reduction="mean", get_not_nans=False)
    post_trans = Compose([EnsureType(), Activations(sigmoid=True), AsDiscrete(threshold_values=True)])
    saver = SaveImage(output_dir="./output", output_ext=".nii.gz", output_postfix="seg")
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = UNet(
        spatial_dims=3,
        in_channels=1,
        out_channels=1,
        channels=(16, 32, 64, 128, 256),
        strides=(2, 2, 2, 2),
        num_res_units=2,
    ).to(device)

    model.load_state_dict(torch.load("best_metric_model_segmentation3d_array.pth"))
    model.eval()
    with torch.no_grad():
        for val_data in val_loader:
            val_images, val_labels = val_data[0].to(device), val_data[1].to(device)
            # define sliding window size and batch size for windows inference
            roi_size = (96, 96, 96)
            sw_batch_size = 4
            val_outputs = sliding_window_inference(val_images, roi_size, sw_batch_size, model)
            val_outputs = [post_trans(i) for i in decollate_batch(val_outputs)]
            val_labels = decollate_batch(val_labels)
            meta_data = decollate_batch(val_data[2])
            # compute metric for current iteration
            dice_metric(y_pred=val_outputs, y=val_labels)
            for val_output, data in zip(val_outputs, meta_data):
                saver(val_output, data)
        # aggregate the final mean dice result
        print("evaluation metric:", dice_metric.aggregate().item())
        # reset the status
        dice_metric.reset()

if __name__ == "__main__":
    with tempfile.TemporaryDirectory() as tempdir:
        main(tempdir)


text:
import cv2
import numpy as np
import ell_utilities

# Class to hold info about the model that the app needs to call the model and display result correctly
class ModelHelper:
    def __init__(self, modelName, modelFiles, labelsFile, inputHeightAndWidth = (224, 224), scaleFactor = 1/255, threshold = 0.25):
        """ Helper class to store information about the model we want to use.
        modelName - string name of the model
        modelFiles - list of strings containing darknet .cfg filename and darknet .weights filename, or CNTK model file name.
        labelsFile - string name of labels that correspond to the predictions output of the model
        inputHeightAndWidth - a list of two values giving the rows and columns of the input image for the model e.g. (224, 224)
        scaleFactor - each input pixel may need to be scaled. It is common for models to require an 8-bit pixel
                      to be represented as a value between 0.0 and 1.0, which is the same as multiplying it by 1/255.
        threshold - specifies a prediction threshold. We will ignore prediction values less than this
        """
        self.model_name = modelName
        self.model_files = modelFiles
        self.labels_file = labelsFile
        self.inputHeightAndWidth = inputHeightAndWidth
        self.scaleFactor = scaleFactor
        self.threshold = threshold
        self.labels = self.load_labels(self.labels_file)

    def load_labels(self, fileName):
        labels = []
        with open(fileName) as f:
            labels = f.read().splitlines()
        return labels

    def get_top_n(self, predictions, N):
        """Return at most the top 5 predictions as a list of tuples that meet the threashold."""
        topN = np.zeros([N,2])
        for p in range(len(predictions)):
            for t in range(len(topN)):
                if predictions[p] > topN[t][0]:
                    topN[t] = [predictions[p], p]
                    break
        result = []
        for element in topN:
            if (element[0] > self.threshold):
                result.append((self.labels[int(element[1])], round(element[0],2)))
        return result

    def resize_image(self, image, newSize):
        """Crops, resizes image to outputshape. Returns image as numpy array in in RGB order, with each pixel multiplied by the configured scaleFactor."""
        if (image.shape[0] > image.shape[1]):
            rowStart = 0
            rowEnd = image.shape[1]
            colStart = int((image.shape[0] - image.shape[1]) / 2)
            colEnd = image.shape[1]
        else:
            rowStart = int( (image.shape[1] - image.shape[0]) / 2)
            rowEnd = image.shape[0]
            colStart = 0
            colEnd = image.shape[0]

        cropped = image[rowStart:rowEnd, colStart:colEnd]
        resized = cv2.resize(cropped, newSize)
        return resized

    def prepare_image_for_predictor(self, image):
        """Crops, resizes image to outputshape. Returns image as numpy array in in RGB order, with each pixel multiplied by the configured scaleFactor."""
        resized = self.resize_image(image, self.inputHeightAndWidth)
        resized = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB)
        resized = resized * self.scaleFactor
        resized = resized.astype(np.float).ravel()
        return resized

    def draw_label(self, image, label):
        """Helper to draw text onto an image"""
        cv2.rectangle(image, (0, 0), (image.shape[1], 40), (50, 200, 50), cv2.FILLED)
        cv2.putText(image, label, (10,25), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 0), 2, 8)
        return

    def save_ell_predictor_to_file(self, predictor, filePath, intervalMs = 0):
        """Saves an ELL predictor to file so that it can be compiled to run on a device, with an optional stepInterval in milliseconds"""
        name = self.model_name
        if (intervalMs > 0):
            ell_map = ell_utilities.ell_steppable_map_from_float_predictor(
                predictor, intervalMs, name + "InputCallback", name + "OutputCallback")
            ell_map.Save(filePath)
        else:
            ell_map = ell_utilities.ell_map_from_float_predictor(predictor)
            ell_map.Save(filePath)

max_stars_repo_name: Dream-maerD/ELL-master

max_issues_repo_name: Dream-maerD/ELL-master

max_forks_repo_name: Dream-maerD/ELL-master


text:
import functools
from typing import (
    Any,
    Callable,
    Dict,
    List,
    Tuple,
    Type,
    TypeVar,
    Union,
    cast,
    overload,
)

import numpy as np
import torch

# Note that we define two container TypeVars:
# - A bound container, whose output type exactly matches the input type
#       -> For moving across devices, for example, a List[torch.Tensor] will always
#          return a List[torch.Tensor]
# - And a constrained container, whose output type is only guaranteed to match at the
#   top-level
#       -> For converting NumPy -> Torch, a List[np.ndarray] will return a
#          List[torch.Tensor]; this is really difficult to represent in Python, so we
#          just mark the output as a List[Any]

BoundContainer = TypeVar("BoundContainer", bound=Union[Dict, List, Tuple])
Key = TypeVar("Key")

_ConstrainedContainer = TypeVar("_ConstrainedContainer", Dict, List, Tuple)
_InputType = TypeVar("_InputType", np.ndarray, torch.Tensor)
_OutputType = TypeVar("_OutputType", np.ndarray, torch.Tensor)

@overload
def _convert_recursive(
    x: _InputType,
    convert: Callable[[_InputType], _OutputType],
    input_type: Type,
) -> _OutputType:
    ...

@overload
def _convert_recursive(
    x: _ConstrainedContainer,
    convert: Callable[[_InputType], _OutputType],
    input_type: Type,
) -> _ConstrainedContainer:
    ...

def _convert_recursive(x, convert, input_type):
    """Private conversion helper. Recursively calls a conversion function on inputs
    within a nested set of containers.
    """

    # Conversion base case
    if isinstance(x, input_type):
        x = cast(_InputType, x)
        return convert(x)

    # Convert containers: bind arguments to helper function
    convert_recursive = functools.partial(
        _convert_recursive, convert=convert, input_type=input_type
    )

    # Convert dictionaries of values
    if isinstance(x, dict):
        x = cast(dict, x)
        return dict(zip(x.keys(), map(convert_recursive, x.values())))

    # Convert lists of values
    if isinstance(x, list):
        x = cast(list, x)
        return list(map(convert_recursive, x))

    # Convert tuples of values
    if isinstance(x, tuple):
        x = cast(tuple, x)
        if hasattr(x, "_fields"):  # NamedTuple
            return type(x)(*map(convert_recursive, x))
        else:
            return tuple(map(convert_recursive, x))

    # Unsupported input types
    assert False, f"Unsupported datatype {type(x)}!"

@overload
def to_device(
    x: torch.Tensor, device: torch.device, detach: bool = False
) -> torch.Tensor:
    ...

@overload
def to_device(
    x: BoundContainer, device: torch.device, detach: bool = False
) -> BoundContainer:
    ...

def to_device(x, device, detach=False):
    """Move a torch tensor, list, tuple (standard or named), or dict of tensors to a
    different device. Recursively applied for nested containers.

    Args:
        x (torch.Tensor, list, tuple (standard or named), or dict): Tensor or container
            of tensors to move.
        device (torch.device): Target device.
        detach (bool, optional): If set, detaches tensors after moving. Defaults to
            False.

    Returns:
        torch.Tensor, list, tuple (standard or named), or dict: Output, type will mirror
        input.
    """

    def convert(x):
        if detach:
            x = x.detach()
        return x.to(device)

    return _convert_recursive(x, convert=convert, input_type=torch.Tensor)

# This a lot of boilerplate, but seems impossible to reproduce same level of specificity
# with TypeVars

@overload
def to_torch(
    x: np.ndarray,
    device: str = "cpu",
    convert_doubles_to_floats: bool = True,
) -> torch.Tensor:
    ...

@overload
def to_torch(
    x: List[np.ndarray],
    device: str = "cpu",
    convert_doubles_to_floats: bool = True,
) -> List[torch.Tensor]:
    ...

@overload
def to_torch(
    x: List,
    device: str = "cpu",
    convert_doubles_to_floats: bool = True,
) -> List:
    ...

@overload
def to_torch(
    x: Tuple[np.ndarray, ...],
    device: str = "cpu",
    convert_doubles_to_floats: bool = True,
) -> Tuple[torch.Tensor, ...]:
    ...

@overload
def to_torch(
    x: Tuple,
    device: str = "cpu",
    convert_doubles_to_floats: bool = True,
) -> Tuple:
    ...

@overload
def to_torch(
    x: Dict[Key, np.ndarray],
    device: str = "cpu",
    convert_doubles_to_floats: bool = True,
) -> Dict[Key, torch.Tensor]:
    ...

@overload
def to_torch(
    x: Dict[Key, Any],
    device: str = "cpu",
    convert_doubles_to_floats: bool = True,
) -> Dict[Key, Any]:
    ...

def to_torch(
    x,
    device="cpu",
    convert_doubles_to_floats=True,
):
    """Converts a NumPy array, list, tuple (standard or named), or dict of NumPy arrays
    for use in PyTorch.  Recursively applied for nested containers.

    Args:
        x (np.ndarray, list, tuple (standard or named), or dict): Array or container of
            arrays to convert to torch tensors.
        device (torch.device, optional): Torch device to create tensors on. Defaults to
            `"cpu"`.
        convert_doubles_to_floats (bool, optional): If set, converts 64-bit floats to
            32-bit. Defaults to True.

    Returns:
        torch.Tensor, list, tuple (standard or named), or dict: Output, type will mirror input.
    """

    def convert(x: np.ndarray) -> torch.Tensor:
        output = torch.from_numpy(x)
        if x.dtype == np.float64 and convert_doubles_to_floats:
            output = output.float()
        output = output.to(device)
        return output

    return _convert_recursive(x, convert=convert, input_type=np.ndarray)

@overload
def to_numpy(x: torch.Tensor) -> np.ndarray:
    ...

@overload
def to_numpy(x: List[torch.Tensor]) -> List[np.ndarray]:
    ...

@overload
def to_numpy(x: List) -> List:
    ...

@overload
def to_numpy(x: Tuple[torch.Tensor, ...]) -> Tuple[np.ndarray, ...]:
    ...

@overload
def to_numpy(x: Tuple) -> Tuple:
    ...

@overload
def to_numpy(x: Dict[Key, torch.Tensor]) -> Dict[Key, np.ndarray]:
    ...

@overload
def to_numpy(x: Dict[Key, Any]) -> Dict[Key, Any]:
    ...

def to_numpy(x):
    """Converts a tensor, list, tuple (standard or named), or dict of tensors for use in
    Numpy. Recursively applied for nested containers.

    Args:
        x (torch.Tensor, list, tuple (standard or named), or dict): Tensor or container
            of tensors to convert to NumPy.

    Returns:
        np.ndarray, list, tuple (standard or named), or dict: Output, type will mirror input.
    """

    def convert(x: torch.Tensor) -> np.ndarray:
        output = x.detach().cpu().numpy()
        return output

    return _convert_recursive(x, convert=convert, input_type=torch.Tensor)

max_stars_repo_name: brentyi/hfdsajk

max_issues_repo_name: brentyi/hfdsajk

max_forks_repo_name: brentyi/hfdsajk


text:
### Backend for simulating data

#Imports have to be here in order for the packages to be available to functions imported from this backend.
import sys, os, os.path, h5py, time
import pandas as pd
import numpy as np

from os import walk
from multiprocessing import Pool
from diffpy.srreal.pdfcalculator import DebyePDFCalculator, PDFCalculator
from diffpy.Structure import loadStructure, Structure, Lattice, Atom

from diffpy.Structure import Structure   #DiffPy imports
from diffpy.Structure import Atom
from diffpy.Structure import loadStructure, Structure, Lattice

from ase.data import covalent_radii, atomic_numbers, chemical_symbols
from ase.cluster.cubic import FaceCenteredCubic, BodyCenteredCubic, SimpleCubic
from ase.lattice.hexagonal import Hexagonal, HexagonalClosedPacked, Graphite
from ase.cluster.decahedron import Decahedron
from ase.cluster.icosahedron import Icosahedron
from ase.cluster.octahedron import Octahedron

from tqdm import tqdm
import shutil, mendeleev
from shutil import copyfile
from scipy import spatial

def sort_filenames(xyz_path, print_level):
    #Sort through all filenames and sort them into different lists based on structure:
    _, _, filenames = next(walk(xyz_path)) #loads all filenames into a list called filenames
    #structures_list = ["SC", "FCC", "BCC", "HCP", "Icosahedron", "Decahedron", "Octahedron"]
    SC_filenames, FCC_filenames, BCC_filenames, HCP_filenames, ICO_filenames, DEC_filenames, OCT_filenames = [], [], [], [], [], [], []
    for xyzfile in filenames:
        if xyzfile[0] == "S":
            SC_filenames.append(xyzfile)
        if xyzfile[0] == "F":
            FCC_filenames.append(xyzfile)
        if xyzfile[0] == "B":
            BCC_filenames.append(xyzfile)
        if xyzfile[0] == "H":
            HCP_filenames.append(xyzfile)
        if xyzfile[0] == "I":
            ICO_filenames.append(xyzfile)
        if xyzfile[0] == "D":
            DEC_filenames.append(xyzfile)
        if xyzfile[0] == "O":
            OCT_filenames.append(xyzfile)
    sorted_filenames = [SC_filenames, FCC_filenames, BCC_filenames, HCP_filenames, ICO_filenames, DEC_filenames, OCT_filenames]
    if print_level == True:
        print("All xyz files have been sorted into lists")
    return sorted_filenames

def get_simulate_data_backend():
	#Sorted filenames:
	xyz_path = "xyz_files/natoms200/" #Path where the xyz files are
	sorted_filenames = sort_filenames(xyz_path, print_level = False)
	sorted_filenames_flat = [item for sublist in sorted_filenames for item in sublist]

	#Instantiate the PDF_generator class
	PDF_obj = PDF_generator()

	return PDF_obj, sorted_filenames_flat, xyz_path

def make_df_parallelized(sorted_filenames_flat, train_multip, valtest_multip, n_processes, xyz_path): #This is the new parallelized one

    sorted_filenames = sort_filenames(xyz_path, print_level = False)
    sorted_filenames_flat = [item for sublist in sorted_filenames for item in sublist]

    t1 = time.time()

    print(f"Making PDF dataset from the clusters in {xyz_path}.\nThe training set will have {train_multip} PDFs from each cluster and the validation and test set will have {valtest_multip} PDFs from each cluster\nMultithreading: {n_processes} processes")
    #print(f"It should take about {round(0.2*0.75*(train_multip+2*valtest_multip), 1)} minutes")

    reset_parameters()
    PDF_train, PDF_validation, PDF_test  = [], [], []

    #train_multip = 2
    #valtest_multip = 1
    #n_processes = 4
    xyzfileindexes = sorted([n for n in range(len(sorted_filenames_flat))]*(train_multip+2*valtest_multip))

    p = Pool(n_processes)

    result = p.map(PDF_from_index, xyzfileindexes)
    #result = np.array(result)#.reshape(-1)
    p.close()
    p.join()

    PDF_train = []
    PDF_validation = []
    PDF_test = []

    n = 0
    for _ in range(int(len(result)/(train_multip+2*valtest_multip))):
        for i in range(train_multip):
            PDF_train.append(result[n])
            n = n + 1
        for j in range(valtest_multip):
            PDF_validation.append(result[n])
            n = n + 1
            PDF_test.append(result[n])
            n = n + 1

    #Now they're going into dataframes
    index_list = np.arange(1, 301, 1)
    index_list = np.append(index_list, "qmin")
    index_list = np.append(index_list, "qmax")
    index_list = np.append(index_list, "qdamp")
    #index_list = np.append(index_list, "biso") #No longer included
    index_list = np.append(index_list, "filename")

    df_train = pd.DataFrame(data = PDF_train, columns = index_list)
    df_val = pd.DataFrame(data = PDF_validation, columns = index_list)
    df_test = pd.DataFrame(data = PDF_test, columns = index_list)

    #Reduce Memory
    df_train.iloc[:,1:-1] = reduce_mem_usage(df_train.iloc[:,1:-1])
    df_val.iloc[:,1:-1] = reduce_mem_usage(df_val.iloc[:,1:-1])
    df_test.iloc[:,1:-1] = reduce_mem_usage(df_test.iloc[:,1:-1])

    #Split train and val in X and y
    X_train,y_train = df_train.iloc[:,0:-1], df_train.iloc[:,-1]
    X_val,y_val = df_val.iloc[:,0:-1], df_val.iloc[:,-1]
    X_test,y_test = df_test.iloc[:,0:-1], df_test.iloc[:,-1]
    print(f"df_train dimensions: {len(PDF_train)} rows X {len(PDF_train[0])} columns")
    print(f"df_val dimensions: {len(PDF_validation)} rows X {len(PDF_validation[0])} columns")
    print(f"df_test dimensions: {len(PDF_test)} rows X {len(PDF_test[0])} columns")
    t2 = time.time()
    print("Time spent on making PDFs and preparing dataframes:", str((t2-t1)/60)[0:4], " min")
    return X_train, y_train, X_val, y_val, X_test, y_test #, (time.time()-start_time)/60

def save_PDFs(folder_name, X_train, y_train, X_val, y_val, X_test, y_test):

    pdf_path = "PDF_datasets/"
    if os.path.isdir(pdf_path + folder_name):
        print("This directory already exists. Choose a different folder name in order to not overwrite existing dataset...")
        return
    else:
        os.makedirs(pdf_path + folder_name)
    X_train.to_hdf(pdf_path + folder_name + "/X_train.h5", key='df', mode='w')
    y_train.to_hdf(pdf_path + folder_name + "/y_train.h5", key='df', mode='w')
    X_val.to_hdf  (pdf_path + folder_name + "/X_val.h5", key='df', mode='w')
    y_val.to_hdf  (pdf_path + folder_name + "/y_val.h5", key='df', mode='w')
    X_test.to_hdf (pdf_path + folder_name + "/X_test.h5", key='df', mode='w')
    y_test.to_hdf (pdf_path + folder_name + "/y_test.h5", key='df', mode='w')
    print("PDF dataset saved to " + pdf_path + folder_name + "/")

def reduce_mem_usage(df):
    """
    iterate through all the columns of a dataframe and
    modify the data type to reduce memory usage.
    """
    start_mem = df.memory_usage().sum() / 1024**2
    #print(('Memory usage of dataframe is {:.2f}'
    #                 'MB').format(start_mem))

    for col in df.columns:
        col_type = df[col].dtype

        if col_type != object:
            c_min = df[col].min()
            c_max = df[col].max()
            if str(col_type)[:3] == 'int':
                if c_min > np.iinfo(np.int8).min and c_max <\
                  np.iinfo(np.int8).max:
                    df[col] = df[col].astype(np.int8)
                elif c_min > np.iinfo(np.int16).min and c_max <\
                   np.iinfo(np.int16).max:
                    df[col] = df[col].astype(np.int16)
                elif c_min > np.iinfo(np.int32).min and c_max <\
                   np.iinfo(np.int32).max:
                    df[col] = df[col].astype(np.int32)
                elif c_min > np.iinfo(np.int64).min and c_max <\
                   np.iinfo(np.int64).max:
                    df[col] = df[col].astype(np.int64)
            else:
                if c_min > np.finfo(np.float16).min and c_max <\
                   np.finfo(np.float16).max:
                    df[col] = df[col].astype(np.float16)
                elif c_min > np.finfo(np.float32).min and c_max <\
                   np.finfo(np.float32).max:
                    df[col] = df[col].astype(np.float32)
                else:
                    df[col] = df[col].astype(np.float64)
        else:
            df[col] = df[col].astype('category')
    end_mem = df.memory_usage().sum() / 1024**2
    #print(('Memory usage after optimization is: {:.2f}'
    #                          'MB').format(end_mem))
    #print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem)
    #                                         / start_mem))

    return df

def reset_parameters():
    PDF_obj.qmin=0.7
    PDF_obj.qmax=25
    PDF_obj.qdamp=0.04
    PDF_obj.rmin=0
    PDF_obj.rmax=30
    PDF_obj.rstep=0.1
    PDF_obj.biso=1
    PDF_obj.delta2=2

def vary_parameters():
    PDF_obj.qmin = np.random.uniform(0, 2)
    PDF_obj.qmax = np.random.uniform(12, 25)
    PDF_obj.qdamp = np.random.uniform(0.01, 0.04)
    PDF_obj.biso = np.random.uniform(0.1, 1)

def PDF_from_index(xyzfileindex): #Makes a single PDF from an xyz-file with the index as input
    xyz_path = 'xyz_files/natoms200/'

    #if xyzfileindex == 1000 or xyzfileindex == 2000 or xyzfileindex == 3000 or xyzfileindex == 4000:
    #    print(f"{xyzfileindex} / {len(sorted_filenames_flat)}")

    #if xyzfileindex % int(len(sorted_filenames_flat)/10) == 0:            #Shows progress
    #        print(f"{xyzfileindex} / {len(sorted_filenames_flat)}")  #Shows progress
    vary_parameters()
    xgrid, xyz_pdf = PDF_obj.genPDF(xyz_path+sorted_filenames_flat[xyzfileindex], fmt='xyz') #PDF is made here!
    xyz_pdf = xyz_pdf/max(xyz_pdf) #Normalisation
    xyz_pdf = np.append(xyz_pdf, np.array([PDF_obj.qmin, PDF_obj.qmax, PDF_obj.qdamp]))
    xyz_pdf = np.append(xyz_pdf, int(xyzfileindex))
    return xyz_pdf

class PDF_generator:
    def __init__(self, qmin=0.5, qmax=30, qdamp=0.03, rmin=0, rmax=30, rstep=0.1, biso=0.3, delta2=0):
        """
        Class for simulating total scattering data for both crystal and cluster files.

        Parameters
        ----------
        qmin : Smallest q-vector included (float)
        qmax : Instrumental resolution (float)
        qdamp : Instrumental dampening (float)
        rmin : Start of r-grid (float)
        rmax : End of r-grid (float)
        rstep : Spacing between r-grid (float)
        biso : Vibration (float (float)
        delta2 : Correlated vibration (float)
        """

        self.qmin = qmin
        self.qmax = qmax  # Instrument resolution
        self.qdamp = qdamp  # Instrumental dampening
        self.rmin = rmin  # Smallest r value
        self.rmax = rmax  # Can not be less than 10 AA
        self.rstep = rstep  # Nyquist for qmax = 30
        self.biso = biso  # Atomic vibration
        self.delta2 = delta2  # Corelated vibration

    def genPDF(self, clusterFile, fmt='cif'):
        """
        Simulates PDF for input structure.

        Parameters
        ----------
        clusterFile : path for input file (str)
        fmt : cif or xyz, depending on structure type (str)

        Returns
        -------
        r : r-grid (NumPy array)
        Gr : Intensities (NumPy array)
        """
        stru = loadStructure(clusterFile)

        stru.B11 = self.biso
        stru.B22 = self.biso
        stru.B33 = self.biso
        stru.B12 = 0
        stru.B13 = 0
        stru.B23 = 0

        if fmt.lower() == 'cif':
            PDFcalc = PDFCalculator(rmin=self.rmin, rmax=self.rmax, rstep=self.rstep,
                                    qmin=self.qmin, qmax=self.qmax, qdamp=self.qdamp, delta2=self.delta2)
        elif fmt.lower() == 'xyz':
            PDFcalc = DebyePDFCalculator(rmin=self.rmin, rmax=self.rmax, rstep=self.rstep,
                                         qmin=self.qmin, qmax=self.qmax, qdamp=self.qdamp, delta2=self.delta2)
        r0, g0 = PDFcalc(stru)

        self.r = np.array(r0)
        self.Gr = np.array(g0)

        return self.r, self.Gr

    def __str__(self):
        return 'PDF parameters:\n\tqmin: {}\n\tqmax: {}\n\tqdamp: {}\n\trmin: {}' \
                              '\n\trmax {}\n\trstep: {}\n\tbiso: {} \n\tDelta2: {}\n'\
                                        .format(self.qmin, self.qmax, self.qdamp, self.rmin,
                                                self.rmax, self.rstep, self.biso, self.delta2)

structures_list = ["SC", "FCC", "BCC", "HCP", "Icosahedron", "Decahedron", "Octahedron"]

PDF_obj, sorted_filenames_flat, xyz_path = get_simulate_data_backend()

def make_data(path, numberatoms, Geometry, minimum_atoms=0, numberOfBondLengths=1):
    if Geometry=="SC" or Geometry=="FCC" or Geometry=="BCC":
        make_data_SC_FCC_BCC(path, numberatoms, Geometry, minimum_atoms, numberOfBondLengths)
    if Geometry=="HCP":
        make_data_HCP(path, numberatoms, Geometry, minimum_atoms, numberOfBondLengths)
    if Geometry=="Icosahedron":
        make_data_Icosahedron(path, numberatoms, Geometry, minimum_atoms, numberOfBondLengths)
    if Geometry=="Decahedron":
        make_data_Decahedron(path, numberatoms, Geometry, minimum_atoms, numberOfBondLengths)
    if Geometry=="Octahedron":
        make_data_Octahedron(path, numberatoms, Geometry, minimum_atoms, numberOfBondLengths)
    return None

def make_data_SC_FCC_BCC(path, numberatoms, Geometry, minimum_atoms=0, numberOfBondLengths=1):
    global h, k, l, atom, lc
    if numberatoms < 101:
        h_list = [1, 2, 3, 4, 5, 6, 7, 8]
        k_list = [1, 2, 3, 4, 5, 6, 7]
        l_list = [1, 2, 3, 4, 5, 6, 7]
    elif numberatoms < 201 and numberatoms > 101:
        h_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        k_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        l_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    elif numberatoms > 201:
        h_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
        k_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
        l_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

    possible_structures = len(h_list)*len(k_list)*len(l_list)*len(atom_list)*numberOfBondLengths
    pbar = tqdm(total=possible_structures)
    for atom in atom_list:
        structure_list = []
        for h in h_list:
            for k in k_list:
                for l in l_list:
                    if h <= k and h <= l and k <= l:
                        #atom_cov_radii = covalent_radii[atomic_numbers[atom]]
                        atom_cov_radii =  mendeleev.element(atom).metallic_radius/100
                        lc_list = np.linspace(atom_cov_radii*2*0.99 , atom_cov_radii*2*1.01, numberOfBondLengths)
                        if numberOfBondLengths == 1:
                            lc_list = [atom_cov_radii*2]
                        for lc in lc_list:
                            stru1, structure_type = structure_maker(Geometry)
                            xyz1 = stru1.get_positions()
                            if np.shape(xyz1)[0] > 1 and np.shape(xyz1)[0] <= numberatoms and  np.shape(xyz1)[0] >= minimum_atoms:
                                cluster = Structure([Atom(atom, xi) for xi in xyz1])
                                if new_structure_checker(xyz1, structure_list) == False:
                                    structure = np.zeros((numberatoms, 4))
                                    for i in range(len(xyz1)):
                                        structure[i, 0] = atomic_numbers[atom]
                                        structure[i, 1:] = xyz1[i]
                                    structure_list.append(xyz1)
                                    cluster.write(path+str(Geometry)+"_h_"+str(h)+"_k_"+str(k)+"_l_"+str(l)+"_atom_"+str(atom)+"_lc_"+str(lc)+".xyz", format="xyz")
                                    #generator = simPDFs(path+str(Geometry)+"_h_"+str(h)+"_k_"+str(k)+"_l_"+str(l)+"_atom_"+str(atom)+"_lc_"+str(lc)+".xyz", "./")
                                    #r, Gr = generator.getPDF()
                                    #y = [structure_type, h, k, l, 0, 0, 0, 0, 0, 0, 0, 0, atomic_numbers[atom], lc, 0]+Gr.tolist()
                                    #np.savetxt(path+str(Geometry)+"_h_"+str(h)+"_k_"+str(k)+"_l_"+str(l)+"_atom_"+str(atom)+"_lc_"+str(lc)+"_LABEL.txt", y)
                    pbar.update(1)
    pbar.close()
    return None

def make_data_HCP(path, numberatoms, Geometry, minimum_atoms=0, numberOfBondLengths=1):
    global size1, size2, size3, atom, lc1, lc2
    if numberatoms < 101:
        size1_list = [1, 2, 3, 4, 5, 6, 7, 8]
        size2_list = [1, 2, 3, 4, 5, 6, 7, 8]
        size3_list = [1, 2, 3, 4, 5, 6, 7, 8]
    elif numberatoms < 201 and numberatoms > 101:
        size1_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        size2_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        size3_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    elif numberatoms > 201:
        size1_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
        size2_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
        size3_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

    possible_structures = len(size1_list)*len(size2_list)*len(size3_list)*len(atom_list)*numberOfBondLengths
    pbar = tqdm(total=possible_structures)
    for atom in atom_list:
        structure_list = []
        for size1 in size1_list:
            for size2 in size2_list:
                for size3 in size3_list:
                    if size1 <= size2 and size1 <= size3 and size2 <= size3:
                        #atom_cov_radii = covalent_radii[atomic_numbers[atom]]
                        atom_cov_radii =  mendeleev.element(atom).metallic_radius/100
                        lc1_list = np.linspace(atom_cov_radii*2*0.99 , atom_cov_radii*2*1.01, numberOfBondLengths)
                        if numberOfBondLengths == 1:
                            lc1_list = [atom_cov_radii*2]
                        for lc1 in lc1_list:
                            #lc2_list = np.linspace(lc1*2*0.99 , lc1*2*1.01, 10)*1.633
                            lc2_list = np.asarray([lc1])*1.633
                            for lc2 in lc2_list:
                                stru1, structure_type = structure_maker(Geometry)
                                xyz1 = stru1.get_positions()
                                if np.shape(xyz1)[0] > 1 and np.shape(xyz1)[0] <= numberatoms and  np.shape(xyz1)[0] >= minimum_atoms:
                                    cluster = Structure([Atom(atom, xi) for xi in xyz1])
                                    if new_structure_checker(xyz1, structure_list) == False:
                                        structure = np.zeros((numberatoms, 4))
                                        for i in range(len(xyz1)):
                                            structure[i, 0] = atomic_numbers[atom]
                                            structure[i, 1:] = xyz1[i]
                                        structure_list.append(xyz1)
                                        cluster.write(path+str(Geometry)+"_Size1_"+str(size1)+"_Size2_"+str(size2)+"_Size3_"+str(size3)+"_atom_"+str(atom)+"_lc1_"+str(lc1)+"_lc2_"+str(lc2)+".xyz", format="xyz")
                                        #generator = simPDFs(path+str(Geometry)+"_Size1_"+str(size1)+"_Size2_"+str(size2)+"_Size3_"+str(size3)+"_atom_"+str(atom)+"_lc1_"+str(lc1)+"_lc2_"+str(lc2)+".xyz", "./")
                                        #r, Gr = generator.getPDF()
                                        #y = [structure_type, 0, 0, 0, size1, size2, size3, 0, 0, 0, 0, 0, atomic_numbers[atom], lc1, lc2]+Gr.tolist()
                                        #np.savetxt(path+str(Geometry)+"_Size1_"+str(size1)+"_Size2_"+str(size2)+"_Size3_"+str(size3)+"_atom_"+str(atom)+"_lc1_"+str(lc1)+"_lc2_"+str(lc2)+"_LABEL.txt", y)
                                pbar.update(1)
    pbar.close()
    return None

def make_data_Icosahedron(path, numberatoms, Geometry, minimum_atoms=0, numberOfBondLengths=1):
    global atom, shell, lc
    if numberatoms < 101:
        shell_list = [1, 2, 3, 4]
    elif numberatoms < 201 and numberatoms > 101:
        shell_list = [1, 2, 3, 4, 5]
    elif numberatoms > 201:
        shell_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

    possible_structures = len(shell_list)*len(atom_list)*numberOfBondLengths
    pbar = tqdm(total=possible_structures)
    for atom in atom_list:
        structure_list = []
        for shell in shell_list:
            #atom_cov_radii = covalent_radii[atomic_numbers[atom]]
            atom_cov_radii =  mendeleev.element(atom).metallic_radius/100
            lc_list = np.linspace(atom_cov_radii*2*0.99 , atom_cov_radii*2*1.01, numberOfBondLengths)
            if numberOfBondLengths == 1:
                lc_list = [atom_cov_radii*2]
            for lc in lc_list:
                stru1, structure_type = structure_maker(Geometry)
                xyz1 = stru1.get_positions()
                if np.shape(xyz1)[0] > 1 and np.shape(xyz1)[0] <= numberatoms and  np.shape(xyz1)[0] >= minimum_atoms:
                    cluster = Structure([Atom(atom, xi) for xi in xyz1])
                    if new_structure_checker(xyz1, structure_list) == False:
                        structure = np.zeros((numberatoms, 4))
                        for i in range(len(xyz1)):
                            structure[i, 0] = atomic_numbers[atom]
                            structure[i, 1:] = xyz1[i]
                        structure_list.append(xyz1)
                        cluster.write(path+str(Geometry)+"_shell_"+str(shell)+"_atom_"+str(atom)+"_lc_"+str(lc)+".xyz", format="xyz")
                        #generator = simPDFs(path+str(Geometry)+"_shell_"+str(shell)+"_atom_"+str(atom)+"_lc_"+str(lc)+".xyz", "./")
                        #r, Gr = generator.getPDF()
                        #y = [structure_type, 0, 0, 0, 0, 0, 0, shell, 0, 0, 0, 0, atomic_numbers[atom], lc, 0]+Gr.tolist()
                        #np.savetxt(path+str(Geometry)+"_shell_"+str(shell)+"_atom_"+str(atom)+"_lc_"+str(lc)+"_LABEL.txt", y)
                pbar.update(1)
    pbar.close()
    return None

def make_data_Decahedron(path, numberatoms, Geometry, minimum_atoms=0, numberOfBondLengths=1):
    global atom, p, q, r, lc
    if numberatoms < 101:
        p_list = [1, 2, 3, 4]
        q_list = [1, 2, 3, 4]
        r_list = [0, 1, 2, 3, 4]
    elif numberatoms < 201 and numberatoms > 101:
        p_list = [1, 2, 3, 4, 5]
        q_list = [1, 2, 3, 4, 5]
        r_list = [0, 1, 2, 3, 4, 5]
    elif numberatoms > 201:
        p_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
        q_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
        r_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

    possible_structures = len(p_list)*len(q_list)*len(r_list)*len(atom_list)*numberOfBondLengths
    pbar = tqdm(total=possible_structures)
    for atom in atom_list:
        structure_list = []
        for p in p_list:
            for q in q_list:
                for r in r_list:
                    #if p <= q and p <= r and q <= r:
                    #atom_cov_radii = covalent_radii[atomic_numbers[atom]]
                    atom_cov_radii =  mendeleev.element(atom).metallic_radius/100
                    lc_list = np.linspace(atom_cov_radii*2*0.99 , atom_cov_radii*2*1.01, numberOfBondLengths)
                    if numberOfBondLengths == 1:
                        lc_list = [atom_cov_radii*2]
                    for lc in lc_list:
                        stru1, structure_type = structure_maker(Geometry)
                        xyz1 = stru1.get_positions()
                        if np.shape(xyz1)[0] > 1 and np.shape(xyz1)[0] <= numberatoms and  np.shape(xyz1)[0] >= minimum_atoms:
                            cluster = Structure([Atom(atom, xi) for xi in xyz1])
                            if new_structure_checker(xyz1, structure_list) == False:
                                structure = np.zeros((numberatoms, 4))
                                for i in range(len(xyz1)):
                                    structure[i, 0] = atomic_numbers[atom]
                                    structure[i, 1:] = xyz1[i]
                                structure_list.append(xyz1)
                                cluster.write(path+str(Geometry)+"_p_"+str(p)+"_q_"+str(q)+"_r_"+str(r)+"_atom_"+str(atom)+"_lc_"+str(lc)+".xyz", format="xyz")
                                #generator = simPDFs(path+str(Geometry)+"_p_"+str(p)+"_q_"+str(q)+"_r_"+str(r)+"_atom_"+str(atom)+"_lc_"+str(lc)+".xyz", "./")
                                #r_PDF, Gr = generator.getPDF()
                                #y = [structure_type, 0, 0, 0, 0, 0, 0, 0, p, q, r, 0, atomic_numbers[atom], lc, 0]+Gr.tolist()
                                #np.savetxt(path+str(Geometry)+"_p_"+str(p)+"_q_"+str(q)+"_r_"+str(r)+"_atom_"+str(atom)+"_lc_"+str(lc)+"_LABEL.txt", y)
                        pbar.update(1)
    pbar.close()
    return None

def make_data_Octahedron(path, numberatoms, Geometry, minimum_atoms=0, numberOfBondLengths=1):
    global atom, length, lc
    if numberatoms < 101:
        length_list = [2, 3, 4, 5]
    elif numberatoms < 201 and numberatoms > 101:
        length_list = [2, 3, 4, 5, 6, 7]
    elif numberatoms > 201:
        length_list = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

    possible_structures = len(length_list)*len(atom_list)*numberOfBondLengths
    pbar = tqdm(total=possible_structures)
    for atom in atom_list:
        structure_list = []
        for length in length_list:
            #atom_cov_radii = covalent_radii[atomic_numbers[atom]]
            atom_cov_radii =  mendeleev.element(atom).metallic_radius/100
            lc_list = np.linspace(atom_cov_radii*2*0.99 , atom_cov_radii*2*1.01, numberOfBondLengths)
            if numberOfBondLengths == 1:
                lc_list = [atom_cov_radii*2]
            for lc in lc_list:
                stru1, structure_type = structure_maker(Geometry)
                xyz1 = stru1.get_positions()
                if np.shape(xyz1)[0] > 1 and np.shape(xyz1)[0] <= numberatoms and  np.shape(xyz1)[0] >= minimum_atoms:
                    cluster = Structure([Atom(atom, xi) for xi in xyz1])
                    if new_structure_checker(xyz1, structure_list) == False:
                        structure = np.zeros((numberatoms, 4))
                        for i in range(len(xyz1)):
                            structure[i, 0] = atomic_numbers[atom]
                            structure[i, 1:] = xyz1[i]
                        structure_list.append(xyz1)
                        cluster.write(path+str(Geometry)+"_length_"+str(length)+"_atom_"+str(atom)+"_lc_"+str(lc)+".xyz", format="xyz")
                        #generator = simPDFs(path+str(Geometry)+"_length_"+str(length)+"_atom_"+str(atom)+"_lc_"+str(lc)+".xyz", "./")
                        #r, Gr = generator.getPDF()
                        #y = [structure_type, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, length, atomic_numbers[atom], lc, 0]+Gr.tolist()
                        #np.savetxt(path+str(Geometry)+"_length_"+str(length)+"_atom_"+str(atom)+"_lc_"+str(lc)+"_LABEL.txt", y)
                pbar.update(1)
    pbar.close()
    return None

def new_structure_checker(Input_array, list_search):
    for i in range(len(list_search)):
        if np.all(Input_array == list_search[i]) == True:
            return True
        else:
            pass
    return False

def remove_same_structures(path, savePath):
    files = os.listdir(path)
    softadj_list = []
    remove_files = []
    pbar = tqdm(total=len(files))

    for file in files:
        structure = loadStructure(data_dir+file)
        softadj = np.zeros((len(structure), len(structure)))
        for i in range(len(structure)):
            for j in range(len(structure)):
                atom1 = np.array([structure.x[i], structure.y[i], structure.z[i]])
                atom2 = np.array([structure.x[j], structure.y[j], structure.z[j]])
                dist = np.linalg.norm(atom1-atom2)
                softadj[i][j] = dist
        if new_structure_checker(softadj, softadj_list):
            remove_files.append(file)
        else:
            softadj_list.append(softadj)
            copyfile(path+file, savePath+file)
        pbar.update(1)
    pbar.close()

    return remove_files

def structure_maker(Geometry):
    global h, k, l, atom, lc, lc1, lc2, size1, size2, size3, shell, p, q, r, length
    if Geometry=="SC":
        stru = SimpleCubic(atom, surfaces=[[1,0,0], [1,1,0], [1,1,1]], layers=(h,k,l), latticeconstant=lc)
        structure_type = 0
    if Geometry=="FCC":
        stru = FaceCenteredCubic(atom, surfaces=[[1,0,0], [1,1,0], [1,1,1]], layers=(h,k,l), latticeconstant=2*np.sqrt(0.5*lc**2))
        structure_type = 1
    if Geometry=="BCC":
        stru = BodyCenteredCubic(atom, surfaces=[[1,0,0], [1,1,0], [1,1,1]], layers=(h,k,l), latticeconstant=lc)
        structure_type = 2
    if Geometry=="HCP":
        stru = HexagonalClosedPacked(symbol=atom, latticeconstant=(lc1, lc2), size=(size1, size2, size3))
        structure_type = 3
    if Geometry=="Icosahedron":
        stru = Icosahedron(atom, shell, latticeconstant=2*np.sqrt(0.5*lc**2))
        structure_type = 4
    if Geometry=="Decahedron":
        stru = Decahedron(atom, p, q, r, latticeconstant=2*np.sqrt(0.5*lc**2))
        structure_type = 5
    if Geometry=="Octahedron":
        stru = Octahedron(atom, length, latticeconstant=2*np.sqrt(0.5*lc**2))
        structure_type = 6
    return stru, structure_type

def remove_dub(dir1): #new
    files1 = sorted(os.listdir(dir1))
    remove_list = []

    pbar = tqdm(total=len(files1))
    for idx1 in range(len(files1)):
        file1 = files1[idx1]
        dat1 = np.loadtxt(dir1+'/'+file1, skiprows=1, dtype=np.str)
        dat1 = np.array(dat1.T[1:], dtype=np.float)
        dist_mat1 = spatial.distance.cdist(dat1.T, dat1.T, 'euclidean')
        dist_mat1 = np.sort(dist_mat1.reshape(-1))
        pbar.update()
        for idx2 in range(idx1, len(files1)):
            file2 = files1[idx2]

            if file1 == file2:
                continue
            elif file2 in remove_list or file1 in remove_list:
                continue

            dat2 = np.loadtxt(dir1+'/'+file2, skiprows=1, dtype=np.str)
            dat2 = np.array(dat2.T[1:], dtype=np.float)

            if dat1.shape == dat2.shape:
                dist_mat2 = spatial.distance.cdist(dat2.T, dat2.T, 'euclidean')
                dist_mat2 = np.sort(dist_mat2.reshape(-1))

                val = np.array_equal(dist_mat1, dist_mat2)

                if val == True:
                    #print('\t\t',file1, file2) #
                    remove_list.append(file1)
                    os.remove(dir1+'/'+file1)
                    #print(file1, 'has been deleted\n') #

    return None

def simulate_clusters(folder_name, maximum_atoms, minimum_atoms): #old
    data_dir = "xyz_files/" + folder_name + "/"

    if os.path.isdir(data_dir):
        print("This directory already exists. Choose a different folder name...")
        return
    os.makedirs(data_dir)
    structure_type_list = ["SC", "BCC", "FCC", "HCP", "Icosahedron", "Decahedron", "Octahedron"]
    numberOfBondLengths=1

    print("Simulating metal nanoparticle clusters from " + str(minimum_atoms) + " to " + str(maximum_atoms) + " atoms of structure types: SC, BCC, FCC, HCP, Icosahedron, Decahedron and Octahedron")

    for structure_type in structure_type_list:
        make_data(data_dir, maximum_atoms, structure_type, minimum_atoms=5, numberOfBondLengths=1)

    print("All clusters simulated and saved in folder: " + str(data_dir))
    print("Now removing all duplicates. This is a time-consuming process. Lean back and crack open a cold one")

    remove_dub(data_dir)

    print("All duplicates removed")

def simulate_clusters(folder_name, maximum_atoms, minimum_atoms): #tjek
    data_dir = "xyz_files/" + folder_name + "/"
    start_time = time.time()

    if os.path.isdir(data_dir):
        print("This directory already exists. Choose a different folder name...")
        return
    os.makedirs(data_dir)
    structure_type_list = ["SC", "BCC", "FCC", "HCP", "Icosahedron", "Decahedron", "Octahedron"]
    numberOfBondLengths=1

    print("Simulating metal nanoparticle clusters from " + str(minimum_atoms) + " to " + str(maximum_atoms) + " atoms of structure types: SC, BCC, FCC, HCP, Icosahedron, Decahedron and Octahedron")

    for structure_type in structure_type_list:
        make_data(data_dir, maximum_atoms, structure_type, minimum_atoms=5, numberOfBondLengths=1)

    print("All clusters simulated and saved in folder: " + str(data_dir))
    print("Now removing all duplicates. This is a time-consuming process. Lean back and crack open a cold one")

    remove_dub(data_dir)

    print("All duplicates removed")
    end_time = time.time()
    print("Cluster simulation complete! " + str(len(os.listdir(data_dir))) + " metal clusters created. It took " + str((end_time - start_time)/60)[0:5] + " minutes.")

global atom_list #sets atom_list to be a global variable, e.g. also defined inside defined functions
atom_list = ['Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn',
             'Y', 'Zr', 'Nb', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd',
             'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg']

max_stars_repo_name: AndySAnker/MetalFinder

max_issues_repo_name: AndyNano/MetalFinder

max_forks_repo_name: AndyNano/MetalFinder

reason: import numpy,from scipy


text:
import numpy

from aspectizing import any_callable, aspect, woody_logger

aspect(numpy, any_callable, "", woody_logger, dry_run=True)

max_stars_repo_name: amogorkon/pyuse

max_issues_repo_name: amogorkon/justuse

max_forks_repo_name: amogorkon/use


text:
# %%[markdown]
# Author: Nelson Liu
#
# Email: [nliu@uncharted.software](mailto:nliu@uncharted.software)

# %%[markdown]
# Content:
# * Load the model comparison examples from Algebraic Julia (James and Andrew)
# * Plot results

# %%
import json
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
from typing import Dict, Tuple, Any, Optional

# %%[markdown]
# # Load Model Data

# %%

path = "../data/august_2021_demo_repo/Simple_SIR/SimpleSIR_metadata_gromet_PetriNetClassic.json"
with open(path, 'r') as f:
    model_sir = json.load(f)

path = "../data/august_2021_demo_repo/AlgebraicJulia_models/chime+.json"
with open(path, 'r') as f:
    model_chimep = json.load(f)

path = "../data/august_2021_demo_repo/AlgebraicJulia_models/model_comparisons/sir_chime+.json"
with open(path, 'r') as f:
    map_sir_chimep = json.load(f)

f = None
del f

# %%[markdown]
# # Parse GroMEts into NX Objects
def generate_nx_obj(gromet: Dict) -> Any:

    G = nx.MultiDiGraph(uid = gromet['uid'], type = gromet['type'], name = gromet['name'])

    G.add_nodes_from(
        [(j['uid'], {
            'model_uid': gromet['uid'],
            'uid': j['uid'],
            'name': j['name'],
            'type': j['type']
        }) for j in gromet['junctions']]
    )

    G.add_edges_from(
        [(w['src'], w['tgt'], {
            'model_uid': gromet['uid'], 'uid': w['uid']
        })
        for w in gromet['wires']], weight = 1
    )

    return G

# %%
def compare_graphs(G1: Any, G2: Any, map: Optional[Dict], leg_id: Optional[int] = 0, rename: Tuple = (None, None), plot: bool = False, plot_layout: str = 'linear') -> Tuple:

    # Mapping graph
    G_map = nx.MultiDiGraph()
    for rn, g in zip(rename, (G1, G2)):
        G_map.add_nodes_from([(rn + n, g.nodes[n]) for n in g.nodes])
        G_map.add_edges_from([(rn + edge[0], rn + edge[1], g.edges[edge]) for edge in g.edges], weight = 1.0)

    # G1 -> G2 map edges
    if map != None:
        G_map.add_edges_from([(rename[0] + k, rename[1] + v) for k, v in map['legs'][G2.graph['uid']][leg_id].items()], weight = 5.0)

    # Plot bipartite graph
    fig = None
    if plot == True:

        # Colour
        node_col = [0 if G_map.nodes[node]['model_uid'] == G1.graph['uid'] else 1 for node in G_map.nodes]
        edge_col = [
            0 if (G_map.nodes[edge[0]]['model_uid'] == G1.graph['uid']) & (G_map.nodes[edge[1]]['model_uid'] == G1.graph['uid'])
            else 1 if (G_map.nodes[edge[0]]['model_uid'] == G2.graph['uid']) & (G_map.nodes[edge[1]]['model_uid'] == G2.graph['uid'])
            else 0.5 for edge in G_map.edges]

        if plot_layout == 'linear':

            pos_map = {}
            for l, (rn, g) in enumerate(zip(rename, (G1, G2))):

                g_cond = nx.condensation(g)

                k = 0
                for i in nx.topological_sort(g_cond):
                    for j in g_cond.nodes[i]['members']:
                        pos_map[rn + j] = np.array([k, 2 * l])
                        k += 1

            # Align mapped nodes along x-axis
            for k, v in map['legs'][G2.graph['uid']][leg_id].items():

                src = rename[0] + k
                tgt = rename[1] + v

                x = np.max([pos_map[src][0], pos_map[tgt][0]])
                pos_map[src][0] = x
                pos_map[tgt][0] = x

        else:

            # KK Layout
            pos_map = nx.kamada_kawai_layout(G_map, weight = 'weight', center = (0, 0))

        fig, ax = plt.subplots(nrows = 1, ncols = 1, figsize = (16, 12))

        for g, col in zip((G1, G2), ('tab:blue', 'tab:orange')):

            G_map_subg = G_map.subgraph([node for node in G_map.nodes if G_map.nodes[node]['model_uid'] == g.graph['uid']])

            node_size = np.array([500 if G_map_subg.nodes[node]['type'] == 'State' else 50 for node in G_map_subg.nodes])

            __ = nx.draw_networkx_nodes(
                G_map_subg,
                pos = pos_map,
                ax = ax,
                node_size = node_size,
                node_color = col
            )

            __ = nx.draw_networkx_edges(
                G_map_subg,
                pos = pos_map,
                ax = ax,
                edge_color = col,
                connectionstyle = 'arc3,rad=0.3'
            )

            h = nx.draw_networkx_labels(G_map_subg, pos = pos_map, ax = ax, font_color = 'tab:gray', horizontalalignment = 'left', verticalalignment = 'bottom')
            __ = [t.set_rotation(45) for __, t in h.items()]

        G_map_sube = G_map.edge_subgraph([edge for edge in G_map.edges if G_map.nodes[edge[0]]['model_uid'] != G_map.nodes[edge[1]]['model_uid']])
        nx.draw_networkx_edges(G_map_sube, pos = pos_map, ax = ax, edge_color = 'tab:green')

        __ = plt.setp(ax, title = f"{G1.graph['uid']} -> {G2.graph['uid']}", aspect = 1.0, ylim = (-1.5, 3.5))

    return (G_map, fig)

# %%

G_sir = generate_nx_obj(gromet = model_sir)
G_chimep = generate_nx_obj(gromet = model_chimep)

for i in range(2):
    G_map, fig = compare_graphs(G1 = G_sir, G2 = G_chimep, map = map_sir_chimep, leg_id = i, rename = ('SIR ', 'CHIME+ '), plot = True, plot_layout = 'linear')
    fig.savefig(f'../figures/map_sir_chime+_{i}.png', dpi = 150)

# %%

max_stars_repo_name: uncharted-aske/research

max_issues_repo_name: uncharted-aske/research

max_forks_repo_name: uncharted-aske/research

reason: import numpy,import networkx