text:
import os
import numpy as np
import tensorflow as tf
from base_model import Model
from params_init import random_uniform_initializer, random_normal_initializer, xavier_initializer, \
    random_truncated_normal_initializer
from utils.general_utils import Progbar
from utils.general_utils import get_minibatches, print_confusion_matrix, write_wrong_predictions, get_weighted_f1_score
from utils.feature_extraction import DataConfig

class TextCNN(Model):
    """
    A CNN for text classification.
    Uses an embedding layer, followed by a convolutional, max-pooling and softmax layer.
    """

    # TODO change function invocations to include last 2 arguments
    def __init__(self, config, idx2label, word_embeddings, label2idx, char_embeddings):
        self.word_embeddings = word_embeddings
        self.char_embeddings = char_embeddings
        self.idx2label = idx2label
        self.class_names = map(lambda x: x[0], sorted(label2idx.items(), key=lambda x: x[1]))
        self.config = config
        self.build()

    def add_placeholders(self):

        with tf.variable_scope("input_placeholders"):
            self.word_input_placeholder = tf.placeholder(shape=[None, self.config.max_seq_len],
                                                         dtype=tf.int32, name="batch_word_indices")
        with tf.variable_scope("input_char_placeholders"):
            self.char_input_placeholder = tf.placeholder(
                shape=[None, self.config.max_seq_len, self.config.max_word_len],
                dtype=tf.int32, name="batch_char_indices")
        with tf.variable_scope("label_placeholders"):
            self.labels_placeholder = tf.placeholder(shape=[None, self.config.num_classes],
                                                     dtype=tf.float32, name="batch_one_hot_targets")
        with tf.variable_scope("word_regularization"):
            self.dropout_placeholder_word = tf.placeholder(shape=(), dtype=tf.float32, name="dropout")

        with tf.variable_scope("char_regularization"):
            self.dropout_placeholder_char = tf.placeholder(shape=(), dtype=tf.float32, name="dropout")

        with tf.variable_scope("fc_regularization"):
            self.dropout_placeholder_fc = tf.placeholder(shape=(), dtype=tf.float32, name="dropout")

        self.is_training = tf.placeholder(tf.bool, name='is_training')

        self.class_weights = tf.constant([self.config.class_weights], dtype=tf.float32)

    def create_feed_dict(self, inputs_batch, labels_batch=None, keep_prob_word=1, keep_prob_char=1, keep_prob_fc=1,
                         is_training=False):

        feed_dict = {
            self.word_input_placeholder: inputs_batch[0],
            self.char_input_placeholder: inputs_batch[1],
            self.dropout_placeholder_word: keep_prob_word,
            self.dropout_placeholder_char: keep_prob_char,
            self.dropout_placeholder_fc: keep_prob_fc,
            self.is_training: is_training
        }

        if labels_batch is not None:
            feed_dict[self.labels_placeholder] = labels_batch

        return feed_dict

    def gaussian_noise_layer(self, input_layer, std):
        noise = tf.random_normal(shape=tf.shape(input_layer), mean=0.0, stddev=std, dtype=tf.float32)
        return input_layer + noise

    def add_embedding(self):
        with tf.variable_scope("feature_lookup"):
            self.word_embedding_matrix = random_uniform_initializer(self.word_embeddings.shape, "word_embedding_matrix",
                                                                    0.01, trainable=True)

            self.char_embedding_matrix = random_uniform_initializer(self.char_embeddings.shape, "char_embedding_matrix",
                                                                    0.01, trainable=True)

            word_context_embeddings = tf.nn.embedding_lookup(self.word_embedding_matrix, self.word_input_placeholder)
            char_context_embeddings = tf.nn.embedding_lookup(self.char_embedding_matrix, self.char_input_placeholder)

            # temp = tf.cond(self.is_training, True, False)
            if self.config.add_gaussian_noise is True and self.is_training is not None:
                word_context_embeddings = tf.cond(self.is_training,
                                                  lambda: self.gaussian_noise_layer(word_context_embeddings, 0.1),
                                                  lambda: tf.identity(word_context_embeddings))
                char_context_embeddings = tf.cond(self.is_training,
                                                  lambda: self.gaussian_noise_layer(char_context_embeddings, 0.01),
                                                  lambda: tf.identity(char_context_embeddings))

            # [N, H, W] -> [N, H, W, C]
            word_context_embeddings_expanded = tf.expand_dims(word_context_embeddings, -1)
            char_context_embeddings_expanded = tf.expand_dims(char_context_embeddings, -1)

        return word_context_embeddings, word_context_embeddings_expanded, char_context_embeddings, char_context_embeddings_expanded

    """
    def add_prediction_op(self):
        print "***Building network with ReLU activation***"
        word_context_embeddings, word_context_embeddings_expanded, \
        char_context_embeddings, char_context_embeddings_expanded = self.add_embedding()

        # step - 1 :: CNN over characters
        pooled_char_outputs = []
        # char CNN
        for i, char_filter_size in enumerate(self.config.char_filter_sizes):
            with tf.variable_scope("char-conv-maxpool-%s" % char_filter_size):
                # Convolution Layer
                filter_shape = [1, char_filter_size, self.config.char_embedding_dim, 1,
                                self.config.char_num_filters]  # [H, W, in_c, out_c]

                # try xavior also
                # filter = random_truncated_normal_initializer(filter_shape, "filter", stddev=0.1)
                filter = tf.Variable(tf.truncated_normal(filter_shape, stddev=0.1), name="W")
                b = tf.Variable(tf.constant(0.1, shape=[self.config.char_num_filters]), name="conv_bias")

                conv = tf.nn.conv3d(
                    char_context_embeddings_expanded,
                    filter,
                    strides=[1, 1, 1, 1, 1],
                    padding="VALID",
                    name="conv")
                print "conv shape:", conv.get_shape().as_list()
                h = tf.nn.tanh(tf.nn.bias_add(conv, b), name="relu")  # [B, new_H, new_W, out_c]

                # h_batch_norm = tf.contrib.layers.batch_norm(h,
                #                                   center=True, scale=True,
                #                                   is_training=self.is_training,
                #                                   scope='bn')
                h_shape = h.get_shape().as_list()
                h_4d = tf.reshape(h, [-1, h_shape[2], h_shape[3], h_shape[4]], "char_4d_h")

                pooled = tf.nn.max_pool(
                    h_4d,
                    ksize=[1, self.config.max_word_len - char_filter_size + 1, 1, 1],  # why k_size[2] = 1?
                    strides=[1, 1, 1, 1],
                    padding='VALID',
                    name="pool")
                pooled_shape = pooled.get_shape().as_list()
                pooled_5d = tf.reshape(pooled,
                                       [-1, h_shape[1], pooled_shape[1], pooled_shape[2], pooled_shape[3]])

                pooled_char_outputs.append(pooled_5d)

        char_num_filters_total = self.config.char_num_filters * len(self.config.char_filter_sizes)
        self.h_pool_char = tf.concat(pooled_char_outputs, 4)  # collect across all output channels [B, T, o_h, o_w, o_c]
        self.h_pool_char_flat = tf.reshape(self.h_pool_char, [-1, self.config.max_seq_len,
                                                              char_num_filters_total])  # [B, T, num_features]

        # Step -2 :: Highway layer(s) over char-CNN
        if self.config.use_highway_layer:
            print("***Adding Highway Layer on top of char CNN***")
            curr_input = self.h_pool_char_flat
            for i in range(self.config.num_highway_layers):
                curr_input_2d = tf.reshape(curr_input, [-1, char_num_filters_total])
                # Highway Layer
                with tf.variable_scope("highway_layer_" + str(i + 1)):
                    with tf.variable_scope("transform_gate"):  # use negative bias = -1 (ref: paper, blogs)
                        W_T = xavier_initializer((char_num_filters_total, char_num_filters_total), "W_T")
                        # b_T = xavier_initializer((char_num_filters_total,), "bias_T")
                        b_T = tf.Variable(tf.constant(-2., shape=[char_num_filters_total, ]), name="bias_T")
                        activations_T = tf.nn.sigmoid(
                            tf.nn.xw_plus_b(curr_input_2d, W_T, b_T, name="transform_activations"))
                        print("transformed activations shape: {}".format(activations_T.get_shape().as_list()))

                    with tf.variable_scope("output_gate"):
                        W = xavier_initializer((char_num_filters_total, char_num_filters_total), "W")
                        b = xavier_initializer((char_num_filters_total,), "bias")
                        activations_output = tf.nn.relu(tf.nn.xw_plus_b(curr_input_2d, W, b,
                                                                        name="out_activations"))
                        print("output activations shape: {}".format(activations_output.get_shape().as_list()))

                    activations_carry = 1. - activations_T
                    highway_output = activations_T * activations_output + activations_carry * curr_input_2d
                    curr_input = highway_output
                    self.highway_output = tf.reshape(highway_output, [-1, self.config.max_seq_len,
                                                                      char_num_filters_total], name="highway_output")

        pooled_char_cnn_word_outputs = []
        if self.config.use_highway_layer:
            char_cnn_word_input = tf.expand_dims(self.highway_output, -1)
        else:
            char_cnn_word_input = tf.expand_dims(self.h_pool_char_flat, -1)

        # Step-3: word-CNN over representation obtained from char-CNN + optional Highway layer(s)
        for i, word_filter_size in enumerate(self.config.word_filter_sizes):
            with tf.variable_scope("char-CNN-word-conv-maxpool-%s" % word_filter_size):
                # Convolution Layer
                filter_shape = [word_filter_size, char_num_filters_total, 1,
                                self.config.word_num_filters]  # [H, W, in_c, out_c]

                # try xavior also
                # filter = random_truncated_normal_initializer(filter_shape, "filter", stddev=0.1)
                filter = tf.Variable(tf.truncated_normal(filter_shape, stddev=0.1), name="W")
                b = tf.Variable(tf.constant(0.1, shape=[self.config.word_num_filters]), name="conv_bias")

                conv = tf.nn.conv2d(
                    char_cnn_word_input,
                    filter,
                    strides=[1, 1, 1, 1],
                    padding="VALID",
                    name="conv")
                print "conv shape:", conv.get_shape().as_list()
                h = tf.nn.relu(tf.nn.bias_add(conv, b), name="relu")  # [B, new_H, new_W, out_c]

                # h_batch_norm = tf.contrib.layers.batch_norm(h,
                #                                   center=True, scale=True,
                #                                   is_training=self.is_training,
                #                                   scope='bn')

                pooled = tf.nn.max_pool(
                    h,
                    ksize=[1, self.config.max_seq_len - word_filter_size + 1, 1, 1],  # why k_size[2] = 1?
                    strides=[1, 1, 1, 1],
                    padding='VALID',
                    name="pool")
                pooled_char_cnn_word_outputs.append(pooled)

        # Combine all the pooled features
        word_num_filters_total = self.config.word_num_filters * len(self.config.word_filter_sizes)
        self.h_pool_char_cnn_word = tf.concat(pooled_char_cnn_word_outputs,
                                              3)  # collect across all output channels  [B, T, out_H, out_d]
        self.h_pool_char_cnn_word_2d = tf.reshape(self.h_pool_char_cnn_word,
                                                  [-1, word_num_filters_total])  # [B, num_features]

        # Step - 4: word-CNN over pre-trained embeddings
        pooled_word_outputs = []

        # word CNN
        for i, word_filter_size in enumerate(self.config.word_filter_sizes):
            with tf.variable_scope("word-conv-maxpool-%s" % word_filter_size):
                # Convolution Layer
                filter_shape = [word_filter_size, self.config.embedding_dim, 1,
                                self.config.word_num_filters]  # [H, W, in_c, out_c]

                # try xavior also
                # filter = random_truncated_normal_initializer(filter_shape, "filter", stddev=0.1)
                filter = tf.Variable(tf.truncated_normal(filter_shape, stddev=0.1), name="W")
                b = tf.Variable(tf.constant(0.1, shape=[self.config.word_num_filters]), name="conv_bias")

                conv = tf.nn.conv2d(
                    word_context_embeddings_expanded,
                    filter,
                    strides=[1, 1, 1, 1],
                    padding="VALID",
                    name="conv")
                print "conv shape:", conv.get_shape().as_list()
                h = tf.nn.relu(tf.nn.bias_add(conv, b), name="relu")  # [B, new_H, new_W, out_c]

                # h_batch_norm = tf.contrib.layers.batch_norm(h,
                #                                   center=True, scale=True,
                #                                   is_training=self.is_training,
                #                                   scope='bn')

                pooled = tf.nn.max_pool(
                    h,
                    ksize=[1, self.config.max_seq_len - word_filter_size + 1, 1, 1],  # why k_size[2] = 1?
                    strides=[1, 1, 1, 1],
                    padding='VALID',
                    name="pool")
                pooled_word_outputs.append(pooled)

        # Combine all the pooled features
        word_num_filters_total = self.config.word_num_filters * len(self.config.word_filter_sizes)
        self.h_pool_word = tf.concat(pooled_word_outputs,
                                     3)  # collect across all output channels  [B, T, out_H, out_d]
        self.h_pool_word_2d = tf.reshape(self.h_pool_word, [-1, word_num_filters_total])  # [B, num_features]

        # Step-5: concat features from both word CNN's
        self.batch_vectors = tf.concat([self.h_pool_char_cnn_word_2d, self.h_pool_word_2d],
                                       1)  # [B, num_features]

        feature_vec_len = self.batch_vectors.get_shape().as_list()[1]
        activations = self.batch_vectors

        # Step-6: FC layer + dropout
        if self.config.use_fc_layer:
            # Final (unnormalized) scores and predictions
            with tf.variable_scope("fc_layer"):
                W = xavier_initializer((feature_vec_len, self.config.fc_layer_dim), "W")
                b = xavier_initializer((self.config.fc_layer_dim,), "bias")
                activations = tf.nn.dropout(
                    tf.nn.relu(tf.nn.xw_plus_b(self.batch_vectors, W, b, name="prediction_logits")),
                    keep_prob=self.dropout_placeholder_fc)
            feature_vec_len = activations.get_shape().as_list()[1]

        # Step-7: softmax layer
        with tf.variable_scope("output_layer"):
            W1 = xavier_initializer((feature_vec_len, self.config.num_classes), "W")
            b1 = xavier_initializer((self.config.num_classes,), "bias")
            predictions = tf.nn.xw_plus_b(activations, W1, b1, name="prediction_logits")

        return predictions
    """

    def add_prediction_op(self):
        print "***Building network with ReLU activation***"
        word_context_embeddings, word_context_embeddings_expanded, \
        char_context_embeddings, char_context_embeddings_expanded = self.add_embedding()

        # step - 1 :: CNN over characters
        pooled_char_outputs = []
        # char CNN
        for i, char_filter_size in enumerate(self.config.char_filter_sizes):
            with tf.variable_scope("char-conv-maxpool-%s" % char_filter_size):
                # Convolution Layer
                filter_shape = [1, char_filter_size, self.config.char_embedding_dim, 1,
                                self.config.char_num_filters]  # [H, W, in_c, out_c]

                # try xavior also
                # filter = random_truncated_normal_initializer(filter_shape, "filter", stddev=0.1)
                filter = tf.Variable(tf.truncated_normal(filter_shape, stddev=0.1), name="W")
                b = tf.Variable(tf.constant(0.1, shape=[self.config.char_num_filters]), name="conv_bias")

                conv = tf.nn.conv3d(
                    char_context_embeddings_expanded,
                    filter,
                    strides=self.config.char_stride,
                    padding="VALID",
                    name="conv")
                print "conv shape:", conv.get_shape().as_list()
                h = tf.nn.tanh(tf.nn.bias_add(conv, b), name="relu")  # [B, new_H, new_W, out_c]

                # h_batch_norm = tf.contrib.layers.batch_norm(h,
                #                                   center=True, scale=True,
                #                                   is_training=self.is_training,
                #                                   scope='bn')
                h_shape = h.get_shape().as_list()
                h_4d = tf.reshape(h, [-1, h_shape[2], h_shape[3], h_shape[4]], "char_4d_h")

                pooled = tf.nn.max_pool(
                    h_4d,
                    ksize=[1, h_4d.get_shape().as_list()[1], 1, 1],  # why k_size[2] = 1?
                    strides=[1, 1, 1, 1],
                    padding='VALID',
                    name="pool")
                pooled_shape = pooled.get_shape().as_list()
                pooled_5d = tf.reshape(pooled,
                                       [-1, h_shape[1], pooled_shape[1], pooled_shape[2], pooled_shape[3]])

                pooled_char_outputs.append(pooled_5d)

        char_num_filters_total = self.config.char_num_filters * len(self.config.char_filter_sizes)
        self.h_pool_char = tf.concat(pooled_char_outputs, 4)  # collect across all output channels [B, T, o_h, o_w, o_c]
        self.h_pool_char_flat = tf.reshape(self.h_pool_char, [-1, self.config.max_seq_len,
                                                              char_num_filters_total])  # [B, T, num_features]

        # Step -2 :: Highway layer(s) over char-CNN
        if self.config.use_highway_layer:
            print("***Adding Highway Layer on top of char CNN***")
            curr_input = self.h_pool_char_flat
            for i in range(self.config.num_highway_layers):
                curr_input_2d = tf.reshape(curr_input, [-1, char_num_filters_total])
                # Highway Layer
                with tf.variable_scope("highway_layer_" + str(i + 1)):
                    with tf.variable_scope("transform_gate"):  # use negative bias = -1 (ref: paper, blogs)
                        W_T = xavier_initializer((char_num_filters_total, char_num_filters_total), "W_T")
                        # b_T = xavier_initializer((char_num_filters_total,), "bias_T")
                        b_T = tf.Variable(tf.constant(-2., shape=[char_num_filters_total, ]), name="bias_T")
                        activations_T = tf.nn.sigmoid(
                            tf.nn.xw_plus_b(curr_input_2d, W_T, b_T, name="transform_activations"))
                        print("transformed activations shape: {}".format(activations_T.get_shape().as_list()))

                    with tf.variable_scope("output_gate"):
                        W = xavier_initializer((char_num_filters_total, char_num_filters_total), "W")
                        b = xavier_initializer((char_num_filters_total,), "bias")
                        activations_output = tf.nn.relu(tf.nn.xw_plus_b(curr_input_2d, W, b,
                                                                        name="out_activations"))
                        print("output activations shape: {}".format(activations_output.get_shape().as_list()))

                    activations_carry = 1. - activations_T
                    highway_output = activations_T * activations_output + activations_carry * curr_input_2d
                    curr_input = highway_output
                    self.highway_output = tf.reshape(highway_output, [-1, self.config.max_seq_len,
                                                                      char_num_filters_total], name="highway_output")

        pooled_char_cnn_word_outputs = []
        if self.config.use_highway_layer:
            char_word_context_embeddings = self.highway_output
        else:
            char_word_context_embeddings = self.h_pool_char_flat

        # Step-3: concat features
        self.context_embeddings = tf.expand_dims(tf.concat([word_context_embeddings, char_word_context_embeddings],
                                                           2), -1)
        feature_vec_len = self.context_embeddings.get_shape().as_list()[2]

        # Step - 4: word-CNN
        pooled_word_outputs = []

        # word CNN
        for i, word_filter_size in enumerate(self.config.word_filter_sizes):
            with tf.variable_scope("word-conv-maxpool-%s" % word_filter_size):
                # Convolution Layer
                filter_shape = [word_filter_size, feature_vec_len, 1,
                                self.config.word_num_filters]  # [H, W, in_c, out_c]

                # try xavior also
                # filter = random_truncated_normal_initializer(filter_shape, "filter", stddev=0.1)
                filter = tf.Variable(tf.truncated_normal(filter_shape, stddev=0.1), name="W")
                b = tf.Variable(tf.constant(0.1, shape=[self.config.word_num_filters]), name="conv_bias")

                conv = tf.nn.conv2d(
                    self.context_embeddings,
                    filter,
                    strides=self.config.word_stride,
                    padding="VALID",
                    name="conv")
                print "conv shape:", conv.get_shape().as_list()
                h = tf.nn.relu(tf.nn.bias_add(conv, b), name="relu")  # [B, new_H, new_W, out_c]

                # h_batch_norm = tf.contrib.layers.batch_norm(h,
                #                                   center=True, scale=True,
                #                                   is_training=self.is_training,
                #                                   scope='bn')

                pooled = tf.nn.max_pool(
                    h,
                    ksize=[1, h.get_shape().as_list()[1], 1, 1],  # why k_size[2] = 1?
                    strides=[1, 1, 1, 1],
                    padding='VALID',
                    name="pool")
                pooled_word_outputs.append(pooled)

        # Combine all the pooled features
        word_num_filters_total = self.config.word_num_filters * len(self.config.word_filter_sizes)
        self.h_pool_word = tf.concat(pooled_word_outputs,
                                     3)  # collect across all output channels  [B, T, out_H, out_d]
        self.h_pool_word_2d = tf.reshape(self.h_pool_word,
                                         [-1, word_num_filters_total])  # [B, num_features]

        activations = self.h_pool_word_2d
        feature_vec_len = word_num_filters_total
        # Step-5: FC layer + dropout
        if self.config.use_fc_layer:
            # Final (unnormalized) scores and predictions
            with tf.variable_scope("fc_layer"):
                W = xavier_initializer((feature_vec_len, self.config.fc_layer_dim), "W")
                b = xavier_initializer((self.config.fc_layer_dim,), "bias")
                activations = tf.nn.dropout(
                    tf.nn.relu(tf.nn.xw_plus_b(self.h_pool_word_2d, W, b, name="prediction_logits")),
                    keep_prob=self.dropout_placeholder_fc)
            feature_vec_len = activations.get_shape().as_list()[1]

        # Step-6: softmax layer
        with tf.variable_scope("output_layer"):
            W1 = xavier_initializer((feature_vec_len, self.config.num_classes), "W")
            b1 = xavier_initializer((self.config.num_classes,), "bias")
            predictions = tf.nn.xw_plus_b(tf.nn.dropout(activations, keep_prob=self.dropout_placeholder_word), W1, b1,
                                          name="prediction_logits")

        return predictions

    def l2_loss_sum(self, tvars):
        return tf.add_n([tf.nn.l2_loss(t) for t in tvars], "l2_norms_sum")

    def write_predictions(self, pred, path):
        predicted_label_ids = tf.argmax(tf.nn.softmax(pred), axis=1)
        predicted_labels = map(lambda x: self.idx2label[x], predicted_label_ids)
        np.savetxt(path, predicted_labels)

    def add_loss_op(self, pred):
        tvars = tf.trainable_variables()
        without_bias_tvars = [tvar for tvar in tvars if 'bias' not in tvar.name]

        with tf.variable_scope("loss"):
            # weighted_labels = self.labels_placeholder * self.class_weights
	    weight_per_instance = tf.transpose(tf.matmul(self.labels_placeholder, tf.transpose(self.class_weights))) #shape [1, batch_size]

            weighted_cross_entropy_loss = tf.reduce_mean(tf.multiply(weight_per_instance, tf.nn.softmax_cross_entropy_with_logits(
                labels=self.labels_placeholder, logits=pred), name="batch_xentropy_loss"))

            l2_loss = tf.multiply(self.config.reg_val, self.l2_loss_sum(without_bias_tvars), name="l2_loss")
            loss = tf.add(weighted_cross_entropy_loss, l2_loss, name="total_batch_loss")

        tf.summary.scalar("batch_loss", loss)
        return loss

    def add_accuracy_op(self, pred):
        with tf.variable_scope("accuracy"):
            accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(pred, axis=1),
                                                       tf.argmax(self.labels_placeholder, axis=1)), dtype=tf.float32),
                                      name="curr_batch_accuracy")
        return accuracy

    def get_prediction_labels(self, pred):
        predicted_ids = tf.argmax(pred, axis=1)
        target_ids = tf.argmax(self.labels_placeholder, axis=1)
        return predicted_ids, target_ids

    def add_training_op(self, loss):
        # update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
        # with tf.control_dependencies(update_ops):
        with tf.variable_scope("optimizer"):
            optimizer = tf.train.AdamOptimizer(learning_rate=self.config.lr, name="adam_optimizer")
            tvars = tf.trainable_variables()
            grad_tvars = optimizer.compute_gradients(loss, tvars)
            self.write_gradient_summaries(grad_tvars)
            train_op = optimizer.apply_gradients(grad_tvars)

        return train_op

    def train_on_batch(self, sess, inputs_batch, labels_batch, merged):
        feed = self.create_feed_dict(inputs_batch, labels_batch=labels_batch,
                                     keep_prob_word=self.config.keep_prob, keep_prob_fc=self.config.keep_prob_fc,
                                     is_training=True)
        _, summary, loss = sess.run([self.train_op, merged, self.loss], feed_dict=feed)
        return summary, loss

    def write_gradient_summaries(self, grad_tvars):
        with tf.variable_scope("gradient_summaries"):
            for (grad, tvar) in grad_tvars:
                mean = tf.reduce_mean(grad)
                stddev = tf.sqrt(tf.reduce_mean(tf.square(grad - mean)))
                tf.summary.histogram("{}/hist".format(tvar.name), grad)
                tf.summary.scalar("{}/mean".format(tvar.name), mean)
                tf.summary.scalar("{}/stddev".format(tvar.name), stddev)
                tf.summary.scalar("{}/sparsity".format(tvar.name), tf.nn.zero_fraction(grad))

    def run_epoch(self, sess, config, dataset, train_writer, merged):
        prog = Progbar(target=1 + len(dataset.train_inputs[0]) / config.batch_size)
        for i, (train_x, train_y) in enumerate(get_minibatches([dataset.train_inputs, dataset.train_targets],
                                                               config.batch_size, is_multi_feature_input=True)):
            print "word input, char input, outout: {}, {}, {}".format(np.array(train_x[0]).shape,
                                                                      np.array(train_x[1]).shape,
                                                                      np.array(train_y).shape)

            summary, loss = self.train_on_batch(sess, train_x, train_y, merged)
            prog.update(i + 1, [("train loss", loss)])

        # feed = self.create_feed_dict(dataset.train_inputs, labels_batch=dataset.train_targets,
        #                              keep_prob_word=self.config.keep_prob, keep_prob_fc=self.config.keep_prob_fc,
        #                              is_training=False)
        # train_accuracy = sess.run(self.accuracy, feed_dict=feed)
        # print "- train Accuracy: {:.2f}".format(train_accuracy * 100.0)

        return summary, loss  # returns for Last batch

    def run_valid_epoch(self, sess, dataset, valid_writer, merged):
        print "\nEvaluating on dev set",
        total_correct = 0
        total_loss = []
        predicted_ids = []
        target_ids = []

        for i, (valid_x, valid_y) in enumerate(
                get_minibatches([dataset.valid_inputs, dataset.valid_targets], self.config.test_batch_size,
                                is_multi_feature_input=True)):
            batch_feed = self.create_feed_dict(valid_x, labels_batch=valid_y, is_training=False)
            batch_predictions, batch_loss, batch_accuracy = sess.run([self.pred, self.loss, self.accuracy],
                                                                     feed_dict=batch_feed)

            total_correct += (batch_accuracy * len(valid_y))
            total_loss.append(batch_loss)

            predicted_ids.extend(list(np.argmax(batch_predictions, axis=1)))
            target_ids.extend(list(np.argmax(valid_y, axis=1)))

        valid_loss = sum(total_loss) / float(len(total_loss))
        valid_accuracy = float(total_correct) / len(dataset.valid_targets)

        valid_f1_score = get_weighted_f1_score(predicted_ids, target_ids)

        return valid_loss, valid_accuracy, valid_f1_score

    def dump_incorrect_predictions(self, predictions, targets, offset, incorrect_predictions_path, predictions_path):
        predicted_label_ids = np.argmax(predictions, axis=1)
        predicted_labels = map(lambda x: self.idx2label[x], predicted_label_ids)

        # dump predictions
        f = open(predictions_path, "a")
        for each in predicted_labels:
            f.write(each + "\n")
        f.close()

        # dump incorrect predictions
        actual_label_ids = np.argmax(targets, axis=1)
        actual_labels = map(lambda x: self.idx2label[x], actual_label_ids)
        write_wrong_predictions(actual_labels, predicted_labels, offset, incorrect_predictions_path)

    def run_test_epoch(self, sess, dataset):
        print "\nEvaluating on Test set",
        total_correct = 0
        total_loss = []
        predicted_ids = []
        target_ids = []

        incorrect_predictions_path = os.path.join(DataConfig.data_dir_path, DataConfig.model_dir,
                                                  DataConfig.test_incorrect_predictions_file)
        predictions_path = os.path.join(DataConfig.data_dir_path, DataConfig.model_dir,
                                        DataConfig.test_predictions_file)

        if os.path.exists(predictions_path):
            os.remove(predictions_path)
        if os.path.exists(incorrect_predictions_path):
            os.remove(incorrect_predictions_path)

        offset = 0

        for i, (test_x, test_y) in enumerate(
                get_minibatches([dataset.test_inputs, dataset.test_targets], self.config.test_batch_size, shuffle=False,
                                is_multi_feature_input=True)):
            batch_feed = self.create_feed_dict(test_x, labels_batch=test_y, is_training=False)
            batch_predictions, batch_loss, batch_accuracy = sess.run([self.pred, self.loss, self.accuracy],
                                                                     feed_dict=batch_feed)

            total_correct += (batch_accuracy * len(test_y))
            total_loss.append(batch_loss)

            predicted_ids.extend(list(np.argmax(batch_predictions, axis=1)))
            target_ids.extend(list(np.argmax(test_y, axis=1)))

            self.dump_incorrect_predictions(batch_predictions, test_y, offset, incorrect_predictions_path,
                                            predictions_path)
            offset += len(test_y)

        test_loss = sum(total_loss) / float(len(total_loss))
        test_accuracy = float(total_correct) / len(dataset.test_targets)

        test_f1_score = get_weighted_f1_score(predicted_ids, target_ids)

        return test_loss, test_accuracy, test_f1_score

        # predicted_ids, target_ids = sess.run([self.prediction_labels, self.target_labels], feed_dict=feed)
        # print_confusion_matrix(predicted_ids, target_ids, self.class_names, "/home/asjindal/metlife_test_cm.png")

        # return test_loss, test_accuracy

    def fit(self, sess, saver, config, dataset, train_writer, valid_writer, merged, resume_training=False):

        if resume_training:
            _, best_valid_accuracy, best_valid_f1_score = self.run_valid_epoch(sess, dataset, valid_writer, merged)
        else:
            best_valid_accuracy = 0.
            best_valid_f1_score = 0.

	print "current best valid_accuracy:{:.2f}\tvalid_f1_score:{:.2f}".format(best_valid_accuracy, best_valid_f1_score)

        for epoch in range(config.n_epochs):
            print "Epoch {:} out of {:}".format(epoch + 1, self.config.n_epochs)

            summary, loss = self.run_epoch(sess, config, dataset, train_writer, merged)

            if (epoch + 1) % dataset.model_config.run_valid_after_epochs == 0:
                valid_loss, valid_accuracy, valid_f1_score = self.run_valid_epoch(sess, dataset, valid_writer, merged)
                print "\n- valid Accuracy: {:.2f}".format(valid_accuracy * 100.0)
                print "- valid f1-score: {:.2f}".format(valid_f1_score * 100.0)
                print "- valid loss: {:.4f}".format(valid_loss)

                valid_accuracy_summary = tf.summary.scalar("valid_UAS", tf.constant(valid_accuracy, dtype=tf.float32))
                valid_writer.add_summary(sess.run(valid_accuracy_summary), epoch + 1)

                if self.config.accuracy_metric == "accuracy":
                    if valid_accuracy > best_valid_accuracy:
                        best_valid_accuracy = valid_accuracy
                        if saver:
                            print "New best dev accuracy! Saving model.."
                            saver.save(sess, os.path.join(DataConfig.data_dir_path, DataConfig.model_dir,
                                                          DataConfig.model_name))
                elif self.config.accuracy_metric == "f1_score":
                    if valid_f1_score > best_valid_f1_score:
                        best_valid_f1_score = valid_f1_score
                        if saver:
                            print "New best dev f1-score! Saving model.."
                            saver.save(sess, os.path.join(DataConfig.data_dir_path, DataConfig.model_dir,
                                                          DataConfig.model_name))

            # trainable variables summary -> only for training
            if (epoch + 1) % dataset.model_config.write_summary_after_epochs == 0:
                train_writer.add_summary(summary, global_step=epoch + 1)

        print


text:
from mss import mss
from PIL import Image
import sys
import time
import mss.tools as MSSTools
import io
import numpy as np
import cv2
import pyaudio
import aubio
import numpy as np

# ##############################################################
# Commandline arguments:
# arg[1] = Display preview of monitor (0), or run (1 - also runs audio | anything else will not run audio)
# arg[2] = Monitor to capture
# arg[3] = X_COORD
# arg[4] = Y_COORD
# arg[5] = Width of screen to capture
# arg[6] = Height of screen to capture
# arg[7] = Section # by index
# arg[8] = How many subsections we need to split and calculate dominant RGB for within the section index (for optimization) (sections.Count)
#
# Example execution for the top left of Monitor 1, with a 200x200 box:
# py -3.6 .\clientcapture.py 1 1 0 0 1920 200 0 20 -- Example of capturing a 1920x1080 monitor with 20 subsections (this is testing TOP)
#  py -3.6 .\clientcapture.py 1 1 1820 0 100 1080 3 15 -- Example of capturing a 1920x1080 monitor with 15 subsections (this is testing RIGHT)
# Example of section for testing monitor 1 (with open image)
# py -3.6 .\clientcapture.py 0 1
# ##############################################################

# ##############################################################
# For testing image, use
# t = Image.open(io.BytesIO(raw_bytes))
# t.show()
# ##############################################################

#start = time.time()

if sys.argv[1] == '1':
	SIMULATED_SQUARES = 10
	TIME_IN_SECS = 10
	# CHANGE AT YOUR OWN RISK
	CHUNK = 2**11
	RATE = 44100
	# CHANGE AT YOUR OWN RISK

	p=pyaudio.PyAudio()
	stream=p.open(format=pyaudio.paInt16,channels=1,rate=RATE,input=True,
				frames_per_buffer=CHUNK)

def readSoundOutputAlpha():
	data = np.frombuffer(stream.read(CHUNK, exception_on_overflow = False),dtype=np.int16)
	peak=np.average(np.abs(data))*2
	# colorBars = int(50*peak/2**10) % (1+SIMULATED_SQUARES)
	colorBars = int(3*peak/2**6)
	# bars="#"*colorBars
	# print("%05d %s"%(peak,bars))
	if(colorBars > 255):
		colorBars = 255
	return colorBars

with mss() as sct:
	#print(sys.argv)
	if sys.argv[1] == '0':
		MONITOR_NUMBER = int(sys.argv[2])
		mon = sct.monitors[MONITOR_NUMBER]
		monitor = {
			"top": mon["top"],
			"left": mon["left"],
			"width": mon["width"],
			"height": mon["height"],
			"mon": MONITOR_NUMBER
		}

		im = sct.grab(monitor)
		raw = MSSTools.to_png(im.rgb, im.size)
		b = Image.open(io.BytesIO(raw))
		b.show()
	else:
		SECTION_IND = sys.argv[7]
		SUB_SECTION_COUNT = int(sys.argv[8])

		X_COORD = int(sys.argv[3])
		Y_COORD = int(sys.argv[4])
		WIDTH = int(sys.argv[5])
		HEIGHT = int(sys.argv[6])
		MONITOR_NUMBER = int(sys.argv[2])
		mon = sct.monitors[MONITOR_NUMBER]

		# Capture a bbox using percent values
		monitor = {
			"top": mon["top"] + Y_COORD,
			"left": mon["left"] + X_COORD,
			"width": WIDTH,
			"height": HEIGHT,
			"mon": MONITOR_NUMBER
		}
		isVert = True if WIDTH == 100 else False

		pixels_per_subsection = 0
		if isVert:
			pixels_per_subsection = int(HEIGHT / SUB_SECTION_COUNT)
		else:
			pixels_per_subsection = int(WIDTH / SUB_SECTION_COUNT)

		# Continuously loop until process is killed
		while True:
			image_output = 'image_in_sec_' + SECTION_IND + '_.png'.format(**monitor)
			im = sct.grab(monitor)
			raw = MSSTools.to_png(im.rgb, im.size)

			#b = Image.open(io.BytesIO(raw))
			#b.show()
			#break

			#Split image into equal sections
			img = Image.open(io.BytesIO(raw))
			sub_sections = []
			curr_x = 0
			curr_y = 0
			for i in np.arange(SUB_SECTION_COUNT):
				if isVert:
					area = (curr_x, curr_y, WIDTH, curr_y + pixels_per_subsection)
					sub_sections.append(img.crop(area))
					curr_y += pixels_per_subsection
				else:
					area = (curr_x, curr_y, curr_x + pixels_per_subsection, HEIGHT)
					sub_sections.append(img.crop(area))
					curr_x += pixels_per_subsection

			rgb = ''
			for i in np.arange(SUB_SECTION_COUNT):
				sub_section_image = sub_sections[i]
				raw = io.BytesIO()
				sub_section_image.save(raw, format='PNG')
				raw = raw.getvalue()
				nparr = np.frombuffer(raw, np.uint8)
				cimg = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
				avg_per_row = np.average(cimg, axis=0)
				avg = np.average(avg_per_row, axis=0)
				rgb +=  str(int(avg[2])) + ' ' + str(int(avg[1])) + ' ' + str(int(avg[0])) + '|'
			#get rid of extranneous pipe char
			rgb = rgb[:-1]
			#print('Runtime: ' + str(time.time()-start))
			#time.sleep(1)

			if sys.argv[1] == '1':
				alph = str(readSoundOutputAlpha())
				#Print such that the read order is R G B|R G B|R G B--SECTION_IND (split by double dash, then bar, then split by space)
				#If section object labels that it's passing in a '1' for sys.argv[1], then it should expect len()
				rgb = alph + ' ' + rgb
				print(rgb + '--' + SECTION_IND)
			else:
				print(rgb + '--' + SECTION_IND)

			sys.stdout.flush()
stream.stop_stream()
stream.close()
p.terminate()

ext: py

max_stars_repo_name: rgboys/Reactive-RGB

max_issues_repo_name: rgboys/Reactive-RGB

max_forks_repo_name: rgboys/Reactive-RGB

reason: import numpy


text:
# This module acts as a placeholder for generated schema.  After
# `setup_schema` is run from `models`, each table will have an
# associated schema here.  E.g., `models.Dog` will be matched by `schema.Dog`.

# From
# https://marshmallow-sqlalchemy.readthedocs.io/en/latest/recipes.html#automatically-generating-schemas-for-sqlalchemy-models

from marshmallow_sqlalchemy import (
    ModelConversionError as _ModelConversionError,
    ModelSchema as _ModelSchema,
)

from marshmallow import (
    Schema as _Schema,
    fields,
    validate,
    post_load,
    pre_dump,
    ValidationError,
)
from marshmallow_enum import EnumField

from baselayer.app.models import Base as _Base, DBSession as _DBSession
from baselayer.app.env import load_env
from skyportal.enum_types import (
    ALLOWED_SPECTRUM_TYPES,
    default_spectrum_type,
    py_allowed_bandpasses,
    py_allowed_magsystems,
    py_followup_priorities,
    ALLOWED_BANDPASSES,
    ALLOWED_MAGSYSTEMS,
    force_render_enum_markdown,
)

from astropy.table import Table
import operator

import sys
import inspect
import numpy as np
from enum import Enum

_, cfg = load_env()
# The default lim mag n-sigma to consider a photometry point as a detection
PHOT_DETECTION_THRESHOLD = cfg["misc.photometry_detection_threshold_nsigma"]

def validate_fluxerr(fluxerr):
    if isinstance(fluxerr, (float, int, str)):
        return float(fluxerr) >= 0
    return all([float(el) >= 0 for el in fluxerr])

class ApispecEnumField(EnumField):
    """See https://github.com/justanr/marshmallow_enum/issues/24#issue-335162592"""

    def __init__(self, enum, *args, **kwargs):
        super().__init__(enum, *args, **kwargs)
        self.metadata['enum'] = [e.name for e in enum]

class Response(_Schema):
    status = ApispecEnumField(Enum('status', ['error', 'success']), required=True)
    message = fields.String()
    data = fields.Dict()

class Error(Response):
    status = ApispecEnumField(Enum('status', ['error']), required=True)

class newsFeedPrefs(_Schema):
    numItems = fields.String()

class UserPreferences(_Schema):
    newsFeed = fields.Nested(newsFeedPrefs)

class UpdateUserPreferencesRequestJSON(_Schema):
    preferences = fields.Nested(UserPreferences)

def success(schema_name, base_schema=None):
    schema_fields = {
        'status': ApispecEnumField(Enum('status', ['success']), required=True),
        'message': fields.String(),
    }

    if base_schema is not None:
        if isinstance(base_schema, list):
            schema_fields['data'] = fields.List(
                fields.Nested(base_schema[0]),
            )
        else:
            schema_fields['data'] = fields.Nested(base_schema)

    return type(schema_name, (_Schema,), schema_fields)

def setup_schema():
    """For each model, install a marshmallow schema generator as
    `model.__schema__()`, and add an entry to the `schema`
    module.

    """
    # for class_ in _Base._decl_class_registry.values():
    for mapper in _Base.registry.mappers:
        class_ = mapper.class_
        if hasattr(class_, '__tablename__'):
            if class_.__name__.endswith('Schema'):
                raise _ModelConversionError(
                    "For safety, setup_schema can not be used when a"
                    "Model class ends with 'Schema'"
                )

            def add_schema(schema_class_name, exclude=[], add_to_model=False):
                """Add schema to module namespace, and, optionally, to model object.

                Parameters
                ----------
                schema_class_name : str
                    Name of schema.
                exclude : list of str, optional
                    List of model attributes to exclude from schema. Defaults to `[]`.
                add_to_model : bool, optional
                    Boolean indicating whether to install this schema generator
                    on the model as `model.__schema__`. Defaults to `False`.
                """
                schema_class_meta = type(
                    f'{schema_class_name}_meta',
                    (),
                    {
                        'model': class_,
                        'sqla_session': _DBSession,
                        'ordered': True,
                        'exclude': [],
                        'include_fk': True,
                        'include_relationships': False,
                    },
                )
                for exclude_attr in exclude:
                    if (
                        hasattr(class_, exclude_attr)
                        and getattr(class_, exclude_attr) is not None
                    ):
                        schema_class_meta.exclude.append(exclude_attr)

                schema_class = type(
                    schema_class_name, (_ModelSchema,), {'Meta': schema_class_meta}
                )

                if add_to_model:
                    setattr(class_, '__schema__', schema_class)

                setattr(sys.modules[__name__], schema_class_name, schema_class())

            schema_class_name = class_.__name__
            add_schema(
                schema_class_name,
                exclude=['healpix', 'created_at', 'modified'],
                add_to_model=True,
            )
            add_schema(
                f'{schema_class_name}NoID',
                exclude=[
                    'created_at',
                    'id',
                    'modified',
                    'owner_id',
                    'last_modified_by_id',
                    'healpix',
                ],
            )
            if schema_class_name == "Obj":
                add_schema(
                    f'{schema_class_name}Post',
                    exclude=[
                        'created_at',
                        'redshift_history',
                        'modified',
                        'internal_key',
                    ],
                )

class PhotBaseFlexible:
    """This is the base class for two classes that are used for rendering the
    input data to `PhotometryHandler.post` in redoc. These classes are only
    used for generating documentation and not for validation, serialization,
    or deserialization."""

    mjd = fields.Field(
        metadata={
            'description': (
                'MJD of the observation(s). Can be a given as a '
                'scalar or a 1D list. If a scalar, will be '
                'broadcast to all values given as lists. '
                'Null values not allowed.'
            ),
        },
        required=True,
    )

    filter = fields.Field(
        required=True,
        metadata={
            'description': (
                'The bandpass of the observation(s). '
                'Can be given as a scalar or a 1D list. '
                'If a scalar, will be broadcast to all values '
                'given as lists. Null values not allowed. Allowed values: '
                f'{force_render_enum_markdown(ALLOWED_BANDPASSES)}'
            )
        },
    )

    obj_id = fields.Field(
        metadata={
            'description': (
                'ID of the `Obj`(s) to which the '
                'photometry will be attached. '
                'Can be given as a scalar or a 1D list. '
                'If a scalar, will be broadcast to all values '
                'given as lists. Null values are not allowed.'
            )
        },
        required=True,
    )

    instrument_id = fields.Field(
        metadata={
            'description': (
                'ID of the `Instrument`(s) with which the '
                'photometry was acquired. '
                'Can be given as a scalar or a 1D list. '
                'If a scalar, will be broadcast to all values '
                'given as lists. Null values are not allowed.'
            ),
        },
        required=True,
    )

    assignment_id = fields.Integer(
        metadata={
            'description': 'ID of the classical assignment which generated the photometry'
        },
        required=False,
        missing=None,
    )

    ra = fields.Field(
        metadata={
            'description': (
                'ICRS Right Ascension of the centroid '
                'of the photometric aperture [deg]. '
                'Can be given as a scalar or a 1D list. '
                'If a scalar, will be broadcast to all values '
                'given as lists. Null values allowed.'
            )
        },
        required=False,
        missing=None,
    )

    dec = fields.Field(
        metadata={
            'description': (
                'ICRS Declination of the centroid '
                'of the photometric aperture [deg]. '
                'Can be given as a scalar or a 1D list. '
                'If a scalar, will be broadcast to all values '
                'given as lists. Null values allowed.'
            )
        },
        required=False,
        missing=None,
    )

    ra_unc = fields.Field(
        metadata={
            'description': 'Uncertainty on RA [arcsec]. '
            'Can be given as a scalar or a 1D list. '
            'If a scalar, will be broadcast to all values '
            'given as lists. Null values allowed.'
        },
        required=False,
        missing=None,
    )

    dec_unc = fields.Field(
        metadata={
            'description': 'Uncertainty on dec [arcsec]. '
            'Can be given as a scalar or a 1D list. '
            'If a scalar, will be broadcast to all values '
            'given as lists. Null values allowed.'
        },
        required=False,
        missing=None,
    )

    origin = fields.Field(
        metadata={
            'description': "Provenance of the Photometry. If a record is "
            "already present with identical origin, only the "
            "groups or streams list will be updated (other data assumed "
            "identical). Defaults to None."
        },
        missing=None,
    )

    group_ids = fields.Field(
        metadata={
            "description": "List of group IDs to which photometry points will be visible. "
            "If 'all', will be shared with site-wide public group (visible to all users "
            "who can view associated source)."
        },
        required=False,
        missing=[],
    )

    stream_ids = fields.Field(
        metadata={
            'description': "List of stream IDs to which photometry points will be visible."
        },
        required=False,
        missing=[],
    )

    altdata = fields.Field(
        metadata={
            "description": (
                "Misc. alternative metadata stored in JSON "
                "format, e.g. `{'calibration': {'source': 'ps1',"
                "'color_term': 0.012}, 'photometry_method': 'allstar', "
                "'method_reference': 'Masci et al. (2015)'}`. Can be a list of "
                "dicts or a single dict which will be broadcast to all values."
            )
        },
        missing=None,
        default=None,
        required=False,
    )

class PhotFluxFlexible(_Schema, PhotBaseFlexible):
    """This is one of two classes used for rendering the
    input data to `PhotometryHandler.post` in redoc. These classes are only
    used for generating documentation and not for validation, serialization,
    or deserialization."""

    required_keys = [
        'magsys',
        'mjd',
        'filter',
        'obj_id',
        'instrument_id',
        'fluxerr',
        'zp',
    ]

    magsys = fields.Field(
        required=True,
        metadata={
            'description': (
                'The magnitude system to which the flux, flux error, '
                'and the zeropoint are tied. '
                'Can be given as a scalar or a 1D list. '
                'If a scalar, will be broadcast to all values '
                'given as lists. Null values not allowed. Allowed values: '
                f'{force_render_enum_markdown(ALLOWED_MAGSYSTEMS)}'
            ),
        },
    )

    flux = fields.Field(
        metadata={
            'description': (
                'Flux of the observation(s) in counts. '
                'Can be given as a scalar or a 1D list. '
                'If a scalar, will be broadcast to all values '
                'given as lists. Null values allowed, to accommodate,'
                'e.g., upper limits from ZTF1, where flux is not provided '
                'for non-detections. For a given photometry '
                'point, if `flux` is null, `fluxerr` is '
                'used to derive a n-sigma limiting magnitude '
                '(where n is configurable; 3.0 by default) '
                'when the photometry point is requested in '
                'magnitude space from the Photomety GET api.'
            ),
        },
        required=False,
        missing=None,
    )

    fluxerr = fields.Field(
        metadata={
            'description': 'Gaussian error on the flux in counts. '
            'Can be given as a scalar or a 1D list. '
            'If a scalar, will be broadcast to all values '
            'given as lists. Null values not allowed.'
        },
        required=True,
        validate=validate_fluxerr,
    )

    zp = fields.Field(
        metadata={
            'description': 'Magnitude zeropoint, given by `zp` in the '
            'equation `m = -2.5 log10(flux) + zp`. '
            '`m` is the magnitude of the object in the '
            'magnitude system `magsys`. '
            'Can be given as a scalar or a 1D list. '
            'Null values not allowed.'
        },
        required=True,
    )

class PhotMagFlexible(_Schema, PhotBaseFlexible):
    """This is one of two classes used for rendering the
    input data to `PhotometryHandler.post` in redoc. These classes are only
    used for generating documentation and not for validation, serialization,
    or deserialization."""

    required_keys = [
        'magsys',
        'limiting_mag',
        'mjd',
        'filter',
        'obj_id',
        'instrument_id',
    ]

    magsys = fields.Field(
        required=True,
        metadata={
            'description': 'The magnitude system to which the magnitude, '
            'magnitude error, and limiting magnitude are tied. '
            'Can be given as a scalar or a 1D list. '
            'If a scalar, will be broadcast to all values '
            'given as lists. Null values not allowed. Allowed values: '
            f'{force_render_enum_markdown(ALLOWED_MAGSYSTEMS)}'
        },
    )

    mag = fields.Field(
        metadata={
            'description': 'Magnitude of the observation in the '
            'magnitude system `magsys`. '
            'Can be given as a scalar or a 1D list. '
            'If a scalar, will be broadcast to all values '
            'given as lists. Null values allowed for non-detections. '
            'If `mag` is null, the corresponding '
            '`magerr` must also be null.'
        },
        required=False,
        missing=None,
    )

    magerr = fields.Field(
        metadata={
            'description': 'Magnitude of the observation in the '
            'magnitude system `magsys`. '
            'Can be given as a scalar or a 1D list. '
            'If a scalar, will be broadcast to all values '
            'given as lists. Null values allowed for non-detections. '
            'If `magerr` is null, the corresponding `mag` '
            'must also be null.'
        },
        required=False,
        missing=None,
    )

    limiting_mag = fields.Field(
        metadata={
            'description': 'Limiting magnitude of the image '
            'in the magnitude system `magsys`. '
            'Can be given as a scalar or a 1D list. '
            'If a scalar, will be broadcast to all values '
            'given as lists. Null values not allowed.'
        },
        required=True,
    )

    limiting_mag_nsigma = fields.Field(
        metadata={
            'description': 'Number of standard deviations '
            'above the background that the limiting '
            'magnitudes correspond to. Null values '
            f'not allowed. Default = {PHOT_DETECTION_THRESHOLD}.'
        },
        required=False,
        missing=PHOT_DETECTION_THRESHOLD,
    )

class PhotBase:
    """This is the base class of two classes that are used for deserializing
    and validating the postprocessed input data of `PhotometryHandler.post`
    and `PhotometryHandler.put` and for generating the API docs of
    PhotometryHandler.get`.
    """

    mjd = fields.Number(
        metadata={'description': 'MJD of the observation.'}, required=True
    )
    magsys = ApispecEnumField(
        py_allowed_magsystems,
        required=True,
        metadata={
            'description': 'The magnitude system to which the '
            'flux and the zeropoint are tied.'
        },
    )
    filter = ApispecEnumField(
        py_allowed_bandpasses,
        required=True,
        metadata={'description': 'The bandpass of the observation.'},
    )

    obj_id = fields.String(
        metadata={
            'description': 'ID of the Object to which the '
            'photometry will be attached.'
        },
        required=True,
    )

    instrument_id = fields.Integer(
        metadata={
            'description': 'ID of the instrument with which'
            ' the observation was carried '
            'out.'
        },
        required=True,
    )

    assignment_id = fields.Integer(
        metadata={
            'description': 'ID of the classical assignment which generated the photometry'
        },
        required=False,
        missing=None,
    )

    origin = fields.Field(
        metadata={
            'description': (
                "Provenance of the Photometry. If a record is "
                "already present with identical origin, only the "
                "groups or streams list will be updated (other data assumed "
                "identical). Defaults to None."
            )
        },
        missing=None,
    )

    ra = fields.Number(
        metadata={
            "description": (
                'ICRS Right Ascension of the centroid '
                'of the photometric aperture [deg].'
            )
        },
        missing=None,
        default=None,
    )
    dec = fields.Number(
        metadata={
            'description': 'ICRS Declination of the centroid '
            'of the photometric aperture [deg].'
        },
        missing=None,
        default=None,
    )

    ra_unc = fields.Number(
        metadata={'description': 'Uncertainty on RA [arcsec].'},
        missing=None,
        default=None,
    )

    dec_unc = fields.Number(
        metadata={'description': 'Uncertainty on dec [arcsec].'},
        missing=None,
        default=None,
    )

    alert_id = fields.Integer(
        metadata={
            'description': (
                "Corresponding alert ID. If a record is "
                "already present with identical alert ID, only the "
                "groups list will be updated (other alert data assumed "
                "identical). Defaults to None."
            )
        },
        missing=None,
        default=None,
    )

    altdata = fields.Dict(
        metadata={
            "description": (
                "Misc. alternative metadata stored in JSON "
                "format, e.g. `{'calibration': {'source': 'ps1',"
                "'color_term': 0.012}, 'photometry_method': 'allstar', "
                "'method_reference': 'Masci et al. (2015)'}`"
            )
        },
        missing=None,
        default=None,
    )

    @post_load
    def enum_to_string(self, data, **kwargs):
        # convert enumified data back to strings
        data['filter'] = data['filter'].name
        data['magsys'] = data['magsys'].name
        return data

class PhotometryFlux(_Schema, PhotBase):
    """This is one of two classes that are used for deserializing
    and validating the postprocessed input data of `PhotometryHandler.post`
    and `PhotometryHandler.put` and for generating the API docs of
    PhotometryHandler.get`.
    """

    flux = fields.Number(
        metadata={
            'description': 'Flux of the observation in counts. '
            'Can be null to accommodate upper '
            'limits from ZTF1, where no flux is measured '
            'for non-detections. If flux is null, '
            'the flux error is used to derive a '
            'limiting magnitude.'
        },
        required=False,
        missing=None,
        default=None,
    )

    fluxerr = fields.Number(
        metadata={'description': 'Gaussian error on the flux in counts.'}, required=True
    )

    zp = fields.Number(
        metadata={
            'description': 'Magnitude zeropoint, given by `ZP` in the '
            'equation m = -2.5 log10(flux) + `ZP`. '
            'm is the magnitude of the object in the '
            'magnitude system `magsys`.'
        },
        required=True,
    )

    @post_load
    def parse_flux(self, data, **kwargs):
        """Return a `Photometry` object from a `PhotometryFlux` marshmallow
        schema.

        Parameters
        ----------
        data : dict
            The instance of the PhotometryFlux schema to convert to Photometry.

        Returns
        -------
        Photometry
            The Photometry object generated from the PhotometryFlux object.
        """

        from skyportal.models import Instrument, Obj, PHOT_SYS, PHOT_ZP, Photometry
        from sncosmo.photdata import PhotometricData

        # get the instrument
        instrument = Instrument.query.get(data['instrument_id'])
        if not instrument:
            raise ValidationError(f'Invalid instrument ID: {data["instrument_id"]}')

        # get the object
        obj = Obj.query.get(data['obj_id'])  # TODO : implement permissions checking
        if not obj:
            raise ValidationError(f'Invalid object ID: {data["obj_id"]}')

        if data["filter"] not in instrument.filters:
            raise ValidationError(
                f"Instrument {instrument.name} has no filter " f"{data['filter']}."
            )

        # convert flux to microJanskies.
        table = Table([data])
        if data['flux'] is None:
            # this needs to be non-null for the conversion step
            # will be replaced later with null
            table['flux'] = 0.0

        # conversion happens here
        photdata = PhotometricData(table).normalized(zp=PHOT_ZP, zpsys=PHOT_SYS)

        # replace with null if needed
        final_flux = None if data['flux'] is None else photdata.flux[0]

        p = Photometry(
            obj_id=data['obj_id'],
            mjd=data['mjd'],
            flux=final_flux,
            fluxerr=photdata.fluxerr[0],
            instrument_id=data['instrument_id'],
            assignment_id=data['assignment_id'],
            filter=data['filter'],
            ra=data['ra'],
            dec=data['dec'],
            ra_unc=data['ra_unc'],
            dec_unc=data['dec_unc'],
        )
        if 'alert_id' in data and data['alert_id'] is not None:
            p.alert_id = data['alert_id']
        return p

class PhotometryMag(_Schema, PhotBase):
    """This is one of  two classes that are used for deserializing
    and validating the postprocessed input data of `PhotometryHandler.post`
    and `PhotometryHandler.put` and for generating the API docs of
    `PhotometryHandler.get`.
    """

    mag = fields.Number(
        metadata={
            'description': 'Magnitude of the observation in the '
            'magnitude system `magsys`. Can be null '
            'in the case of a non-detection.'
        },
        required=False,
        missing=None,
        default=None,
    )
    magerr = fields.Number(
        metadata={
            'description': 'Magnitude error of the observation in '
            'the magnitude system `magsys`. Can be '
            'null in the case of a non-detection.'
        },
        required=False,
        missing=None,
        default=None,
    )
    limiting_mag = fields.Number(
        metadata={
            'description': 'Limiting magnitude of the image '
            'in the magnitude system `magsys`.'
        },
        required=True,
    )

    @post_load
    def parse_mag(self, data, **kwargs):
        """Return a `Photometry` object from a `PhotometryMag` marshmallow
        schema.

        Parameters
        ----------
        data : dict
            The instance of the PhotometryMag schema to convert to Photometry.

        Returns
        -------
        Photometry
            The Photometry object generated from the PhotometryMag dict.
        """

        from skyportal.models import Instrument, Obj, PHOT_SYS, PHOT_ZP, Photometry
        from sncosmo.photdata import PhotometricData

        # check that mag and magerr are both null or both not null, not a mix
        ok = any(
            [
                all([op(field, None) for field in [data['mag'], data['magerr']]])
                for op in [operator.is_, operator.is_not]
            ]
        )

        if not ok:
            raise ValidationError(
                f'Error parsing packet "{data}": mag '
                f'and magerr must both be null, or both be '
                f'not null.'
            )

        # get the instrument
        instrument = Instrument.query.get(data['instrument_id'])
        if not instrument:
            raise ValidationError(f'Invalid instrument ID: {data["instrument_id"]}')

        # get the object
        obj = Obj.query.get(data['obj_id'])  # TODO: implement permissions checking
        if not obj:
            raise ValidationError(f'Invalid object ID: {data["obj_id"]}')

        if data["filter"] not in instrument.filters:
            raise ValidationError(
                f"Instrument {instrument.name} has no filter " f"{data['filter']}."
            )

        # determine if this is a limit or a measurement
        hasmag = data['mag'] is not None

        if hasmag:
            flux = 10 ** (-0.4 * (data['mag'] - PHOT_ZP))
            fluxerr = data['magerr'] / (2.5 / np.log(10)) * flux
        else:
            nsigflux = 10 ** (-0.4 * (data['limiting_mag'] - PHOT_ZP))
            flux = None
            fluxerr = nsigflux / PHOT_DETECTION_THRESHOLD

        # convert flux to microJanskies.
        table = Table(
            [
                {
                    'flux': flux,
                    'fluxerr': fluxerr,
                    'magsys': data['magsys'],
                    'zp': PHOT_ZP,
                    'filter': data['filter'],
                    'mjd': data['mjd'],
                }
            ]
        )
        if flux is None:
            # this needs to be non-null for the conversion step
            # will be replaced later with null
            table['flux'] = 0.0

        # conversion happens here
        photdata = PhotometricData(table).normalized(zp=PHOT_ZP, zpsys=PHOT_SYS)

        # replace with null if needed
        final_flux = None if flux is None else photdata.flux[0]

        p = Photometry(
            obj_id=data['obj_id'],
            mjd=data['mjd'],
            flux=final_flux,
            fluxerr=photdata.fluxerr[0],
            instrument_id=data['instrument_id'],
            assignment_id=data['assignment_id'],
            filter=data['filter'],
            ra=data['ra'],
            dec=data['dec'],
            ra_unc=data['ra_unc'],
            dec_unc=data['dec_unc'],
        )
        if 'alert_id' in data and data['alert_id'] is not None:
            p.alert_id = data['alert_id']
        return p

class AssignmentSchema(_Schema):
    # For generating API docs and extremely basic validation

    run_id = fields.Integer(required=True)
    obj_id = fields.String(
        required=True, metadata={'description': 'The ID of the object to observe.'}
    )
    priority = ApispecEnumField(
        py_followup_priorities,
        required=True,
        metadata={
            "description": ('Priority of the request, ' '(lowest = 1, highest = 5).')
        },
    )
    status = fields.String(metadata={'description': 'The status of the request'})
    comment = fields.String(
        metadata={'description': 'An optional comment describing the request.'}
    )

class ObservationHandlerPost(_Schema):
    telescopeName = fields.String(
        required=True,
        metadata={"description": ('The telescope name associated with the fields')},
    )
    instrumentName = fields.String(
        required=True,
        metadata={"description": ('The instrument name associated with the fields')},
    )
    observationData = fields.Field(
        metadata={'description': 'Observation data dictionary list'}
    )

class ObservationExternalAPIHandlerPost(_Schema):

    start_date = fields.Field(
        required=True, metadata={'description': "start date of the request."}
    )

    end_date = fields.Field(
        required=True, metadata={'description': "end date of the request."}
    )

    allocation_id = fields.Integer(
        required=True,
        metadata={'description': "Followup request allocation ID."},
    )

class ObservationASCIIFileHandlerPost(_Schema):
    instrumentID = fields.String(
        required=True,
        metadata={"description": ('The instrument ID associated with the fields')},
    )
    observationData = fields.Field(
        metadata={'description': 'Observation data Ascii string'}
    )

class ObservingRunPost(_Schema):
    instrument_id = fields.Integer(
        required=True,
        metadata={
            "description": ('The ID of the instrument to be ' 'used in this run.')
        },
    )

    # name of the PI
    pi = fields.String(metadata={'description': 'The PI of the observing run.'})
    observers = fields.String(metadata={'description': 'The names of the observers'})
    group_id = fields.Integer(
        metadata={'description': 'The ID of the group this run is associated with.'}
    )
    calendar_date = fields.Date(
        metadata={"description": 'The local calendar date of the run.'}, required=True
    )

class GcnHandlerPut(_Schema):
    xml = fields.String(metadata={'description': 'VOEvent XML content.'})

class GcnEventHandlerGet(_Schema):
    tags = fields.List(fields.Field(), metadata={'description': 'Event tags'})
    dateobs = fields.Field(metadata={'description': 'UTC event timestamp'})
    localizations = fields.List(
        fields.Field(), metadata={'description': 'Healpix localizations'}
    )
    notices = fields.List(
        fields.Field(), metadata={'description': 'VOEvent XML notices'}
    )
    lightcurve = fields.String(metadata={'description': 'URL for light curve'})

class LocalizationHandlerGet(_Schema):
    localization_name = fields.String(metadata={'description': 'Localization name'})
    dateobs = fields.String(metadata={'description': 'UTC event timestamp'})
    flat_2d = fields.List(
        fields.Float, metadata={'description': 'Flattened 2D healpix map'}
    )
    contour = fields.Field(metadata={'description': 'GeoJSON contours of healpix map'})

class GcnEventViewsHandlerGet(_Schema):
    tags = fields.List(fields.Field(), metadata={'description': 'Event list'})

class FollowupRequestPost(_Schema):

    obj_id = fields.String(
        required=True,
        metadata={'description': "ID of the target Obj."},
    )

    payload = fields.Field(
        required=False, metadata={'description': "Content of the followup request."}
    )

    status = fields.String(
        missing="pending submission",
        metadata={'description': "The status of the request."},
        required=False,
    )

    allocation_id = fields.Integer(
        required=True,
        metadata={'description': "Followup request allocation ID."},
    )

    target_group_ids = fields.List(
        fields.Integer,
        required=False,
        metadata={
            'description': (
                'IDs of groups to share the results of the f' 'ollowup request with.'
            )
        },
    )

class ObservationPlanPost(_Schema):

    gcnevent_id = fields.Integer(
        required=True,
        metadata={'description': "ID of the GcnEvent."},
    )

    payload = fields.Field(
        required=False, metadata={'description': "Content of the followup request."}
    )

    status = fields.String(
        missing="pending submission",
        metadata={'description': "The status of the request."},
        required=False,
    )

    allocation_id = fields.Integer(
        required=True,
        metadata={'description': "Followup request allocation ID."},
    )

    localization_id = fields.Integer(
        required=True,
        metadata={'description': "Localization ID."},
    )

    target_group_ids = fields.List(
        fields.Integer,
        required=False,
        metadata={
            'description': (
                'IDs of groups to share the results of the followup request with.'
            )
        },
    )

class ObservingRunGet(ObservingRunPost):
    owner_id = fields.Integer(
        metadata={'description': 'The User ID of the owner of this run.'}
    )
    ephemeris = fields.Field(metadata={'description': 'Observing run ephemeris data.'})
    id = fields.Integer(metadata={'description': 'Unique identifier for the run.'})

    @pre_dump
    def serialize(self, data, **kwargs):
        data.ephemeris = data.instrument.telescope.ephemeris(data.calendar_noon)
        return data

class ObservingRunGetWithAssignments(ObservingRunGet):
    assignments = fields.List(fields.Field())
    instrument = fields.Field()

class PhotometryRangeQuery(_Schema):
    instrument_ids = fields.List(
        fields.Integer,
        metadata={
            'description': (
                "IDs of the instruments to query "
                "for photometry from. If `None`, "
                "queries all instruments."
            )
        },
        required=False,
        missing=None,
        default=None,
    )

    min_date = fields.DateTime(
        required=False,
        metadata={
            'description': (
                'Query for photometry taken after '
                'this UT `DateTime`. For an '
                'open-ended interval use `None`.'
            )
        },
        missing=None,
        default=None,
    )

    max_date = fields.DateTime(
        required=False,
        metadata={
            'description': (
                'Query for photometry taken before '
                'this UT `DateTime`. For an '
                'open-ended interval use `None`.'
            )
        },
        missing=None,
        default=None,
    )

class SpectrumAsciiFileParseJSON(_Schema):

    wave_column = fields.Integer(
        missing=0,
        metadata={
            'description': (
                "The 0-based index of the ASCII column corresponding "
                "to the wavelength values of the spectrum (default 0)."
            )
        },
    )
    flux_column = fields.Integer(
        missing=1,
        metadata={
            'description': (
                "The 0-based index of the ASCII column corresponding to "
                "the flux values of the spectrum (default 1)."
            )
        },
    )
    fluxerr_column = fields.Integer(
        missing=None,
        metadata={
            'description': (
                "The 0-based index of the ASCII column corresponding to the flux "
                "error values of the spectrum (default None). If a column for errors "
                "is provided, set to the corresponding 0-based column number, "
                "otherwise, it will be ignored."
            )
        },
    )

    ascii = fields.String(
        metadata={
            'description': """The content of the ASCII file to be parsed.

The file can optionally contain a header which will be parsed and stored.

The lines that make up the ASCII header must appear at the beginning of the \
file and all be formatted the same way within a single file. They can be \
formatted in one of two ways.

```
1) # KEY: VALUE
2) # KEY = VALUE / COMMENT
```

`astropy.io.ascii.read` is used to load the table into Python memory. An \
attempt is made to parse the header first using method 1, then method 2.

Example of format 1:

```
# XTENSION: IMAGE
# BITPIX: -32
# NAXIS: 2
# NAXIS1: 433
# NAXIS2: 1
# RA: 230.14
```

Example of format 2:

```
# FILTER  = 'clear   '           / Filter
# EXPTIME =              600.003 / Total exposure time (sec); avg. of R&B
# OBJECT  = 'ZTF20abpuxna'       / User-specified object name
# TARGNAME= 'ZTF20abpuxna_S1'    / Target name (from starlist)
# DICHNAME= '560     '           / Dichroic
# GRISNAME= '400/3400'           / Blue grism
# GRANAME = '400/8500'           / Red grating
# WAVELEN =        7829.41406250 / Red specified central wavelength
# BLUFILT = 'clear   '           / Blue filter
# REDFILT = 'Clear   '           / Red filter
# SLITNAME= 'long_1.0'           / Slitmask
# INSTRUME= 'LRIS+LRISBLUE'      / Camera
# TELESCOP= 'Keck I  '           / Telescope name
# BLUDET  = 'LRISB   '           / LRIS blue detector
# REDDET  = 'LRISR3  '           / LRIS red detector
# OBSERVER= 'Andreoni Anand De'  / Observer name
# REDUCER = '        '           / Name of reducer
# LPIPEVER= '2020.06 '           / LPipe version number
# HOSTNAME= 'gayatri '           / LPipe host computer name
# IDLVER  = '8.1     '           / IDL version number
# DATE    = '2020-09-15T09:47:10' / UT end of last exposure
```

The data must be at least 2 column ascii (wavelength, flux). If flux errors are \
provided in an additional column, the column must be specified in the call. \
If more than 2 columns are given, by default the first two are interpreted as \
(wavelength, flux). The column indices of each of these arguments can be controlled \
by passing the integer column index to the POST JSON.

Examples of valid data sections:

Many-column ASCII:

```
   10295.736  2.62912e-16  1.67798e-15  2.24407e-17    4084    75.956  5.48188e+15  0
   10296.924  2.96887e-16  1.57197e-15  2.21469e-17    4085    75.959  5.42569e+15  0
   10298.112  3.20429e-16  1.45017e-15  2.16863e-17    4086    75.962  5.36988e+15  0
   10299.301  3.33367e-16  1.06116e-15  1.94187e-17    4087    75.965  5.31392e+15  0
   10300.489  3.09943e-16  6.99539e-16  1.67183e-17    4088    75.968  5.25836e+15  0
   10301.678  3.48273e-16  5.56194e-16  1.59555e-17    4089    75.972  5.20314e+15  0
   10302.866  3.48102e-16  5.28483e-16  1.58033e-17    4090    75.975  5.15146e+15  0
   10304.055  3.78640e-16  6.00997e-16  1.67462e-17    4091    75.978  5.10058e+15  0
   10305.243  4.28820e-16  7.18759e-16  1.81534e-17    4092    75.981  5.05032e+15  0
   10306.432  4.13152e-16  7.54203e-16  1.83965e-17    4093    75.984  5.00097e+15  0
```

3-column ASCII:

```
8993.2 1.148e-16 7.919e-34
9018.7 1.068e-16 6.588e-34
9044.3 1.056e-16 5.660e-34
9069.9 9.763e-17 5.593e-34
9095.4 1.048e-16 8.374e-34
9121.0 1.026e-16 8.736e-34
9146.6 8.472e-17 9.505e-34
9172.1 9.323e-17 7.592e-34
9197.7 1.050e-16 7.863e-34
9223.3 8.701e-17 7.135e-34
```

2-column ASCII:

```
      10045.1    0.0217740
      10046.3    0.0182158
      10047.4    0.0204764
      10048.6    0.0231833
      10049.8    0.0207157
      10051.0    0.0185226
      10052.2    0.0200072
      10053.4    0.0205159
      10054.5    0.0199460
      10055.7    0.0210533
```

2-column ASCII:
```
7911.60 1.045683
7920.80 1.046414
7930.00 1.235362
7939.20 0.783466
7948.40 1.116153
7957.60 1.375844
7966.80 1.029127
7976.00 1.019637
7985.20 0.732859
7994.40 1.236514
```

"""
        },
        required=True,
    )

class SpectrumAsciiFilePostJSON(SpectrumAsciiFileParseJSON):
    obj_id = fields.String(
        metadata={'description': 'The ID of the object that the spectrum is of.'},
        required=True,
    )

    instrument_id = fields.Integer(
        metadata={'description': 'The ID of the instrument that took the spectrum.'},
        required=True,
    )

    type = fields.String(
        validate=validate.OneOf(ALLOWED_SPECTRUM_TYPES),
        required=False,
        metadata={
            'by_value': True,
            'description': f'''Type of spectrum. One of: {', '.join(f"'{t}'" for t in ALLOWED_SPECTRUM_TYPES)}.
                    Defaults to 'f{default_spectrum_type}'.''',
        },
    )

    label = fields.String(
        metadata={
            'description': 'User defined label to be placed in plot legends, '
            'instead of the default <instrument>-<date taken>.'
        },
        required=False,
    )

    observed_at = fields.DateTime(
        metadata={'description': 'The ISO UTC time the spectrum was taken.'},
        required=True,
    )

    group_ids = fields.List(
        fields.Integer,
        metadata={'description': "The IDs of the groups to share this spectrum with."},
    )

    filename = fields.String(
        metadata={'description': "The original filename (for bookkeeping purposes)."},
        required=True,
    )
    reduced_by = fields.List(
        fields.Integer,
        metadata={
            'description': "IDs of the Users who reduced this Spectrum, or to use as points of contact given an external reducer."
        },
        missing=[],
    )

    external_reducer = fields.String(
        metadata={'description': "Free text provided as an external reducer"},
        required=False,
        missing=None,
    )

    observed_by = fields.List(
        fields.Integer,
        metadata={
            'description': "IDs of the Users who observed this Spectrum, or to use as points of contact given an external observer."
        },
        missing=[],
    )

    external_observer = fields.String(
        metadata={'description': "Free text provided as an external observer"},
        required=False,
        missing=None,
    )

    followup_request_id = fields.Integer(
        required=False,
        metadata={
            'description': (
                'ID of the Followup request that generated this spectrum, ' 'if any.'
            )
        },
    )

    assignment_id = fields.Integer(
        required=False,
        metadata={
            'description': (
                'ID of the classical assignment that generated this spectrum, '
                'if any.'
            )
        },
    )

class SpectrumPost(_Schema):

    wavelengths = fields.List(
        fields.Float,
        required=True,
        metadata={'description': "Wavelengths of the spectrum [Angstrom]."},
    )

    fluxes = fields.List(
        fields.Float,
        required=True,
        metadata={'description': "Flux of the Spectrum [F_lambda, arbitrary units]."},
    )

    errors = fields.List(
        fields.Float,
        metadata={
            'description': "Errors on the fluxes of the spectrum [F_lambda, same units as `fluxes`.]"
        },
    )

    obj_id = fields.String(
        required=True,
        metadata={'description': "ID of this Spectrum's Obj."},
    )

    observed_at = fields.DateTime(
        metadata={'description': 'The ISO UTC time the spectrum was taken.'},
        required=True,
    )

    reduced_by = fields.List(
        fields.Integer,
        metadata={
            'description': "IDs of the Users who reduced this Spectrum, or to use as points of contact given an external reducer."
        },
        missing=[],
    )

    external_reducer = fields.String(
        metadata={'description': "Free text provided as an external reducer"},
        required=False,
        missing=None,
    )

    observed_by = fields.List(
        fields.Integer,
        metadata={
            'description': "IDs of the Users who observed this Spectrum, or to use as points of contact given an external observer."
        },
        missing=[],
    )

    external_observer = fields.String(
        metadata={'description': "Free text provided as an external observer"},
        required=False,
        missing=None,
    )

    origin = fields.String(
        required=False, metadata={'description': "Origin of the spectrum."}
    )

    type = fields.String(
        validate=validate.OneOf(ALLOWED_SPECTRUM_TYPES),
        required=False,
        metadata={
            "description": f'''Type of spectrum. One of: {''.join(f"'{t}'" for t in ALLOWED_SPECTRUM_TYPES)}.
                         Defaults to 'f{default_spectrum_type}'.'''
        },
    )

    label = fields.String(
        required=False,
        metadata={
            'description': "User defined label (can be used to replace default instrument/date labeling on plot legends)."
        },
    )

    instrument_id = fields.Integer(
        required=True,
        metadata={'description': "ID of the Instrument that acquired the Spectrum."},
    )

    group_ids = fields.Field(
        missing=[],
        metadata={
            'description': 'IDs of the Groups to share this spectrum with. Set to "all"'
            ' to make this spectrum visible to all users.'
        },
    )

    followup_request_id = fields.Integer(
        required=False,
        metadata={
            'description': 'ID of the Followup request that generated this spectrum, '
            'if any.'
        },
    )

    assignment_id = fields.Integer(
        required=False,
        metadata={
            'description': 'ID of the classical assignment that generated this spectrum, '
            'if any.'
        },
    )

    altdata = fields.Field(
        metadata={'description': 'Miscellaneous alternative metadata.'}
    )

class GroupIDList(_Schema):

    group_ids = fields.List(fields.Integer, required=True)

class GalaxyHandlerPost(_Schema):
    catalog_name = fields.String(metadata={"description": 'Galaxy catalog name.'})
    catalog_data = fields.List(
        fields.Field(), metadata={"description": 'Galaxy catalog data'}
    )

def register_components(spec):
    print('Registering schemas with APISpec')

    schemas = inspect.getmembers(
        sys.modules[__name__], lambda m: isinstance(m, _Schema)
    )

    for (name, schema) in schemas:
        spec.components.schema(name, schema=schema)

        single = 'Single' + name
        arrayOf = 'ArrayOf' + name + 's'
        spec.components.schema(single, schema=success(single, schema))
        spec.components.schema(arrayOf, schema=success(arrayOf, [schema]))

# Replace schemas by instantiated versions
# These are picked up in `setup_schema` for the registry
Response = Response()
Error = Error()
Success = success('Success')
SinglePhotometryFlux = success('SinglePhotometryFlux', PhotometryFlux)
SinglePhotometryMag = success('SinglePhotometryMag', PhotometryMag)
PhotometryFlux = PhotometryFlux()
PhotometryMag = PhotometryMag()
PhotMagFlexible = PhotMagFlexible()
PhotFluxFlexible = PhotFluxFlexible()
ObservingRunPost = ObservingRunPost()
ObservingRunGet = ObservingRunGet()
AssignmentSchema = AssignmentSchema()
ObservingRunGetWithAssignments = ObservingRunGetWithAssignments()
PhotometryRangeQuery = PhotometryRangeQuery()
SpectrumAsciiFilePostJSON = SpectrumAsciiFilePostJSON()
FollowupRequestPost = FollowupRequestPost()
ObservationPlanPost = ObservationPlanPost()
ObservationExternalAPIHandlerPost = ObservationExternalAPIHandlerPost()
SpectrumAsciiFileParseJSON = SpectrumAsciiFileParseJSON()
SpectrumPost = SpectrumPost()
GroupIDList = GroupIDList()

max_stars_repo_name: Ejashba/skyportal

max_issues_repo_name: Ejashba/skyportal

max_forks_repo_name: Ejashba/skyportal

reason: import numpy,from astropy


text:
import numpy as np
import numpy.matlib
from kadal.misc.sampling.samplingplan import scale

def paregopre(yall,idx=False):
    """
    Pre-processing solutions for ParEGO

    Input:
      Yall - Original responses

    Output
       YN - Scalarized responses with random weights
    """
    NF = 11
    WGA = np.transpose([np.arange(0,1+1/(NF-1),1/(NF-1))])
    WGA = np.hstack((WGA,1-WGA))
    if idx is False:
        IDR = np.random.permutation(np.size(WGA,0))
        IDR = np.random.choice(IDR)
    else:
        IDR = idx
    WG = WGA[IDR,:]
    FFN,_ = scale(yall,0,range=np.vstack((np.min(yall,0),np.max(yall,0))))
    rho = 0.05

    YN = np.zeros(shape=[np.size(FFN,0),1])
    for IH in range(0,np.size(FFN,0)):
        YN[IH,:] = np.max((WG*(FFN[IH,:])),0) + rho*np.sum((WG*FFN[IH,:]),0)

    return YN


text:
import theano
import theano.tensor as T
import lasagne as nn
from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams

class SpatialDropoutLayer(Layer):
    """Spatial dropout layer
    Sets whole filter activations to zero with probability p. See notes for
    disabling dropout during testing.
    Parameters
    ----------
    incoming : a :class:`Layer` instance or a tuple
        the layer feeding into this layer, or the expected input shape
    p : float or scalar tensor
        The probability of setting a value to zero
    rescale : bool
        If true the input is rescaled with input / (1-p) when deterministic
        is False.
    Notes
    -----
    The spatial dropout layer is a regularizer that randomly sets whole the
    values of whole features to zero. This is an adaptation of normal dropout,
    which is generally useful in fully convolutional settings, such as [1]_.

    It is also called a feature dropout layer.

    During training you should set deterministic to false and during
    testing you should set deterministic to true.
    If rescale is true the input is scaled with input / (1-p) when
    deterministic is false, see references for further discussion. Note that
    this implementation scales the input at training time.
    References
    ----------
    .. [1] Oliveira, G. Valada, A., Bollen, C., Bugard, W., Brox. T. (2016):
           Deep Learning for Human Part Discovery in Images. IEEE
           International Conference on Robotics and Automation (ICRA), IEEE,
           2016.
    """
    def __init__(self, incoming, p=0.5, rescale=True, **kwargs):
        super(SpatialDropoutLayer, self).__init__(incoming, **kwargs)
        self._srng = RandomStreams(get_rng().randint(1, 2147462579))
        self.p = p
        self.rescale = rescale

    def get_output_for(self, input, deterministic=False, **kwargs):
        """
        Parameters
        ----------
        input : tensor
            output from the previous layer
        deterministic : bool
            If true dropout and scaling is disabled, see notes
        """
        if deterministic or self.p == 0:
            return input
        else:
            # Using theano constant to prevent upcasting
            one = T.constant(1)

            retain_prob = one - self.p
            if self.rescale:
                input /= retain_prob

            mask = _srng.binomial(input.shape[:2], p=retain_prob,
                                      dtype=theano.config.floatX)
            axes = [0, 1] + (['x'] * (input.ndim - 2))
            mask = mask.dimshuffle(*axes)

            return input * mask

reason: import theano,from theano


text:
import math
from PIL import Image, ImageFilter, ImageChops
import operator
import os
import numpy as np

# https://www.hdm-stuttgart.de/~maucher/Python/MMCodecs/html/basicFunctions.html
def entropy(signal):
    lensig = signal.size
    symset = list(set(signal))
    numsym = len(symset)
    propab = [np.size(signal[signal == i]) / (1.0 * lensig) for i in symset]
    ent = np.sum([p * np.log2(1.0 / p) for p in propab])
    return ent

# https://www.hdm-stuttgart.de/~maucher/Python/MMCodecs/html/basicFunctions.html
def entropy_matrix(greyIm, N = 3):
    S = greyIm.shape
    E = np.array(greyIm)
    for row in range(S[0]):
        for col in range(S[1]):
            Lx = np.max([0, col - N])
            Ux = np.min([S[1], col + N])
            Ly = np.max([0, row - N])
            Uy = np.min([S[0], row + N])
            region = greyIm[Ly:Uy, Lx:Ux].flatten()
            E[row, col] = entropy(region)

    return E

def entropy_matrix_image(colorIm):
    greyIm = colorIm.convert('L')
    colorIm = np.array(colorIm)
    greyIm = np.array(greyIm)

    return entropy_matrix(greyIm)

def complexity_score(ha):
    return np.sum(entropy_matrix(entropy_matrix_image(
        ha
    )))

def is_interesting(image, bottom_threshold=500, width=80, height=80):
        image.resize((width, height), Image.ANTIALIAS)
        score = complexity_score(image)

        return bottom_threshold < score

def process_image_set(filenames, images, type, bottom_threshold=500, top_threshold=9999999):
    imin = -1
    imax = 0

    correct_count = 0

    for i in range(0, len(filenames)):
        print 'Processing %s...' % filenames[i]
        img = images[i].resize((80, 80))
        score = complexity_score(img)

        interesting = score<top_threshold and score>bottom_threshold

        correct = (type.lower() == 'interesting') == interesting

        if correct:
            correct_count += 1

        print '%s, %s, %s\t\t%s\t(%s)' % (type, filenames[i], score, 'INTERESTING' if interesting else 'NONINTERESTING','correct' if correct else 'incorrect')

        if imin is -1:
            imin = score

        if imin > score:
            imin = score

        if imax < score:
            imax = score

    stats = (imin, imax, imax - imin, float(correct_count)/float(len(images))*100)

    print 'min: %s, max: %s, range: %s, accuracy: %s%%' % stats

    return stats

def main(root="test_images"):
    interesting_filenames = os.listdir("%s/interesting" % root)
    uninteresting_filenames = os.listdir("%s/uninteresting" % root)

    interesting_images = []
    for name in interesting_filenames:
        interesting_images.append(Image.open("%s/interesting/%s" % (root, name)))
    uninteresting_images = []
    for name in uninteresting_filenames:
        uninteresting_images.append(Image.open("%s/uninteresting/%s" % (root, name)))

    interesting_stats = process_image_set(interesting_filenames, interesting_images, 'interesting')
    print '----'
    uninteresting_stats = process_image_set(uninteresting_filenames, uninteresting_images, 'uninteresting')

    print '----'

    print uninteresting_stats[1] - interesting_stats[0]

if __name__ == "__main__":
    main(root="test_images")

max_stars_repo_name: jake-billings/research-blockchain

max_issues_repo_name: jake-billings/research-blockchain

max_forks_repo_name: jake-billings/research-blockchain