  ciphertext = []
  # generate Vigenere table
  layers = []
  for i in range(len(plain_vocab)):
    layers.append(ShiftEncryptionLayer(plain_vocab, i))

  for i, sentence in enumerate(plaintext):
    cipher_sentence = []
    for j, character in enumerate(sentence):
      key_idx = key[j % len(key)]
      encrypted_char = layers[key_idx].encrypt_character(character)
      cipher_sentence.append(encrypted_char)
    ciphertext.append(cipher_sentence)

  return ciphertext

"""Cipher data generators."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from collections import deque

# Dependency imports

import numpy as np

from tensor2tensor.data_generators import algorithmic
from tensor2tensor.utils import registry

@registry.register_problem
class AlgorithmicCipherShift5(algorithmic.AlgorithmicProblem):
  """Shift cipher."""

  @property
  def num_symbols(self):
    return 5

  @property
  def distribution(self):
    return [0.4, 0.3, 0.2, 0.08, 0.02]

  @property
  def shift(self):
    return 1

  def generator(self, nbr_symbols, max_length, nbr_cases):
    plain_vocab = range(nbr_symbols)
    indices = generate_plaintext_random(
        plain_vocab, self.distribution, nbr_cases, max_length)
    codes = encipher_shift(indices, plain_vocab, self.shift)
    for plain, code in zip(indices, codes):
      yield {"inputs": plain, "targets": code}

  @property
  def train_length(self):
    return 100

  @property
  def dev_length(self):
    return self.train_length

@registry.register_problem
class AlgorithmicCipherVigenere5(algorithmic.AlgorithmicProblem):
  """Vinegre cipher."""

  @property
  def num_symbols(self):
    return 5

  @property
  def distribution(self):
    return [0.4, 0.3, 0.2, 0.08, 0.02]

  @property
  def key(self):
    return [1, 3]

  def generator(self, nbr_symbols, max_length, nbr_cases):
    plain_vocab = range(nbr_symbols)
    indices = generate_plaintext_random(plain_vocab, self.distribution,
                                        nbr_cases, max_length)
    codes = encipher_vigenere(indices, plain_vocab, self.key)
    for plain, code in zip(indices, codes):
      yield {"inputs": plain, "targets": code}

  @property
  def train_length(self):
    return 200

  @property
  def dev_length(self):
    return self.train_length

@registry.register_problem
class AlgorithmicCipherShift200(AlgorithmicCipherShift5):
  """Shift cipher."""

  @property
  def num_symbols(self):
    return 200

  @property
  def distribution(self):
    vals = range(self.num_symbols)
    val_sum = sum(vals)
    return [v / val_sum for v in vals]

@registry.register_problem
class AlgorithmicCipherVigenere200(AlgorithmicCipherVigenere5):
  """Vinegre cipher."""

  @property
  def num_symbols(self):
    return 200

  @property
  def distribution(self):
    vals = range(self.num_symbols)
    val_sum = sum(vals)
    return [v / val_sum for v in vals]

  @property
  def key(self):
    return [1, 3]

class ShiftEncryptionLayer(object):
  """A single layer for shift."""

  def __init__(self, vocab, shift):
    """Initialize shift layer.

    Args:
      vocab: (list of String) the vocabulary
      shift: (Integer) the amount of shift apply to the alphabet.
        Positive number implies shift to the right, negative number
        implies shift to the left.
    """
    self.shift = shift
    alphabet = vocab
    shifted_alphabet = deque(alphabet)
    shifted_alphabet.rotate(shift)
    self.encrypt = dict(zip(alphabet, list(shifted_alphabet)))
    self.decrypt = dict(zip(list(shifted_alphabet), alphabet))

  def encrypt_character(self, character):
    return self.encrypt[character]

  def decrypt_character(self, character):
    return self.decrypt[character]

def generate_plaintext_random(plain_vocab, distribution, train_samples,
                              length):
  """Generates samples of text from the provided vocabulary.

  Args:
    plain_vocab: vocabulary.
    distribution: distribution.
    train_samples: samples for training.
    length: length.

  Returns:
    train_indices (np.array of Integers): random integers for training.
      shape = [num_samples, length]
    test_indices (np.array of Integers): random integers for testing.
      shape = [num_samples, length]
    plain_vocab   (list of Integers): unique vocabularies.
  """
  if distribution is not None:
    assert len(distribution) == len(plain_vocab)

  train_indices = np.random.choice(
      range(len(plain_vocab)), (train_samples, length), p=distribution)

  return train_indices

def encipher_shift(plaintext, plain_vocab, shift):
  """Encrypt plain text with a single shift layer.

  Args:
    plaintext (list of list of Strings): a list of plain text to encrypt.
    plain_vocab (list of Integer): unique vocabularies being used.
    shift (Integer): number of shift, shift to the right if shift is positive.
  Returns:
    ciphertext (list of Strings): encrypted plain text.
  """
  ciphertext = []
  cipher = ShiftEncryptionLayer(plain_vocab, shift)

  for _, sentence in enumerate(plaintext):
    cipher_sentence = []
    for _, character in enumerate(sentence):
      encrypted_char = cipher.encrypt_character(character)
      cipher_sentence.append(encrypted_char)
    ciphertext.append(cipher_sentence)

  return ciphertext

def encipher_vigenere(plaintext, plain_vocab, key):
  """Encrypt plain text with given key.

  Args:
    plaintext (list of list of Strings): a list of plain text to encrypt.
    plain_vocab (list of Integer): unique vocabularies being used.
    key (list of Integer): key to encrypt cipher using Vigenere table.

  Returns:
    ciphertext (list of Strings): encrypted plain text.
  """


    import pytorch_reservoir

    if isinstance(a, int):
        a = torch.arange(a, dtype=dtype, device=device)
    if not torch.is_tensor(a):
        a = torch.tensor(a)

    assert a.dim() == 1, 'jactorch.choice supports only 1-D input.'
    a = a.to(dtype=dtype, device=device)

    if p is not None:
        assert a.size() == p.size()
        return pytorch_reservoir.choice(a, p.to(device=device), replace, k)

    return pytorch_reservoir.choice(a, replace, k)

# File   : sample.py
# Author : Jiayuan Mao
# Email  : example@nnthink.com
# This file is part of Jacinle.

import torch
import torch.autograd as autograd

from jacinle.utils.vendor import requires_vendors
from .indexing import one_hot_nd

__all__ = ['sample_bernoulli', 'sample_multinomial', 'choice']

class SampleBernoulli(autograd.Function):
    @staticmethod
    def forward(ctx, input):
        rand = input.new(*input.size())
        torch.rand(input.size(), out=rand)
        return (rand > input).float()

    @staticmethod
    def backward(ctx, grad_output):
        return grad_output

def sample_bernoulli(input):
    return SampleBernoulli.apply(input)

class SampleMultinomial(autograd.Function):
    @staticmethod
    def forward(ctx, input, dim):
        input = input.transpose(dim, -1)
        input_flatten = input.contiguous().view(-1, input.size(-1))
        rand = torch.multinomial(input_flatten, 1).view(input.size()[:-1])
        output = one_hot_nd(rand, input.size(dim))
        output = output.transpose(dim, -1)
        return output.float()

    @staticmethod
    def backward(ctx, grad_output):
        return grad_output, None

def sample_multinomial(input, dim=-1):
    return SampleMultinomial.apply(input, dim)

@requires_vendors('pytorch_reservoir')
def choice(a, k=1, replace=True, p=None, dtype=None, device=None):
    """
    Generates a random sample from a given 1-D array.

    Args:
        a (torch.Tensor): 1-D tensor or int.
        k (int, optional): number of samples to be drawn.
        replace (bool, optional): whether the sample is with or without replacement.
        p (torch.Tensor, optional): an optional weight parameter. Not necessarily to be normalized.

    Returns:
        torch.Tensor: 1-D outputs of k sampled data from `a`.
    """


    g = []
    v = []
    for tower in grad_list:
        g.append([x[0] for x in tower])
        v.append([x[1] for x in tower])
    return g, v

import itertools
import os
from collections import OrderedDict

import numpy as np
import six
import tensorflow as tf
import tensorflow.contrib.graph_editor as ge
from tensorflow.core.framework import node_def_pb2
from tensorflow.python.framework import device as pydev
from tensorflow.python.training import device_setter
from tensorflow.python.util import nest

from video_prediction.utils import ffmpeg_gif
from video_prediction.utils import gif_summary

IMAGE_SUMMARIES = "image_summaries"
EVAL_SUMMARIES = "eval_summaries"

def local_device_setter(num_devices=1,
                        ps_device_type='cpu',
                        worker_device='/cpu:0',
                        ps_ops=None,
                        ps_strategy=None):
    if ps_ops == None:
        ps_ops = ['Variable', 'VariableV2', 'VarHandleOp']

    if ps_strategy is None:
        ps_strategy = device_setter._RoundRobinStrategy(num_devices)
    if not six.callable(ps_strategy):
        raise TypeError("ps_strategy must be callable")

    def _local_device_chooser(op):
        current_device = pydev.DeviceSpec.from_string(op.device or "")

        node_def = op if isinstance(op, node_def_pb2.NodeDef) else op.node_def
        if node_def.op in ps_ops:
            ps_device_spec = pydev.DeviceSpec.from_string(
                '/{}:{}'.format(ps_device_type, ps_strategy(op)))

            ps_device_spec.merge_from(current_device)
            return ps_device_spec.to_string()
        else:
            worker_device_spec = pydev.DeviceSpec.from_string(worker_device or "")
            worker_device_spec.merge_from(current_device)
            return worker_device_spec.to_string()

    return _local_device_chooser

def replace_read_ops(loss_or_losses, var_list):
    """
    Replaces read ops of each variable in `vars` with new read ops obtained
    from `read_value()`, thus forcing to read the most up-to-date values of
    the variables (which might incur copies across devices).
    The graph is seeded from the tensor(s) `loss_or_losses`.
    """
    # ops between var ops and the loss
    ops = set(ge.get_walks_intersection_ops([var.op for var in var_list], loss_or_losses))
    if not ops:  # loss_or_losses doesn't depend on any var in var_list, so there is nothiing to replace
        return

    # filter out variables that are not involved in computing the loss
    var_list = [var for var in var_list if var.op in ops]

    for var in var_list:
        output, = var.op.outputs
        read_ops = set(output.consumers()) & ops
        for read_op in read_ops:
            with tf.name_scope('/'.join(read_op.name.split('/')[:-1])):
                with tf.device(read_op.device):
                    read_t, = read_op.outputs
                    consumer_ops = set(read_t.consumers()) & ops
                    # consumer_sgv might have multiple inputs, but we only care
                    # about replacing the input that is read_t
                    consumer_sgv = ge.sgv(consumer_ops)
                    consumer_sgv = consumer_sgv.remap_inputs([list(consumer_sgv.inputs).index(read_t)])
                    ge.connect(ge.sgv(var.read_value().op), consumer_sgv)

def print_loss_info(losses, *tensors):
    def get_descendants(tensor, tensors):
        descendants = []
        for child in tensor.op.inputs:
            if child in tensors:
                descendants.append(child)
            else:
                descendants.extend(get_descendants(child, tensors))
        return descendants

    name_to_tensors = itertools.chain(*[tensor.items() for tensor in tensors])
    tensor_to_names = OrderedDict([(v, k) for k, v in name_to_tensors])

    print(tf.get_default_graph().get_name_scope())
    for name, (loss, weight) in losses.items():
        print('  %s (%r)' % (name, weight))
        descendant_names = []
        for descendant in set(get_descendants(loss, tensor_to_names.keys())):
            descendant_names.append(tensor_to_names[descendant])
        for descendant_name in sorted(descendant_names):
            print('    %s' % descendant_name)

def with_flat_batch(flat_batch_fn, ndims=4):
    def fn(x, *args, **kwargs):
        shape = tf.shape(x)
        flat_batch_shape = tf.concat([[-1], shape[-(ndims-1):]], axis=0)
        flat_batch_shape.set_shape([ndims])
        flat_batch_x = tf.reshape(x, flat_batch_shape)
        flat_batch_r = flat_batch_fn(flat_batch_x, *args, **kwargs)
        r = nest.map_structure(lambda x: tf.reshape(x, tf.concat([shape[:-(ndims-1)], tf.shape(x)[1:]], axis=0)),
                               flat_batch_r)
        return r
    return fn

def transpose_batch_time(x):
    if isinstance(x, tf.Tensor) and x.shape.ndims >= 2:
        return tf.transpose(x, [1, 0] + list(range(2, x.shape.ndims)))
    else:
        return x

def dimension(inputs, axis=0):
    shapes = [input_.shape for input_ in nest.flatten(inputs)]
    s = tf.TensorShape([None])
    for shape in shapes:
        s = s.merge_with(shape[axis:axis + 1])
    dim = s[0].value
    return dim

def unroll_rnn(cell, inputs, scope=None, use_dynamic_rnn=True):
    """Chooses between dynamic_rnn and static_rnn if the leading time dimension is dynamic or not."""
    dim = dimension(inputs, axis=0)
    if use_dynamic_rnn or dim is None:
        return tf.nn.dynamic_rnn(cell, inputs, dtype=tf.float32,
                                 swap_memory=False, time_major=True, scope=scope)
    else:
        return static_rnn(cell, inputs, scope=scope)

def static_rnn(cell, inputs, scope=None):
    """Simple version of static_rnn."""
    with tf.variable_scope(scope or "rnn") as varscope:
        batch_size = dimension(inputs, axis=1)
        state = cell.zero_state(batch_size, tf.float32)
        flat_inputs = nest.flatten(inputs)
        flat_inputs = list(zip(*[tf.unstack(flat_input, axis=0) for flat_input in flat_inputs]))
        flat_outputs = []
        for time, flat_input in enumerate(flat_inputs):
            if time > 0:
                varscope.reuse_variables()
            input_ = nest.pack_sequence_as(inputs, flat_input)
            output, state = cell(input_, state)
            flat_output = nest.flatten(output)
            flat_outputs.append(flat_output)
        flat_outputs = [tf.stack(flat_output, axis=0) for flat_output in zip(*flat_outputs)]
        outputs = nest.pack_sequence_as(output, flat_outputs)
        return outputs, state

def maybe_pad_or_slice(tensor, desired_length):
    length = tensor.shape.as_list()[0]
    if length < desired_length:
        paddings = [[0, desired_length - length]] + [[0, 0]] * (tensor.shape.ndims - 1)
        tensor = tf.pad(tensor, paddings)
    elif length > desired_length:
        tensor = tensor[:desired_length]
    assert tensor.shape.as_list()[0] == desired_length
    return tensor

def tensor_to_clip(tensor):
    if tensor.shape.ndims == 6:
        # concatenate last dimension vertically
        tensor = tf.concat(tf.unstack(tensor, axis=-1), axis=-3)
    if tensor.shape.ndims == 5:
        # concatenate batch dimension horizontally
        tensor = tf.concat(tf.unstack(tensor, axis=0), axis=2)
    if tensor.shape.ndims == 4:
        # keep up to the first 3 channels
        tensor = tf.image.convert_image_dtype(tensor, dtype=tf.uint8, saturate=True)
    else:
        raise NotImplementedError
    return tensor

def tensor_to_image_batch(tensor):
    if tensor.shape.ndims == 6:
        # concatenate last dimension vertically
        tensor= tf.concat(tf.unstack(tensor, axis=-1), axis=-3)
    if tensor.shape.ndims == 5:
        # concatenate time dimension horizontally
        tensor = tf.concat(tf.unstack(tensor, axis=1), axis=2)
    if tensor.shape.ndims == 4:
        # keep up to the first 3 channels
        tensor = tf.image.convert_image_dtype(tensor, dtype=tf.uint8, saturate=True)
    else:
        raise NotImplementedError
    return tensor

def _as_name_scope_map(values):
    name_scope_to_values = {}
    for name, value in values.items():
        name_scope = name.split('/')[0]
        name_scope_to_values.setdefault(name_scope, {})
        name_scope_to_values[name_scope][name] = value
    return name_scope_to_values

def add_image_summaries(outputs, max_outputs=8, collections=None):
    if collections is None:
        collections = [tf.GraphKeys.SUMMARIES, IMAGE_SUMMARIES]
    for name_scope, outputs in _as_name_scope_map(outputs).items():
        with tf.name_scope(name_scope):
            for name, output in outputs.items():
                if max_outputs:
                    output = output[:max_outputs]
                output = tensor_to_image_batch(output)
                if output.shape[-1] not in (1, 3):
                    # these are feature maps, so just skip them
                    continue
                tf.summary.image(name, output, collections=collections)

def add_gif_summaries(outputs, max_outputs=8, collections=None):
    if collections is None:
        collections = [tf.GraphKeys.SUMMARIES, IMAGE_SUMMARIES]
    for name_scope, outputs in _as_name_scope_map(outputs).items():
        with tf.name_scope(name_scope):
            for name, output in outputs.items():
                if max_outputs:
                    output = output[:max_outputs]
                output = tensor_to_clip(output)
                if output.shape[-1] not in (1, 3):
                    # these are feature maps, so just skip them
                    continue
                gif_summary.gif_summary(name, output[None], fps=4, collections=collections)

def add_scalar_summaries(losses_or_metrics, collections=None):
    for name_scope, losses_or_metrics in _as_name_scope_map(losses_or_metrics).items():
        with tf.name_scope(name_scope):
            for name, loss_or_metric in losses_or_metrics.items():
                if isinstance(loss_or_metric, tuple):
                    loss_or_metric, _ = loss_or_metric
                tf.summary.scalar(name, loss_or_metric, collections=collections)

def add_summaries(outputs, collections=None):
    scalar_outputs = OrderedDict()
    image_outputs = OrderedDict()
    gif_outputs = OrderedDict()
    for name, output in outputs.items():
        if not isinstance(output, tf.Tensor):
            continue
        if output.shape.ndims == 0:
            scalar_outputs[name] = output
        elif output.shape.ndims == 4:
            image_outputs[name] = output
        elif output.shape.ndims > 4 and output.shape[4].value in (1, 3):
            gif_outputs[name] = output
    add_scalar_summaries(scalar_outputs, collections=collections)
    add_image_summaries(image_outputs, collections=collections)
    add_gif_summaries(gif_outputs, collections=collections)

def plot_buf(y):
    def _plot_buf(y):
        from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
        from matplotlib.figure import Figure
        import io
        fig = Figure(figsize=(3, 3))
        canvas = FigureCanvas(fig)
        ax = fig.add_subplot(111)
        ax.plot(y)
        ax.grid(axis='y')
        fig.tight_layout(pad=0)

        buf = io.BytesIO()
        fig.savefig(buf, format='png')
        buf.seek(0)
        return buf.getvalue()

    s = tf.py_func(_plot_buf, [y], tf.string)
    return s

def add_plot_image_summaries(metrics, collections=None):
    if collections is None:
        collections = [IMAGE_SUMMARIES]
    for name_scope, metrics in _as_name_scope_map(metrics).items():
        with tf.name_scope(name_scope):
            for name, metric in metrics.items():
                try:
                    buf = plot_buf(metric)
                except:
                    continue
                image = tf.image.decode_png(buf, channels=4)
                image = tf.expand_dims(image, axis=0)
                tf.summary.image(name, image, max_outputs=1, collections=collections)

def plot_summary(name, x, y, display_name=None, description=None, collections=None):
    """
    Hack that uses pr_curve summaries for 2D plots.

    Args:
        x: 1-D tensor with values in increasing order.
        y: 1-D tensor with static shape.

    Note: tensorboard needs to be modified and compiled from source to disable
    default axis range [-0.05, 1.05].
    """
    from tensorboard import summary as summary_lib
    x = tf.convert_to_tensor(x)
    y = tf.convert_to_tensor(y)
    with tf.control_dependencies([
        tf.assert_equal(tf.shape(x), tf.shape(y)),
        tf.assert_equal(y.shape.ndims, 1),
    ]):
        y = tf.identity(y)
    num_thresholds = y.shape[0].value
    if num_thresholds is None:
        raise ValueError('Size of y needs to be statically defined for num_thresholds argument')
    summary = summary_lib.pr_curve_raw_data_op(
        name,
        true_positive_counts=tf.ones(num_thresholds),
        false_positive_counts=tf.ones(num_thresholds),
        true_negative_counts=tf.ones(num_thresholds),
        false_negative_counts=tf.ones(num_thresholds),
        precision=y[::-1],
        recall=x[::-1],
        num_thresholds=num_thresholds,
        display_name=display_name,
        description=description,
        collections=collections)
    return summary

def add_plot_summaries(metrics, x_offset=0, collections=None):
    for name_scope, metrics in _as_name_scope_map(metrics).items():
        with tf.name_scope(name_scope):
            for name, metric in metrics.items():
                plot_summary(name, x_offset + tf.range(tf.shape(metric)[0]), metric, collections=collections)

def add_plot_and_scalar_summaries(metrics, x_offset=0, collections=None):
    for name_scope, metrics in _as_name_scope_map(metrics).items():
        with tf.name_scope(name_scope):
            for name, metric in metrics.items():
                tf.summary.scalar(name, tf.reduce_mean(metric), collections=collections)
                plot_summary(name, x_offset + tf.range(tf.shape(metric)[0]), metric, collections=collections)

def convert_tensor_to_gif_summary(summ):
    if isinstance(summ, bytes):
        summary_proto = tf.Summary()
        summary_proto.ParseFromString(summ)
        summ = summary_proto

    summary = tf.Summary()
    for value in summ.value:
        tag = value.tag
        try:
            images_arr = tf.make_ndarray(value.tensor)
        except TypeError:
            summary.value.add(tag=tag, image=value.image)
            continue

        if len(images_arr.shape) == 5:
            images_arr = np.concatenate(list(images_arr), axis=-2)
        if len(images_arr.shape) != 4:
            raise ValueError('Tensors must be 4-D or 5-D for gif summary.')
        channels = images_arr.shape[-1]
        if channels < 1 or channels > 4:
            raise ValueError('Tensors must have 1, 2, 3, or 4 color channels for gif summary.')

        encoded_image_string = ffmpeg_gif.encode_gif(images_arr, fps=4)

        image = tf.Summary.Image()
        image.height = images_arr.shape[-3]
        image.width = images_arr.shape[-2]
        image.colorspace = channels  # 1: grayscale, 2: grayscale + alpha, 3: RGB, 4: RGBA
        image.encoded_image_string = encoded_image_string
        summary.value.add(tag=tag, image=image)
    return summary

def compute_averaged_gradients(opt, tower_loss, **kwargs):
    tower_gradvars = []
    for loss in tower_loss:
        with tf.device(loss.device):
            gradvars = opt.compute_gradients(loss, **kwargs)
            tower_gradvars.append(gradvars)

    # Now compute global loss and gradients.
    gradvars = []
    with tf.name_scope('gradient_averaging'):
        all_grads = {}
        for grad, var in itertools.chain(*tower_gradvars):
            if grad is not None:
                all_grads.setdefault(var, []).append(grad)
        for var, grads in all_grads.items():
            # Average gradients on the same device as the variables
            # to which they apply.
            with tf.device(var.device):
                if len(grads) == 1:
                    avg_grad = grads[0]
                else:
                    avg_grad = tf.multiply(tf.add_n(grads), 1. / len(grads))
            gradvars.append((avg_grad, var))
    return gradvars

# the next 3 function are from tensorpack:
def split_grad_list(grad_list):
    """
    Args:
        grad_list: K x N x 2

    Returns:
        K x N: gradients
        K x N: variables
    """

def merge_grad_list(all_grads, all_vars):
    """
    Args:
        all_grads (K x N): gradients
        all_vars(K x N): variables

    Return:
        K x N x 2: list of list of (grad, var) pairs
    """
    return [list(zip(gs, vs)) for gs, vs in zip(all_grads, all_vars)]

def allreduce_grads(all_grads, average):
    """
    All-reduce average the gradients among K devices. Results are broadcasted to all devices.

    Args:
        all_grads (K x N): List of list of gradients. N is the number of variables.
        average (bool): average gradients or not.

    Returns:
        K x N: same as input, but each grad is replaced by the average over K devices.
    """
    from tensorflow.contrib import nccl
    nr_tower = len(all_grads)
    if nr_tower == 1:
        return all_grads
    new_all_grads = []  # N x K
    for grads in zip(*all_grads):
        summed = nccl.all_sum(grads)

        grads_for_devices = []  # K
        for g in summed:
            with tf.device(g.device):
                # tensorflow/benchmarks didn't average gradients
                if average:
                    g = tf.multiply(g, 1.0 / nr_tower)
            grads_for_devices.append(g)
        new_all_grads.append(grads_for_devices)

    # transpose to K x N
    ret = list(zip(*new_all_grads))
    return ret

def _reduce_entries(*entries):
    num_gpus = len(entries)
    if entries[0] is None:
        assert all(entry is None for entry in entries[1:])
        reduced_entry = None
    elif isinstance(entries[0], tf.Tensor):
        if entries[0].shape.ndims == 0:
            reduced_entry = tf.add_n(entries) / tf.to_float(num_gpus)
        else:
            reduced_entry = tf.concat(entries, axis=0)
    elif np.isscalar(entries[0]) or isinstance(entries[0], np.ndarray):
        if np.isscalar(entries[0]) or entries[0].ndim == 0:
            reduced_entry = sum(entries) / float(num_gpus)
        else:
            reduced_entry = np.concatenate(entries, axis=0)
    elif isinstance(entries[0], tuple) and len(entries[0]) == 2:
        losses, weights = zip(*entries)
        loss = tf.add_n(losses) / tf.to_float(num_gpus)
        if isinstance(weights[0], tf.Tensor):
            with tf.control_dependencies([tf.assert_equal(weight, weights[0]) for weight in weights[1:]]):
                weight = tf.identity(weights[0])
        else:
            assert all(weight == weights[0] for weight in weights[1:])
            weight = weights[0]
        reduced_entry = (loss, weight)
    else:
        raise NotImplementedError
    return reduced_entry

def reduce_tensors(structures, shallow=False):
    if len(structures) == 1:
        reduced_structure = structures[0]
    else:
        if shallow:
            if isinstance(structures[0], dict):
                shallow_tree = type(structures[0])([(k, None) for k in structures[0]])
            else:
                shallow_tree = type(structures[0])([None for _ in structures[0]])
            reduced_structure = nest.map_structure_up_to(shallow_tree, _reduce_entries, *structures)
        else:
            reduced_structure = nest.map_structure(_reduce_entries, *structures)
    return reduced_structure

def get_checkpoint_restore_saver(checkpoint, var_list=None, skip_global_step=False, restore_to_checkpoint_mapping=None):
    if os.path.isdir(checkpoint):
        # latest_checkpoint doesn't work when the path has special characters
        checkpoint = tf.train.latest_checkpoint(checkpoint)
    checkpoint_reader = tf.pywrap_tensorflow.NewCheckpointReader(checkpoint)
    checkpoint_var_names = checkpoint_reader.get_variable_to_shape_map().keys()
    restore_to_checkpoint_mapping = restore_to_checkpoint_mapping or (lambda name, _: name.split(':')[0])
    if not var_list:
        var_list = tf.global_variables()
    restore_vars = {restore_to_checkpoint_mapping(var.name, checkpoint_var_names): var for var in var_list}
    if skip_global_step and 'global_step' in restore_vars:
        del restore_vars['global_step']
    # restore variables that are both in the global graph and in the checkpoint
    restore_and_checkpoint_vars = {name: var for name, var in restore_vars.items() if name in checkpoint_var_names}
    restore_saver = tf.train.Saver(max_to_keep=1, var_list=restore_and_checkpoint_vars, filename=checkpoint)
    # print out information regarding variables that were not restored or used for restoring
    restore_not_in_checkpoint_vars = {name: var for name, var in restore_vars.items() if
                                      name not in checkpoint_var_names}
    checkpoint_not_in_restore_var_names = [name for name in checkpoint_var_names if name not in restore_vars]
    if skip_global_step and 'global_step' in checkpoint_not_in_restore_var_names:
        checkpoint_not_in_restore_var_names.remove('global_step')
    if restore_not_in_checkpoint_vars:
        print("global variables that were not restored because they are "
              "not in the checkpoint:")
        for name, _ in sorted(restore_not_in_checkpoint_vars.items()):
            print("    ", name)
    if checkpoint_not_in_restore_var_names:
        print("checkpoint variables that were not used for restoring "
              "because they are not in the graph:")
        for name in sorted(checkpoint_not_in_restore_var_names):
            print("    ", name)
    return restore_saver, checkpoint

def pixel_distribution(pos, height, width):
    batch_size = pos.get_shape().as_list()[0]
    y, x = tf.unstack(pos, 2, axis=1)

    x0 = tf.cast(tf.floor(x), 'int32')
    x1 = x0 + 1
    y0 = tf.cast(tf.floor(y), 'int32')
    y1 = y0 + 1

    Ia = tf.reshape(tf.one_hot(y0 * width + x0, height * width), [batch_size, height, width])
    Ib = tf.reshape(tf.one_hot(y1 * width + x0, height * width), [batch_size, height, width])
    Ic = tf.reshape(tf.one_hot(y0 * width + x1, height * width), [batch_size, height, width])
    Id = tf.reshape(tf.one_hot(y1 * width + x1, height * width), [batch_size, height, width])

    x0_f = tf.cast(x0, 'float32')
    x1_f = tf.cast(x1, 'float32')
    y0_f = tf.cast(y0, 'float32')
    y1_f = tf.cast(y1, 'float32')
    wa = ((x1_f - x) * (y1_f - y))[:, None, None]
    wb = ((x1_f - x) * (y - y0_f))[:, None, None]
    wc = ((x - x0_f) * (y1_f - y))[:, None, None]
    wd = ((x - x0_f) * (y - y0_f))[:, None, None]

    return tf.add_n([wa * Ia, wb * Ib, wc * Ic, wd * Id])

def flow_to_rgb(flows):
    """The last axis should have dimension 2, for x and y values."""

    def cartesian_to_polar(x, y):
        magnitude = tf.sqrt(tf.square(x) + tf.square(y))
        angle = tf.atan2(y, x)
        return magnitude, angle

    mag, ang = cartesian_to_polar(*tf.unstack(flows, axis=-1))
    ang_normalized = (ang + np.pi) / (2 * np.pi)
    mag_min = tf.reduce_min(mag)
    mag_max = tf.reduce_max(mag)
    mag_normalized = (mag - mag_min) / (mag_max - mag_min)
    hsv = tf.stack([ang_normalized, tf.ones_like(ang), mag_normalized], axis=-1)
    rgb = tf.image.hsv_to_rgb(hsv)
    return rgb


import struct

TYPE_UID = 0x00
TYPE_URL = 0x10
TYPE_TLM = 0x20

_DEFAULT_FRAME = (
    b"\x02"      # Flags length
    b"\x01"      # Flags data type value
    b"\x00"      # Flags data
    b"\x03"      # Service UUID length
    b"\x03"      # Service UUID data type value
    b"\xAA\xFE"  # 16-bit Eddystone UUID
    b"\x04"      # Service Data length
    b"\x16"      # Service Data data type value
    b"\xAA\xFE"  # 16-bit Eddystone UUID
)

_FLAGS_INDEX = 2
_DEFAULT_FLAGS = 0x06

_LENGTH_INDEX = 7

def _check_for_valid_eddystone(frame, expected_len=None):
    frame_len = len(frame)

    # Verify the length of the advertisement payload.
    # The advertisement contains many length bytes, make sure those lengths add up to the total frame length.
    parse_len = 0
    while True:
        # The length of the field plus the byte for the length of the field
        parse_len += frame[parse_len] + 1

        # The seventh byte is always the eddystone length. Make sure is matches the expected length if specified.
        if expected_len is not None and parse_len == _LENGTH_INDEX and frame[parse_len] != expected_len:
            return False

        # Invalid length bytes in payload
        if parse_len > frame_len:
            return False
        elif parse_len == frame_len:
            break

    # All Eddystone advertisements have the same first 12 bytes (excluding the payload length byte and data flags)
    if (
        frame[:_FLAGS_INDEX] != _DEFAULT_FRAME[:_FLAGS_INDEX] or
        frame[_FLAGS_INDEX + 1:_LENGTH_INDEX] != _DEFAULT_FRAME[_FLAGS_INDEX + 1:_LENGTH_INDEX] or
        frame[8:11] != _DEFAULT_FRAME[8:11]
    ):
        return False

    return True

class _EddystoneGenericFrame(object):
    """
    This class is a generic Advertising frame providing common functions, not to be instantiated.
    """

    def __init__(self, eddystone_type, payload_len, data_flags):
        self._frame = bytearray()
        self._frame.extend(_DEFAULT_FRAME)
        self._frame[_FLAGS_INDEX] = data_flags
        self._frame.append(eddystone_type)  # Eddystone type
        # Extends the frame to have payload_len number of zero bytes at the end
        self._frame += bytearray(payload_len)
        self._set_payload_length(payload_len)

    def _set_payload_length(self, length):
        self._frame[_LENGTH_INDEX] = 4 + length  # 7th byte specifies the payload len. There are 4 bytes that are used in all frames

    def set_raw_payload(self, payload):
        payload_len = len(payload)
        if payload_len > 19:
            raise TypeError("The payload is too large")

        # Cut off the existing payload (beyond the default frame)
        offset = len(_DEFAULT_FRAME)
        self._frame = self._frame[:offset + 1]
        # Place the new payload at the end
        self._frame.extend(payload)
        self._set_payload_length(payload_len)

    def get_bytes(self) -> bytes:
        """
        Get the advertisement payload. Used to send this frame.
        """
        return bytes(self._frame)

    def _validate_payload(self, expected_len=None):
        return _check_for_valid_eddystone(self._frame, expected_len)

    def validate_payload(self):
        return self._validate_payload(None)

    @property
    def eddystone_type(self):
        if len(self._frame) >= 13 and self._frame[11] in [TYPE_UID, TYPE_URL, TYPE_TLM]:
            return self._frame[11]
        else:
            return None

class EddystoneURLFrame(_EddystoneGenericFrame):
    """
    Eddystone-URL frame broadcasts ranging data and a URL using a compressed encoding format.
    See http://example.com for format details.
    """
    # The ordering of the elements in both of the following list are significant for encoding them.
    _EXTENSIONS = [
        ".com/", ".org/", ".edu/", ".net/", ".info/", ".biz/", ".gov/",
        ".com", ".org", ".edu", ".net", ".info", ".biz", ".gov",
    ]

    _SCHEMES = [
        "http://www.",
        "https://www.",
        "http://",
        "https://",
    ]

    def __init__(self, ranging_data, url, data_flags=_DEFAULT_FLAGS):
        super().__init__(eddystone_type=TYPE_URL, payload_len=3, data_flags=data_flags)
        self.ranging_data = ranging_data
        self.url = url

    @property
    def ranging_data(self) -> int:
        """
        Get or set the ranging data, specified in decibel-milliwatts (dBm). Defined as the calibrated Tx power at 0 m.
        """
        return struct.unpack('>b', self._frame[12:13])[0]

    @ranging_data.setter
    def ranging_data(self, ranging_data: int):
        if ranging_data < -100 or ranging_data > 20:
            raise ValueError("ranging_data is out of range")

        tx_power_byte = struct.pack('>b', ranging_data)
        self._frame = self._frame[:12] + tx_power_byte + self._frame[13:]

    def __find_scheme_id(self, input_url):
        for i in range(len(self._SCHEMES)):
            if input_url.startswith(self._SCHEMES[i]):
                return i, len(self._SCHEMES[i])
        else:
            raise ValueError("The URL does not use a supported prefix scheme")

    def __find_extension_id(self, input_url, pos):
        # Check if this matches a supported extension
        for ext_id in range(len(self._EXTENSIONS)):
            extension = self._EXTENSIONS[ext_id]
            if input_url.startswith(extension, pos):
                return ext_id
        return None

    @property
    def url(self) -> str:
        """
        Get or set the URL. Encoded internally as defined by RFC 1738.
        """
        url = self._frame[13:]
        if len(url) == 0:
            return str()

        if url[0] >= len(self._SCHEMES):
            raise ValueError("Invalid URL scheme")

        decoded_url = self._SCHEMES[url[0]]
        extension_index_max = len(self._EXTENSIONS) - 1
        for c in url[1:]:
            if c <= extension_index_max:  # If this is one of the extensions
                decoded_url += self._EXTENSIONS[c]
            elif 0x21 <= c < 0x7F:
                decoded_url += chr(c)
            else:
                raise ValueError("Invalid URL")

        return decoded_url

    @url.setter
    def url(self, input_url: str):
        encoded_url = bytearray()

        scheme_id, scheme_len = self.__find_scheme_id(input_url)
        encoded_url.append(scheme_id)

        # Start processing after the scheme
        pos = scheme_len
        while pos < len(input_url):
            ext_id = self.__find_extension_id(input_url, pos)
            if ext_id is not None:
                encoded_url += struct.pack('>b', ext_id)
                pos += len(self._EXTENSIONS[ext_id])
            else:
                # Just write the character if a shortened extension wasn't found.
                encoded_url.append(ord(input_url[pos]))
                pos += 1

        # Set the url into the frame
        self._frame = self._frame[:13] + encoded_url
        # Set the length of the payload, +1 for ranging data
        self._set_payload_length(len(encoded_url) + 1)

class EddystoneUIDFrame(_EddystoneGenericFrame):
    """
    Eddystone-UID frame broadcasts ranging data and
    an unique 16-byte Beacon ID composed of a 10-byte namespace and a 6-byte instance.
    See http://example.com for format details.
    """

    def __init__(self, ranging_data, uid, data_flags=_DEFAULT_FLAGS):
        super().__init__(eddystone_type=TYPE_UID, payload_len=19, data_flags=data_flags)
        # A minimum viable UID frame is 19 bytes of zeros
        self.ranging_data = ranging_data
        self.uid = uid

    @property
    def ranging_data(self) -> int:
        """
        Get or set the ranging data, specified in decibel-milliwatts (dBm). Defined as the calibrated Tx power at 0 m.
        """
        return struct.unpack('>b', self._frame[12:13])[0]

    @ranging_data.setter
    def ranging_data(self, ranging_data: int):
        if ranging_data < -100 or ranging_data > 20:
            raise ValueError("ranging_data is out of range")

        ranging_data_byte = struct.pack('>b', ranging_data)
        self._frame = self._frame[:12] + ranging_data_byte + self._frame[13:]

    @property
    def uid(self) -> bytes:
        """
        Get or set the UID. An Eddystone-UID beacon ID is 16 bytes long, consisting of a 10-byte namespace component and
        a 6-byte instance component.
        """
        return bytes(self._frame[13:29])

    @uid.setter
    def uid(self, uid: bytes):
        if len(uid) != 16:
            raise ValueError("The UID field is an incorrect size, expected 16 bytes")

        # Insert UID with an extra zeroed two bytes at the end that are reserved for future use.
        self._frame = self._frame[:13] + uid + self._frame[29:]

    def validate_payload(self):
        # All UUID fields are of the same length: 23 bytes
        return self._validate_payload(23)

class EddystoneTLMFrame(_EddystoneGenericFrame):
    """
    Eddystone-TLM frame broadcasts telemetry information about the beacon itself such as battery voltage,
    device temperature, and counts of broadcast packets.
    See http://example.com for format details.
    """

    def __init__(self, advertisement_count, time_sec, beacon_temperature=-128, battery_voltage=0, data_flags=_DEFAULT_FLAGS):
        super().__init__(eddystone_type=TYPE_TLM, payload_len=13, data_flags=data_flags)
        self.battery_voltage = battery_voltage
        self.beacon_temperature = beacon_temperature
        self.advertisement_count = advertisement_count
        self.time_sec = time_sec

    @staticmethod
    def __to_fixed88(fl):
        """
        Convert from a float to a fixed point 8.8
        """
        # limited to Q 8.8 fixed point range. valid range: -2^7 < temperature < 2^7 - 2^-8
        if fl < -128 or fl > 127.9961:
            raise ValueError("Out of range of representable values")
        return struct.pack('>h', int(fl * (2 ** 8)))

    @staticmethod
    def __from_fixed88(fp):
        """
        Convert from fixed point 8.8 to a float
        """
        return float(struct.unpack('>h', fp)[0] * (2 ** -8))

    @property
    def battery_voltage(self) -> float:
        """
        Get or set the battery voltage, specified in volts with a resolution of mV.
        """
        b = self._frame[13:15]
        return float(struct.unpack('>H', b)[0]) / 1000

    @battery_voltage.setter
    def battery_voltage(self, voltage: float):
        voltage = int(voltage * 1000)
        if voltage & ~0xFFFF:
            raise ValueError("Voltage is out of range")

        voltage_bytes = struct.pack('>H', voltage)

        self._frame = self._frame[:13] + voltage_bytes + self._frame[15:]

    @property
    def beacon_temperature(self) -> float:
        """
        Get or set the temperature, specified in Celsius.
        """
        return self.__from_fixed88(bytes(self._frame[15:17]))

    @beacon_temperature.setter
    def beacon_temperature(self, temperature: float):
        temperature_bytes = self.__to_fixed88(temperature)
        self._frame = self._frame[:15] + temperature_bytes + self._frame[17:]

    @property
    def advertisement_count(self) -> int:
        """
        Get or set the running count of advertisement frames emitted by the beacon since power-on.
        """

    @advertisement_count.setter
    def advertisement_count(self, count: int):
        if count >= 1 << 32:
            raise ValueError("Advertisement count is out of range of representable values")
        count_bytes = struct.pack('>I', count)
        self._frame = self._frame[:17] + count_bytes + self._frame[21:]

    @property
    def time_sec(self) -> float:
        """
        Get or set the time since power-on, specified in seconds with a resolution of tenths of seconds.
        """
        return struct.unpack('>I', self._frame[21:25])[0] / 10.0

    @time_sec.setter
    def time_sec(self, time_sec: float):
        count = int(time_sec * 10)
        if count >= 1 << 32:
            raise ValueError("Time stamp out of range")
        count_bytes = struct.pack('>I', count)
        self._frame = self._frame[:21] + count_bytes

    def validate_payload(self):
        # All TLM fields are of the same size: 17 bytes
        return super()._validate_payload(17)

def parse(frame: bytes):
    """
    Parses a raw advertisement frame, returning a parsed Eddystone frame.
    :param frame: The raw advertisement to be parsed.
    :return: The type of the frame and a parsed Eddystone frame of that type:
        int, (EddystoneUIDFrame or EddystoneURLFrame or EddystoneTLMFrame).
    """
    if not _check_for_valid_eddystone(frame):
        raise TypeError("Incoming Eddystone frame is invalid")

    eddy_type = struct.unpack('>b', frame[11:12])[0]
    eddy_len = struct.unpack('>b', frame[_LENGTH_INDEX:_LENGTH_INDEX + 1])[0]
    # Setup a default empty frame to parse the values into
    if eddy_type == TYPE_URL:
        eddy_frame = EddystoneURLFrame(ranging_data=0, url='http://.com')
    elif eddy_type == TYPE_UID:
        eddy_frame = EddystoneUIDFrame(ranging_data=0, uid=bytearray(16))
    elif eddy_type == TYPE_TLM:
        eddy_frame = EddystoneTLMFrame(advertisement_count=0, time_sec=0)
    else:
        raise TypeError("Eddystone type is not supported: {}".format(eddy_type))

    # Place values into frame, Do not need to replace common 4 bytes at start
    eddy_frame.set_raw_payload(frame[(8 + 4):(12 + eddy_len - 4)])

    # Validate the eddystone frame
    if not eddy_frame.validate_payload():
        raise TypeError("Eddystone Payload is invalid")

    return eddy_type, eddy_frame


while pos < len(input_url):
            ext_id = self.__find_extension_id(input_url, pos)
            if ext_id is not None:
                encoded_url += struct.pack('>b', ext_id)
                pos += len(self._EXTENSIONS[ext_id])
            else:
                # Just write the character if a shortened extension wasn't found.
                encoded_url.append(ord(input_url[pos]))
                pos += 1

import struct

TYPE_UID = 0x00
TYPE_URL = 0x10
TYPE_TLM = 0x20

_DEFAULT_FRAME = (
    b"\x02"      # Flags length
    b"\x01"      # Flags data type value
    b"\x00"      # Flags data
    b"\x03"      # Service UUID length
    b"\x03"      # Service UUID data type value
    b"\xAA\xFE"  # 16-bit Eddystone UUID
    b"\x04"      # Service Data length
    b"\x16"      # Service Data data type value
    b"\xAA\xFE"  # 16-bit Eddystone UUID
)

_FLAGS_INDEX = 2
_DEFAULT_FLAGS = 0x06

_LENGTH_INDEX = 7

def _check_for_valid_eddystone(frame, expected_len=None):
    frame_len = len(frame)

    # Verify the length of the advertisement payload.
    # The advertisement contains many length bytes, make sure those lengths add up to the total frame length.
    parse_len = 0
    while True:
        # The length of the field plus the byte for the length of the field
        parse_len += frame[parse_len] + 1

        # The seventh byte is always the eddystone length. Make sure is matches the expected length if specified.
        if expected_len is not None and parse_len == _LENGTH_INDEX and frame[parse_len] != expected_len:
            return False

        # Invalid length bytes in payload
        if parse_len > frame_len:
            return False
        elif parse_len == frame_len:
            break

    # All Eddystone advertisements have the same first 12 bytes (excluding the payload length byte and data flags)
    if (
        frame[:_FLAGS_INDEX] != _DEFAULT_FRAME[:_FLAGS_INDEX] or
        frame[_FLAGS_INDEX + 1:_LENGTH_INDEX] != _DEFAULT_FRAME[_FLAGS_INDEX + 1:_LENGTH_INDEX] or
        frame[8:11] != _DEFAULT_FRAME[8:11]
    ):
        return False

    return True

class _EddystoneGenericFrame(object):
    """
    This class is a generic Advertising frame providing common functions, not to be instantiated.
    """

    def __init__(self, eddystone_type, payload_len, data_flags):
        self._frame = bytearray()
        self._frame.extend(_DEFAULT_FRAME)
        self._frame[_FLAGS_INDEX] = data_flags
        self._frame.append(eddystone_type)  # Eddystone type
        # Extends the frame to have payload_len number of zero bytes at the end
        self._frame += bytearray(payload_len)
        self._set_payload_length(payload_len)

    def _set_payload_length(self, length):
        self._frame[_LENGTH_INDEX] = 4 + length  # 7th byte specifies the payload len. There are 4 bytes that are used in all frames

    def set_raw_payload(self, payload):
        payload_len = len(payload)
        if payload_len > 19:
            raise TypeError("The payload is too large")

        # Cut off the existing payload (beyond the default frame)
        offset = len(_DEFAULT_FRAME)
        self._frame = self._frame[:offset + 1]
        # Place the new payload at the end
        self._frame.extend(payload)
        self._set_payload_length(payload_len)

    def get_bytes(self) -> bytes:
        """
        Get the advertisement payload. Used to send this frame.
        """
        return bytes(self._frame)

    def _validate_payload(self, expected_len=None):
        return _check_for_valid_eddystone(self._frame, expected_len)

    def validate_payload(self):
        return self._validate_payload(None)

    @property
    def eddystone_type(self):
        if len(self._frame) >= 13 and self._frame[11] in [TYPE_UID, TYPE_URL, TYPE_TLM]:
            return self._frame[11]
        else:
            return None

class EddystoneURLFrame(_EddystoneGenericFrame):
    """
    Eddystone-URL frame broadcasts ranging data and a URL using a compressed encoding format.
    See http://example.com for format details.
    """
    # The ordering of the elements in both of the following list are significant for encoding them.
    _EXTENSIONS = [
        ".com/", ".org/", ".edu/", ".net/", ".info/", ".biz/", ".gov/",
        ".com", ".org", ".edu", ".net", ".info", ".biz", ".gov",
    ]

    _SCHEMES = [
        "http://www.",
        "https://www.",
        "http://",
        "https://",
    ]

    def __init__(self, ranging_data, url, data_flags=_DEFAULT_FLAGS):
        super().__init__(eddystone_type=TYPE_URL, payload_len=3, data_flags=data_flags)
        self.ranging_data = ranging_data
        self.url = url

    @property
    def ranging_data(self) -> int:
        """
        Get or set the ranging data, specified in decibel-milliwatts (dBm). Defined as the calibrated Tx power at 0 m.
        """
        return struct.unpack('>b', self._frame[12:13])[0]

    @ranging_data.setter
    def ranging_data(self, ranging_data: int):
        if ranging_data < -100 or ranging_data > 20:
            raise ValueError("ranging_data is out of range")

        tx_power_byte = struct.pack('>b', ranging_data)
        self._frame = self._frame[:12] + tx_power_byte + self._frame[13:]

    def __find_scheme_id(self, input_url):
        for i in range(len(self._SCHEMES)):
            if input_url.startswith(self._SCHEMES[i]):
                return i, len(self._SCHEMES[i])
        else:
            raise ValueError("The URL does not use a supported prefix scheme")

    def __find_extension_id(self, input_url, pos):
        # Check if this matches a supported extension
        for ext_id in range(len(self._EXTENSIONS)):
            extension = self._EXTENSIONS[ext_id]
            if input_url.startswith(extension, pos):
                return ext_id
        return None

    @property
    def url(self) -> str:
        """
        Get or set the URL. Encoded internally as defined by RFC 1738.
        """
        url = self._frame[13:]
        if len(url) == 0:
            return str()

        if url[0] >= len(self._SCHEMES):
            raise ValueError("Invalid URL scheme")

        decoded_url = self._SCHEMES[url[0]]
        extension_index_max = len(self._EXTENSIONS) - 1
        for c in url[1:]:
            if c <= extension_index_max:  # If this is one of the extensions
                decoded_url += self._EXTENSIONS[c]
            elif 0x21 <= c < 0x7F:
                decoded_url += chr(c)
            else:
                raise ValueError("Invalid URL")

        return decoded_url

    @url.setter
    def url(self, input_url: str):
        encoded_url = bytearray()

        scheme_id, scheme_len = self.__find_scheme_id(input_url)
        encoded_url.append(scheme_id)

        # Start processing after the scheme
        pos = scheme_len

        # Set the url into the frame
        self._frame = self._frame[:13] + encoded_url
        # Set the length of the payload, +1 for ranging data
        self._set_payload_length(len(encoded_url) + 1)

class EddystoneUIDFrame(_EddystoneGenericFrame):
    """
    Eddystone-UID frame broadcasts ranging data and
    an unique 16-byte Beacon ID composed of a 10-byte namespace and a 6-byte instance.
    See http://example.com for format details.
    """

    def __init__(self, ranging_data, uid, data_flags=_DEFAULT_FLAGS):
        super().__init__(eddystone_type=TYPE_UID, payload_len=19, data_flags=data_flags)
        # A minimum viable UID frame is 19 bytes of zeros
        self.ranging_data = ranging_data
        self.uid = uid

    @property
    def ranging_data(self) -> int:
        """
        Get or set the ranging data, specified in decibel-milliwatts (dBm). Defined as the calibrated Tx power at 0 m.
        """
        return struct.unpack('>b', self._frame[12:13])[0]

    @ranging_data.setter
    def ranging_data(self, ranging_data: int):
        if ranging_data < -100 or ranging_data > 20:
            raise ValueError("ranging_data is out of range")

        ranging_data_byte = struct.pack('>b', ranging_data)
        self._frame = self._frame[:12] + ranging_data_byte + self._frame[13:]

    @property
    def uid(self) -> bytes:
        """
        Get or set the UID. An Eddystone-UID beacon ID is 16 bytes long, consisting of a 10-byte namespace component and
        a 6-byte instance component.
        """
        return bytes(self._frame[13:29])

    @uid.setter
    def uid(self, uid: bytes):
        if len(uid) != 16:
            raise ValueError("The UID field is an incorrect size, expected 16 bytes")

        # Insert UID with an extra zeroed two bytes at the end that are reserved for future use.
        self._frame = self._frame[:13] + uid + self._frame[29:]

    def validate_payload(self):
        # All UUID fields are of the same length: 23 bytes
        return self._validate_payload(23)

class EddystoneTLMFrame(_EddystoneGenericFrame):
    """
    Eddystone-TLM frame broadcasts telemetry information about the beacon itself such as battery voltage,
    device temperature, and counts of broadcast packets.
    See http://example.com for format details.
    """

    def __init__(self, advertisement_count, time_sec, beacon_temperature=-128, battery_voltage=0, data_flags=_DEFAULT_FLAGS):
        super().__init__(eddystone_type=TYPE_TLM, payload_len=13, data_flags=data_flags)
        self.battery_voltage = battery_voltage
        self.beacon_temperature = beacon_temperature
        self.advertisement_count = advertisement_count
        self.time_sec = time_sec

    @staticmethod
    def __to_fixed88(fl):
        """
        Convert from a float to a fixed point 8.8
        """
        # limited to Q 8.8 fixed point range. valid range: -2^7 < temperature < 2^7 - 2^-8
        if fl < -128 or fl > 127.9961:
            raise ValueError("Out of range of representable values")
        return struct.pack('>h', int(fl * (2 ** 8)))

    @staticmethod
    def __from_fixed88(fp):
        """
        Convert from fixed point 8.8 to a float
        """
        return float(struct.unpack('>h', fp)[0] * (2 ** -8))

    @property
    def battery_voltage(self) -> float:
        """
        Get or set the battery voltage, specified in volts with a resolution of mV.
        """
        b = self._frame[13:15]
        return float(struct.unpack('>H', b)[0]) / 1000

    @battery_voltage.setter
    def battery_voltage(self, voltage: float):
        voltage = int(voltage * 1000)
        if voltage & ~0xFFFF:
            raise ValueError("Voltage is out of range")

        voltage_bytes = struct.pack('>H', voltage)

        self._frame = self._frame[:13] + voltage_bytes + self._frame[15:]

    @property
    def beacon_temperature(self) -> float:
        """
        Get or set the temperature, specified in Celsius.
        """
        return self.__from_fixed88(bytes(self._frame[15:17]))

    @beacon_temperature.setter
    def beacon_temperature(self, temperature: float):
        temperature_bytes = self.__to_fixed88(temperature)
        self._frame = self._frame[:15] + temperature_bytes + self._frame[17:]

    @property
    def advertisement_count(self) -> int:
        """
        Get or set the running count of advertisement frames emitted by the beacon since power-on.
        """
        return struct.unpack('>I', self._frame[17:21])[0]

    @advertisement_count.setter
    def advertisement_count(self, count: int):
        if count >= 1 << 32:
            raise ValueError("Advertisement count is out of range of representable values")
        count_bytes = struct.pack('>I', count)
        self._frame = self._frame[:17] + count_bytes + self._frame[21:]

    @property
    def time_sec(self) -> float:
        """
        Get or set the time since power-on, specified in seconds with a resolution of tenths of seconds.
        """
        return struct.unpack('>I', self._frame[21:25])[0] / 10.0

    @time_sec.setter
    def time_sec(self, time_sec: float):
        count = int(time_sec * 10)
        if count >= 1 << 32:
            raise ValueError("Time stamp out of range")
        count_bytes = struct.pack('>I', count)
        self._frame = self._frame[:21] + count_bytes

    def validate_payload(self):
        # All TLM fields are of the same size: 17 bytes
        return super()._validate_payload(17)

def parse(frame: bytes):
    """
    Parses a raw advertisement frame, returning a parsed Eddystone frame.
    :param frame: The raw advertisement to be parsed.
    :return: The type of the frame and a parsed Eddystone frame of that type:
        int, (EddystoneUIDFrame or EddystoneURLFrame or EddystoneTLMFrame).
    """
    if not _check_for_valid_eddystone(frame):
        raise TypeError("Incoming Eddystone frame is invalid")

    eddy_type = struct.unpack('>b', frame[11:12])[0]
    eddy_len = struct.unpack('>b', frame[_LENGTH_INDEX:_LENGTH_INDEX + 1])[0]
    # Setup a default empty frame to parse the values into
    if eddy_type == TYPE_URL:
        eddy_frame = EddystoneURLFrame(ranging_data=0, url='http://.com')
    elif eddy_type == TYPE_UID:
        eddy_frame = EddystoneUIDFrame(ranging_data=0, uid=bytearray(16))
    elif eddy_type == TYPE_TLM:
        eddy_frame = EddystoneTLMFrame(advertisement_count=0, time_sec=0)
    else:
        raise TypeError("Eddystone type is not supported: {}".format(eddy_type))

    # Place values into frame, Do not need to replace common 4 bytes at start
    eddy_frame.set_raw_payload(frame[(8 + 4):(12 + eddy_len - 4)])

    # Validate the eddystone frame
    if not eddy_frame.validate_payload():
        raise TypeError("Eddystone Payload is invalid")

    return eddy_type, eddy_frame


    del args
    del kwargs

    def gen():
      n_annotations = len(FAKE_ID)
      for i in range(num_examples):
        yield generate_fake_example(
            w=FAKE_W[i % n_annotations],
            h=FAKE_H[i % n_annotations],
            identifier=FAKE_ID[i % n_annotations])

    return tf.data.Dataset.from_generator(
        gen,
        output_types=self.info.features.dtype,
        output_shapes=self.info.features.shape,
    )


        key_obj = DSA.import_key(self.der_public)
        self.failIf(key_obj.has_private())
        self.assertEqual(self.y, key_obj.y)
        self.assertEqual(self.p, key_obj.p)
        self.assertEqual(self.q, key_obj.q)
        self.assertEqual(self.g, key_obj.g)


		self.queue = queue
		self.name = environment_name
		self.options = options or dict()

		self.max_restarts = 1
		self.restarts = 0

		self.process = multiprocessing.Process(target=_run, kwargs=dict(
			name=self.name,
			queue=self.queue,
			options=self.options,
		))

		self.__last_state = True

import threading
import multiprocessing

from colorlog import ColoredFormatter

def _run(name, queue, options):
	"""
	The actual process that runs the separate controller instance.

	:param name: name of the process
	:param queue: Queue of the binding parent.
	:param options: Custom Options
	:type name: str
	"""
	from pyplanet.core.instance import Controller
	from pyplanet.utils.log import initiate_logger, QueueHandler
	import logging

	if 'tokio' in options and options['tokio'] is True:
		import asyncio
		import tokio
		policy = tokio.TokioLoopPolicy()
		asyncio.set_event_loop_policy(policy)
		asyncio.set_event_loop(tokio.new_event_loop())
		logging.warning('Using experimental Tokio Asyncio Loop!')

	# Logging to queue.
	if multiprocessing.get_start_method() != 'fork':  # pragma: no cover
		initiate_logger()
		root_logger = logging.getLogger()
		formatter = ColoredFormatter(
			'%(log_color)s%(levelname)-8s%(reset)s %(yellow)s[%(threadName)s][%(name)s]%(reset)s %(blue)s%(message)s'
		)
		queue_handler = QueueHandler(queue)
		queue_handler.setFormatter(formatter)
		root_logger.addHandler(queue_handler)

	logging.getLogger(__name__).info('Starting pool process for \'{}\'...'.format(name))

	# Setting thread name to our process name.
	threading.main_thread().setName(name)

	instance = Controller.prepare(name).instance
	instance._queue = queue

	instance.start()

class InstanceProcess:
	"""
	The InstanceProcess is the encapsulation around the real controller instance.

	.. warning::

		This code is still being executed at the main process!!

	"""

	def __init__(self, queue, environment_name='default', pool=None, options=None):
		"""
		Create an environment process of the controller itself.

		:param queue: Queue to hook on.
		:param environment_name: Name of environment.
		:param pool: Pool.
		:param options: Custom options.
		:type queue: multiprocessing.Queue
		:type environment_name: str
		:type pool: multiprocessing.Pool
		:type options: dict
		"""

	@property
	def did_die(self):
		"""
		Boolean determinating if the process did die.
		"""
		if not self.is_alive() and self.__last_state:
			self.__last_state = False
			return True
		return False

	@property
	def exitcode(self):
		"""
		Exit code of process.

		:return: Exit code.
		"""
		return self.process.exitcode

	@property
	def will_restart(self):
		"""
		Boolean: Is the process able to restart (not reached max_restarts).
		"""
		return self.restarts < self.max_restarts

	def is_alive(self):
		"""
		Call process method is_alive()
		"""
		return self.process.is_alive()

	def start(self):
		"""
		Start the process.
		"""
		return self.process.start()

	def shutdown(self):
		"""
		Shutdown (terminate) process.
		"""
		try:
			return self.process.terminate()
		except:
			pass
		return None

	def graceful(self):
		"""
		Graceful shutdown the process.
		"""
		self.process.join(timeout=10)


        network_profile_config = state.lookup_item(models.NetworkProfileConfig)
        if not network_profile_config:
            network_profiles = []
            wireless_mesh_type = 'ad-hoc'
        else:
            network_profiles = network_profile_config.profiles or []
            wireless_mesh_type = network_profile_config.wireless_mesh_type

        context.update({
            'network_profiles': network_profiles,
            'wireless_mesh_type': wireless_mesh_type,
        })

from nodewatcher.core.registry import forms as registry_forms

from nodewatcher.modules.vpn.tunneldigger import models as td_models

from .. import models

class NetworkProfile(registry_forms.FormDefaultsModule):
    """
    Form defaults module that stores node's network profiles into the
    module context.

    Exported context properties:
    - ``network_profiles`` contains a list of network profile strings
    - ``wireless_mesh_type`` contains the type of wireless mesh
    """

    def pre_configure(self, context, state, create):
        """
        Get node type for the node that is being edited.
        """

class ClearInterfaces(registry_forms.FormDefaultsModule):
    """
    Form defaults module that removes all interfaces during the configuration
    stage.
    """

    def configure(self, context, state, create):
        def filter_remove_item(item):
            # Do not remove tunneldigger interfaces as they are already handled by other
            if isinstance(item, td_models.TunneldiggerInterfaceConfig):
                return False

            return True
        state.remove_items('core.interfaces', filter=filter_remove_item)


        self._utm_source = None

        if utm_source is not None:
            self.utm_source = utm_source

class UtmSource(object):
    """The utm source of an Ganalytics object."""

    def __init__(self, utm_source=None):
        """Create a UtmSource object

        :param utm_source: Name of the referrer source.
            (e.g. Google, SomeDomain.com, or Marketing Email)
        :type utm_source: string, optional
        """

    @property
    def utm_source(self):
        """Name of the referrer source. (e.g. Google, SomeDomain.com, or
           Marketing Email)

        :rtype: string
        """
        return self._utm_source

    @utm_source.setter
    def utm_source(self, value):
        """Name of the referrer source. (e.g. Google, SomeDomain.com, or
           Marketing Email)

        :param value: Name of the referrer source.
        (e.g. Google, SomeDomain.com, or Marketing Email)
        :type value: string
        """
        self._utm_source = value

    def get(self):
        """
        Get a JSON-ready representation of this UtmSource.

        :returns: This UtmSource, ready for use in a request body.
        :rtype: string
        """
        return self.utm_source