from .calc_flag_sensitivity import calc_flag_sensitivity
from .pqtl_aggregate_results import pqtl_aggregate_results
from .pqtl_highchart import pqtl_highchart
from .pqtl_network_plot import pqtl_network_plot
from .pqtl_table import pqtl_format_table
from .pqtl_utils import (
    calc_api_flag_pleio,
    calc_flag_hetero,
    num_to_round,
    query_api_pqtl_cached,
)

PVALUE_THR_PROTEINS = 1.00
PVALUE_THR_NON_PROTEINS = 0.05

def pqtl_main(query, method, search_flag, overwrite: bool = False):
    """Returns the table of results,
    i.e. (MR, sensitivity analyses, SNP-info),
    per the query type ('method')
    and search entity ('searchtype'), i.e. 'proteins' or 'traits'
    """
    hierarchy: bool = False
    if search_flag == "proteins":
        pvalue_thr = PVALUE_THR_PROTEINS
    else:
        pvalue_thr = PVALUE_THR_NON_PROTEINS
    if method not in ["simple", "mrres", "sglmr", "inst", "sense"]:
        raise
    if method == "simple":
        (
            pqtl_results,
            plot_output,
            headers,
            result_table,
            count,
        ) = pqtl_main_simple(
            query=query,
            pvalue_thr=pvalue_thr,
            search_flag=search_flag,
            overwrite=overwrite,
        )
    elif method == "mrres":
        (
            pqtl_results,
            plot_output,
            headers,
            result_table,
            count,
        ) = pqtl_main_mrres(
            query=query,
            pvalue_thr=pvalue_thr,
            search_flag=search_flag,
            overwrite=overwrite,
        )
    elif method == "sglmr":
        (
            pqtl_results,
            plot_output,
            headers,
            result_table,
            count,
        ) = pqtl_main_sglmr(
            query=query,
            pvalue_thr=pvalue_thr,
            search_flag=search_flag,
            overwrite=overwrite,
        )
    elif method == "inst":
        (
            pqtl_results,
            plot_output,
            headers,
            result_table,
            count,
        ) = pqtl_main_inst(
            query=query,
            pvalue_thr=pvalue_thr,
            search_flag=search_flag,
            overwrite=overwrite,
        )
        hierarchy = True
    elif method == "sense":
        (
            pqtl_results,
            plot_output,
            headers,
            result_table,
            count,
        ) = pqtl_main_sense(
            query=query,
            pvalue_thr=pvalue_thr,
            search_flag=search_flag,
            overwrite=overwrite,
        )
        hierarchy = True

    if count > 12:
        hierarchy = False
    no_results: bool = False
    if len(result_table) == 0:
        no_results = True

    table_output = pqtl_format_table(headers=headers, table_data=result_table)
    res = {
        "table_output": table_output,
        "plot_output": plot_output,
        "no_results": no_results,
        "hierarchy": hierarchy,
        "search_flag": search_flag,
    }
    return res

def pqtl_main_simple(query, pvalue_thr, search_flag, overwrite: bool = False):
    pqtl_results = query_api_pqtl_cached(
        query=query,
        rtype="simple",
        pvalue=pvalue_thr,
        searchflag=search_flag,
        overwrite=overwrite,
    )
    plot_output = pqtl_network_plot(
        data=pqtl_results, method="simple", search_flag=search_flag
    )
    headers = [
        "Protein",
        "Trait",
        "MRBase ID",
        "Protein associates with trait",
        "Low heterogeneity",
        "rsID",
        "Cis acting instrument",
        "Correct causal direction",
        "Instrument associates with one protein",
        "Shared causal variant",
    ]

    result_table = []
    count = 0
    for row in pqtl_results["results"]:
        count = count + 1
        stg_flag, coloc_flag = calc_flag_sensitivity(
            row["direction"],
            row["steiger_pvalue"],
            row["coloc_prob"],
            row["pvalue"],
            row["ld_check"],
        )
        consist_flag = calc_flag_hetero(row["q_pvalue"])
        ptcount = calc_api_flag_pleio(row["rsID"], "count")
        result_table.append(
            [
                row["expID"],
                row["outID"],
                row["outID_mrbase"],
                row["pvalue"],
                consist_flag,
                row["rsID"],
                row["trans_cis"],
                stg_flag,
                ptcount,
                coloc_flag,
            ]
        )

    results = pqtl_aggregate_results(result_table, search_flag)
    result_table = results

    return pqtl_results, plot_output, headers, result_table, count

def pqtl_main_mrres(query, pvalue_thr, search_flag, overwrite: bool = False):
    pqtl_results = query_api_pqtl_cached(
        query=query,
        rtype="mrres",
        pvalue=pvalue_thr,
        searchflag=search_flag,
        overwrite=overwrite,
    )
    plot_output = pqtl_highchart(
        data=pqtl_results, method="mrres", search_flag=search_flag
    )
    headers = [
        "Protein",
        "Trait",
        "MRBase ID",
        "N SNP",
        "Method",
        "Effect Size",
        "S.E.",
        "p-value",
    ]

    result_table = []
    count = 0
    for row in pqtl_results["results"]:
        count = count + 1
        result_table.append(
            [
                row["expID"],
                row["outID"],
                row["outID_mrbase"],
                row["nsnp"],
                row["method"],
                num_to_round(row["beta"], 4),
                num_to_round(row["se"], 4),
                row["pvalue"],
            ]
        )

    return pqtl_results, plot_output, headers, result_table, count

def pqtl_main_sglmr(query, pvalue_thr, search_flag, overwrite: bool = False):
    pqtl_results = query_api_pqtl_cached(
        query=query,
        rtype="sglmr",
        pvalue=pvalue_thr,
        searchflag=search_flag,
        overwrite=overwrite,
    )
    plot_output = pqtl_highchart(
        data=pqtl_results, method="sglmr", search_flag=search_flag
    )
    headers = [
        "rsID",
        "Protein",
        "Trait",
        "MRBase ID",
        "SNP reliability",
        "Effect Size",
        "S.E.",
        "p-value",
        "Cis Trans",
    ]

    result_table = []
    count = 0
    for row in pqtl_results["results"]:
        count = count + 1
        result_table.append(
            [
                row["rsID"],
                row["expID"],
                row["outID"],
                row["outID_mrbase"],
                row["tier"],
                num_to_round(row["beta_sgl"], 4),
                num_to_round(row["se_slg"], 4),
                row["pvalue_sgl"],
                row["trans_cis"],
            ]
        )

    return pqtl_results, plot_output, headers, result_table, count

def pqtl_main_inst(query, pvalue_thr, search_flag, overwrite: bool = False):
    pqtl_results = query_api_pqtl_cached(
        query=query,
        rtype="inst",
        pvalue=pvalue_thr,
        searchflag=search_flag,
        overwrite=overwrite,
    )
    plot_output = pqtl_network_plot(
        data=pqtl_results, method="inst", search_flag=search_flag
    )
    headers = [
        "rsID",
        "Protein",
        "Trait",
        "MRBase ID",
        "EA",
        "NEA",
        "EAF",
        "Cis Trans",
        "N Exposure",
        "N Outcome",
        "Study Exposure",
        "Study Outcome",
    ]

    result_table = []
    count = 0
    for row in pqtl_results["results"]:
        count = count + 1
        result_table.append(
            [
                row["rsID"],
                row["expID"],
                row["outID"],
                row["outID_mrbase"],
                row["ea"],
                row["nea"],
                num_to_round(row["eaf_exp"], 4),
                row["trans_cis"],
                row["sample_exp"],
                row["sample_out"],
                row["author_exp"],
                row["author_out"],
            ]
        )

    return pqtl_results, plot_output, headers, result_table, count

def pqtl_main_sense(query, pvalue_thr, search_flag, overwrite: bool = False):
    pqtl_results = query_api_pqtl_cached(
        query=query,
        rtype="sense",
        pvalue=pvalue_thr,
        searchflag=search_flag,
        overwrite=overwrite,
    )
    plot_output = pqtl_network_plot(
        data=pqtl_results, method="sense", search_flag=search_flag
    )
    headers = [
        "rsID",
        "Protein",
        "Trait",
        "MRBase ID",
        "SNP reliability",
        "Direction",
        "Steiger p-value",
        "Associated proteins",
        "Post. prob. colocalization",
        "Outcome SNP",
        "LD Value",
        "Heterogeneity p-value",
    ]

    result_table = []
    count = 0
    for row in pqtl_results["results"]:
        count = count + 1
        ptlist = calc_api_flag_pleio(row["rsID"], "proteins")
        result_table.append(
            [
                row["rsID"],
                row["expID"],
                row["outID"],
                row["outID_mrbase"],
                row["tier"],
                row["direction"],
                row["steiger_pvalue"],
                ptlist,
                row["coloc_prob"],
                row["outcome_snp"],
                row["ld_check"],
                row["q_pvalue"],
            ]
        )

    return pqtl_results, plot_output, headers, result_table, count


class Node:
    def __init__(self, v):
        self.value = v
        self.prev = None
        self.next = None

class LinkedList2:
    def __init__(self):
        self.head = None
        self.tail = None

    def add_in_tail(self, item):
        if self.head is None:
            self.head = item
            item.prev = None
            item.next = None
        else:
            self.tail.next = item
            item.prev = self.tail
        self.tail = item

    def find(self, val):
        node = self.head
        while node is not None:
            if node.value == val:
                return node
            node = node.next
        return None

    def find_all(self, val):
        node = self.head
        result = []
        while node is not None:
            if node.value == val:
                result.append(node)
            node = node.next
        return result

    def delete(self, val, all=False):
        nodes = self.find_all(val)
        for del_n in (nodes[::-1] if all else nodes[:1]):
            if del_n is self.head and del_n.next is None:
                self.clean()
            elif del_n is self.tail:
                self.tail = del_n.prev
                del_n.prev.next = None
            elif del_n is self.head:
                self.head = del_n.next
                del_n.next.prev = None
            else:
                del_n.prev.next = del_n.next
                del_n.next.prev = del_n.prev

            del_n.prev = None
            del_n.next = None

    def clean(self):
        self.__init__()

    def len(self):
        node = self.head
        _len = 0
        while node is not None:
            _len += 1
            node = node.next

        return _len

    def insert(self, afterNode, newNode):
        if afterNode is self.tail or afterNode is None:
            self.add_in_tail(newNode)
        else:
            newNode.prev = afterNode
            afterNode.next.prev = newNode
            newNode.next = afterNode.next
            afterNode.next = newNode

    def add_in_head(self, newNode):
        node = self.head
        self.head = newNode
        newNode.next = node
        node.prev = newNode

    def print(self):
        node = self.head
        print("forvard", end=" ")
        while node:
            print(node.value, end=" ")
            node = node.next

        node = self.tail
        print("back", end=" ")
        while node:
            print(node.value, end=" ")
            node = node.prev
        print("")


import argparse
import zipfile
import re
import collections
import numpy as np
from gensim.models import KeyedVectors
from six.moves import xrange
import random
import torch
import gensim
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
from torch.autograd import Variable
from models import SkipGramModel
from models import CBOWModel
from inference import Word2Vec
from inference import save_embeddings

from gensim.test.utils import datapath

model_list = ['CBOW', 'skipgram']

cmd_parser = argparse.ArgumentParser(description = None)

# Argumentos

#Dados de Entrada
cmd_parser.add_argument('-d', '--data', default = 'data/2.txt', help = 'Data file for word2vec training.')

#Dados de Saida
cmd_parser.add_argument('-o', '--output', default = 'embeddings.bin', help = 'Output embeddings filename.')

#Imagem de Saida
cmd_parser.add_argument('-p', '--plot', default = 'tsne.png', help = 'Plotting output filename.')

#Configurações da Imagem de Saida
cmd_parser.add_argument('-pn', '--plot_num', default = 3, type = int, help = 'Plotting data number.')

#Tamanho do Vocabulário
cmd_parser.add_argument('-s', '--size', default = 50000, type = int, help = 'Vocabulary size.')

# Argumentos do Modelo de Treinamento
cmd_parser.add_argument('-m', '--mode', default = 'CBOW', choices = model_list, help = 'Training model.')
cmd_parser.add_argument('-bs', '--batch_size', default = 128, type = int, help = 'Training batch size.')
cmd_parser.add_argument('-ns', '--num_skips', default = 2, type = int, help = 'How many times to reuse an input to generate a label.')
cmd_parser.add_argument('-sw', '--skip_window', default = 2, type = int, help = 'How many words to consider left and right.')
cmd_parser.add_argument('-ed', '--embedding_dim', default = 128, type = int, help = 'Dimension of the embedding vector.')
cmd_parser.add_argument('-lr', '--learning_rate', default = 0.025, type = float, help = 'Learning rate')
cmd_parser.add_argument('-i', '--num_steps', default = 50, type = int, help = 'Number of steps to run.')
cmd_parser.add_argument('-ne', '--negative_example', default = 5, type = int, help = 'Number of negative examples.')

#Função que faz a leitura dos dados
def read_data(filename):
    """Extrai o primeiro arquivo contido em um arquivo .zip com uma lista de palavras, ou então extrai diretamente do arquivo .txt."""
    if filename.endswith('.zip'):
        with zipfile.ZipFile(filename) as f:
            text = f.read(f.namelist()[0]).decode('ascii')
    else:
        with open(filename, "r") as f:
            text = f.read()
    return [word.lower() for word in re.compile('\w+').findall(text)]

#Função que cria o dataset
def build_dataset(words, n_words):
    """Processar as entradas brutas do dataset.
        Retorna:
            data:               Lista de códigos (inteiros de 0 a vocabulary_size - 1).
                                Este é o texto original, mas as palavras são substituídas por seus códigos
            count:              Lista de palavras (strings) para contagem de ocorrências
            dictionary:         Mapa de palavras (strings) para seus códigos (inteiros)
            reverse_dictionary: Mapa de códigos (inteiros) para palavras (strings)
    """

    count = [['UNK', -1]]
    count.extend(collections.Counter(words).most_common(n_words - 1))
    dictionary = dict()

    for word, _ in count:
        dictionary[word] = len(dictionary)

    data = list()
    unk_count = 0

    for word in words:
        index = dictionary.get(word, 0)
        if index == 0:  # dictionary['UNK']
            unk_count += 1
        data.append(index)

    count[0][1] = unk_count
    reversed_dictionary = dict(zip(dictionary.values(), dictionary.keys()))

    return data, count, dictionary, reversed_dictionary

#Função que gera um lote de dados de treinamento
def generate_batch(data, data_index, batch_size, num_skips, skip_window):
    """Gera um lote de dados de treinamento
        Retorna:
            centers:        Lista de índices de palavras centrais para esse lote.
            contexts:       Lista de índices de contextos para esse lote.
            data_index:     Indice dos dados atuais para o próximo lote.
    """

    assert batch_size % num_skips == 0
    assert num_skips <= 2 * skip_window

    centers = np.ndarray(shape = (batch_size), dtype = np.int32)
    contexts = np.ndarray(shape = (batch_size, 1), dtype = np.int32)
    span = 2 * skip_window + 1
    buffer = collections.deque(maxlen=span)

    if data_index + span > len(data):
        data_index = 0

    buffer.extend(data[data_index:data_index + span])
    data_index += span

    for i in range(batch_size // num_skips):
        context_words = [w for w in range(span) if w != skip_window]
        words_to_use = random.sample(context_words, num_skips)
        for j, context_word in enumerate(words_to_use):
            centers[i * num_skips + j] = buffer[skip_window]
            contexts[i * num_skips + j, 0] = buffer[context_word]
        if data_index == len(data):
            for word in data[:span]:
                buffer.append(word)
            data_index = span
        else:
            buffer.append(data[data_index])
            data_index += 1

    # Voltar um pouco para evitar pular palavras no final de um lote
    data_index = (data_index + len(data) - span) % len(data)

    return torch.LongTensor(centers), torch.LongTensor(contexts), data_index

#Função que faz o treinamento
def train(data, word_count, mode, vocabulary_size, embedding_dim, batch_size, num_skips, skip_window, num_steps, learning_rate, neg_num):
    """Processo de Treinamento e Backpropagation, retorna o embedding final como result"""

    if mode == 'CBOW':
        model = CBOWModel(vocabulary_size, embedding_dim)
    elif mode == 'skipgram':
        model = SkipGramModel(vocabulary_size, embedding_dim, neg_num, word_count)
    else:
        raise ValueError("Modelo \"%s\" não é suportado" % model)

    optimizer = torch.optim.SGD(model.parameters(), lr = learning_rate)
    loss_function = torch.nn.NLLLoss()
    data_index = 0
    loss_val = 0

    for i in xrange(num_steps):
        # Preparar dados de feed e forward pass
        centers, contexts, data_index = generate_batch(data, data_index, batch_size, num_skips, skip_window)
        if mode == 'CBOW':
            y_pred = model(contexts)
            loss = loss_function(y_pred, centers)
        elif mode == 'skipgram':
            loss = model(centers, contexts)
        else:
            raise ValueError("Modelo \"%s\" não é suportado" % model)

        # Gradientes Zero, execute um backward pass, e atualize os pesos.
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # Imprimir o valor da perda para certos passos
        loss_val += loss.item()
        if i > 0 and i % (num_steps/100) == 0:
            print('Perda média no passo', i, ':', loss_val/(num_steps/100))
            loss_val = 0

    return model.get_embeddings()

#Função que Plota a Imagem
def tsne_plot(embeddings, num, reverse_dictionary, filename):
    """Plotar o resultado tSNE de embeddings para um subconjunto de palavras"""

    tsne = TSNE(perplexity = 30, n_components = 2, init='pca', n_iter = 5000, method='exact')
    low_dim_embs = tsne.fit_transform(final_embeddings[:num, :])
    low_dim_labels = [reverse_dictionary[i] for i in xrange(num)]

    assert low_dim_embs.shape[0] >= len(low_dim_labels), 'More labels than embeddings'

    plt.figure(figsize=(18, 18))  # Em polegadas

    for i, label in enumerate(low_dim_labels):
        x, y = low_dim_embs[i, :]
        plt.scatter(x, y)
        plt.annotate(label, xy = (x, y), xytext = (5, 2), textcoords = 'offset points', ha = 'right', va = 'bottom')
    print("Salvando imagem no arquivo:", filename)
    plt.savefig(filename)

#Função Main
if __name__ == '__main__':

    args = cmd_parser.parse_args()

    # Pré-processamento dos dados
    vocabulary = read_data(args.data)
    print('Tamanho dos Dados:', len(vocabulary))
    data, count, dictionary, reverse_dictionary = build_dataset(vocabulary, args.size)

    vocabulary_size = min(args.size, len(count))
    print('Tamanho do Vocabulário:', vocabulary_size)

    word_count = [c[1] for c in count]

    # Treinamento do Modelo
    final_embeddings = train(data = data,
                             word_count = word_count,
                             mode = args.mode,
                             vocabulary_size = vocabulary_size,
                             embedding_dim = args.embedding_dim,
                             batch_size = args.batch_size,
                             num_skips = args.num_skips,
                             skip_window = args.skip_window,
                             num_steps = args.num_steps,
                             learning_rate = args.learning_rate,
                             neg_num = args.negative_example)

    norm = torch.sqrt(torch.cumsum(torch.mul(final_embeddings, final_embeddings), 1))
    nomalized_embeddings = (final_embeddings/norm).numpy()

    # Salvando resultados e plotando imagem
    save_embeddings(args.output, final_embeddings, dictionary)
    tsne_plot(embeddings = nomalized_embeddings, num = min(vocabulary_size, args.plot_num), reverse_dictionary = reverse_dictionary, filename = args.plot)

    w2v = Word2Vec()
    w2v.from_file('embeddings.bin')

    word = 'the'
    print('Embeddings da palavra:', word)
    print(w2v.inference('the'))

    word = 'of'
    print('Embeddings da palavra:', word)
    print(w2v.inference('of'))

    model = KeyedVectors.load_word2vec_format(datapath(('/usr/local/lib/python3.6/dist-packages/gensim/test/test_data/euclidean_vectors.bin')), binary = True)  # C binary format
    stringA = 'of'
    stringB = 'the'

    print(model.most_similar(positive=[stringA, stringB], negative=[stringA, stringB], topn=10))

    model = KeyedVectors.load_word2vec_format(datapath(('/home/fuchs/Documentos/MESTRADO/Masters/Code/word2vec-master/embeddings.bin')), encoding='utf8', unicode_errors='ignore', binary=True)  # C binary format
    stringA = 'of'
    stringB = 'the'

    print(model.most_similar(positive=[stringA, stringB], negative=[stringA, stringB], topn=10))


# 무승부와 패배를 같이 진행하면 안된다! 무승부 3번이면 패배 2번 이런 식으로 살펴보아야 한다. (둘 중에 하나만 살펴야!)

answer = []

for _ in range(4):
    results = list(map(int, input().split()))     # 승, 무, 패 결과 입력받아 1차원 리스트에 담기
    team_results = [[results[i], results[i+1], results[i+2]] for i in range(0, len(results), 3)]     # results를 가공하여 팀별로 [승, 무, 패] 결과 저장 (2차원 리스트)
    team_results.sort(reverse=True)     # 승이 많은 팀부터 내림차순 정렬 (승이 같으면 무승부, 무승부가 같으면 패가 많은 팀 기준으로 내림차순 정렬)

    # 승, 무, 패의 합이 5가 되지 않는지를 확인
    for results in team_results:
        if results[0] + results[1] + results[2] != 5:
            answer.append(0)
            break
    else:
        for i in range(len(team_results)):
            cnt = 0     # 패배와 성공을 매칭할때의 cnt

            # 패배가 많은 것부터 승리와 매칭해야 하기 때문에 team_results를 거꾸로 진행한다.
            for j in range(len(team_results)-1, -1, -1):
                win = team_results[i][0]     # 현재 팀의 승리 수
                draw = team_results[i][1]     # 현재 팀의 무승부 수
                lose = team_results[i][2]     # 현재 팀의 패배 수
                if j != i:     # 현재 팀에 해당하지 않을 경우
                    other_draw = team_results[j][1]     # 다른 팀의 무승부 수
                    other_lose = team_results[j][2]     # 다른 팀의 패배 수
                    if win > 0 and other_lose > 0 and cnt != win:     # 현재 팀의 승리 수가 0보다 클 경우
                        team_results[j][2] -= 1     # 다른 팀의 패배 부분과 짝지어지므로 -1하기
                        cnt += 1
                    elif draw > 0 and other_draw > 0:     # 현재 팀의 무승부 수와 다른 팀의 무승부 수 모두 남아 있을 경우
                        team_results[i][1] -= 1
                        team_results[j][1] -= 1     # 서로 짝지어질 수 있으므로 두 팀의 무승부 부분 1씩 감소
        else:      # break 없이 통과하면
            # 위의 코드로 인해 변형된 team_result에서 무승부와 패배 부분의 합이 0이 되지 않으면 불가능한 결과이다.
            draw_sum = 0
            lose_sum = 0
            for result in team_results:
                draw_sum += result[1]
                lose_sum += result[2]
                if draw_sum != 0 or lose_sum != 0:
                    answer.append(0)
                    break
            else:
                answer.append(1)

for item in answer:
    print(item, end=' ')

월드컵 나중에 다시.py


def solution(food):
    result = []
    idx = 0
    for i in range(1, len(food)):
        if food[i] % 2 == 1:
            food[i] -= 1
        for _ in range(food[i]):
            result.insert(idx, i)
        idx += food[i] // 2
    result.insert(idx, 0)
    return ''.join(map(str, result))

print(solution([1, 3, 4, 6]))
print(solution([1, 7, 1, 2]))

# 간단한 풀이
def solution(food):
    answer = ''
    for f in range(1, len(food)):
         answer += str(f)*(food[f]//2)     # 0 기준으로 이전에 놓일 숫자들을 먼저 answer에 채움.  // 는 몫만 반환하기 때문에 food[f]가 홀수인 경우도 자동 처리 가능
    return answer + '0' + ''.join(list(answer)[::-1])     # answer 문자열 + '0' + answer(string)을 list화시켜 그것을 뒤집은 배열을 다시 string화 시킨 값

python_programmers_school/level 1/푸드 파이트 대회.py

푸드 파이트 대회.py


# implementation of card game - Memory

import simplegui
import random

# constants to define play area and look of the game
CARD_W = 50 # pixels in x direction
CARD_H = 100 # pixels in y direction
TOTAL_CARDS = 16 # total cards in play
CARDS_PER_ROW = 4 # number of cards to place in a row (make sure it is a factor of total)
WIDTH = CARDS_PER_ROW * CARD_W # canvas width is number of cards per row
HEIGHT = (TOTAL_CARDS / CARDS_PER_ROW) * CARD_H # canvas height is number of card rows

PLAY_1 = ("0", "1", "2", "3", "4", "5", "6" ,"7")
PLAY_2 = ("A", "B", "C", "D", "E", "F", "G", "H")
PLAY_3 = ("!", "@", "#", "$", "%", "&", "*", "?")
PLAY_4 = ("Z", "Y", "X", "W", "V", "U", "T", "S")
PLAY_5 = (":)", ":|", ":(", ";(", ":s", "B)", "8o", ":p")
PLAY_6 = ("  ", " .", "..", ".:", "::", " -", ".-", ":-")
PLAY_7 = ("--", "-/", "//", "|/", "||", "\\|", "\\\\", "-\\")
PLAY_8 = ("at", "be", "go", "hi", "in", "my", "no", "on")
PLAYS = (PLAY_1, PLAY_2, PLAY_3, PLAY_4, PLAY_5, PLAY_6, PLAY_7, PLAY_8)

# variables to keep card value and flips: total cards / 2 because it keeps pairs of values
cards = list(range(TOTAL_CARDS / 2))
cards.extend(range(TOTAL_CARDS / 2))
index1 = len(cards) # point somewhere invalid initially
index2 = len(cards) # point somewhere invalid initially
play_set = 0

# helper function to initialize globals
def new_game():
    global cards
    global exposed
    global state
    global turn_counter
    global play_set

    state = 0
    play_set = 0
    random.shuffle(cards)
    # make all the cards unflipped in this list
    exposed = [False for card in cards]
    #reset and display the turns counter
    turn_counter = 0
    label.set_text("Turns =" + str(turn_counter))

# define event handlers
def mouseclick(pos):
    global exposed
    global state
    global index1
    global index2
    global turn_counter
    global play_set

    # add game state logic here
    # calculate the index number from the mouse position
    idx_y = pos[1] / CARD_H
    idx_x = pos[0] / CARD_W
    idx = idx_y * CARDS_PER_ROW + idx_x

    # we are not clicking on a previously exposed card
    if False == exposed[idx]:
        # start state, like 2 cards exposed state
        if 0 == state:
            # one card exposed after this click
            state = 1
            play_set = cards[idx]
            # expose the selected card
            exposed[idx] = True
            # remember this card is exposed
            index1 = idx

        # another card being exposed
        elif 1 == state:
            # 2 cards exposed after this click
            state = 2
            # expose the selected card
            exposed[idx] = True
            # remember this card is exposed
            index2 = idx

            # 2 cards exposed = 1 turn taken
            turn_counter += 1
            # show the new number of turns
            label.set_text("Turns =" + str(turn_counter))

        # new pair being selected
        else:
            # shall we hide card pair that did not match ?
            if cards[index1] != cards[index2]:
                # hide first selection
                exposed[index1] = False
                # hide second selection
                exposed[index2] = False

            # only 1 card exposed after this click
            state = 1
            # remember this selection
            index1 = idx
            # remove the old second selection
            index2 = len(cards)
            # expose the selected card
            exposed[idx] = True

# cards are logically 50x100 pixels in size
def draw(canvas):
    # loop over all the cards in the list
    for idx in range(len(exposed)):
        # calculate the card corners for this card
        x1 = (idx % CARDS_PER_ROW) * CARD_W
        y1 = (idx / CARDS_PER_ROW) * CARD_H
        x2 = x1 + (CARD_W - 1)
        y2 = y1 + CARD_H
        xt = 20 - (play_set / 4 * 10)

        # if exposed, we draw the face and the edges
        if True == exposed[idx]:
            # show the face, which is just the number as a string
            canvas.draw_text(PLAYS[play_set][cards[idx]], (x1 + xt, y1 + 5 + CARD_H / 2), 24, "White")
            # frame the number showing the edge of the card
            canvas.draw_polyline([(x1, y1),(x2, y1),(x2, y2),(x1, y2),(x1, y1)],1,"White")
        # if hidden, we draw the card back
        else:
            canvas.draw_polygon([(x1, y1),(x2, y1),(x2, y2),(x1, y2),(x1, y1)],1,"Black","Green")

# create frame and add a button and labels
frame = simplegui.create_frame("Memory", WIDTH, HEIGHT)
frame.add_button("Reset", new_game)
label = frame.add_label("Turns = 0")

# register event handlers
frame.set_mouseclick_handler(mouseclick)
frame.set_draw_handler(draw)

# get things rolling
new_game()
frame.start()

# Always remember to review the grading rubric


'''try:
    a = 1200/0
except:
    print("Divisão por zer, não da pra fazer")'''

'''try:
    a = 2/0
except Exception as erro:
    print("Aconteceu algum erro:", erro)'''

import Time

def abre_arquivo ():
    try:
        arquivo = open('arquivodoido.txt')
        return arquivo
    except Exception as erro:
        print("Aconteceu algum erro:", erro)
        return False
while not abre_arquivo():
    print('Tentando abrir o arquivo')
    time.sleep(5)

print("Consegui abrir o arquivo")


"""Containers module."""

from typing import Optional

from dependency_injector import containers, providers

from kafkaescli import constants
from kafkaescli.core.config.services import ConfigFileService, ConfigService
from kafkaescli.core.consumer.services import ConsumeService
from kafkaescli.core.middleware.models import MiddlewareHook
from kafkaescli.core.middleware.services import MiddlewareService
from kafkaescli.core.producer.services import ProduceService
from kafkaescli.infra.kafka import Consumer, Producer
from kafkaescli.infra.webhook import WebhookHandler

class Container(containers.DeclarativeContainer):
    # overridable config
    config_file_path = providers.Object(constants.DEFAULT_CONFIG_FILE_PATH)
    overrides = providers.Dict()
    profile_name = providers.Object(str)

    # Services
    config_file_service = providers.Factory(ConfigFileService, config_file_path=config_file_path)
    config_service = providers.Factory(
        ConfigService,
        config_file_service=config_file_service,
        profile_name=profile_name,
        overrides=overrides,
    )
    consumer = providers.Factory(
        Consumer,
        config_service=config_service,
    )
    producer = providers.Factory(
        Producer,
        config_service=config_service,
    )
    webhook_handler = providers.Factory(
        WebhookHandler,
    )
    hook_after_consume = providers.Factory(
        MiddlewareService, callback=MiddlewareHook.AFTER_CONSUME, config_service=config_service
    )
    hook_before_produce = providers.Factory(
        MiddlewareService, callback=MiddlewareHook.BEFORE_PRODUCE, config_service=config_service
    )
    consume_service = providers.Factory(
        ConsumeService,
        consumer=consumer,
        webhook_handler=webhook_handler,
        hook_after_consume=hook_after_consume,
    )
    produce_service = providers.Factory(
        ProduceService,
        producer=producer,
        hook_before_produce=hook_before_produce,
    )


import os
import sys
import time
import logging as log

# importのサーチパスを追加
sys.path.insert(0,os.path.join(os.path.dirname(__file__),"../common"))

import numpy as np

from openvino.inference_engine import IECore

# ユーザ定義モジュール
from frame_processor import FrameProcessor
from yolo_detector import YoloDetector

class YoloFrameProcessor(FrameProcessor) :
    def __init__(self, args):
        # 推論に使用するデバイス一覧
        used_devices = set([args.d_yolo])

        super(YoloFrameProcessor, self).__init__(args, used_devices)

        # モデルのロード
        log.info("Loading models")
        if (args.m_yolo) :
            log.info("    YOLO model")
            yolo_detector_net = self.load_model(args.m_yolo)
            self.yolo_detector = YoloDetector(yolo_detector_net,
                                              confidence_threshold=args.t_yolo, iou_threshold=args.iou_threshold)
            self.yolo_detector.deploy(args.d_yolo, self.iecore)

            # ラベルのロード
            label_path = os.path.splitext(args.m_yolo)[0] + ".labels"
            self.yolo_detector.labels_map = self.load_label(label_path)

        else :
            # YOLOモデルが指定されていなければエラー
            log.error("--m_yolo option is mandatory")
            raise RuntimeError("--m_yolo option is mandatory")

        log.info("Models are loaded")

    # フレーム毎の処理
    def process(self, frame):
        assert len(frame.shape) == 3,    "Expected input frame in (H, W, C) format"
        assert frame.shape[2] in [3, 4], "Expected BGR or BGRA input"

        # 前処理
        # orig_image = frame.copy()
        frame = frame.transpose((2, 0, 1)) # HWC to CHW
        frame = np.expand_dims(frame, axis=0)

        # 検出器初期化
        self.yolo_detector.clear()

        # log.info("Face Detect")
        # 認識処理
        self.yolo_detector.start_async(frame)

        # 結果取得
        rois = self.yolo_detector.get_roi_proposals(frame)

        return rois

    # パフォーマンスステータスの取得
    def get_performance_stats(self):
        stats = {'yolo_detector': self.yolo_detector.get_performance_stats()}
        return stats


'''
# mit_course_number_6.0001_problem_set3_solutions

MIT Course 6.0001: Introduction to Computer Science and Programming in Python

Author: Eshgin Guluzade

Specialty: Mechanical Engineer

Country: Azerbaijan

My LinkedIn: https://www.linkedin.com/in/eshginguluzade/

My Quora: https://www.quora.com/profile/Eshgin-Guluzade

My Youtube Channel: https://www.youtube.com/channel/UCr6yufueEVaXBHgM8x1YlTw
'''

def get_word_score(word, n):
     points = 0
     second_component = 0
     word = word.lower()

     for i in word:
             if i in SCRABBLE_LETTER_VALUES:
                 points = points + SCRABBLE_LETTER_VALUES[i]
             else:
                 continue

     second_component = (7*len(word)) - (3 * (n - len(word)))

     if second_component < 1:
         second_component = 1

     return points * second_component

def display_hand(hand):

    for letter in hand.keys():
        for j in range(hand[letter]):
             print(letter, end=' ')      # print all on the same line
    print()                              # print an empty line

Problem 2 Dealing with hands____display_hand(hand).py


from bkbase.dataflow.batch.gateway.py_gateway import get_spark_conf

conf = get_spark_conf()

def get_batch_spark_conf():
    return conf

def get_string_conf(key, default=None):
    value = str(conf.get(key, default))
    if value is None:
        raise Exception("Can't get spark configuration: %s" % key)
    return value

def get_boolean_conf(key, default=None):
    value = conf._jconf.getBoolean(key, default)
    if value is None:
        raise Exception("Can't get spark configuration: %s" % key)
    return value

ENABLE_TEST = False

DATAFLOWAPI_URL_PREFIX = get_string_conf("spark.uc.batch.code.dataflow.url.prefix")
STOREKITAPI_URL_PREFIX = get_string_conf("spark.uc.batch.code.storekit.url.prefix")
DATABUSAPI_URL_PREFIX = get_string_conf("spark.uc.batch.code.databus.url.prefix")
DATAMANAGEAPI_URL_PREFIX = get_string_conf("spark.uc.batch.code.datamanage.url.prefix")
TIMEZONE = get_string_conf("spark.uc.batch.code.timezone", "Asia/Shanghai")

ENABLE_MONITOR = get_boolean_conf("spark.uc.batch.code.monitor.enable", True)

SELF_DEPENDENCY_PATH_PREFIX = "/api/flow_copy"
SELF_DEPENDENCY_ORIGIN_KEY = "origin_path"
SELF_DEPENDENCY_COPY_KEY = "copy_path"

SCHEDULE_TIME_CONF = "spark.uc.batch.code.schedule.time"

RESERVED_FIELDS = [
    {"field": "thedate", "type": "int"},
    {"field": "dtEventTime", "type": "string"},
    {"field": "dtEventTimeStamp", "type": "long"},
    {"field": "localTime", "type": "string"},
]


import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import confusion_matrix, accuracy_score

# Veri setini yükle
data = pd.read_csv('data1.csv', sep=';')

# Ondalık ayracı düzelt
data = data.replace(',', '.', regex=True)

# Öznitelikler ve etiketleri ayır
X = data.drop('class', axis=1).astype(float)
y = data['class']

# Veriyi eğitim ve test setlerine ayır
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# PCA ile öznitelik çıkarımı
pca = PCA(n_components=10)  # Yeni öznitelik sayısı
X_train_pca = pca.fit_transform(X_train)
X_test_pca = pca.transform(X_test)

# KNN sınıflandırması
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train_pca, y_train)
y_pred = knn.predict(X_test_pca)

# Karşıtlık matrisi (Confusion Matrix) ve doğruluk (Accuracy) değeri
cm = confusion_matrix(y_test, y_pred)
accuracy = accuracy_score(y_test, y_pred)

print("Karşıtlık Matrisi:")
print(cm)
print("Doğruluk (Accuracy) Değeri: {:.2f}".format(accuracy))


import os
import time
from discord.ext import commands
import discord
from pyscreenshot import grab

TOKEN = ''

# import json
# import requests
# URL = 'https://discordapp.com/oauth2/authorize?&client_id=816481315913859112&scope=bot&permissions=2048'

bot = commands.Bot(command_prefix='')

@bot.event
async def on_ready():
    print("Бот запущен.")

@bot.command()
async def ping(ctx):
    """-----Пинг до бота. """

    ping = round(bot.latency * 1000)
    await ctx.send(f"мой пинг {ping} мс. А твой?")

@bot.command()
async def clr(ctx, amount: int):
    """-----Удаляет сообщения. clr N -  удалит N последних сообщений. """

    await ctx.channel.purge(limit=amount + 1)
    await ctx.send(f"{amount} сообщения(ий) было удалено.")
    await ctx.send("Clean", tts=True)
    time.sleep(5)
    await ctx.channel.purge(limit=2)
    try:
        os.remove('box.png')
    except:
        pass

@bot.command()
async def ss(ctx):
    """-----Делает скриншот."""
    im = grab(bbox=(0, 0, 960, 1080))
    im.save('box.png')
    file = discord.File("box.png", filename="box.png")
    await ctx.send(file=file)

@bot.command()
async def login(ctx):
    """-----Логин-пароль для площадок."""
    with open('login', encoding='UTF-8') as f:
        s = f.read()
        print(s)
    await ctx.send(s, tts=False)

# Так как мы указали префикс в settings, обращаемся к словарю с ключом prefix.
# @bot.command()  # Не передаём аргумент pass_context, так как он был нужен в старых версиях.
# async def fox(ctx):
#     response = requests.get('https://some-random-api.ml/img/fox')  # Get-запрос
#     json_data = json.loads(response.text)  # Извлекаем JSON
#
#     embed = discord.Embed(color=0xff9900, title='Random Fox')  # Создание Embed'a
#     embed.set_image(url=json_data['link'])  # Устанавливаем картинку Embed'a
#     await ctx.send(embed=embed)  # Отправляем Embed

bot.run(TOKEN)


"""The data models used in RASCIL:

"""

__all__ = [
    "Configuration",
    "GainTable",
    "PointingTable",
    "Image",
    "GridData",
    "ConvolutionFunction",
    "Skycomponent",
    "SkyModel",
    "BlockVisibility",
    "FlagTable",
    "QA",
    "ScienceDataModel",
]

import logging
import warnings

import numpy
import xarray
from astropy import constants as const
from astropy import units as u
from astropy.coordinates import SkyCoord
from astropy.time import Time
from astropy.utils.exceptions import AstropyDeprecationWarning
from astropy.wcs import FITSFixedWarning

from rascil.data_models.polarisation import (
    PolarisationFrame,
    ReceptorFrame,
    polarisation_frame_from_names,
)
from rascil.data_models.xarray_coordinate_support import image_wcs, griddata_wcs, cf_wcs

warnings.simplefilter("ignore", FITSFixedWarning)
warnings.simplefilter("ignore", AstropyDeprecationWarning)

log = logging.getLogger("rascil-logger")

class XarrayAccessorMixin:
    """Convenience methods to access the fields of the xarray"""

    def __init__(self, xarray_obj):
        self._obj = xarray_obj

    def size(self):
        """Return size in GB"""
        size = self._obj.nbytes
        return size / 1024.0 / 1024.0 / 1024.0

    def datasizes(self):
        """Return string describing sizes of data variables
        :return: string
        """
        s = "Dataset size: {:.3f} GB\n".format(self._obj.nbytes / 1024 / 1024 / 1024)
        for var in self._obj.data_vars:
            s += "\t[{}]: \t{:.3f} GB\n".format(
                var, self._obj[var].nbytes / 1024 / 1024 / 1024
            )
        return s

class Configuration(xarray.Dataset):
    """A Configuration describes an array configuration.

    Here is an example::

        <xarray.Configuration>
        Dimensions:   (id: 115, spatial: 3)
        Coordinates:
          * id        (id) int64 0 1 2 3 4 5 6 7 8 ... 107 108 109 110 111 112 113 114
          * spatial   (spatial) <U1 'X' 'Y' 'Z'
        Data variables:
            names     (id) <U6 'M000' 'M001' 'M002' ... 'SKA102' 'SKA103' 'SKA104'
            xyz       (id, spatial) float64 -0.0 9e-05 1.053e+03 ... -810.3 1.053e+03
            diameter  (id) float64 13.5 13.5 13.5 13.5 13.5 ... 15.0 15.0 15.0 15.0 15.0
            mount     (id) <U4 'azel' 'azel' 'azel' 'azel' ... 'azel' 'azel' 'azel'
            vp_type   (id) <U7 'MEERKAT' 'MEERKAT' 'MEERKAT' ... 'MID' 'MID' 'MID'
            offset    (id, spatial) float64 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0
            stations  (id) <U3 '0' '1' '2' '3' '4' '5' ... '110' '111' '112' '113' '114'
        Attributes:
            rascil_data_model:  Configuration
            name:               MID
            location:           (5109237.71471275, 2006795.66194638, -3239109.1838011...
            receptor_frame:     <rascil.data_models.polarisation.ReceptorFrame object...
            frame:

    """

    __slots__ = ()

    def __init__(
        self,
        name="",
        location=None,
        names=None,
        xyz=None,
        mount="alt-az",
        frame="",
        receptor_frame=ReceptorFrame("linear"),
        diameter=None,
        offset=None,
        stations="%s",
        vp_type=None,
    ):

        """Configuration object describing data for processing

        :param name: Name of configuration e.g. 'LOWR3'
        :param location: Location of array as an astropy EarthLocation
        :param names: Names of the dishes/stations
        :param xyz: Geocentric coordinates of dishes/stations
        :param mount: Mount types of dishes/stations 'altaz' | 'xy' | 'equatorial'
        :param frame: Reference frame of locations
        :param receptor_frame: Receptor frame
        :param diameter: Diameters of dishes/stations (m)
        :param offset: Axis offset (m)
        :param stations: Identifiers of the dishes/stations
        :param vp_type: Type of voltage pattern (string)
        """

        super().__init__()

        nants = len(names)
        if isinstance(stations, str):
            stations = [stations % ant for ant in range(nants)]
            if isinstance(names, str):
                names = [names % ant for ant in range(nants)]
            if isinstance(mount, str):
                mount = numpy.repeat(mount, nants)
        if offset is None:
            offset = numpy.zeros([nants, 3])
        if vp_type is None:
            vp_type = numpy.repeat("", nants)

        coords = {"id": list(range(nants)), "spatial": ["X", "Y", "Z"]}

        datavars = dict()
        datavars["names"] = xarray.DataArray(
            names, coords={"id": list(range(nants))}, dims=["id"]
        )
        datavars["xyz"] = xarray.DataArray(xyz, coords=coords, dims=["id", "spatial"])
        datavars["diameter"] = xarray.DataArray(
            diameter, coords={"id": list(range(nants))}, dims=["id"]
        )
        datavars["mount"] = xarray.DataArray(
            mount, coords={"id": list(range(nants))}, dims=["id"]
        )
        datavars["vp_type"] = xarray.DataArray(
            vp_type, coords={"id": list(range(nants))}, dims=["id"]
        )
        datavars["offset"] = xarray.DataArray(
            offset, coords=coords, dims=["id", "spatial"]
        )
        datavars["stations"] = xarray.DataArray(
            stations, coords={"id": list(range(nants))}, dims=["id"]
        )

        attrs = dict()
        attrs["rascil_data_model"] = "Configuration"
        attrs["name"] = name  # Name of configuration
        attrs["location"] = location  # EarthLocation
        attrs["receptor_frame"] = receptor_frame
        attrs["frame"] = frame

        super().__init__(datavars, coords=coords, attrs=attrs)

    def __sizeof__(self):
        """Override default method to return size of dataset
        :return: int
        """
        # Dask uses sizeof() class to get memory occupied by various data
        # objects. For custom data objects like this one, dask falls back to
        # sys.getsizeof() function to get memory usage. sys.getsizeof() in
        # turns calls __sizeof__() magic method to get memory size. Here we
        # override the default method (which gives size of reference table)
        # to return size of Dataset.
        return int(self.nbytes)

    def to_native_dataset(self):
        """
        Convert to plain Dataset. Needed, e.g., for xarray.concat.
        This makes sure that the child class is represented as its parent class.
        """
        # use-case:
        # RASCIL-defined classes that inherit from xarray.Dataset, do not
        # take attrs and an input argument; xarray.concat tries to call the
        # subclass with attrs arg, because it assumes that the subclass takes
        # the same args as the Dataset class; we need to manually accommodate for this
        return xarray.Dataset(self, coords=self.coords, attrs=self.attrs)

@xarray.register_dataset_accessor("configuration_acc")
class ConfigurationAccessor(XarrayAccessorMixin):
    """Convenience methods to access the fields of the Configuration"""

    def __init__(self, xarray_obj):
        super().__init__(xarray_obj)

    @property
    def nants(self):
        """Names of the dishes/stations"""
        return len(self._obj["names"])

class GainTable(xarray.Dataset):
    """Gain table with: time, antenna,  weight columns

    The weight is usually that output from gain solvers.

    Here is an example::

        <xarray.GainTable>
        Dimensions:    (antenna: 115, frequency: 3, receptor1: 2, receptor2: 2, time: 3)
        Coordinates:
          * time       (time) float64 5.085e+09 5.085e+09 5.085e+09
          * antenna    (antenna) int64 0 1 2 3 4 5 6 7 ... 108 109 110 111 112 113 114
          * frequency  (frequency) float64 1e+08 1.05e+08 1.1e+08
          * receptor1  (receptor1) <U1 'X' 'Y'
          * receptor2  (receptor2) <U1 'X' 'Y'
        Data variables:
            gain       (time, antenna, frequency, receptor1, receptor2) complex128 (0...
            weight     (time, antenna, frequency, receptor1, receptor2) float64 1.0 ....
            residual   (time, frequency, receptor1, receptor2) float64 0.0 0.0 ... 0.0
            interval   (time) float32 99.72697 99.72697 99.72697
            datetime   (time) datetime64[ns] 2000-01-01T03:54:07.843184299 ... 2000-0...
        Attributes:
            rascil_data_model:  GainTable
            receptor_frame:     <rascil.data_models.polarisation.ReceptorFrame object...
            phasecentre:        <SkyCoord (ICRS): (ra, dec) in deg    (180., -35.)>
            configuration:      <xarray.Configuration> Dimensions:   (id: 115, spati...

    """

    __slots__ = ()

    def __init__(
        self,
        gain: numpy.array = None,
        time: numpy.array = None,
        interval=None,
        weight: numpy.array = None,
        residual: numpy.array = None,
        frequency: numpy.array = None,
        receptor_frame: ReceptorFrame = ReceptorFrame("linear"),
        phasecentre=None,
        configuration=None,
        jones_type="T",
    ):
        """Create a gaintable from arrays

        The definition of gain is:

            Vobs = g_i g_j^* Vmodel

        :param gain: Complex gain [nrows, nants, nchan, nrec, nrec]
        :param time: Centroid of solution [nrows]
        :param interval: Interval of validity
        :param weight: Weight of gain [nrows, nchan, nrec, nrec]
        :param residual: Residual of fit [nchan, nrec, nrec]
        :param frequency: Frequency [nchan]
        :param receptor_frame: Receptor frame
        :param phasecentre: Phasecentre (SkyCoord)
        :param configuration: Configuration
        :param jones_type: Type of gain: T, G, B, etc
        """

        super().__init__()

        ntimes, nants, nchan, nrec, _ = gain.shape
        antennas = range(nants)
        coords = {
            "time": time,
            "antenna": antennas,
            "frequency": frequency,
            "receptor1": receptor_frame.names,
            "receptor2": receptor_frame.names,
        }

        datavars = dict()
        datavars["gain"] = xarray.DataArray(
            gain, dims=["time", "antenna", "frequency", "receptor1", "receptor2"]
        )
        datavars["weight"] = xarray.DataArray(
            weight, dims=["time", "antenna", "frequency", "receptor1", "receptor2"]
        )
        datavars["residual"] = xarray.DataArray(
            residual, dims=["time", "frequency", "receptor1", "receptor2"]
        )
        datavars["interval"] = xarray.DataArray(interval, dims=["time"])
        datavars["datetime"] = xarray.DataArray(
            Time(time / 86400.0, format="mjd", scale="utc").datetime64, dims="time"
        )
        attrs = dict()
        attrs["rascil_data_model"] = "GainTable"
        attrs["receptor_frame"] = receptor_frame
        attrs["phasecentre"] = phasecentre
        attrs["configuration"] = configuration
        attrs["jones_type"] = jones_type

        super().__init__(datavars, coords=coords, attrs=attrs)

    def __sizeof__(self):
        """Override default method to return size of dataset
        :return: int
        """
        # Dask uses sizeof() class to get memory occupied by various data
        # objects. For custom data objects like this one, dask falls back to
        # sys.getsizeof() function to get memory usage. sys.getsizeof() in
        # turns calls __sizeof__() magic method to get memory size. Here we
        # override the default method (which gives size of reference table)
        # to return size of Dataset.
        return int(self.nbytes)

    def to_native_dataset(self):
        """
        Convert to plain Dataset. Needed, e.g., for xarray.concat.
        This makes sure that the child class is represented as its parent class.
        """
        # use-case:
        # RASCIL-defined classes that inherit from xarray.Dataset, do not
        # take attrs and an input argument; xarray.concat tries to call the
        # subclass with attrs arg, because it assumes that the subclass takes
        # the same args as the Dataset class; we need to manually accommodate for this
        return xarray.Dataset(self, coords=self.coords, attrs=self.attrs)

@xarray.register_dataset_accessor("gaintable_acc")
class GainTableAccessor(XarrayAccessorMixin):
    def __init__(self, xarray_obj):
        super().__init__(xarray_obj)

    @property
    def ntimes(self):
        """Number of times (i.e. rows) in this table"""
        return self._obj["gain"].shape[0]

    @property
    def nants(self):
        """Number of dishes/stations"""
        return self._obj["gain"].shape[1]

    @property
    def nchan(self):
        """Number of channels"""
        return self._obj["gain"].shape[2]

    @property
    def nrec(self):
        """Number of receivers"""
        return len(self._obj["receptor1"])

    @property
    def receptors(self):
        """Receptors"""
        return self._obj["receptor1"]

class PointingTable(xarray.Dataset):
    """Pointing table with data_models: time, antenna, offset[:, chan, rec, 2], weight columns

    Here is an example::

        <xarray.PointingTable>
        Dimensions:    (angle: 2, antenna: 115, frequency: 3, receptor: 2, time: 3)
        Coordinates:
          * time       (time) float64 5.085e+09 5.085e+09 5.085e+09
          * antenna    (antenna) int64 0 1 2 3 4 5 6 7 ... 108 109 110 111 112 113 114
          * frequency  (frequency) float64 1e+08 1.05e+08 1.1e+08
          * receptor   (receptor) <U1 'X' 'Y'
          * angle      (angle) <U2 'az' 'el'
        Data variables:
            pointing   (time, antenna, frequency, receptor, angle) float64 -0.0002627...
            nominal    (time, antenna, frequency, receptor, angle) float64 -3.142 ......
            weight     (time, antenna, frequency, receptor, angle) float64 1.0 ... 1.0
            residual   (time, frequency, receptor, angle) float64 0.0 0.0 ... 0.0 0.0
            interval   (time) float64 99.73 99.73 99.73
            datetime   (time) datetime64[ns] 2000-01-01T03:54:07.843184299 ... 2000-0...
        Attributes:
            rascil_data_model:  PointingTable
            receptor_frame:     <rascil.data_models.polarisation.ReceptorFrame object...
            pointing_frame:     azel
            pointingcentre:     <SkyCoord (ICRS): (ra, dec) in deg    (180., -35.)>
            configuration:      <xarray.Configuration> Dimensions:   (id: 115, spati...

    """

    __slots__ = ()

    def __init__(
        self,
        data=None,
        pointing: numpy.array = None,
        nominal: numpy.array = None,
        time: numpy.array = None,
        interval=None,
        weight: numpy.array = None,
        residual: numpy.array = None,
        frequency: numpy.array = None,
        receptor_frame: ReceptorFrame = ReceptorFrame("linear"),
        pointing_frame: str = "local",
        pointingcentre=None,
        configuration=None,
    ):
        """Create a pointing table from arrays

        :param data: Structured data (used in copying)
        :param pointing: Pointing (rad) [:, nants, nchan, nrec, 2]
        :param nominal: Nominal pointing (rad) [:, nants, nchan, nrec, 2]
        :param time: Centroid of solution [:]
        :param interval: Interval of validity
        :param weight: Weight [: nants, nchan, nrec]
        :param residual: Residual [: nants, nchan, nrec, 2]
        :param frequency: [nchan]
        :param receptor_frame: e.g. Receptor_frame("linear")
        :param pointing_frame: Pointing frame
        :param pointingcentre: SkyCoord
        :param configuration: Configuration
        """
        super().__init__()

        ntimes, nants, nchan, nrec, _ = pointing.shape
        antennas = range(nants)

        coords = {
            "time": time,
            "antenna": antennas,
            "frequency": frequency,
            "receptor": receptor_frame.names,
            "angle": ["az", "el"],
        }

        datavars = dict()
        datavars["pointing"] = xarray.DataArray(
            pointing, dims=["time", "antenna", "frequency", "receptor", "angle"]
        )
        datavars["nominal"] = xarray.DataArray(
            nominal, dims=["time", "antenna", "frequency", "receptor", "angle"]
        )
        datavars["weight"] = xarray.DataArray(
            weight, dims=["time", "antenna", "frequency", "receptor", "angle"]
        )
        datavars["residual"] = xarray.DataArray(
            residual, dims=["time", "frequency", "receptor", "angle"]
        )
        datavars["interval"] = xarray.DataArray(interval, dims=["time"])
        datavars["datetime"] = xarray.DataArray(
            Time(time / 86400.0, format="mjd", scale="utc").datetime64, dims="time"
        )

        attrs = dict()
        attrs["rascil_data_model"] = "PointingTable"
        attrs["receptor_frame"] = receptor_frame
        attrs["pointing_frame"] = pointing_frame
        attrs["pointingcentre"] = pointingcentre
        attrs["configuration"] = configuration

        super().__init__(datavars, coords=coords, attrs=attrs)

    def __sizeof__(self):
        """Override default method to return size of dataset
        :return: int
        """
        # Dask uses sizeof() class to get memory occupied by various data
        # objects. For custom data objects like this one, dask falls back to
        # sys.getsizeof() function to get memory usage. sys.getsizeof() in
        # turns calls __sizeof__() magic method to get memory size. Here we
        # override the default method (which gives size of reference table)
        # to return size of Dataset.
        return int(self.nbytes)

    def to_native_dataset(self):
        """
        Convert to plain Dataset. Needed, e.g., for xarray.concat.
        This makes sure that the child class is represented as its parent class.
        """
        # use-case:
        # RASCIL-defined classes that inherit from xarray.Dataset, do not
        # take attrs and an input argument; xarray.concat tries to call the
        # subclass with attrs arg, because it assumes that the subclass takes
        # the same args as the Dataset class; we need to manually accommodate for this
        return xarray.Dataset(self, coords=self.coords, attrs=self.attrs)

@xarray.register_dataset_accessor("pointingtable_acc")
class PointingTableAccessor(XarrayAccessorMixin):
    def __init__(self, xarray_obj):
        super().__init__(xarray_obj)

    @property
    def nants(self):
        """Number of dishes/stations"""
        return self._obj["pointing"].shape[1]

    @property
    def nchan(self):
        """Number of channels"""
        return len(self._obj["pointing"].frequency)

    @property
    def nrec(self):
        """Number of receptors"""
        return self.receptor_frame.nrec

class Image(xarray.Dataset):
    """Image class with pixels as an xarray.DataArray and the AstroPy`implementation of
    a World Coodinate System <http://docs.astropy.org/en/stable/wcs>`_

    The actual image values are kept in a data_var of the xarray.Dataset called "pixels"

    Many operations can be done conveniently using xarray processing_components on Image or on
    numpy operations on Image["pixels"].data. If the "pixels" data variable is chunked then
    Dask is automatically used whereever possible to distribute processing.

    Here is an example::

        <xarray.Image>
        Dimensions:       (chan: 3, pol: 4, x: 256, y: 256)
        Coordinates:
            frequency     (chan) float64 1e+08 1.01e+08 1.02e+08
            polarisation  (pol) <U1 'I' 'Q' 'U' 'V'
          * y             (y) float64 -35.11 -35.11 -35.11 ... -34.89 -34.89 -34.89
          * x             (x) float64 179.9 179.9 179.9 179.9 ... 180.1 180.1 180.1
            ra            (x, y) float64 180.1 180.1 180.1 180.1 ... 179.9 179.9 179.9
            dec           (x, y) float64 -35.11 -35.11 -35.11 ... -34.89 -34.89 -34.89
        Dimensions without coordinates: chan, pol
        Data variables:
            pixels        (chan, pol, y, x) float64 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0
        Attributes:
            rascil_data_model:  Image
            frame:              icrs

    """

    __slots__ = ()

    def __init__(self, data, polarisation_frame=None, wcs=None, clean_beam=None):
        """Create an Image

        Note that the spatial coordinates x, y are linear. ra, dec coordinates can be
        image via :py:func:`rascil.processing_components.image.operations.image_add_ra_dec_grid`

        The addition of ra, dec grid enables selections such as:

        secd = 1.0 / numpy.cos(numpy.deg2rad(im.dec_grid))
        r = numpy.hypot(
            (im.ra_grid - im.ra) * secd,
            im.dec_grid - im.image.dec,
        )
        show_image(im.where(r < 0.3, 0.0))
        plt.show()

        :param data: pixel values
        :param polarisation_frame: as a PolarisationFrame object
        :param wcs: WCS object
        :param clean_beam: dict e.g. {"bmaj":0.1, "bmin":0.05, "bpa":-60.0}. Units are deg, deg, deg
        :return: Image (i.e. xarray.Dataset)
        """
        super().__init__()

        nchan, npol, ny, nx = data.shape

        frequency = wcs.sub([4]).wcs_pix2world(range(nchan), 0)[0]
        cellsize = numpy.deg2rad(numpy.abs(wcs.wcs.cdelt[1]))
        ra = numpy.deg2rad(wcs.wcs.crval[0])
        dec = numpy.deg2rad(wcs.wcs.crval[1])

        # Define the dimensions
        dims = ["frequency", "polarisation", "y", "x"]

        # Define the coordinates on these dimensions
        coords = {
            "frequency": ("frequency", frequency),
            "polarisation": ("polarisation", polarisation_frame.names),
            "y": numpy.linspace(
                dec - cellsize * ny / 2, dec + cellsize * ny / 2, ny, endpoint=False
            ),
            "x": numpy.linspace(
                ra - cellsize * nx / 2, ra + cellsize * nx / 2, nx, endpoint=False
            ),
        }

        assert (
            data.shape[0] == nchan
        ), "Number of frequency channels {} and data shape {} are incompatible".format(
            len(frequency), data.shape
        )
        assert (
            data.shape[1] == npol
        ), "Polarisation frame {} and data shape {} are incompatible".format(
            polarisation_frame.type, data.shape
        )
        assert coords["x"][0] != coords["x"][-1]
        assert coords["y"][0] != coords["y"][-1]

        assert len(coords["y"]) == ny
        assert len(coords["x"]) == nx

        data_vars = dict()
        data_vars["pixels"] = xarray.DataArray(data, dims=dims, coords=coords)

        if isinstance(clean_beam, dict):
            for key in ["bmaj", "bmin", "bpa"]:
                if key not in clean_beam.keys():
                    raise KeyError(f"Image: clean_beam must have key {key}")

        attrs = {
            "rascil_data_model": "Image",
            "_polarisation_frame": polarisation_frame.type,
            "_projection": (wcs.wcs.ctype[0], wcs.wcs.ctype[1]),
            "spectral_type": wcs.wcs.ctype[3],
            "clean_beam": clean_beam,
            "refpixel": (wcs.wcs.crpix),
            "channel_bandwidth": wcs.wcs.cdelt[3],
            "ra": ra,
            "dec": dec,
        }

        super().__init__(data_vars, coords=coords, attrs=attrs)

    def __sizeof__(self):
        """Override default method to return size of dataset
        :return: int
        """
        # Dask uses sizeof() class to get memory occupied by various data
        # objects. For custom data objects like this one, dask falls back to
        # sys.getsizeof() function to get memory usage. sys.getsizeof() in
        # turns calls __sizeof__() magic method to get memory size. Here we
        # override the default method (which gives size of reference table)
        # to return size of Dataset.
        return int(self.nbytes)

    def to_native_dataset(self):
        """
        Convert to plain Dataset. Needed, e.g., for xarray.concat.
        This makes sure that the child class is represented as its parent class.
        """
        # use-case:
        # RASCIL-defined classes that inherit from xarray.Dataset, do not
        # take attrs and an input argument; xarray.concat tries to call the
        # subclass with attrs arg, because it assumes that the subclass takes
        # the same args as the Dataset class; we need to manually accommodate for this
        return xarray.Dataset(self, coords=self.coords, attrs=self.attrs)

@xarray.register_dataset_accessor("image_acc")
class ImageAccessor(XarrayAccessorMixin):
    def __init__(self, xarray_obj):
        super().__init__(xarray_obj)

    @property
    def shape(self):
        """Shape of array

        :return:
        """
        return self._obj["pixels"].data.shape

    @property
    def nchan(self):
        """Number of channels

        :return: Number of channels
        """
        return len(self._obj.frequency)

    @property
    def npol(self):
        """Number of polarisations

        :return: Number of polarisations
        """
        return PolarisationFrame(self._obj.attrs["_polarisation_frame"]).npol

    @property
    def polarisation_frame(self):
        """Polarisation frame (from coords)

        :return:
        """
        return PolarisationFrame(self._obj.attrs["_polarisation_frame"])

    @property
    def projection(self):
        """Projection (from coords)

        :return:
        """
        return self._obj.attrs["_projection"]

    @property
    def phasecentre(self):
        """Return the phasecentre as a SkyCoord

        :return:
        """
        return SkyCoord(
            numpy.rad2deg(self._obj.attrs["ra"]) * u.deg,
            numpy.rad2deg(self._obj.attrs["dec"]) * u.deg,
            frame="icrs",
            equinox="J2000",
        )

    @property
    def wcs(self):
        """Return the equivalent WCS

        :return:
        """
        return image_wcs(self._obj)

class GridData(xarray.Dataset):
    """Class to hold Gridded data for Fourier processing
    - Has four or more coordinates: [chan, pol, z, y, x] where x can be u, l; y can be v, m; z can be w, n

    The conventions for indexing in WCS and numpy are opposite.
    - In astropy.wcs, the order is (longitude, latitude, polarisation, frequency)
    - in numpy, the order is (frequency, polarisation, depth, latitude, longitude)

    .. warning::
        The polarisation_frame is kept in two places, the WCS and the polarisation_frame
        variable. The latter should be considered definitive.

    Here is an example::

        <xarray.Image>
        Dimensions:       (chan: 3, l: 256, m: 256, pol: 4)
        Coordinates:
            frequency     (chan) float64 1e+08 1.01e+08 1.02e+08
            polarisation  (pol) <U1 'I' 'Q' 'U' 'V'
          * m             (m) float64 -35.11 -35.11 -35.11 ... -34.89 -34.89 -34.89
          * l             (l) float64 179.9 179.9 179.9 179.9 ... 180.1 180.1 180.1
            ra            (l, m) float64 180.1 180.1 180.1 180.1 ... 179.9 179.9 179.9
            dec           (l, m) float64 -35.11 -35.11 -35.11 ... -34.89 -34.89 -34.89
        Dimensions without coordinates: chan, pol
        Data variables:
            pixels        (chan, pol, m, l) float64 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0
        Attributes:
            rascil_data_model:  Image

    """

    __slots__ = ()

    def __init__(self, data, polarisation_frame=None, grid_wcs=None):
        """Create a GridData

        :param polarisation_frame:
        :return: GridData
        """

        super().__init__()

        nchan, npol, nv, nu = data.shape

        frequency = grid_wcs.sub([4]).wcs_pix2world(range(nchan), 0)[0]

        assert npol == polarisation_frame.npol
        cu = grid_wcs.wcs.crval[0]
        cv = grid_wcs.wcs.crval[1]
        du = grid_wcs.wcs.cdelt[0]
        dv = grid_wcs.wcs.cdelt[1]

        dims = ["frequency", "polarisation", "u", "v"]

        # Define the coordinates on these dimensions
        coords = {
            "frequency": frequency,
            "polarisation": polarisation_frame.names,
            "v": numpy.linspace(cv - dv * nv / 2, cv + dv * nv / 2, nv, endpoint=False),
            "u": numpy.linspace(cu - du * nu / 2, cu + du * nu / 2, nu, endpoint=False),
        }

        attrs = dict()

        attrs["rascil_data_model"] = "GridData"
        attrs["_polarisation_frame"] = polarisation_frame.type

        data_vars = dict()
        data_vars["pixels"] = xarray.DataArray(data, dims=dims, coords=coords)
        super().__init__(data_vars, coords=coords, attrs=attrs)

    def __sizeof__(self):
        """Override default method to return size of dataset
        :return: int
        """
        # Dask uses sizeof() class to get memory occupied by various data
        # objects. For custom data objects like this one, dask falls back to
        # sys.getsizeof() function to get memory usage. sys.getsizeof() in
        # turns calls __sizeof__() magic method to get memory size. Here we
        # override the default method (which gives size of reference table)
        # to return size of Dataset.
        return int(self.nbytes)

    def to_native_dataset(self):
        """
        Convert to plain Dataset. Needed, e.g., for xarray.concat.
        This makes sure that the child class is represented as its parent class.
        """
        # use-case:
        # RASCIL-defined classes that inherit from xarray.Dataset, do not
        # take attrs and an input argument; xarray.concat tries to call the
        # subclass with attrs arg, because it assumes that the subclass takes
        # the same args as the Dataset class; we need to manually accommodate for this
        return xarray.Dataset(self, coords=self.coords, attrs=self.attrs)

@xarray.register_dataset_accessor("griddata_acc")
class GridDataAccessor(XarrayAccessorMixin):
    def __init__(self, xarray_obj):
        super().__init__(xarray_obj)

    @property
    def nchan(self):
        """Number of channels"""
        return len(self._obj.frequency)

    def npol(self):
        """Number of polarisations

        :return: Number of polarisations
        """
        return PolarisationFrame(self._obj.attrs["_polarisation_frame"]).npol

    @property
    def polarisation_frame(self):
        """Polarisation frame (from coords)

        :return:
        """
        return PolarisationFrame(self._obj.attrs["_polarisation_frame"])

    @property
    def shape(self):
        """Shape of data array"""
        return self._obj["pixels"].data.shape

    @property
    def griddata_wcs(self):
        """Return the equivalent WCS

        :return:
        """
        return griddata_wcs(self._obj)

    @property
    def projection_wcs(self):
        """Return the equivalent WCS

        :return:
        """
        return image_wcs(self._obj)

class ConvolutionFunction(xarray.Dataset):
    """Class to hold Convolution function for Fourier processing
    - Has four or more coordinates: [chan, pol, z, y, x] where x can be u, l; y can be v, m; z can be w, n

    The cf has axes [chan, pol, dy, dx, y, x] where z, y, x are spatial axes in either sky or Fourier plane. The
    order in the WCS is reversed so the grid_WCS describes UU, VV, WW, STOKES, FREQ axes

    The axes UU,VV have the same physical stride as the image, The axes DUU, DVV are subsampled.

    Convolution function holds the original sky plane projection in the projection_wcs.

    Here is an example::

        <xarray.ConvolutionFunction>
        Dimensions:       (du: 8, dv: 8, frequency: 1, polarisation: 1, u: 16, v: 16, w: 1)
        Coordinates:
          * frequency     (frequency) float64 1e+08
          * polarisation  (polarisation) <U1 'I'
          * w             (w) float64 0.0
          * dv            (dv) float64 -1.031e+05 -7.735e+04 ... 5.157e+04 7.735e+04
          * du            (du) float64 -1.031e+05 -7.735e+04 ... 5.157e+04 7.735e+04
          * v             (v) float64 -1.65e+06 -1.444e+06 ... 1.238e+06 1.444e+06
          * u             (u) float64 -1.65e+06 -1.444e+06 ... 1.238e+06 1.444e+06
        Data variables:
            pixels        (frequency, polarisation, w, dv, du, v, u) complex128 0j .....
        Attributes:
            rascil_data_model:   ConvolutionFunction
            grid_wcs:            WCS Keywords Number of WCS axes: 7 CTYPE : 'UU' ...
            projection_wcs:      WCS Keywords Number of WCS axes: 4 CTYPE : 'RA--...
            polarisation_frame:  stokesI

    """

    __slots__ = ()

    def __init__(self, data, cf_wcs=None, polarisation_frame=None):
        """Create ConvolutionFunction

        :param data: Data for cf
        :param cf_wcs: Astropy WCS object for the grid
        :param polarisation_frame: Polarisation_frame e.g. PolarisationFrame('linear')
        """

        super().__init__()

        nchan, npol, nw, oversampling, _, support, _ = data.shape
        frequency = cf_wcs.sub(["spectral"]).wcs_pix2world(range(nchan), 0)[0]

        assert (
            npol == polarisation_frame.npol
        ), "Mismatch between requested image polarisation and actual visibility polarisation"

        du = cf_wcs.wcs.cdelt[0]
        dv = cf_wcs.wcs.cdelt[1]
        ddu = cf_wcs.wcs.cdelt[0] / oversampling
        ddv = cf_wcs.wcs.cdelt[1] / oversampling
        cu = cf_wcs.wcs.crval[0]
        cv = cf_wcs.wcs.crval[1]
        cdu = oversampling // 2
        cdv = oversampling // 2

        wstep = numpy.abs(cf_wcs.wcs.cdelt[4])

        coords = {
            "frequency": frequency,
            "polarisation": polarisation_frame.names,
            "dv": numpy.linspace(
                cdv - ddv * oversampling / 2,
                cdv + ddv * oversampling / 2,
                oversampling,
                endpoint=False,
            ),
            "du": numpy.linspace(
                cdu - ddu * oversampling / 2,
                cdu + ddu * oversampling / 2,
                oversampling,
                endpoint=False,
            ),
            "w": numpy.linspace(-wstep * nw / 2, wstep * nw / 2, nw, endpoint=False),
            "v": numpy.linspace(
                cv - dv * support / 2, cv + dv * support / 2, support, endpoint=False
            ),
            "u": numpy.linspace(
                cu - du * support / 2, cu + du * support / 2, support, endpoint=False
            ),
        }

        if nw == 1:
            coords["w"]: numpy.zeros([1])

        dims = ["frequency", "polarisation", "w", "dv", "du", "u", "v"]

        assert coords["u"][0] != coords["u"][-1]
        assert coords["v"][0] != coords["v"][-1]

        attrs = dict()
        attrs["rascil_data_model"] = "ConvolutionFunction"
        attrs["_polarisation_frame"] = polarisation_frame.type

        nchan = len(frequency)
        npol = polarisation_frame.npol
        if data is None:
            data = numpy.zeros(
                [nchan, npol, nw, oversampling, oversampling, support, support],
                dtype="complex",
            )
        else:
            assert data.shape == (
                nchan,
                npol,
                nw,
                oversampling,
                oversampling,
                support,
                support,
            ), "Polarisation frame {} and data shape {} are incompatible".format(
                polarisation_frame.type, data.shape
            )
        data_vars = dict()
        data_vars["pixels"] = xarray.DataArray(data, dims=dims, coords=coords)
        super().__init__(data_vars, coords=coords, attrs=attrs)

    def __sizeof__(self):
        """Override default method to return size of dataset
        :return: int
        """
        # Dask uses sizeof() class to get memory occupied by various data
        # objects. For custom data objects like this one, dask falls back to
        # sys.getsizeof() function to get memory usage. sys.getsizeof() in
        # turns calls __sizeof__() magic method to get memory size. Here we
        # override the default method (which gives size of reference table)
        # to return size of Dataset.
        return int(self.nbytes)

    def to_native_dataset(self):
        """
        Convert to plain Dataset. Needed, e.g., for xarray.concat.
        This makes sure that the child class is represented as its parent class.
        """
        # use-case:
        # RASCIL-defined classes that inherit from xarray.Dataset, do not
        # take attrs and an input argument; xarray.concat tries to call the
        # subclass with attrs arg, because it assumes that the subclass takes
        # the same args as the Dataset class; we need to manually accommodate for this
        return xarray.Dataset(self, coords=self.coords, attrs=self.attrs)

@xarray.register_dataset_accessor("convolutionfunction_acc")
class ConvolutionFunctionAccessor(XarrayAccessorMixin):
    def __init__(self, xarray_obj):
        super().__init__(xarray_obj)

    @property
    def nchan(self):
        """Number of channels"""
        return len(self._obj.frequency)

    @property
    def npol(self):
        """Number of polarisations"""
        return PolarisationFrame(self._obj.attrs["_polarisation_frame"]).npol

    @property
    def cf_wcs(self):
        """Return the equivalent WCS

        :return:
        """
        return cf_wcs(self._obj)

    @property
    def shape(self):
        """Shape of data array"""
        return self._obj["pixels"].data.shape

    @property
    def polarisation_frame(self):
        """Polarisation frame (from coords)

        :return:
        """
        return PolarisationFrame(self._obj.attrs["_polarisation_frame"])

class Skycomponent:
    """Skycomponents are used to represent compact sources on the sky. They possess direction,
    flux as a function of frequency and polarisation, shape (with params), and polarisation frame.

    For example, the following creates and predicts the visibility from a collection of point sources
    drawn from the GLEAM catalog::

        sc = create_low_test_skycomponents_from_gleam(flux_limit=1.0,
                                                    polarisation_frame=PolarisationFrame("stokesIQUV"),
                                                    frequency=frequency, kind='cubic',
                                                    phasecentre=phasecentre,
                                                    radius=0.1)
        model = create_image_from_visibility(vis, cellsize=0.001, npixel=512, frequency=frequency,
                                            polarisation_frame=PolarisationFrame('stokesIQUV'))

        bm = create_low_test_beam(model=model)
        sc = apply_beam_to_skycomponent(sc, bm)
        vis = dft_skycomponent_visibility(vis, sc)
    """

    def __init__(
        self,
        direction=None,
        frequency=None,
        name=None,
        flux=None,
        shape="Point",
        polarisation_frame=PolarisationFrame("stokesIQUV"),
        params=None,
    ):
        """Define the required structure

        :param direction: SkyCoord
        :param frequency: numpy.array [nchan]
        :param name: user friendly name
        :param flux: numpy.array [nchan, npol]
        :param shape: str e.g. 'Point' 'Gaussian'
        :param polarisation_frame: Polarisation_frame e.g. PolarisationFrame('stokesIQUV')
        :param params: numpy.array shape dependent parameters
        """

        self.direction = direction
        self.frequency = numpy.array(frequency)
        self.name = name
        self.flux = numpy.array(flux)
        self.shape = shape
        if params is None:
            params = {}
        self.params = params
        self.polarisation_frame = polarisation_frame

        assert len(self.frequency.shape) == 1, frequency
        assert len(self.flux.shape) == 2, flux
        assert (
            self.frequency.shape[0] == self.flux.shape[0]
        ), "Frequency shape %s, flux shape %s" % (self.frequency.shape, self.flux.shape)
        assert (
            polarisation_frame.npol == self.flux.shape[1]
        ), "Polarisation is %s, flux shape %s" % (
            polarisation_frame.type,
            self.flux.shape,
        )

    @property
    def nchan(self):
        """Number of channels"""
        return self.flux.shape[0]

    @property
    def npol(self):
        """Number of polarisations"""
        return self.flux.shape[1]

    def __str__(self):
        """Default printer for Skycomponent"""
        s = "Skycomponent:\n"
        s += "\tName: %s\n" % self.name
        s += "\tFlux: %s\n" % self.flux
        s += "\tFrequency: %s\n" % self.frequency
        s += "\tDirection: %s\n" % self.direction
        s += "\tShape: %s\n" % self.shape

        s += "\tParams: %s\n" % self.params
        s += "\tPolarisation frame: %s\n" % str(self.polarisation_frame.type)
        return s

class SkyModel:
    """A model for the sky, including an image, components, gaintable and a mask"""

    def __init__(
        self, image=None, components=None, gaintable=None, mask=None, fixed=False
    ):
        """A model of the sky as an image, components, gaintable and a mask

        Use copy_skymodel to make a proper copy of skymodel
        :param image: Image
        :param components: List of components
        :param gaintable: Gaintable for this skymodel
        :param mask: Mask for the image
        :param fixed: Is this model fixed?
        """
        if components is None:
            components = []

        # if image is not None:
        ##assert isinstance(image, Image), image
        self.image = image

        self.components = [sc for sc in components]
        self.gaintable = gaintable

        # if mask is not None:
        #    #assert isinstance(mask, Image), mask
        self.mask = mask

        self.fixed = fixed

    def __sizeof__(self):
        """Override default method to return size of dataset
        :return: int
        """
        # Dask uses sizeof() class to get memory occupied by various data
        # objects. For custom data objects like this one, dask falls back to
        # sys.getsizeof() function to get memory usage. sys.getsizeof() in
        # turns calls __sizeof__() magic method to get memory size. Here we
        # override the default method (which gives size of reference table)
        # to return size of Dataset.

        # Get size of reference tables
        obj_size = int(super().__sizeof__())

        # Add size of image data object
        if self.image is not None:
            obj_size += int(self.image.nbytes)

        # Add size of gaintable data object
        if self.gaintable is not None:
            obj_size += int(self.gaintable.nbytes)

        # Add size of gaintable data object
        if self.mask is not None:
            obj_size += int(self.mask.nbytes)

        return obj_size

    def __str__(self):
        """Default printer for SkyModel"""
        s = "SkyModel: fixed: %s\n" % self.fixed
        for i, sc in enumerate(self.components):
            s += str(sc)
        s += "\n"

        s += str(self.image)
        s += "\n"

        s += str(self.mask)
        s += "\n"

        s += str(self.gaintable)

        return s

class BlockVisibility(xarray.Dataset):
    """BlockVisibility xarray Dataset class

    BlockVisibility is defined to hold an observation with one direction.

    The phasecentre is the direct of delay tracking i.e. n=0. If uvw are rotated then this
    should be updated with the new delay tracking centre.

    Polarisation frame is the same for the entire data set and can be stokesI, circular, circularnp, linear, linearnp

    The configuration is stored as an attribute.

    Here is an example::

        <xarray.BlockVisibility>
        Dimensions:            (baselines: 6670, frequency: 3, polarisation: 4, time: 3, uvw_index: 3)
        Coordinates:
          * time               (time) float64 5.085e+09 5.085e+09 5.085e+09
          * baselines          (baselines) MultiIndex
          - antenna1           (baselines) int64 0 0 0 0 0 0 ... 112 112 112 113 113 114
          - antenna2           (baselines) int64 0 1 2 3 4 5 ... 112 113 114 113 114 114
          * frequency          (frequency) float64 1e+08 1.05e+08 1.1e+08
          * polarisation       (polarisation) <U2 'XX' 'XY' 'YX' 'YY'
          * uvw_index          (uvw_index) <U1 'u' 'v' 'w'
        Data variables:
            integration_time   (time) float32 99.72697 99.72697 99.72697
            datetime           (time) datetime64[ns] 2000-01-01T03:54:07.843184299 .....
            vis                (time, baselines, frequency, polarisation) complex128 ...
            weight             (time, baselines, frequency, polarisation) float32 0.0...
            imaging_weight     (time, baselines, frequency, polarisation) float32 0.0...
            flags              (time, baselines, frequency, polarisation) int32 0.0...
            uvw                (time, baselines, uvw_index) float64 0.0 0.0 ... 0.0 0.0
            uvw_lambda         (time, baselines, frequency, uvw_index) float64 0.0 .....
            uvdist_lambda      (time, baselines, frequency) float64 0.0 0.0 ... 0.0 0.0
            channel_bandwidth  (frequency) float64 1e+07 1e+07 1e+07
        Attributes:
            phasecentre:         <SkyCoord (ICRS): (ra, dec) in deg    (180., -35.)>
            configuration:       <xarray.Configuration>Dimensions:   (id: 115, spat...
            polarisation_frame:  linear
            source:              unknown
            meta:                None

    """

    __slots__ = ()

    def __init__(
        self,
        frequency=None,
        channel_bandwidth=None,
        phasecentre=None,
        configuration=None,
        uvw=None,
        time=None,
        vis=None,
        weight=None,
        integration_time=None,
        flags=None,
        baselines=None,
        polarisation_frame=PolarisationFrame("stokesI"),
        imaging_weight=None,
        source="anonymous",
        meta=None,
        low_precision="float64",
    ):
        """BlockVisibility

        :param frequency: Frequency [nchan]
        :param channel_bandwidth: Channel bandwidth [nchan]
        :param phasecentre: Phasecentre (SkyCoord)
        :param configuration: Configuration
        :param uvw: UVW coordinates (m) [:, nant, nant, 3]
        :param time: Time (UTC) [:]
        :param baselines: List of baselines
        :param flags: Flags [:, nant, nant, nchan]
        :param weight: [:, nant, nant, nchan, npol]
        :param imaging_weight: [:, nant, nant, nchan, npol]
        :param integration_time: Integration time [:]
        :param polarisation_frame: Polarisation_Frame e.g. Polarisation_Frame("linear")
        :param source: Source name
        :param meta: Meta info
        """

        super().__init__()

        if weight is None:
            weight = numpy.ones(vis.shape)
        else:
            assert weight.shape == vis.shape

        if imaging_weight is None:
            imaging_weight = weight
        else:
            assert imaging_weight.shape == vis.shape

        if integration_time is None:
            integration_time = numpy.ones_like(time)
        else:
            assert len(integration_time) == len(time)

        k = (frequency / const.c).value
        if len(frequency) == 1:
            uvw_lambda = (uvw * k)[..., numpy.newaxis, :]
        else:
            uvw_lambda = numpy.einsum("tbs,k->tbks", uvw, k)

        nchan = len(frequency)
        npol = polarisation_frame.npol
        # Define the names of the dimensions

        coords = {
            "time": time,
            "baselines": baselines,
            "frequency": frequency,
            "polarisation": polarisation_frame.names,
            "spatial": ["u", "v", "w"],
        }

        datavars = dict()
        datavars["integration_time"] = xarray.DataArray(
            integration_time.astype(low_precision), dims=["time"], attrs={"units": "s"}
        )
        datavars["datetime"] = xarray.DataArray(
            Time(time / 86400.0, format="mjd", scale="utc").datetime64,
            dims=["time"],
            attrs={"units": "s"},
        )
        datavars["vis"] = xarray.DataArray(
            vis,
            dims=["time", "baselines", "frequency", "polarisation"],
            attrs={"units": "Jy"},
        )
        datavars["weight"] = xarray.DataArray(
            weight.astype(low_precision),
            dims=["time", "baselines", "frequency", "polarisation"],
        )
        datavars["imaging_weight"] = xarray.DataArray(
            imaging_weight.astype(low_precision),
            dims=["time", "baselines", "frequency", "polarisation"],
        )
        datavars["flags"] = xarray.DataArray(
            flags.astype(int),
            dims=["time", "baselines", "frequency", "polarisation"],
        )
        datavars["uvw"] = xarray.DataArray(
            uvw, dims=["time", "baselines", "spatial"], attrs={"units": "m"}
        )

        datavars["uvw_lambda"] = xarray.DataArray(
            uvw_lambda,
            dims=["time", "baselines", "frequency", "spatial"],
            attrs={"units": "lambda"},
        )
        datavars["uvdist_lambda"] = xarray.DataArray(
            numpy.hypot(uvw_lambda[..., 0], uvw_lambda[..., 1]),
            dims=["time", "baselines", "frequency"],
            attrs={"units": "lambda"},
        )

        datavars["channel_bandwidth"] = xarray.DataArray(
            channel_bandwidth, dims=["frequency"], attrs={"units": "Hz"}
        )

        attrs = dict()
        attrs["rascil_data_model"] = "BlockVisibility"
        attrs["configuration"] = configuration  # Antenna/station configuration
        attrs["source"] = source
        attrs["phasecentre"] = phasecentre
        attrs["_polarisation_frame"] = polarisation_frame.type
        attrs["meta"] = meta

        super().__init__(datavars, coords=coords, attrs=attrs)

    def __sizeof__(self):
        """Override default method to return size of dataset
        :return: int
        """
        # Dask uses sizeof() class to get memory occupied by various data
        # objects. For custom data objects like this one, dask falls back to
        # sys.getsizeof() function to get memory usage. sys.getsizeof() in
        # turns calls __sizeof__() magic method to get memory size. Here we
        # override the default method (which gives size of reference table)
        # to return size of Dataset.
        return int(self.nbytes)

    def to_native_dataset(self):
        """
        Convert to plain Dataset. Needed, e.g., for xarray.concat.
        This makes sure that the child class is represented as its parent class.
        """
        # use-case:
        # RASCIL-defined classes that inherit from xarray.Dataset, do not
        # take attrs and an input argument; xarray.concat tries to call the
        # subclass with attrs arg, because it assumes that the subclass takes
        # the same args as the Dataset class; we need to manually accommodate for this
        return xarray.Dataset(self, coords=self.coords, attrs=self.attrs)

@xarray.register_dataset_accessor("blockvisibility_acc")
class BlockVisibilityAccessor(XarrayAccessorMixin):
    def __init__(self, xarray_obj):
        super().__init__(xarray_obj)

    @property
    def rows(self):
        """Rows"""
        return range(len(self._obj.time))

    @property
    def ntimes(self):
        """Number of times (i.e. rows) in this table"""
        return len(self._obj["time"])

    @property
    def nchan(self):
        """Number of channels"""
        return len(self._obj["frequency"])

    @property
    def npol(self):
        """Number of polarisations"""
        return len(self._obj.polarisation)

    @property
    def polarisation_frame(self):
        """Polarisation frame (from coords)

        :return:
        """
        return PolarisationFrame(self._obj.attrs["_polarisation_frame"])

    @property
    def nants(self):
        """Number of antennas"""
        return self._obj.configuration.configuration_acc.nants

    @property
    def nbaselines(self):
        """Number of Baselines"""
        return len(self._obj["baselines"])

    @property
    def u(self):
        """u coordinate (metres) [nrows, nbaseline]"""
        return self._obj["uvw"][..., 0]

    @property
    def v(self):
        """v coordinate (metres) [nrows, nbaseline]"""
        return self._obj["uvw"][..., 1]

    @property
    def w(self):
        """w coordinate (metres) [nrows, nbaseline]"""
        return self._obj["uvw"][..., 2]

    @property
    def u_lambda(self):
        """u coordinate (wavelengths) [nrows, nbaseline]"""
        return self._obj["uvw_lambda"][..., 0]

    @property
    def v_lambda(self):
        """v coordinate (wavelengths) [nrows, nbaseline]"""
        return self._obj["uvw_lambda"][..., 1]

    @property
    def w_lambda(self):
        """w coordinate (wavelengths) [nrows, nbaseline]"""
        return self._obj["uvw_lambda"][..., 2]

    @property
    def uvdist(self):
        """uv distance (metres) [nrows, nbaseline]"""
        return numpy.hypot(self.u, self.v)

    @property
    def uvdist_lambda(self):
        """uv distance (metres) [nrows, nbaseline]"""
        return numpy.hypot(self.u_lambda, self.v_lambda)

    @property
    def uvwdist(self):
        """uv distance (metres) [nrows, nbaseline]"""
        return numpy.hypot(self.u, self.v, self.w)

    @property
    def flagged_vis(self):
        """Flagged complex visibility [nrows, nbaseline, nchan, npol]

        Note that a numpy or dask array is returned, not an xarray dataarray
        """
        return self._obj["vis"].data * (1 - self._obj["flags"].data)

    @property
    def flagged_weight(self):
        """Weight [: npol]

        Note that a numpy or dask array is returned, not an xarray dataarray
        """
        return self._obj["weight"].data * (1 - self._obj["flags"].data)

    @property
    def flagged_imaging_weight(self):
        """Flagged Imaging_weight[nrows, nbaseline, nchan, npol]

        Note that a numpy or dask array is returned, not an xarray dataarray
        """
        return self._obj["imaging_weight"].data * (1 - self._obj["flags"].data)

    @property
    def nvis(self):
        """Number of visibilities (in total)"""
        return numpy.product(self._obj.vis.shape)

class FlagTable(xarray.Dataset):
    """Flag table class

    Flags, time, integration_time, frequency, channel_bandwidth, pol,
    in an xarray.

    The configuration is also an attribute
    """

    __slots__ = ()

    def __init__(
        self,
        baselines=None,
        flags=None,
        frequency=None,
        channel_bandwidth=None,
        configuration=None,
        time=None,
        integration_time=None,
        polarisation_frame=None,
    ):
        """FlagTable

        :param frequency: Frequency [nchan]
        :param channel_bandwidth: Channel bandwidth [nchan]
        :param configuration: Configuration
        :param time: Time (UTC) [ntimes]
        :param flags: Flags [ntimes, nbaseline, nchan]
        :param integration_time: Integration time [ntimes]
        """
        super().__init__()

        coords = {
            "time": time,
            "baselines": baselines,
            "frequency": frequency,
            "polarisation": polarisation_frame.names,
        }

        datavars = dict()
        datavars["flags"] = xarray.DataArray(
            flags, dims=["time", "baselines", "frequency", "polarisation"]
        )
        datavars["integration_time"] = xarray.DataArray(integration_time, dims=["time"])
        datavars["channel_bandwidth"] = xarray.DataArray(
            channel_bandwidth, dims=["frequency"]
        )
        datavars["datetime"] = xarray.DataArray(
            Time(time / 86400.0, format="mjd", scale="utc").datetime64, dims="time"
        )

        attrs = dict()
        attrs["rascil_data_model"] = "FlagTable"
        attrs["_polarisation_frame"] = polarisation_frame.type
        attrs["configuration"] = configuration  # Antenna/station configuration

        super().__init__(datavars, coords=coords, attrs=attrs)

    def __sizeof__(self):
        """Override default method to return size of dataset
        :return: int
        """
        # Dask uses sizeof() class to get memory occupied by various data
        # objects. For custom data objects like this one, dask falls back to
        # sys.getsizeof() function to get memory usage. sys.getsizeof() in
        # turns calls __sizeof__() magic method to get memory size. Here we
        # override the default method (which gives size of reference table)
        # to return size of Dataset.
        return int(self.nbytes)

    def to_native_dataset(self):
        """
        Convert to plain Dataset. Needed, e.g., for xarray.concat.
        This makes sure that the child class is represented as its parent class.
        """
        # use-case:
        # RASCIL-defined classes that inherit from xarray.Dataset, do not
        # take attrs and an input argument; xarray.concat tries to call the
        # subclass with attrs arg, because it assumes that the subclass takes
        # the same args as the Dataset class; we need to manually accommodate for this
        return xarray.Dataset(self, coords=self.corords, attrs=self.attrs)

@xarray.register_dataset_accessor("flagtable_acc")
class FlagTableAccessor(XarrayAccessorMixin):
    def __init__(self, xarray_obj):
        super().__init__(xarray_obj)

    @property
    def nchan(self):
        """Number of channels"""
        return len(self._obj["frequency"])

    @property
    def npol(self):
        """Number of polarisations"""
        return self.polarisation_frame.npol

    @property
    def polarisation_frame(self):
        """Polarisation frame (from coords)

        :return:
        """
        return PolarisationFrame(self._obj.attrs["_polarisation_frame"])

    @property
    def nants(self):
        """Number of antennas"""
        return self.attrs["configuration"].configuration_acc.nants

    @property
    def nbaselines(self):
        """Number of Baselines"""
        return len(self["baselines"])

class QA:
    """Quality assessment

    :param origin: str, origin e.g. "continuum_imaging_pipeline"
    :param data: Data containing standard fields
    :param context: Context of QA e.g. "Cycle 5"

    """

    def __init__(self, origin=None, data=None, context=None):
        """QA

        :param origin:
        :param data:
        :param context:
        """
        self.origin = origin  # Name of function originating QA assessment
        self.data = data  # Dictionary containing standard fields
        self.context = context  # Context string

    def __str__(self):
        """Default printer for QA"""
        s = "Quality assessment:\n"
        s += "\tOrigin: %s\n" % self.origin
        s += "\tContext: %s\n" % self.context
        s += "\tData:\n"
        for dataname in self.data.keys():
            s += "\t\t%s: %r\n" % (dataname, str(self.data[dataname]))
        return s

class ScienceDataModel:
    """Science Data Model: not defined yet"""

    def __init__(self):
        pass

    def __str__(self):
        """Default printer for Science Data Model"""
        return ""