import pathlib

import pytest
from flexmock import flexmock

from ibata.cli_app import *
from ibata.downloaders.TransactionDownloader import TransactionDownloader

@pytest.fixture
def start_cli_fake():
    """Prevents starting everything if cli is successful"""
    flexmock(TransactionDownloaderResolver, get_transaction_downloader=0)
    flexmock(TransactionDownloader, get_transactions=0)
    flexmock(TransactionAnalyzer, __init__=0)
    flexmock(TransactionAnalyzer, categorize_transactions=0)
    flexmock(TransactionAnalyzer, get_categories_from_transactions=0)
    flexmock(CategoriesSummary, print=0)
    flexmock(PlotMaker, show_and_save_plot=0)
    flexmock(ResultSaver, save_result=0)

config_dir = pathlib.Path(__file__).parent / "fixtures"

@pytest.mark.parametrize('options', (["-f", "2020-01-01", "-t", "2020-01-01", "-c", config_dir / "ibata_ok.cfg"],
                                     ["-e", "-c", config_dir / "ibata_ok.cfg"]))
def test_ok_required(start_cli_fake, runner, options):
    result = runner.invoke(ibata, options)
    print(result.exit_code)
    assert result.exit_code == 1

def test_valid_bank():
    banks = TransactionDownloaderResolver.BANKS.keys()
    for bank in banks:
        assert bank == check_valid_bank(None, None, bank)

def test_invalid_bank():
    with pytest.raises(click.exceptions.BadParameter):
        check_valid_bank(None, None, "bank")

@pytest.mark.parametrize('date', (None, "2020-01-04", "1994-10-15"))
def test_check_valid_date(date):
    assert date == check_valid_date(None, None, date)

@pytest.mark.parametrize('date', ("None", "20201-01-04", "1994-20-15", "1994-12-35", "1994-10-15-16"))
def test_check_invalid_date(date):
    with pytest.raises(click.exceptions.BadParameter):
        check_valid_date(None, None, date)

@pytest.mark.parametrize(['date_from', 'date_to'],
                         [('2020-01-01', '2020-01-01'), ('2020-01-01', '2020-01-02'), ('2020-01-01', '2021-01-02')])
def test_check_valid_dates(date_from, date_to):
    assert check_valid_dates(date_from, date_to)

@pytest.mark.parametrize(['date_from', 'date_to'],
                         [('2020-01-01', '2019-01-01'), ('2020-02-01', '2020-01-31'), (None, '2021-01-02'),
                          ('2020-02-01', None)])
def test_check_invalid_dates(date_from, date_to):
    with pytest.raises(click.exceptions.BadParameter):
        check_valid_dates(date_from, date_to)

def test_check_valid_config_file_callback(config_file, config_file_object):
    assert config_file == check_valid_config_file_callback(None, None, config_file_object)

@pytest.mark.parametrize('file_name', ("ibata_wrong_categories.cfg", "ibata_not_existing_categories.cfg",
                                       "ibata_no_token.cfg", "ibata_no_fio_section.cfg", "ibata_no_categories_file.cfg",
                                       "ibata_no_categories.cfg"))
def test_check_invalid_config_file_callback(config_dir, file_name):
    config_file = config_dir / file_name
    file = flexmock(name=config_file)
    with pytest.raises(click.exceptions.BadParameter):
        check_valid_config_file_callback(None, None, file)

@pytest.mark.parametrize('output_format', ("SUMMARY", "CATEGORIES", "ALL", "NONE"))
def test_validate_output_format(output_format):
    assert output_format == validate_output_format(None, None, output_format)

@pytest.mark.parametrize('output_format', ("SUMMAR", "", "ANSJA"))
def test_validate_output_format_wrong(output_format):
    with pytest.raises(click.exceptions.BadParameter):
        validate_output_format(None, None, output_format)

@pytest.mark.parametrize('save_format', ("TXT", "JSON", "CSV", "NONE"))
def test_validate_save_format(save_format):
    assert save_format == validate_save_format(None, None, save_format)

@pytest.mark.parametrize('save_format', ("", "JasSON", "CSasV"))
def test_validate_save_format_wrong(save_format):
    with pytest.raises(click.exceptions.BadParameter):
        validate_save_format(None, None, save_format)

@pytest.mark.parametrize('options', (["-c", config_dir / "ibata_ok.cfg"], ["-f", "2020-01-01", "-c", config_dir / "ibata_ok.cfg"],
                                     ["-t", "2020-01-01", "-c", config_dir / "ibata_ok.cfg"]))
def test_missing_required(start_cli_fake, runner, options):
    result = runner.invoke(ibata, options)
    print(result.exit_code)
    assert result.exit_code == 2
    assert "is required" in result.output


import numpy as np
import os
from matplotlib import pyplot as plt

n_users = 943
n_items = 1682
k = 10
lamda = 0.5
epoches = 30

R_data = np.zeros((n_users, n_items))
R_test = np.zeros((n_users, n_items))

losses = []

with open("./ml-100k/u1.base") as f:
    for line in f.readlines():
        data = line.strip().split()
        R_data[int(data[0])-1][int(data[1])-1] = data[2]

with open("./ml-100k/u1.test") as f:
    for line in f.readlines():
        data = line.strip().split()
        R_test[int(data[0])-1][int(data[0])-1] = data[2]

P_user = np.random.random((n_users, k))
Q_item = np.random.random((n_items, k))

for epoch in range(epoches):
    P_user = np.dot(R_data, np.dot(np.linalg.inv(np.dot(Q_item.T, Q_item) + lamda), Q_item.T).T)
    Q_item = np.dot(R_data.T, np.dot(np.linalg.inv(np.dot(P_user.T, P_user) + lamda), P_user.T).T)

    R_predict = np.dot(P_user, Q_item.transpose())

    diff = 0
    for i in range(R_test.shape[0]):
        for j in range(R_test.shape[1]):
            if R_test[i, j] != 0:
                diff += (R_test[i, j] - R_predict[i, j]) ** 2

    Lvalidation = diff / (n_users * n_items)
    losses.append(Lvalidation)

fig, ax = plt.subplots()
ax.plot(losses)
plt.show()


# /usr/bin/python
# coding: utf-8

class Solution:

    def __init__(self):
        self.row_status = []
        self.col_status = []
        self.box_status = []
        self.board = []
        self.done = False

    def scanBoard(self):
        for row in range(9):
            for col in range(9):
                if self.board[row][col] != '.':
                    num = int(self.board[row][col])
                    box_num = row // 3 * 3 + col // 3
                    # print(row, col, box_num, num)
                    self.row_status[row][num-1] = False
                    self.col_status[col][num-1] = False
                    self.box_status[box_num][num-1] = False

    def placeNum(self, row, col):
        if row == 9:
            self.done = True
            return
        next_row = row + 1 if col == 8 else row
        next_col = col + 1 if col != 8 else 0
        # print(row, col, next_row, next_col)
        if self.board[row][col] == '.':
            box_num = row // 3 * 3 + col // 3
            for num in range(9):
                if self.row_status[row][num] and self.col_status[col][num] and \
                   self.box_status[box_num][num]:
                    self.row_status[row][num] = False
                    self.col_status[col][num] = False
                    self.box_status[box_num][num] = False
                    self.board[row][col] = str(num+1)
                    self.placeNum(next_row, next_col)
                    if self.done:
                        return
                    self.board[row][col] = '.'
                    self.row_status[row][num] = True
                    self.col_status[col][num] = True
                    self.box_status[box_num][num] = True
        else:
            self.placeNum(next_row, next_col)

    def solveSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: void Do not return anything, modify board in-place instead.
        """
        self.board = board
        self.row_status = [[True for i in range(9)] for j in range(9)]
        self.col_status = [[True for i in range(9)] for j in range(9)]
        self.dia_status = [[True for i in range(9)] for j in range(2)]
        self.box_status = [[True for i in range(9)] for j in range(9)]
        self.scanBoard()
        self.placeNum(0, 0)

print(Solution().solveSudoku([[".",".","9","7","4","8",".",".","."],["7",".",".",".",".",".",".",".","."],[".","2",".","1",".","9",".",".","."],[".",".","7",".",".",".","2","4","."],[".","6","4",".","1",".","5","9","."],[".","9","8",".",".",".","3",".","."],[".",".",".","8",".","3",".","2","."],[".",".",".",".",".",".",".",".","6"],[".",".",".","2","7","5","9",".","."]]
))


# coding:utf-8
from django.shortcuts import render
from django.views import View
from decimal import Decimal

from meuspedidos_app.models import ProdutoModel, ItemModel, PedidoModel
from meuspedidos_app.views.funcoes import verificar_rentabilidade, remover_ponto_decimal, remover_zeros_final
from meuspedidos_app.views.pedido import PedidoView

class ProdutoView(View):

    @classmethod
    def Listar(self, request, msg=None, tipo_msg=None, id=None):
        context_dict = {}

        if id or 'pedido_edit' in request.session:  # edição de pedido
            template = 'pedido_edit.html'
            if id:
                request.session['pedido_edit'] = id
                id_pedido = id
            else:
                id_pedido = request.session['pedido_edit']

            if request.session and 'pedido' in request.session:
                ItemModel.objects.filter(pedido=request.session['pedido']).delete()
                del request.session['pedido']
                PedidoModel.objects.filter(status=False).delete()

            pedido = PedidoModel.objects.get(pk=id_pedido)
            pedido.status = False
            pedido.save()
            context_dict['pedido'] = pedido
        else:  # novo pedido
            template = 'produtos.html'
            id_pedido = request.session['pedido']

        existe_item_pedido = False
        itens = ItemModel.objects.filter(pedido=id_pedido)

        if itens:
            for item in itens:
                preco_unitario_produto = remover_ponto_decimal(item.produto.preco_unitario)
                preco_pago = remover_zeros_final(item.preco)

                if verificar_rentabilidade(preco_unitario_produto, preco_pago) != 0:
                    existe_item_pedido = True
                    break

        context_dict['existe_item_pedido'] = existe_item_pedido
        context_dict['produtos'] = ProdutoModel.objects.all().order_by('nome')
        context_dict['msg'] = msg
        context_dict['tipo_msg'] = tipo_msg
        return render(request, template, context_dict)

    @classmethod
    def ListarProdutosAdmin(self, request):
        context_dict = {}

        context_dict['produtos'] = ProdutoModel.objects.all().order_by('nome')
        return render(request, 'produtos_admin.html', context_dict)

    @classmethod
    def AdicionarRemoverProduto(self, request, msg=None, tipo_msg=None):
        if request.session:
            if 'pedido' in request.session:
                id_pedido = request.session['pedido']
            elif 'pedido_edit' in request.session:
                id_pedido = request.session['pedido_edit']
            else:
                id_pedido = None

            if id_pedido:
                id_produto = request.POST.get('id_produto')
                produto = ProdutoModel.objects.get(pk=id_produto)
                qtd = request.POST.get('qtd')
                preco_pago = request.POST.get('preco_pago')

                if ItemModel.objects.filter(pedido=id_pedido, produto=id_produto):
                    PedidoView.remover_item(id_pedido, id_produto)
                    msg = "Item removido com sucesso."
                    tipo_msg = "green"
                else:
                    if not qtd or not preco_pago:
                        msg = "Os campos quantidade e preço devem ser preenchidos para adicionar um pedido"
                        tipo_msg = "red"
                    elif int(qtd) <= 0 or Decimal(preco_pago.replace(',', '')) <= 0:
                        msg = "A quantidade e o preço devem ser maior que zero"
                        tipo_msg = "red"
                    else:
                        qtd = int(qtd)

                        if qtd % produto.multiplo == 0:
                            if preco_pago.find(',') == -1:
                                preco_pago = preco_pago + ',00'
                            preco_pago = Decimal(preco_pago.replace(',', ''))
                            PedidoView.adicionar_item(id_pedido, id_produto, preco_pago, qtd)
                            msg = "Item adicionado com sucesso."
                            tipo_msg = "green"
                        else:
                            msg = "A quantidade tem que obedecer o número Múltiplo!"
                            tipo_msg = "red"
            else:
                msg = "Algo deu errado, tente novamente"
                tipo_msg = "red"
        else:
            msg = "Algo deu errado, tente novamente"
            tipo_msg = "red"

        return self.Listar(request, msg, tipo_msg)


import requests
import json
session = requests.session()

domain = "https://mb.com.ph"
ch_url = "https://check-host.net:443/check-http?host=" + domain + "&max_nodes=24"
ch_headers = {"User-Agent": "curl/7.54.0", "Accept": "application/json", "Connection": "close"}

result = session.get(ch_url, headers=ch_headers)
tangina = json.loads(result.text)

url = str(tangina['permanent_link'])

def monitor_url(url1):

    bot_token = ''
    bot_chatID = ''
    send_text = 'https://api.telegram.org/bot' + bot_token + '/sendMessage?chat_id=' + bot_chatID + '&disable_web_page_preview=1&parse_mode=Markdown&text=' + url1

    response = requests.get(send_text)

    return response.json()

test = monitor_url("URL: " + url +"")


from celery.schedules import crontab
from datetime import timedelta

BROKER_URL = 'sqla+sqlite:///seeoh.sqlite'

CELERY_ENABLE_UTC = True
CELERY_TIMEZONE = 'Asia/Seoul'
CELERYBEAT_SCHEDULE = {
  'every-six-hours': {
    'task': 'seeoh.tweet',
    'schedule': crontab(hour='7,13,19', minute=30),
    'args': (),
  },
  # 'every-minute': {
    # 'task': 'seeoh.tweet',
    # 'schedule': crontab(minute='*'),
    # 'args': (),
  # },
}

CELERY_IMPORTS = ("seeoh", )

CELERY_ANNOTATIONS = {"seeoh.tweet": {"rate_limit": "10/s"}}


N, M = map(int, input().split())
data = list(map(int, input().split()))

video_max = max(data)
start = video_max
end   = sum(data)

ans = 10**9
while start <= end:
    mid = (start + end)//2
    cnt = 1
    tmp = 0

    for i in range(N):
        if tmp+data[i] <= mid:
            tmp += data[i]
        else:
            tmp = data[i]
            cnt += 1

        if cnt > M:
            break

    if cnt > M:
        start = mid+1
    else:
        end = mid-1
        if mid >= video_max:
            ans = min(ans, mid)

print(ans)


# Написати програму для обчислення добутку двох натуральних чисел,
# використовуючи лише операцію додавання.

# 3 * 4 = 0 + 4 + 4 + 4
m, n = map(int, input().split())

res = 0
i = 0
while i < m:
    res += n  # res = res + n
    i += 1

print(res)


import os
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
import torch

def plot_loss_acc(train_loss, val_loss,fig_name):
    x = np.arange(len(train_loss))

    fig, ax1 = plt.subplots()
    ax1.set_xlabel('epoch')
    ax1.set_ylabel('loss')
    lns1 = ax1.plot(x, train_loss, 'y-', label='train_loss')
    lns2 = ax1.plot(x, val_loss, 'g-', label='val_loss')
    lns = lns1+lns2
    labs = [l.get_label() for l in lns]
    fig.tight_layout()
    plt.title(fig_name)

    plt.savefig(os.path.join('./diagram', fig_name))


lst = input("Enter you dictionary: ")
lst = lst[1:-1]
lst = lst.split(",")
dic = {}
for elm in lst:
    elm = elm.lstrip(" '")
    elm = elm.rstrip("'")
    year ="20"+ elm[0:2]
    deptcode = elm[3:5]
    print(deptcode)
    if deptcode == "01":
        dept = "CSE"
    elif deptcode == "41":
        dept = "CS"
    elif deptcode=="21":
        dept = "EEE"
    else:
        dept = "Other"
    if year not in dic.keys():
        dic[year] = {dept:[elm]}
    else:
        if dept not in dic[year].keys():
            dic[year][dept] = [elm]
        else:
            temp = dic[year][dept]
            temp.append(elm)
            dic[year][dept] = temp
final = {}
for key,val in dic.items():
    temp = {}
    for k,v in val.items():
        temp[k] = tuple(v)
    final[key] = temp
print(final)
#print(dic)


# coding: utf8

import argparse
from distutils.util import strtobool

from colorama import Fore

TRAIN_CATEGORIES = {
    # General parent group
    'POSITIONAL': '%sPositional arguments%s' % (Fore.BLUE, Fore.RESET),
    'COMPUTATIONAL': '%sComputational resources%s' % (Fore.BLUE, Fore.RESET),
    'DATA': '%sData management%s' % (Fore.BLUE, Fore.RESET),
    'CROSS-VALIDATION': '%sCross-validation arguments%s' % (Fore.BLUE, Fore.RESET),
    'OPTIMIZATION': '%sOptimization parameters%s' % (Fore.BLUE, Fore.RESET),
    # Other parent groups
    'TRANSFER LEARNING': '%sTransfer learning%s' % (Fore.BLUE, Fore.RESET),
    'AUTOENCODER': '%sAutoencoder specific%s' % (Fore.BLUE, Fore.RESET),
    # Slice-level
    'SLICE': '%sSlice-level parameters%s' % (Fore.BLUE, Fore.RESET),
    'SLICE CNN': '%sSlice-level CNN parameters%s' % (Fore.BLUE, Fore.RESET),
    # Patch arguments
    'PATCH': '%sPatch-level parameters%s' % (Fore.BLUE, Fore.RESET),
    'PATCH CNN': '%sPatch-level CNN parameters%s' % (Fore.BLUE, Fore.RESET),
    # ROI-based arguments
    'ROI': '%sROI-based parameters%s' % (Fore.BLUE, Fore.RESET),
    'ROI CNN': '%sROI-based CNN parameters%s' % (Fore.BLUE, Fore.RESET),
    # Other optional arguments
    'OPTIONAL': '%sOther options%s' % (Fore.BLUE, Fore.RESET),
    # Model selection
    'MODEL': '%sModel selection%s' % (Fore.BLUE, Fore.RESET),
    # Display
    'DISPLAY': '%sResults display%s' % (Fore.BLUE, Fore.RESET),
}

def extract_tensors(args):
    import sys
    from clinica.utils.stream import FilterOut
    from clinica.pipelines.deeplearning_prepare_data.deeplearning_prepare_data_cli import DeepLearningPrepareDataCLI

    sys.stdout = FilterOut(sys.stdout)

    dl_prepare_data_cli = DeepLearningPrepareDataCLI()
    dl_prepare_data_cli.run_command(args)

def qc_func(args):
    from .quality_check.t1_linear.quality_check import quality_check as linear_qc
    from .quality_check.t1_volume.quality_check import quality_check as volume_qc

    if args.preprocessing == "t1-linear":
        linear_qc(
            args.caps_dir,
            args.output_path,
            tsv_path=args.subjects_sessions_tsv,
            threshold=args.threshold,
            batch_size=args.batch_size,
            num_workers=args.nproc,
            gpu=not args.use_cpu
        )
    elif args.preprocessing == "t1-volume":
        volume_qc(
            args.caps_dir,
            args.output_dir,
            args.group_label
        )

def generate_data_func(args):
    from .tools.data.generate_data import (generate_random_dataset,
                                           generate_trivial_dataset,
                                           generate_shepplogan_dataset)

    if args.mode == "random":
        generate_random_dataset(
            caps_dir=args.caps_dir,
            tsv_path=args.subjects_sessions_tsv,
            output_dir=args.output_dir,
            n_subjects=args.n_subjects,
            mean=args.mean,
            sigma=args.sigma,
            preprocessing=args.preprocessing)
    elif args.mode == "trivial":
        generate_trivial_dataset(
            caps_dir=args.caps_dir,
            tsv_path=args.subjects_sessions_tsv,
            output_dir=args.output_dir,
            n_subjects=args.n_subjects,
            preprocessing=args.preprocessing,
            mask_path=args.mask_path,
            atrophy_percent=args.atrophy_percent,
        )
    else:
        labels_distribution = {"AD": args.AD_subtypes_distribution, "CN": args.CN_subtypes_distribution}
        generate_shepplogan_dataset(
            output_dir=args.output_dir,
            img_size=args.image_size,
            labels_distribution=labels_distribution,
            samples=args.n_subjects,
            smoothing=args.smoothing
        )

def rs_func(args):
    from .train.random_search import launch_search

    launch_search(args)

# Function to dispatch training to corresponding function
def train_func(args):
    from .train import train_autoencoder, train_multi_cnn, train_single_cnn

    if args.network_type == "autoencoder":
        args.transfer_learning_selection = "best_loss"
        train_autoencoder(args)
    elif args.network_type == "cnn":
        train_single_cnn(args)
    elif args.network_type == "multicnn":
        train_multi_cnn(args)
    else:
        raise NotImplementedError('Framework %s not implemented in clinicadl' % args.network_type)

# Function to dispatch command line options from classify to corresponding
# function
def classify_func(args):
    from .classify.inference import classify

    classify(
        args.caps_directory,
        args.tsv_path,
        args.model_path,
        args.prefix_output,
        labels=not args.no_labels,
        gpu=not args.use_cpu,
        prepare_dl=args.use_extracted_features,
        selection_metrics=args.selection_metrics,
        diagnoses=args.diagnoses,
        verbose=args.verbose
    )

# Functions to dispatch command line options from tsvtool to corresponding
# function
def tsv_restrict_func(args):
    from .tools.tsv.restriction import aibl_restriction, oasis_restriction

    if args.dataset == "AIBL":
        aibl_restriction(args.merged_tsv, args.results_path)
    elif args.dataset == "OASIS":
        oasis_restriction(args.merged_tsv, args.results_path)

def tsv_getlabels_func(args):
    from .tools.tsv.data_formatting import get_labels

    get_labels(
        args.merged_tsv,
        args.missing_mods,
        args.results_path,
        diagnoses=args.diagnoses,
        modality=args.modality,
        restriction_path=args.restriction_path,
        time_horizon=args.time_horizon,
        variables_of_interest=args.variables_of_interest,
        remove_smc=not args.keep_smc,
        verbose=args.verbose
    )

def tsv_split_func(args):
    from .tools.tsv.data_split import split_diagnoses

    split_diagnoses(
        args.formatted_data_path,
        n_test=args.n_test,
        subset_name=args.subset_name,
        MCI_sub_categories=args.MCI_sub_categories,
        t_val_threshold=args.t_val_threshold,
        p_val_threshold=args.p_val_threshold,
        ignore_demographics=args.ignore_demographics,
        verbose=args.verbose
    )

def tsv_kfold_func(args):
    from .tools.tsv.kfold_split import split_diagnoses

    split_diagnoses(
        args.formatted_data_path,
        n_splits=args.n_splits,
        subset_name=args.subset_name,
        MCI_sub_categories=args.MCI_sub_categories,
        stratification=args.stratification,
        verbose=args.verbose
    )

def tsv_analysis_func(args):
    from .tools.tsv.demographics_analysis import demographics_analysis

    demographics_analysis(
        args.merged_tsv,
        args.formatted_data_path,
        args.results_path,
        diagnoses=args.diagnoses
    )

def interpret_func(args):
    from .interpret.group_backprop import group_backprop
    from .interpret.individual_backprop import individual_backprop

    if args.task == "group":
        group_backprop(args)
    elif args.task == "individual":
        individual_backprop(args)
    else:
        raise ValueError("Unknown task %s for interpretation" % args.task)

def parse_command_line():
    parser = argparse.ArgumentParser(
        prog='clinicadl',
        description='Deep learning software for neuroimaging datasets')

    parser.add_argument('-l', '--logname',
                        dest='logname',
                        default="clinicaDL.log",
                        metavar=('file.log'),
                        help='Define the log file name (default: clinicaDL.log)')
    parser.add_argument("-V", "--version",
                        dest='version',
                        action='store_true', default=False,
                        help="ClinicaDL's installed version")

    parent_parser = argparse.ArgumentParser(add_help=False)
    parent_parser.add_argument('--verbose', '-v', action='count', default=0)

    subparser = parser.add_subparsers(
        title='''Task to execute with clinicadl:''',
        description='''What kind of task do you want to use with clinicadl?
            (tsvtool, preprocessing, generate, train, classify).''',
        dest='task',
        help='''****** Tasks proposed by clinicadl ******''')

    # subparser.required = True

    # Generate synthetic data
    generate_parser = subparser.add_parser(
        'generate',
        help='Generate synthetic data for functional tests.'
    )

    generate_subparser = generate_parser.add_subparsers(
        title='''Type of synthetic data generated''',
        description='''What type of synthetic data do you want to generate?
                (random, trivial).''',
        dest='mode',
        help='''****** Synthetic datasets proposed by clinicadl ******''')

    # generate_subparser.required = True

    # Positional arguments
    generate_rs_parent_parser = argparse.ArgumentParser(add_help=False)
    generate_rs_parent_parser.add_argument(
        'caps_dir',
        help='Data using CAPS structure.',
        default=None
    )
    generate_rs_parent_parser.add_argument(
        'preprocessing',
        type=str,
        choices=['t1-linear', 't1-extensive'],
        help="Preprocessing used to generate synthetic data."
    )
    generate_rs_parent_parser.add_argument(
        'output_dir',
        help='Folder containing the synthetic dataset.',
    )
    generate_rs_parent_parser.add_argument(
        "--subjects_sessions_tsv", "-tsv",
        help='TSV file containing a list of subjects with their sessions.',
        type=str, default=None
    )
    generate_rs_parent_parser.add_argument(
        '--n_subjects',
        type=int,
        default=300,
        help="Number of subjects in each class of the synthetic dataset."
    )

    generate_random_parser = generate_subparser.add_parser(
        "random",
        parents=[
            generate_rs_parent_parser],
        help="Generate a random dataset in which gaussian noise is added to brain images.")
    generate_random_parser.add_argument(
        '--mean',
        type=float,
        default=0,
        help="Mean value of the noise added for the random dataset."
    )
    generate_random_parser.add_argument(
        '--sigma',
        type=float,
        default=0.5,
        help="Standard deviation of the noise added for the random dataset."
    )
    generate_random_parser.set_defaults(func=generate_data_func)

    generate_trivial_parser = generate_subparser.add_parser(
        "trivial",
        parents=[
            generate_rs_parent_parser],
        help="Generate a trivial dataset in which gaussian half of the brain is atrophied.")
    generate_trivial_parser.add_argument(
        '--mask_path',
        type=str,
        help='path to the extracted masks to generate the two labels.',
        default=None
    )
    generate_trivial_parser.add_argument(
        '--atrophy_percent',
        type=float,
        default=60,
        help='percentage of atrophy applied'
    )
    generate_trivial_parser.set_defaults(func=generate_data_func)

    # generate_shepplogan_parser = generate_subparser.add_parser(
    #     "shepplogan",
    #     help="Generate a dataset of 2D images including 3 subtypes based on Shepp Logan phantom."
    # )
    # generate_shepplogan_parser.add_argument(
    #     'output_dir',
    #     help='Folder containing the synthetic dataset.',
    # )
    # generate_shepplogan_parser.add_argument(
    #     '--n_subjects',
    #     type=int,
    #     default=300,
    #     help="Number of subjects in each class of the synthetic dataset."
    # )
    # generate_shepplogan_parser.add_argument(
    #     '--image_size',
    #     type=int,
    #     default=128,
    #     help="Size in pixels of the squared images."
    # )
    # generate_shepplogan_parser.add_argument(
    #     '--CN_subtypes_distribution', '-Csd',
    #     type=float, nargs='+',
    #     default=[1.0, 0.0, 0.0],
    #     help="Probability of each subtype to be drawn in CN label."
    # )
    # generate_shepplogan_parser.add_argument(
    #     '--AD_subtypes_distribution', '-Asd',
    #     type=float, nargs='+',
    #     default=[0.05, 0.85, 0.10],
    #     help="Probability of each subtype to be drawn in AD label."
    # )
    # generate_shepplogan_parser.add_argument(
    #     '--smoothing',
    #     action='store_true',
    #     default=False,
    #     help='Adds random smoothing to generated data.'
    # )
    # generate_shepplogan_parser.set_defaults(func=generate_data_func)

    # Preprocessing
    from clinica.pipelines.t1_linear.t1_linear_cli import T1LinearCLI
    from clinica.engine.cmdparser import init_cmdparser_objects
    from .preprocessing.t1_extensive.t1_extensive_cli import T1ExtensiveCli
    preprocessing_parser = subparser.add_parser(
        'preprocessing',
        help='Preprocess T1w-weighted images with t1-linear or t1-extensive pipelines.'
    )

    preprocessing_subparser = preprocessing_parser.add_subparsers(
        title='''Preprocessing task to execute with clinicadl:''',
        description='''What kind of task do you want to perform with clinicadl?
                (run, quality-check, extract-tensor).''',
        dest='preprocessing_task',
        help='''****** Tasks proposed by clinicadl ******''')
    preprocessing_subparser.required = True

    run_parser = preprocessing_subparser.add_parser(
        'run',
        help='Preprocess T1w-weighted images with t1-linear or t1-extensive pipelines.'
    )
    run_parser._positionals.title = ('%sclinicadl preprocessing expects one of the following pipelines%s'
                                     % (Fore.GREEN, Fore.RESET))

    def preprocessing_help(args):
        print('%sNo pipeline was specified. Type clinica preprocessing -h for details%s' %
              (Fore.RED, Fore.RESET))

    run_parser.set_defaults(func=preprocessing_help)

    init_cmdparser_objects(
        parser,
        run_parser.add_subparsers(dest='preprocessing'),
        [
            T1LinearCLI(),
            T1ExtensiveCli(),
        ]
    )

    extract_parser = preprocessing_subparser.add_parser(
        'extract-tensor',
        help='Prepare data generated Clinica for PyTorch with Tensor extraction (image, patches or slices).'
    )
    clinica_comp = extract_parser.add_argument_group('%sClinica mandatory arguments%s' % (Fore.BLUE, Fore.RESET))
    clinica_comp.add_argument(
        "caps_directory",
        help='Path to the CAPS directory.'
    )
    clinica_comp.add_argument("modality",
                              help='''For which modality the tensor will be extracted.
            't1-linear': images prepocessed with t1-linear pipeline.
            't1-extensive': images preprocessed with t1-extensive pipeline.
            'custom': find images with a custom suffix in their filename and
            transform them to tensor format.''',
                              choices=['t1-linear', 't1-extensive', 'custom'], default='t1-linear'
                              )

    clinica_comp.add_argument(
        "extract_method",
        help='''Format of the extracted features. Three options:
        'image' to convert to PyTorch tensor the complete 3D image,
        'patch' to extract 3D volumetric patches and
        'slice' to extract 2D slices from the image.
        By default the features are extracted from the cropped image.''',
        choices=['image', 'slice', 'patch'],
        default='image'
    )

    optional = extract_parser.add_argument_group('%sPipeline options%s' % (Fore.BLUE, Fore.RESET))
    optional.add_argument(
        '-uui', '--use_uncropped_image',
        help='''Use the uncropped image instead of the
        cropped image generated by t1-linear.''',
        default=False, action="store_true"
    )

    optional_patch = extract_parser.add_argument_group(
        "%sPipeline options if you chose ‘patch’ extraction%s" % (Fore.BLUE, Fore.RESET)
    )
    optional_patch.add_argument(
        '-ps', '--patch_size',
        help='''Patch size (default: --patch_size 50).''',
        type=int, default=50
    )
    optional_patch.add_argument(
        '-ss', '--stride_size',
        help='''Stride size (default: --stride_size 50).''',
        type=int, default=50
    )
    optional_slice = extract_parser.add_argument_group(
        "%sPipeline options if you chose ‘slice’ extraction%s" % (Fore.BLUE, Fore.RESET)
    )
    optional_slice.add_argument(
        '-sd', '--slice_direction',
        help='''Slice direction. Three options:
            '0' -> Sagittal plane,
            '1' -> Coronal plane or
            '2' -> Axial plane
            (default: sagittal plane i.e. --slice_direction 0)''',
        type=int, default=0
    )
    optional_slice.add_argument(
        '-sm', '--slice_mode',
        help='''Slice mode. Two options: 'rgb' to save the slice in
            three identical channels, ‘single’ to save the slice in a
            single channel (default: --slice_mode rgb).''',
        choices=['rgb', 'single'], default='rgb'
    )
    optional_custom = extract_parser.add_argument_group(
        "%sPipeline options if you chose ‘custom’ modality%s" % (Fore.BLUE, Fore.RESET)
    )
    optional_custom.add_argument(
        '-cn', '--custom_suffix',
        help='''Custom suffix filename, e.g.:
            'graymatter_space-Ixi549Space_modulated-off_probability.nii.gz', or
            'segm-whitematter_probability.nii.gz'
            ''',
        type=str, default=''
    )

    # Clinica standard arguments (e.g. --n_procs)
    clinica_standard_options = extract_parser.add_argument_group('%sClinica standard options%s' % (Fore.BLUE, Fore.RESET))
    clinica_standard_options.add_argument(
        "-tsv", "--subjects_sessions_tsv",
        help='TSV file containing a list of subjects with their sessions.'
    )
    clinica_standard_options.add_argument(
        "-wd", "--working_directory",
        help='Temporary directory to store pipelines intermediate results.'
    )
    clinica_standard_options.add_argument(
        "-np", "--n_procs",
        metavar='N', type=int,
        help='Number of cores used to run in parallel.'
    )

    extract_parser.set_defaults(func=extract_tensors)

    qc_parser = preprocessing_subparser.add_parser(
        'quality-check',
        help='Performs quality check procedure for t1-linear pipeline.'
             'Original code can be found at https://github.com/vfonov/deep-qc'
    )

    qc_subparsers = qc_parser.add_subparsers(
        title='''Preprocessing pipelines available''',
        description='''Which preprocessing pipeline do you want to check?''',
        dest='preprocessing',
        help='''****** Preprocessing pipelines ******''')

    qc_subparsers.required = True
    qc_linear_parser = qc_subparsers.add_parser(
        't1-linear',
        help='Performs quality check on t1-linear pipeline.'
    )
    qc_linear_parser.add_argument("caps_dir",
                                  help='Data using CAPS structure.',
                                  type=str)
    qc_linear_parser.add_argument("output_path",
                                  help="Path to the output tsv file (filename included).",
                                  type=str)

    qc_linear_parser.add_argument("--subjects_sessions_tsv", "-tsv",
                                  help='TSV file containing a list of subjects with their sessions.',
                                  type=str, default=None)
    qc_linear_parser.add_argument("--threshold",
                                  help='The threshold on the output probability to decide if the image '
                                       'passed or failed. (default=0.5)',
                                  type=float, default=0.5)
    qc_linear_parser.add_argument('--batch_size',
                                  help='Batch size used in DataLoader (default=1).',
                                  default=1, type=int)
    qc_linear_parser.add_argument("-np", "--nproc",
                                  help='Number of cores used the quality check. (default=2)',
                                  type=int, default=2)
    qc_linear_parser.add_argument('-cpu', '--use_cpu', action='store_true',
                                  help='If provided, will use CPU instead of GPU.',
                                  default=False)
    qc_linear_parser.set_defaults(func=qc_func)

    qc_volume_parser = qc_subparsers.add_parser(
        't1-volume',
        help='Performs quality check on t1-volume pipeline.'
    )
    qc_volume_parser.add_argument("caps_dir",
                                  help='Data using CAPS structure.',
                                  type=str)
    qc_volume_parser.add_argument("output_dir",
                                  help="Path to the output directory containing TSV files.",
                                  type=str)
    qc_volume_parser.add_argument("group_label",
                                  help="Identifier for the group of subjects used to create the DARTEL template.",
                                  type=str)
    qc_volume_parser.set_defaults(func=qc_func)

    # random search parsers
    rs_generate_parser = subparser.add_parser(
        'random-search',
        parents=[parent_parser],
        help='Generate random networks to explore hyper parameters space.',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )
    # rs_subparsers = rs_parser.add_subparsers(
    #     title='''Possibilities for random network training''',
    #     description='''You can generate and train a new random network,
    #     or relaunch a previous random job with some alterations.''',
    #     dest='random_task',
    #     help='''****** Possible tasks ******'''
    # )
    # rs_subparsers.required = True

    # rs_generate_parser = rs_subparsers.add_parser(
    #     'generate',
    #     parents=[parent_parser],
    #     help='Sample a new network and train it.',
    #     formatter_class=argparse.ArgumentDefaultsHelpFormatter
    # )
    rs_pos_group = rs_generate_parser.add_argument_group(
        TRAIN_CATEGORIES["POSITIONAL"]
    )
    rs_pos_group.add_argument("launch_dir", type=str,
                              help="Directory containing the random_search.json file.")
    rs_pos_group.add_argument("name", type=str,
                              help="Name of the job.")

    # Data management
    rs_data_group = rs_generate_parser.add_argument_group(
        TRAIN_CATEGORIES["CROSS-VALIDATION"]
    )
    rs_data_group.add_argument("--n_splits", type=int, default=None,
                               help="If a value is given will load data of a k-fold CV")
    rs_data_group.add_argument("--split", type=int, default=None, nargs="+",
                               help="Will load the specific split wanted.")

    rs_comp_group = rs_generate_parser.add_argument_group(
        TRAIN_CATEGORIES["COMPUTATIONAL"]
    )
    rs_comp_group.add_argument(
        '-cpu', '--use_cpu', action='store_true',
        help='If provided, will use CPU instead of GPU.',
        default=False)
    rs_comp_group.add_argument(
        '-np', '--nproc',
        help='Number of cores used during the training.',
        type=int, default=2)
    rs_comp_group.add_argument(
        '--batch_size',
        default=2, type=int,
        help='Batch size for training.')
    rs_comp_group.add_argument(
        '--evaluation_steps', '-esteps',
        default=0, type=int,
        help='Fix the number of iterations to perform before computing an evaluations. Default will only '
             'perform one evaluation at the end of each epoch.')

    rs_generate_parser.set_defaults(func=rs_func)

    # retrain_parent_parser = return_train_parent_parser(retrain=True)
    # rs_retrain_parser = rs_subparsers.add_parser(
    #     'retrain',
    #     parents=[parent_parser, retrain_parent_parser],
    #     help='Train a network previously created by generate.',
    #     formatter_class=argparse.ArgumentDefaultsHelpFormatter
    # )

    train_parser = subparser.add_parser(
        'train',
        help='Train with your data and create a model.')

    train_subparser = train_parser.add_subparsers(
        title='''Inputs types implemented in clinicadl''',
        description='''What type of input do you want to use?
                (image, patch, roi, slice).''',
        dest='mode',
        help='''****** Input types proposed by clinicadl ******''')

    train_subparser.required = True

    # Transfer learning
    transfer_learning_parent = argparse.ArgumentParser(add_help=False)
    transfer_learning_group = transfer_learning_parent.add_argument_group(
        TRAIN_CATEGORIES["TRANSFER LEARNING"])
    transfer_learning_group.add_argument(
        '--transfer_learning_path',
        help="If an existing path is given, a pretrained model is used.",
        type=str, default=None)

    # Autoencoder
    autoencoder_parent = argparse.ArgumentParser(add_help=False)
    autoencoder_group = autoencoder_parent.add_argument_group(
        TRAIN_CATEGORIES["AUTOENCODER"])
    autoencoder_group.add_argument(
        '--visualization',
        help='Save examples of image reconstructions.',
        action="store_true",
        default=False)

    ######################
    # IMAGE
    ######################
    train_image_parser = train_subparser.add_parser(
        "image",
        help="Train a 3D image-level network.")

    train_image_subparser = train_image_parser.add_subparsers(
        title='''Task to be performed''',
        description='''Autoencoder reconstruction or cnn classification ?''',
        dest='network_type',
        help='''****** Choose a type of network ******''')

    train_parent_parser = return_train_parent_parser(retrain=False)
    train_image_ae_parser = train_image_subparser.add_parser(
        "autoencoder",
        parents=[
            parent_parser,
            train_parent_parser,
            autoencoder_parent,
            transfer_learning_parent],
        help="Train an image-level autoencoder.")

    train_image_ae_parser.set_defaults(func=train_func)

    train_image_cnn_parser = train_image_subparser.add_parser(
        "cnn",
        parents=[
            parent_parser,
            train_parent_parser,
            transfer_learning_parent],
        help="Train an image-level CNN.")
    # /!\ If parents list is changed the arguments won't be in the right group anymore !
    train_image_cnn_parser._action_groups[-1].add_argument(
        '--transfer_learning_selection',
        help="If transfer_learning from CNN, chooses which best transfer model is selected.",
        type=str, default="best_balanced_accuracy", choices=["best_loss", "best_balanced_accuracy"])

    train_image_cnn_parser.set_defaults(func=train_func)

    #########################
    # PATCH
    #########################
    train_patch_parser = train_subparser.add_parser(
        "patch",
        help="Train a 3D patch-level network.")

    train_patch_parent = argparse.ArgumentParser(add_help=False)
    train_patch_group = train_patch_parent.add_argument_group(
        TRAIN_CATEGORIES["PATCH"])
    train_patch_group.add_argument(
        '-ps', '--patch_size',
        help='Patch size',
        type=int, default=50)
    train_patch_group.add_argument(
        '-ss', '--stride_size',
        help='Stride size',
        type=int, default=50)
    train_patch_group.add_argument(
        '--use_extracted_patches',
        help='''If provided the outputs of extract preprocessing are used, else the whole
             MRI is loaded.''',
        default=False, action="store_true")

    train_patch_subparser = train_patch_parser.add_subparsers(
        title='''Task to be performed''',
        description='''Autoencoder reconstruction or (multi)cnn classification ?''',
        dest='network_type',
        help='''****** Choose a type of network ******''')
    train_patch_subparser.required = True

    train_patch_ae_parser = train_patch_subparser.add_parser(
        "autoencoder",
        parents=[parent_parser, train_parent_parser, train_patch_parent, autoencoder_parent, transfer_learning_parent],
        help="Train a 3D patch-level autoencoder.")

    train_patch_ae_parser.set_defaults(func=train_func)

    train_patch_cnn_parser = train_patch_subparser.add_parser(
        "cnn",
        parents=[
            parent_parser,
            train_parent_parser,
            train_patch_parent,
            transfer_learning_parent],
        help="Train a 3D patch-level CNN.")
    # /!\ If parents list is changed the arguments won't be in the right group anymore !
    train_patch_cnn_parser._action_groups[-1].add_argument(
        '--transfer_learning_selection',
        help="If transfer_learning from CNN, chooses which best transfer model is selected.",
        type=str, default="best_balanced_accuracy", choices=["best_loss", "best_balanced_accuracy"])

    train_patch_cnn_group = train_patch_cnn_parser.add_argument_group(
        TRAIN_CATEGORIES["PATCH CNN"])
    train_patch_cnn_group.add_argument(
        '--selection_threshold',
        help='''Threshold on the balanced accuracies to compute the
             subject-level performance. Patches are selected if their balanced
             accuracy > threshold. Default corresponds to no selection.''',
        type=float, default=0.0)

    train_patch_cnn_parser.set_defaults(func=train_func)

    train_patch_multicnn_parser = train_patch_subparser.add_parser(
        "multicnn",
        parents=[
            parent_parser,
            train_parent_parser,
            train_patch_parent,
            transfer_learning_parent],
        help="Train a 3D patch-level multi-CNN (one CNN is trained per patch location).")
    # /!\ If parents list is changed the arguments won't be in the right group anymore !
    train_patch_multicnn_parser._action_groups[-1].add_argument(
        '--transfer_learning_selection',
        help="If transfer_learning from CNN, chooses which best transfer model is selected.",
        type=str, default="best_balanced_accuracy", choices=["best_loss", "best_balanced_accuracy"])

    train_patch_multicnn_group = train_patch_multicnn_parser.add_argument_group(
        TRAIN_CATEGORIES["PATCH CNN"])
    train_patch_multicnn_group.add_argument(
        '--selection_threshold',
        help='''Threshold on the balanced accuracies to compute the
                 subject-level performance. Patches are selected if their balanced
                 accuracy > threshold. Default corresponds to no selection.''',
        type=float, default=0.0)

    train_patch_multicnn_parser.set_defaults(func=train_func)

    #########################
    # ROI
    #########################
    train_roi_parser = train_subparser.add_parser(
        "roi",
        help="Train a ROI-based level network.")

    train_roi_subparser = train_roi_parser.add_subparsers(
        title='''Task to be performed''',
        description='''Autoencoder reconstruction or cnn classification ?''',
        dest='network_type',
        help='''****** Choose a type of network ******''')
    train_roi_subparser.required = True

    train_roi_ae_parser = train_roi_subparser.add_parser(
        "autoencoder",
        parents=[
            parent_parser,
            train_parent_parser,
            autoencoder_parent,
            transfer_learning_parent
        ],
        help="Train a ROI-based autoencoder.")

    train_roi_ae_parser.set_defaults(func=train_func)

    train_roi_cnn_parser = train_roi_subparser.add_parser(
        "cnn",
        parents=[
            parent_parser,
            train_parent_parser,
            transfer_learning_parent],
        help="Train a ROI-based CNN.")
    # /!\ If parents list is changed the arguments won't be in the right group anymore !
    train_roi_cnn_parser._action_groups[-1].add_argument(
        '--transfer_learning_selection',
        help="If transfer_learning from CNN, chooses which best transfer model is selected.",
        type=str, default="best_balanced_accuracy", choices=["best_loss", "best_balanced_accuracy"])

    train_roi_cnn_group = train_roi_cnn_parser.add_argument_group(
        TRAIN_CATEGORIES["ROI CNN"])
    train_roi_cnn_group.add_argument(
        '--selection_threshold',
        help='''Threshold on the balanced accuracies to compute the
             subject-level performance. ROIs are selected if their balanced
             accuracy > threshold. Default corresponds to no selection.''',
        type=float, default=0.0)

    train_roi_cnn_parser.set_defaults(func=train_func)

    train_roi_multicnn_parser = train_roi_subparser.add_parser(
        "multicnn",
        parents=[
            parent_parser,
            train_parent_parser,
            transfer_learning_parent],
        help="Train a ROI-based multi-CNN (one CNN is trained per patch location).")
    # /!\ If parents list is changed the arguments won't be in the right group anymore !
    train_roi_multicnn_parser._action_groups[-1].add_argument(
        '--transfer_learning_selection',
        help="If transfer_learning from CNN, chooses which best transfer model is selected.",
        type=str, default="best_balanced_accuracy", choices=["best_loss", "best_balanced_accuracy"])

    train_roi_multicnn_group = train_roi_multicnn_parser.add_argument_group(
        TRAIN_CATEGORIES["ROI CNN"])
    train_roi_multicnn_group.add_argument(
        '--selection_threshold',
        help='''Threshold on the balanced accuracies to compute the
                         subject-level performance. Patches are selected if their balanced
                         accuracy > threshold. Default corresponds to no selection.''',
        type=float, default=0.0)

    train_roi_multicnn_parser.set_defaults(func=train_func)

    #########################
    # SLICE
    #########################
    train_slice_parser = train_subparser.add_parser(
        "slice",
        help="Train a 2D slice-level CNN.")

    train_slice_subparser = train_slice_parser.add_subparsers(
        title='''Task to be performed''',
        description='''Autoencoder reconstruction or cnn classification ?''',
        dest='network_type',
        help='''****** Choose a type of network ******''')
    train_slice_subparser.required = True

    train_slice_parent = argparse.ArgumentParser(add_help=False)
    train_slice_group = train_slice_parent.add_argument_group(
        TRAIN_CATEGORIES["SLICE"])
    train_slice_group.add_argument(
        '--slice_direction', '-sd',
        help='''Which coordinate axis to take for slicing the MRI.
                 0 for sagittal
                 1 for coronal
                 2 for axial direction.''',
        default=0, type=int)
    train_slice_group.add_argument(
        '--discarded_slices',
        help='''Number of slices discarded from respectively the beginning and
        the end of the MRI volume.  If only one argument is given, it will be
        used for both sides.''',
        default=20, type=int, nargs='+'
    )
    train_slice_group.add_argument(
        '--use_extracted_slices',
        help='''If provided the outputs of extract preprocessing are used, else the whole
                 MRI is loaded.''',
        default=False, action="store_true")

    train_slice_ae_parser = train_slice_subparser.add_parser(
        "autoencoder",
        parents=[parent_parser, train_parent_parser, train_slice_parent, transfer_learning_parent],
        help="Train a 2D slice-level autoencoder.")

    train_slice_ae_parser.set_defaults(func=train_func)

    train_slice_cnn_parser = train_slice_subparser.add_parser(
        "cnn",
        parents=[parent_parser, train_parent_parser, train_slice_parent, transfer_learning_parent],
        help="Train a 2D slice-level CNN.")
    # /!\ If parents list is changed the arguments won't be in the right group anymore !
    train_slice_cnn_parser._action_groups[-1].add_argument(
        '--transfer_learning_selection',
        help="If transfer_learning from CNN, chooses which best transfer model is selected.",
        type=str, default="best_balanced_accuracy", choices=["best_loss", "best_balanced_accuracy"])

    train_slice_cnn_group = train_slice_cnn_parser.add_argument_group(
        TRAIN_CATEGORIES["SLICE CNN"])
    train_slice_cnn_group.add_argument(
        '--selection_threshold',
        help='''Threshold on the balanced accuracies to compute the
                 subject-level performance. Slices are selected if their balanced
                 accuracy > threshold. Default corresponds to no selection.''',
        type=float, default=0.0)

    train_slice_cnn_parser.set_defaults(func=train_func)

    train_slice_multicnn_parser = train_slice_subparser.add_parser(
        "multicnn",
        parents=[parent_parser, train_parent_parser, train_slice_parent, transfer_learning_parent],
        help="Train a 2D slice-level multi-CNN.")
    # /!\ If parents list is changed the arguments won't be in the right group anymore !
    train_slice_multicnn_parser._action_groups[-1].add_argument(
        '--transfer_learning_selection',
        help="If transfer_learning from CNN, chooses which best transfer model is selected.",
        type=str, default="best_balanced_accuracy", choices=["best_loss", "best_balanced_accuracy"])

    train_slice_multicnn_group = train_slice_multicnn_parser.add_argument_group(
        TRAIN_CATEGORIES["SLICE CNN"])
    train_slice_multicnn_group.add_argument(
        '--selection_threshold',
        help='''Threshold on the balanced accuracies to compute the
                 subject-level performance. Slices are selected if their balanced
                 accuracy > threshold. Default corresponds to no selection.''',
        type=float, default=0.0)

    train_slice_multicnn_parser.set_defaults(func=train_func)

    # Classify - Classify a subject or a list of tsv files with the CNN
    # provided as argument.
    # classify_parser: get command line arguments and options

    classify_parser = subparser.add_parser(
        'classify',
        parents=[parent_parser],
        help='''Classify one image or a list of images with your previously
                 trained model.''')
    classify_pos_group = classify_parser.add_argument_group(
        TRAIN_CATEGORIES["POSITIONAL"])
    classify_pos_group.add_argument(
        'caps_directory',
        help='Data using CAPS structure.',
        default=None)
    classify_pos_group.add_argument(
        'tsv_path',
        help='''Path to the file with subjects/sessions to process.
        If it includes the filename will load the tsv file directly.
        Else will load the baseline tsv files of wanted diagnoses produced by tsvtool.''',
        default=None)
    classify_pos_group.add_argument(
        'model_path',
        help='''Path to the folder where the model is stored. Folder structure
                should be the same obtained during the training.''',
        default=None)
    classify_pos_group.add_argument(
        'prefix_output',
        help='Prefix to name the files resulting from the classify task.',
        type=str)

    # Computational resources
    classify_comput_group = classify_parser.add_argument_group(
        TRAIN_CATEGORIES["COMPUTATIONAL"])
    classify_comput_group.add_argument(
        '-cpu', '--use_cpu', action='store_true',
        help='Uses CPU instead of GPU.',
        default=False)
    classify_comput_group.add_argument(
        '-np', '--nproc',
        help='Number of cores used during the task.',
        type=int, default=2)
    classify_comput_group.add_argument(
        '--batch_size',
        default=2, type=int,
        help='Batch size for data loading. (default=2)')

    # Specific classification arguments
    classify_specific_group = classify_parser.add_argument_group(
        TRAIN_CATEGORIES["OPTIONAL"]
    )
    classify_specific_group.add_argument(
        '-nl', '--no_labels', action='store_true',
        help='Add this flag if your dataset does not contain a ground truth.',
        default=False)
    classify_specific_group.add_argument(
        '--use_extracted_features',
        help='''If True the extract slices or patche are used, otherwise the they
                will be extracted on the fly (if necessary).''',
        default=False, action="store_true")
    classify_specific_group.add_argument(
        '--selection_metrics',
        help='''List of metrics to find the best models to evaluate. Default will
        classify best model based on balanced accuracy.''',
        choices=['loss', 'balanced_accuracy'],
        default=['balanced_accuracy'],
        nargs='+'
    )
    classify_specific_group.add_argument(
        "--diagnoses",
        help="List of participants that will be classified.",
        nargs="+", type=str, choices=['AD', 'CN', 'MCI', 'sMCI', 'pMCI'], default=None)

    classify_parser.set_defaults(func=classify_func)

    tsv_parser = subparser.add_parser(
        'tsvtool',
        help='''Handle tsv files for metadata processing and data splits.''')

    tsv_subparser = tsv_parser.add_subparsers(
        title='''Task to execute with tsv tool:''',
        description='''What kind of task do you want to use with tsv tool?
                (restrict, getlabels, split, kfold, analysis).''',
        dest='tsv_task',
        help='''****** Tasks proposed by clinicadl tsv tool ******''')

    tsv_subparser.required = True

    tsv_restrict_subparser = tsv_subparser.add_parser(
        'restrict',
        help='Reproduce restrictions applied to AIBL and OASIS datasets')

    tsv_restrict_subparser.add_argument(
        "dataset",
        help="dataset on which the restriction is performed.",
        choices=["AIBL", "OASIS"],
        type=str)

    tsv_restrict_subparser.add_argument(
        "merged_tsv",
        help="Path to the file obtained by the command clinica iotools merge-tsv.",
        type=str)
    tsv_restrict_subparser.add_argument(
        "results_path",
        help="Path to the output tsv file (filename included).",
        type=str)

    tsv_restrict_subparser.set_defaults(func=tsv_restrict_func)

    tsv_getlabels_subparser = tsv_subparser.add_parser(
        'getlabels',
        parents=[parent_parser],
        help='Get labels in separate tsv files.')

    tsv_getlabels_subparser.add_argument(
        "merged_tsv",
        help="Path to the file obtained by the command clinica iotools merge-tsv.",
        type=str)
    tsv_getlabels_subparser.add_argument(
        "missing_mods",
        help="Path to the folder where the outputs of clinica iotools missing-mods are.",
        type=str)
    tsv_getlabels_subparser.add_argument(
        "results_path",
        type=str,
        help="Path to the folder where tsv files are extracted.")

    # Optional arguments
    tsv_getlabels_subparser.add_argument(
        "--modality", "-mod",
        help="Modality to select sessions. Sessions which do not include the modality will be excluded.",
        default="t1w", type=str)
    tsv_getlabels_subparser.add_argument(
        "--diagnoses",
        help="Labels that must be extracted from merged_tsv.",
        nargs="+", type=str, choices=['AD', 'CN', 'MCI', 'sMCI', 'pMCI'], default=['AD', 'CN'])
    tsv_getlabels_subparser.add_argument(
        "--time_horizon",
        help="Time horizon to analyse stability of MCI subjects.",
        default=36, type=int)
    tsv_getlabels_subparser.add_argument(
        "--restriction_path",
        help="Path to a tsv containing the sessions that can be included.",
        type=str, default=None)
    tsv_getlabels_subparser.add_argument(
        "--variables_of_interest",
        help="Variables of interest that will be kept in the final lists."
             "Default will keep the diagnosis, age and the sex needed for the split procedure.",
        type=str, nargs="+", default=None)
    tsv_getlabels_subparser.add_argument(
        "--keep_smc",
        help="This flag allows to keep SMC participants, else they are removed.",
        default=False, action="store_true"
    )

    tsv_getlabels_subparser.set_defaults(func=tsv_getlabels_func)

    tsv_split_subparser = tsv_subparser.add_parser(
        'split',
        parents=[parent_parser],
        help='Performs one stratified shuffle split on participant level.')
    tsv_split_subparser.add_argument(
        "formatted_data_path",
        help="Path to the folder containing data extracted by clinicadl tsvtool getlabels.",
        type=str)

    # Optional arguments
    tsv_split_subparser.add_argument(
        "--n_test",
        help="If >= 1, number of subjects to put in set with name 'subset_name'. "
             "If < 1, proportion of subjects to put set with name 'subset_name'. "
             "If 0, no training set is created and the whole dataset is considered as one set with name 'subset_name.",
        type=float, default=100.)
    tsv_split_subparser.add_argument(
        "--MCI_sub_categories",
        help="Deactivate default managing of MCI sub-categories to avoid data leakage.",
        action="store_false", default=True)
    tsv_split_subparser.add_argument(
        "--t_val_threshold", "-t",
        help="The threshold used for the chi2 test on sex distributions.",
        default=0.0642, type=float)
    tsv_split_subparser.add_argument(
        "--p_val_threshold", "-p",
        help="The threshold used for the T-test on age distributions.",
        default=0.80, type=float)
    tsv_split_subparser.add_argument(
        "--subset_name",
        help="Name of the subset that is complementary to train.",
        type=str, default="test")
    tsv_split_subparser.add_argument(
        "--ignore_demographics",
        help="If True do not use age and sex to create the splits.",
        default=False, action="store_true"
    )

    tsv_split_subparser.set_defaults(func=tsv_split_func)

    tsv_kfold_subparser = tsv_subparser.add_parser(
        'kfold',
        parents=[parent_parser],
        help='Performs a k-fold split on participant level.')

    tsv_kfold_subparser.add_argument(
        "formatted_data_path",
        help="Path to the folder containing data extracted by clinicadl tsvtool getlabels.",
        type=str)

    # Optional arguments
    tsv_kfold_subparser.add_argument(
        "--n_splits",
        help="Number of folds in the k-fold split."
             "If 0, there is no training set and the whole dataset is considered as a test set.",
        type=int, default=5)
    tsv_kfold_subparser.add_argument(
        "--MCI_sub_categories",
        help="Deactivate default managing of MCI sub-categories to avoid data leakage.",
        action="store_false", default=True)
    tsv_kfold_subparser.add_argument(
        "--subset_name",
        help="Name of the subset that is complementary to train.",
        type=str, default="validation")
    tsv_kfold_subparser.add_argument(
        "--stratification",
        help="Name of a variable used to stratify the k-fold split.",
        type=str, default=None)

    tsv_kfold_subparser.set_defaults(func=tsv_kfold_func)

    tsv_analysis_subparser = tsv_subparser.add_parser(
        'analysis',
        help='Produces a demographic analysis of the extracted labels.')

    tsv_analysis_subparser.add_argument(
        "merged_tsv",
        help="Path to the file obtained by the command clinica iotools merge-tsv.",
        type=str)
    tsv_analysis_subparser.add_argument(
        "formatted_data_path",
        help="Path to the folder containing data extracted by clinicadl tsvtool getlabels.",
        type=str)
    tsv_analysis_subparser.add_argument(
        "results_path",
        help="Path to the output tsv file (filename included).",
        type=str)

    # Modality selection
    tsv_analysis_subparser.add_argument(
        "--diagnoses",
        help="Labels selected for the demographic analysis.",
        default=['AD', 'CN'], nargs="+", type=str, choices=['AD', 'CN', 'MCI', 'sMCI', 'pMCI'])

    tsv_analysis_subparser.set_defaults(func=tsv_analysis_func)

    interpret_parser = subparser.add_parser(
        'interpret',
        help='''Interpret classification performed by a CNN with saliency maps.''')

    interpret_subparser = interpret_parser.add_subparsers(
        title='''Type of saliency map to perform:''',
        description='''Do you want to perform a group saliency map or individual ones?''',
        dest='task',
        help='''****** Saliency maps proposed by clinicadl ******'''
    )
    interpret_subparser.required = True

    interpret_parent_parser = argparse.ArgumentParser(add_help=False)

    interpret_pos_group = interpret_parent_parser.add_argument_group(TRAIN_CATEGORIES["POSITIONAL"])
    interpret_pos_group.add_argument(
        "model_path", type=str,
        help="Path to the model output directory.")
    interpret_pos_group.add_argument(
        "name", type=str,
        help="Name of the interpretation map.")

    interpret_comput_group = interpret_parent_parser.add_argument_group(TRAIN_CATEGORIES["COMPUTATIONAL"])
    interpret_comput_group.add_argument(
        "--batch_size", default=1, type=int,
        help="Batch size for selection of images (keep_true).")
    interpret_comput_group.add_argument(
        '-cpu', '--use_cpu',
        action='store_true', default=False,
        help='Uses gpu instead of cpu if cuda is available.')
    interpret_comput_group.add_argument(
        '-np', '--nproc',
        default=2, type=int,
        help='the number of batches being loaded in parallel.')

    interpret_model_group = interpret_parent_parser.add_argument_group(TRAIN_CATEGORIES["MODEL"])
    interpret_model_group.add_argument(
        "--selection", default=['best_loss'], type=str, nargs="+",
        choices=['best_loss', 'best_balanced_accuracy'],
        help="Loads the model selected on minimal loss or maximum accuracy on validation.")

    interpret_data_group = interpret_parent_parser.add_argument_group(TRAIN_CATEGORIES["DATA"])
    interpret_data_group.add_argument(
        "--tsv_path", type=str, default=None,
        help="TSV path with subjects/sessions to process, if different from classification task.")
    interpret_data_group.add_argument(
        "--caps_dir", type=str, default=None,
        help="Path to input dir of the MRI (preprocessed CAPS_dir), if different from classification task")
    interpret_data_group.add_argument(
        "--diagnosis", "-d", default='AD', type=str,
        help="The images corresponding to this diagnosis only will be loaded.")
    interpret_data_group.add_argument(
        "--target_diagnosis", default=None, type=str,
        help="Which class the gradients explain. If None is given will be equal to diagnosis.")
    interpret_data_group.add_argument(
        "--baseline", action="store_true", default=False,
        help="If provided, only the baseline sessions are used for training.")
    interpret_data_group.add_argument(
        "--keep_true", type=lambda x: bool(strtobool(x)), default=None,
        help="Chooses false or true positive values of the classification. No selection by default")
    interpret_data_group.add_argument(
        "--nifti_template_path", type=str, default=None,
        help="Path to a nifti template to retrieve affine values.")

    interpret_display_group = interpret_parent_parser.add_argument_group(TRAIN_CATEGORIES["DISPLAY"])
    interpret_display_group.add_argument(
        "--vmax", type=float, default=0.5,
        help="Maximum value used in 2D image display.")

    interpret_group_parser = interpret_subparser.add_parser(
        "group",
        parents=[parent_parser, interpret_parent_parser],
        help="Mean saliency map over a list of sessions"
    )

    interpret_group_parser.set_defaults(func=interpret_func)

    interpret_individual_parser = interpret_subparser.add_parser(
        "individual",
        parents=[parent_parser, interpret_parent_parser],
        help="Individual saliency maps for each session in the input TSV file."
    )

    interpret_individual_parser.set_defaults(func=interpret_func)

    return parser

def return_train_parent_parser(retrain=False):
    # Main train parent parser common to train and random search
    train_parent_parser = argparse.ArgumentParser(add_help=False)
    train_pos_group = train_parent_parser.add_argument_group(
        TRAIN_CATEGORIES["POSITIONAL"])
    if retrain:
        train_pos_group.add_argument(
            "model_path", type=str,
            help="Path to the trained model folder.")
        train_pos_group.add_argument(
            "output_dir", type=str,
            help="Directory in which the new job is stored.")
    else:
        train_pos_group.add_argument(
            'caps_dir',
            help='Data using CAPS structure.',
            default=None)
        train_pos_group.add_argument(
            'preprocessing',
            help='Defines the type of preprocessing of CAPS data.',
            choices=['t1-linear', 't1-extensive'], type=str)
        train_pos_group.add_argument(
            'tsv_path',
            help='TSV path with subjects/sessions to process.',
            default=None)
        train_pos_group.add_argument(
            'output_dir',
            help='Folder containing results of the training.',
            default=None)
        train_pos_group.add_argument(
            'model',
            help='CNN Model to be used during the training.',
            default='Conv5_FC3')

    train_comput_group = train_parent_parser.add_argument_group(
        TRAIN_CATEGORIES["COMPUTATIONAL"])
    train_comput_group.add_argument(
        '-cpu', '--use_cpu', action='store_true',
        help='If provided, will use CPU instead of GPU.',
        default=False)
    train_comput_group.add_argument(
        '-np', '--nproc',
        help='Number of cores used during the training. (default=2)',
        type=int, default=2)
    train_comput_group.add_argument(
        '--batch_size',
        default=2, type=int,
        help='Batch size for training. (default=2)')
    train_comput_group.add_argument(
        '--evaluation_steps', '-esteps',
        default=0, type=int,
        help='Fix the number of iterations to perform before computing an evaluations. Default will only '
             'perform one evaluation at the end of each epoch.')

    train_data_group = train_parent_parser.add_argument_group(
        TRAIN_CATEGORIES["DATA"])

    if retrain:
        train_data_group.add_argument(
            "--caps_dir", type=str, default=None,
            help="Data using CAPS structure.")
        train_data_group.add_argument(
            "--tsv_path", type=str, default=None,
            help="TSV path with subjects/sessions to process.")

    train_data_group.add_argument(
        '--diagnoses', '-d',
        help='List of diagnoses that will be selected for training.',
        default=None if retrain else ['AD', 'CN'], nargs='+', type=str, choices=['AD', 'CN', 'MCI', 'sMCI', 'pMCI'])
    train_data_group.add_argument(
        '--baseline',
        help='If provided, only the baseline sessions are used for training.',
        action="store_true",
        default=None if retrain else False)
    train_data_group.add_argument(
        '--unnormalize', '-un',
        help='Disable default MinMaxNormalization.',
        action="store_true",
        default=None if retrain else False)
    train_data_group.add_argument(
        "--data_augmentation", nargs="+", default=None if retrain else False,
        choices=["None", "Noise", "Erasing", "CropPad", "Smoothing"],
        help="Randomly applies transforms on the training set.")
    train_data_group.add_argument(
        '--sampler', '-s',
        help="Sampler choice (random, or weighted for imbalanced datasets)",
        default="random", type=str, choices=["random", "weighted"])

    train_cv_group = train_parent_parser.add_argument_group(
        TRAIN_CATEGORIES["CROSS-VALIDATION"])
    train_cv_group.add_argument(
        '--n_splits',
        help='If a value is given will load data of a k-fold CV. Else will load a single split.',
        type=int, default=None)
    train_cv_group.add_argument(
        '--split',
        help='Train the list of given folds. By default train all folds.',
        type=int, default=None, nargs='+')

    train_optim_group = train_parent_parser.add_argument_group(
        TRAIN_CATEGORIES["OPTIMIZATION"])
    train_optim_group.add_argument(
        '--epochs',
        help='Maximum number of epochs.',
        default=None if retrain else 20, type=int)
    train_optim_group.add_argument(
        '--learning_rate', '-lr',
        help='Learning rate of the optimization.',
        default=None if retrain else 1e-4, type=float)
    train_optim_group.add_argument(
        '--weight_decay', '-wd',
        help='Weight decay value used in optimization.',
        default=None if retrain else 1e-4, type=float)
    train_optim_group.add_argument(
        '--dropout',
        help='rate of dropout that will be applied to dropout layers in CNN.',
        default=None if retrain else 0, type=float)
    train_optim_group.add_argument(
        '--patience',
        help='Number of epochs for early stopping patience.',
        type=int, default=None if retrain else 0)
    train_optim_group.add_argument(
        '--tolerance',
        help='Value for the early stopping tolerance.',
        type=float, default=None if retrain else 0.0)
    train_optim_group.add_argument(
        '--accumulation_steps', '-asteps',
        help='Accumulates gradients during the given number of iterations before performing the weight update '
             'in order to virtually increase the size of the batch.',
        default=None if retrain else 1, type=int)
    # train_optim_group.add_argument(
    #     "--loss",
    #     help="Replaces default losses: cross-entropy for CNN and MSE for autoencoders.",
    #     type=str, default=None if retrain else "default",
    #     choices=["default", "L1", "L1Norm", "SmoothL1", "SmoothL1Norm"])

    return train_parent_parser


a = 6
b = 100

# 解法1：使用其他变量
# c = a
# a = b
# b = c

# 解法2：不适用其他变量
# a = a + b
# b = a - b
# a = a - b
# 解法3：Python特有
a, b = (b, a)

print(a)
print(b)


#idea = 치킨 집 나타낼 수 있는 모든 경우의 수를 표현 -> 모든 경우에 대해 치킨 거리를 구해본다.
from itertools import combinations
def chicken_street( x2 , y2 , x1 , y1 ) :
    return abs(x2-x1) + abs(y2-y1)

N , M = map ( int , input().split(' ') )

maps = [ [0] * N for _ in range ( N ) ]
homes = []
chicken = []
chicken_cnt = 0
answer = []

#preprocessing
for i in range( N ) :
    datas = list( map( int , input().split(' ') ) )
    for j in range( N ) :
        maps[i][j] = datas[j]
        if datas[j] == 1 :
            homes.append( [i,j] )
        if datas[j] == 2 :
            chicken.append( [i,j] )

# 치킨집 경우의 수
for j in range( 1 , M + 1 ) :
    for check_datas in list ( map ( list  , combinations( chicken , j) )  )  :
        min_datas = []
        for home in homes :
            min_data = 9999
            for check_data in check_datas :
                min_data = min ( min_data , chicken_street ( home[0] , home[1] , check_data[0] , check_data[1]) )
            min_datas.append(min_data)
        answer.append( sum(min_datas) )

print ( min ( answer ) )


# 동 : 1, 서 : 2, 남 : 3, 북 : 4
import sys

N = int(sys.stdin.readline())
arr = []
w, h = 0, 0
w_index, h_index = 0, 0
for i in range(6) :
    dir, k = map(int,sys.stdin.readline().split())
    arr.append([dir,k])
for i in range(len(arr)):
    if arr[i][0] == 1 or arr[i][0] == 2 :
        if arr[i][1] > w :
            w = arr[i][1]
            w_index = i
    else :
        if arr[i][1] > h :
            h = arr[i][1]
            h_index = i
sum = 0
sum += w * h - abs(arr[(w_index-1) % 6][1] - arr[(w_index + 1) % 6][1]) * abs(arr[(h_index-1) % 6][1] - arr[(h_index + 1) % 6][1])
print(sum * N)


from tree_code_structure.core.my_tree_sitter import MyTreeSitter

class MyTokens:
    def __init__(self, java_code, tokens, tokens_process_function):
        self._tokens = [tokens_process_function(token) for token in tokens]
        self._tokens_positions = list()
        self._tokens_positions.append(0)
        current_position = 0
        for token in self._tokens:
            pos = java_code.find(token, current_position)
            if pos != -1:
                current_position = pos + len(token)
            # else:
            # raise Exception("Token not found")
            self._tokens_positions.append(current_position)
        self._tokens_positions.append(self._tokens_positions[-1])
        self._index = 0

    def get_current_token_info(self):
        return self.get_current_index(), self.get_current_token()

    def get_current_token(self):
        if self._index >= len(self._tokens_positions):
            return None
        return self._tokens_positions[self._index]

    def get_current_index(self):
        return self._index

    def increase_index(self):
        self._index += 1

class MyNode:
    def __init__(self, tree_sitter: MyTreeSitter):
        self._start_pos, self._end_pos = tree_sitter.get_current_node_start_end()
        self._children = []
        self._start_token_index = int(1e9)
        self._num_tokens = 0
        self._tokens = []

    def add_children(self, my_node):
        # print("add_children")
        if my_node.get_num_tokens() == 0:
            return
        self._start_token_index = min(
            self._start_token_index, my_node.get_start_token_index()
        )
        self._children.append(my_node)
        self._num_tokens += my_node.get_num_tokens()

    def get_start_token_index(self):
        return self._start_token_index

    def get_end_token_index(self):
        return self._start_token_index + self._num_tokens

    def get_num_tokens(self):
        return self._num_tokens

    def get_children(self):
        return self._children

    def is_leaf(self):
        return self.get_children() == 0

    def add_token(self, token_info):
        self._start_token_index = min(self._start_token_index, token_info[0])
        self._tokens.append(token_info)
        self._num_tokens += 1

    def contains_token(self, token):
        if token is None:
            return False
        return self._end_pos >= token

class MyCodeTree:
    def __init__(self):
        self._tree_sitter = MyTreeSitter()
        self._tokens = None
        self._root = None

    @staticmethod
    def _accumulate_ones(sequence_split, max_subtree_size):
        result = list()
        for split in sequence_split:
            if split == 1 and len(result) > 0 and result[-1] < max_subtree_size:
                result[-1] += 1
            else:
                result.append(split)
        return result

    @staticmethod
    def _split_big_leaves(sequence_split, max_subtree_size):
        result = list()
        for split in sequence_split:
            if split <= max_subtree_size:
                result.append(split)
            else:
                while split > max_subtree_size:
                    result.append(max_subtree_size)
                    split -= max_subtree_size
                result.append(split)
        return result

    @staticmethod
    def _post_process_sequence_split(sequence_split, max_subtree_size):
        sequence_split = MyCodeTree._accumulate_ones(sequence_split, max_subtree_size)
        sequence_split = MyCodeTree._split_big_leaves(sequence_split, max_subtree_size)
        return sequence_split

    def process_code(
        self,
        java_code,
        tokens,
        max_subtree_size=16,
        tokens_process_function=lambda x: x[1:] if len(x) > 1 and x[0] == " " else x,
    ):
        self._tree_sitter.process_code(java_code)
        self._tokens = MyTokens(java_code, tokens, tokens_process_function)
        self._root = self._init_traverse_tree_sitter()
        self._tree_sitter.reset()
        sequence_split = self.get_sequence_split(None, max_subtree_size)
        return MyCodeTree._post_process_sequence_split(
            [node.get_num_tokens() for node in sequence_split], max_subtree_size
        )

    def _init_traverse_tree_sitter(self):
        node = MyNode(self._tree_sitter)
        is_leaf = not self._tree_sitter.goto_first_child()
        if is_leaf:
            while node.contains_token(self._tokens.get_current_token()):
                node.add_token(self._tokens.get_current_token_info())
                self._tokens.increase_index()
        else:
            child_node = self._init_traverse_tree_sitter()
            node.add_children(child_node)
            while self._tree_sitter.goto_next_child():
                child_node = self._init_traverse_tree_sitter()
                node.add_children(child_node)
            self._tree_sitter.goto_parent()
        return node

    def get_sequence_split(self, start_node, max_subtree_size):
        if start_node is None:
            start_node = self._root
        # print("num tokens in subtree", start_node.get_num_tokens(), len(start_node.get_children()), start_node.is_leaf())
        subtree_split = list()
        if start_node.get_num_tokens() < max_subtree_size:
            subtree_split.append(start_node)
        else:
            for chile_node in start_node.get_children():
                subtree_split.extend(
                    self.get_sequence_split(chile_node, max_subtree_size)
                )
        return subtree_split


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

import numpy as np
from sklearn import metrics
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.datasets import make_classification as mc

class Berboulli_Naive_Bayes:

    def train (self,x_train,y_train):
        X = x_train
        y = y_train
        #get the number of classes
        classNum = np.amax(y)
        print('classNum',classNum)

        #for each class, train and find the log_odds
        theta_k = np.ones(classNum)
        theta_j_k = np.ones((classNum,X.shape[1]))
        for k in range(classNum):
            print("run for class",k)

            yk = np.array(y)
            #number of class 1 and 0
            y_sum = 0

            #categorize the classes into binary
            for i in range(len(yk)):
                if yk[i] == (k+1):
                    y_sum +=1

            theta_k[k] = y_sum/ len(yk)

            #number of examples where xj =1 and y =1
            num_j_k = 0
            for j in range(X.shape[1]):
                num_j_k = 0
                for l in range(X.shape[0]):
                    if (yk[l] == k+1) & (X[l,j] == 1):
                        num_j_k +=1

                theta_j_k[k,j] = (num_j_k + 1) / (y_sum + 2)
                print('theta, j, k',j ,k, 'is',theta_j_k[k,j])

        self.theta_k = theta_k
        self.theta_j_k = theta_j_k

    def fit (self, x):
        theta_k = self.theta_k
        theta_j_k = self.theta_j_k

        #Choose the class with highest prob
        result = np.zeros(x.shape[0])
        for i in range(len(x)):
            bestClass = 0
            bestProb = -100000

            for k in range(len(theta_k)):
                prob = np.log(theta_k[k])
                for j in range(theta_j_k.shape[1]):
                    prob += x[i][j] *np.log(theta_j_k[k][j]) +(1-x[i][j])*np.log(1-theta_j_k[k][j])
                #print(prob)
                if prob > bestProb:
                    bestClass = k+1
                    bestProb = prob
                    #print("best is ",bestProb)
            result[i] = bestClass

        return result

    def score(self, X_test, Y_test):
        Y_predict = self.fit(X_test)
        #print(Y_predict)
        #print(compareResult)
        count = 0
        print(Y_predict)
        print(Y_test)
        for i in range(len(Y_predict)):
            if Y_predict[i] == Y_test[i]:
                count +=1
        return "score for out NB is ", count/ len(X_test)

class Feature_Processer:
    def split(self,features_set,target_set, ratio,isShuffle):
        X_train, X_test, y_train, y_test = train_test_split(features_set, target_set, train_size=ratio,
                                                            test_size=1-ratio, shuffle = isShuffle)
        return X_train, X_test, y_train, y_test

    def tf_idf(self,X_train,X_test,n_grams,thresold):
        tf_idf_vectorizer = TfidfVectorizer(ngram_range=n_grams,min_df =thresold)
        vectors_train_idf = tf_idf_vectorizer.fit_transform(X_train)
        print()
        vectors_test_idf = tf_idf_vectorizer.transform(X_test)
        return vectors_train_idf,vectors_test_idf

class classifier:
    def __init__(self, x_train, x_test, y_train,y_test):
        self.x_train = x_train
        self.y_train = y_train
        self.x_test = x_test
        self.y_test = y_test

    def multNB(self, alpha):
        # n_estimators = 10
        # model = BC( MultinomialNB(alpha = 0.5), max_samples=1.0, max_features=1.0, n_estimators=n_estimators, n_jobs = -1)
        model = MultinomialNB(alpha=alpha)
        model.fit(self.x_train, self.y_train)
        pred = model.predict(self.x_test)
        print(" MultinomialNB Regression : accurancy_is", metrics.accuracy_score(self.y_test, pred))

    def SelfNaiveByes(self):
        model = Berboulli_Naive_Bayes()
        model.train(self.x_train,self.y_train)
        print(model.score(self.x_test,self.y_test))

if __name__ == '__main__':

    data, label = mc(n_samples = 1000, n_features = 5, n_classes = 2, n_redundant = 0, n_repeated = 0, shift = 0)
    data = np.where(data > 0, 1, 0)
    label = np.where(label == 0, 1,2)
    X_train, X_test, y_train, y_test = Feature_Processer().split(data,label,0.9,True)
    print(X_train)

    clf = classifier(X_train, X_test, y_train, y_test)
    clf.multNB(0.2)
    clf.SelfNaiveByes()


#from django.contrib import admin
from django.urls import path,include
from .views import CourseListView,CourseDetailView,my_course_list_view

app_name='courses'

urlpatterns = [
    #path('admin/', admin.site.urls),
    path('',CourseListView.as_view(),name='courselist'),
    path('<int:pk>',CourseDetailView.as_view(),name='courseDetail'),
    path('my_course_list',my_course_list_view,name='purchased_course_list'),
]


# -*- coding: utf-8 -*-
"""
Created on Wed Apr 14 19:09:39 2021

@author: Ha V. Pham
"""
import os
import shutil
import pandas as pd
from sklearn.model_selection import train_test_split

li = list()
for filename in os.listdir():
    if filename.endswith(".png"):
        if int(float(filename[6:11]))%2 == 0:
           li.append(filename)

df = pd.DataFrame(li, columns = ['name'])
train, test = train_test_split(df, test_size=0.1)

trainpath = "train"
if not os.path.exists(trainpath): #create a new folder for new images if not exists
    os.makedirs(trainpath)
for index, row in train.iterrows():
    filename = row["name"]
    newpath = trainpath + "/"+ filename.replace(".png", ".jpg")
    shutil.copy(filename, newpath)
    with open("train/" + filename.replace(".png", ".txt"), "w+") as img_txt:
        img_txt.write("")
    with open("train.txt", "a") as train_txt:
        train_txt.write("data/obj/train/" + filename + "\n")

testpath = "test"
if not os.path.exists(testpath): #create a new folder for new images if not exists
    os.makedirs(testpath)
for index, row in test.iterrows():
    filename = row["name"]
    newpath = testpath + "/"+ filename.replace(".png", ".jpg")
    shutil.copy(filename, newpath)
    with open("test/" + filename.replace(".png", ".txt"), "w+") as img_txt:
        img_txt.write("")
    with open("test.txt", "a") as test_txt:
        test_txt.write("data/obj/test/" + filename + "\n")


"""
Baidu TTS　Developer by Charley
"""
import voluptuous as vol
from homeassistant.components.tts import Provider, PLATFORM_SCHEMA, CONF_LANG
import homeassistant.helpers.config_validation as cv

import requests
import logging
import json

_Log=logging.getLogger(__name__)

# 默认语言
DEFAULT_LANG = 'zh'

# 支持的语言
SUPPORT_LANGUAGES = [
    'zh',
]

CONF_APIKEY = 'api_key'
CONF_SECRETKEY = 'secret_key'
CONF_SPEED =  'speed'
CONF_PITCH = 'pitch'
CONF_VOLUME = 'volume'
PERSON = 'person'

TOKEN_INTERFACE = 'https://openapi.baidu.com/oauth/2.0/token'
TEXT2AUDIO_INTERFACE = 'http://tsn.baidu.com/text2audio'

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORT_LANGUAGES),
    vol.Optional(CONF_APIKEY): cv.string,
    vol.Optional(CONF_SECRETKEY):cv.string,
    vol.Optional(CONF_SPEED,default='5'): cv.string,
    vol.Optional(CONF_PITCH,default='5'): cv.string,
    vol.Optional(CONF_VOLUME,default='5'): cv.string,
    vol.Optional(PERSON,default='0'): cv.string,
})

def get_engine(hass, config):
    lang = config.get(CONF_LANG)
    apiKey = config.get(CONF_APIKEY)
    secretKey = config.get(CONF_SECRETKEY)
    speed = config.get(CONF_SPEED)
    pitch = config.get(CONF_PITCH)
    volume = config.get(CONF_VOLUME)
    person = config.get(PERSON)

    if apiKey == None:
        _Log.error('Api Key is nil')
        return False
    if secretKey == None:
        _Log.error('secretKey is nil')
        return False

    return BaiduTTS(lang,apiKey,secretKey,speed,pitch,volume,person)

class BaiduTTS (Provider):

    def __init__(self,lang,apiKey,secretKey,speed,pitch,volume,person):
        self._lang = lang
        self._apiKey = apiKey
        self._secretKey = secretKey
        self._speed = speed
        self._pitch = pitch
        self._volume = volume
        self._person = person
        token = self.getToken()
        _Log.info("token =====>" + token)
        self._Token = token

    def getToken(self):
        resp = requests.get(TOKEN_INTERFACE,params={'grant_type': 'client_credentials','client_id':self._apiKey,'client_secret':self._secretKey})
        if resp.status_code != 200:
            _Log.error('Get ToKen Http Error status_code:%s' % resp.status_code)
            return None
        resp.encoding = 'utf-8'
        # toKenjsonStr =  resp.text
        tokenJson =  resp.json()

        if not 'access_token' in tokenJson:
            _Log.error('Get ToKen Json Error!')
            return None
        return tokenJson['access_token']

    @property
    def default_language(self):
        """Default language."""
        return self._lang

    @property
    def supported_languages(self):
        """List of supported languages."""
        return SUPPORT_LANGUAGES

    def get_tts_audio(self, message, language, options=None):
        if self._Token == None:
            self._Token = self.getToken()

        if self._Token == None:
            _Log.error('get_tts_audio Self.ToKen is nil')
            return

        resp = requests.get(TEXT2AUDIO_INTERFACE,params={'tex':message,'lan':language,'tok':self._Token,'ctp':'1','cuid':'HomeAssistant','spd':self._speed,'pit':self._pitch,'vol':self._volume,'per':self._person})

        if resp.status_code == 500:
            _Log.error('Text2Audio Error:500 Not Support.')
            return
        if resp.status_code == 501:
            _Log.error('Text2Audio Error:501 Params Error')
            return
        if resp.status_code == 502:
            _Log.error('Text2Audio Error:502 TokenVerificationError.')
            _Log.Info('Now Get Token!')
            self._Token = self.getToken()
            self.get_tts_audio(message,language,options)
            return
        if resp.status_code == 503:
            _Log.error('Text2Audio Error:503 Composite Error.')
            return

        if resp.status_code != 200:
            _Log.error('get_tts_audio Http Error status_code:%s' % resp.status_code)
            return

        data = resp.content
        return ('mp3',data)


# Create an empty list to store the items
todo_list = []

# Function to add items
def add_item(item):
    todo_list.append(item)
    print("Item added successfully!")

# Function to view items
def view_items():
    if len(todo_list) == 0:
        print("You have no items in your todo list")
    else:
        for item in todo_list:
            print(item)

# Function to remove items
def remove_item(item):
    if item in todo_list:
        todo_list.remove(item)
        print("Item removed successfully!")
    else:
        print("Item not found!")

# Driver code
while True:
    print("1. Add item")
    print("2. View items")
    print("3. Remove item")
    print("4. Exit")
    choice = int(input("Enter your choice: "))

    if choice == 1:
        item = input("Enter the item: ")
        add_item(item)
    elif choice == 2:
        view_items()
    elif choice == 3:
        item = input("Enter the item: ")
        remove_item(item)
    elif choice == 4:
        break
    else:
        print("Invalid choice!")


import concurrent.futures

class OrderedPipe:
    def __init__(self, **kwargs):
        self.inputs = kwargs
        self.task_groups = OrderedPipe.parallel_order(kwargs)

    def parallel_order(dependency_graph):
        in_degree = {node: 0 for node in dependency_graph}
        dependencies = {node: set() for node in dependency_graph}

        for node, (operation, *operands) in dependency_graph.items():
            for operand in operands:
                if operand in dependency_graph:
                    in_degree[node] += 1
                    dependencies[operand].add(node)

        parallel_steps = []

        independent_nodes = [node for node, degree in in_degree.items() if degree == 0]

        while independent_nodes:
            parallel_steps.append(independent_nodes)

            next_step = []

            for node in independent_nodes:
                for dependent in dependencies[node]:
                    in_degree[dependent] -= 1
                    if in_degree[dependent] == 0:
                        next_step.append(dependent)

            independent_nodes = next_step

        return parallel_steps

    def __call__(self, parallel, **kwargs):
        self.inputs.update(kwargs)
        if parallel:
            with concurrent.futures.ThreadPoolExecutor() as executor:
                for tasks in self.task_groups:
                        futures = {}
                        for task in tasks:
                            f, *id_args = self.inputs[task]
                            args = (self.inputs[id_arg] for id_arg in id_args)
                            futures[executor.submit(f, *args)] = task
                        for future in concurrent.futures.as_completed(futures):
                            task = futures[future]
                            output = future.result()
                            self.inputs[task] = output
            return output
        else:
            for tasks in self.task_groups:
                for task in tasks:
                    f, *id_args = self.inputs[task]
                    args = (self.inputs[id_arg] for id_arg in id_args)
                    output = f(*args)
                    self.inputs[task] = output
            return output


from asyncio import Task
from typing import (
    Callable,
    Coroutine,
    Generator,
    Generic,
    List,
    Tuple,
    Type,
    TypeVar,
    Union,
    overload,
)

from mpyc.sectypes import SecureFixedPoint, SecureObject

InnerType = TypeVar("InnerType")
ReturnType = Union[InnerType, List[InnerType], List[List[InnerType]]]

def _ncopy(nested_list: InnerType) -> InnerType: ...
@overload
def _nested_list(
    rt: Type[SecureObject],
    n: int,
    dims: List[int],
) -> ReturnType[SecureObject]: ...
@overload
def _nested_list(
    rt: Type[None],
    n: int,
    dims: List[int],
) -> ReturnType[None]: ...
@overload
def _nested_list(
    rt: Callable[..., SecureFixedPoint],
    n: int,
    dims: List[int],
) -> ReturnType[SecureFixedPoint]: ...
def __reconcile(decl: InnerType, givn: InnerType) -> None: ...
def _reconcile(decl: InnerType, task: Task[InnerType]) -> None: ...
def mpc_coro(
    f: Callable[..., Coroutine[InnerType, None, InnerType]],
    pc: bool = ...,
) -> Callable[..., InnerType]: ...
def mpc_coro_ignore(
    func: Callable[..., Coroutine[InnerType, None, InnerType]]
) -> Callable[..., InnerType]: ...

SomeType = TypeVar("SomeType")

class YieldAwaitable(Generic[SomeType]):
    def __init__(self, value: SomeType) -> None: ...
    def __await__(self) -> Generator[SomeType, None, None]: ...

@overload
def returnType(
    return_type: Type[InnerType],
    *dimensions: int,
) -> YieldAwaitable[Union[InnerType, List[InnerType], List[List[InnerType]]]]: ...
@overload
def returnType(
    return_type: Tuple[Type[SecureObject], bool],
    *dimensions: int,
) -> YieldAwaitable[
    Union[SecureFixedPoint, List[SecureFixedPoint], List[List[SecureFixedPoint]]]
]: ...
@overload
def returnType_no_wrap(
    return_type: Type[None],
    *dimensions: int,
) -> None: ...
@overload
def returnType_no_wrap(
    return_type: Type[InnerType],
    *dimensions: int,
) -> Union[InnerType, List[InnerType], List[List[InnerType]]]: ...
@overload
def returnType_no_wrap(
    return_type: Tuple[Type[SecureObject], bool],
    *dimensions: int,
) -> Union[SecureFixedPoint, List[SecureFixedPoint], List[List[SecureFixedPoint]]]: ...