# Script for distributed training with synchronized batch norm
# Guide for converting a regular training script to a distributed one can
# be found at https://github.com/dougsouza/pytorch-sync-batchnorm-example

import argparse
import datetime
import numbers
import pathlib
import warnings
import logging

import torch
import tqdm
import yaml
import numpy as np

import loss
import options.segment
import datasets.nrw
import datasets.dfc
import models.unet

logger = logging.getLogger(__name__)

def train_and_eval(
    model, optimizer, criterion, train_dataloader, test_dataloader, num_epochs, device
):

    pbar = tqdm.tqdm(total=num_epochs)
    for n_epoch in range(num_epochs):

        loss_train, iou_val_train = train(model, optimizer, criterion, train_dataloader, 'rgb', device)

        loss_test, iou_val_test = evaluate(
            model, criterion, test_dataloader, 'rgb', device
        )

        info_str = "epoch {:3d} train: loss={:6.3f} iou={:6.3f}, test loss={:6.3f} iou={:6.3f}".format(
            n_epoch, loss_train, loss_test, iou_val_train, iou_val_test
        )

        logger.info(info_str)

        pbar.update(1)
        pbar.set_description(info_str)
        pbar.write(info_str)
    return model

def evaluate(model, criterion, dataloader, src="rgb", device='cuda'):
    """ evaluates a model on the given dataset

    Parameters
    ----------

    model: (torch.nn.Module)
        the neural network
    optimizer: (torch.optim)
        optimizer for parameters of model
    criterion: unction
        takes batch_output and batch_labels and computes the loss for the batch
    dataloader: torch.utils.data.DataLoader
        fetches training data

    """

    model.eval()

    running_loss = 0.0
    iou_val = 0.0
    for sample in dataloader:
        sample = {k: v.to(device) for k, v in sample.items()}

        with torch.no_grad():
            output = model(sample[src])

        pred = (output > 0).long()

        loss_t = criterion(output, sample["seg"])
        running_loss += loss_t.item()
        iou_val += loss.iou(pred, sample["seg"]).item()

    running_loss /= len(dataloader)
    iou_val /= len(dataloader)

    return running_loss, iou_val

def train(model, optimizer, criterion, dataloader, src="rgb", device='cuda'):
    """ trains a model for one epoch

    Parameters
    ----------

    model: (torch.nn.Module)
        the neural network
    optimizer: (torch.optim)
        optimizer for parameters of model
    loss_fn: unction
        takes batch_output and batch_labels and computes the loss for the batch
    dataloader: torch.utils.data.DataLoader
        fetches training data

    """

    model.train()

    running_loss = 0.0
    iou_val = 0.0
    for sample in dataloader:
        optimizer.zero_grad()

        sample = {k: v.to(device) for k, v in sample.items()}

        output = model(sample[src])
        pred = (output > 0).long()

        loss_t = criterion(output, sample["seg"])

        loss_t.backward()
        running_loss += loss_t.item()
        iou_val += loss.iou(pred, sample["seg"]).item()
        optimizer.step()

    running_loss /= len(dataloader)
    iou_val /= len(dataloader)

    return running_loss, iou_val

if __name__ == "__main__":

    parser = options.segment.get_parser()
    args = parser.parse_args()

    # Reproducibilty config https://pytorch.org/docs/stable/notes/randomness.html
    if args.seed is not None:
        torch.manual_seed(args.seed)
        np.random.seed(args.seed)
        torch.backends.cudnn.deterministic = True
        torch.backends.cudnn.benchmark = False
        warnings.warn(
            "You have chosen to seed training. "
            "This will turn on the CUDNN deterministic setting, "
            "which can slow down your training considerably! "
            "You may see unexpected behavior when restarting "
            "from checkpoints."
        )

    if len(args.crop) == 1:
        args.crop = args.crop[0]

    if len(args.resize) == 1:
        args.resize = args.resize[0]

    if torch.cuda.is_available():
        device = torch.device("cuda")
    else:
        raise RuntimeError("This scripts expects CUDA to be available")
    OUT_DIR = args.out_dir / options.segment.args2str(args)
    # All process make the directory.
    # This avoids errors when setting up logging later due to race conditions.
    OUT_DIR.mkdir(exist_ok=True)

    ###########
    #         #
    # Logging #
    #         #
    ###########

    logging.basicConfig(
        format="%(asctime)s [%(levelname)-8s] %(message)s",
        level=logging.INFO,
        filename=OUT_DIR / "log_training.txt",
    )
    logger = logging.getLogger()
    logger.info("Saving logs, configs and models to %s", OUT_DIR)

    CONFIG = options.segment.args2dict(args)
    with open(OUT_DIR / "config.yml", "w") as cfg_file:
        yaml.dump(CONFIG, cfg_file)

    #########################
    #                       #
    # Dataset configuration #
    #                       #
    #########################

    train_transforms, test_transforms = options.common.get_transforms(CONFIG)

    dataset_train = options.common.get_dataset(CONFIG, split='train', transforms=train_transforms)
    dataset_test = options.common.get_dataset(CONFIG, split='test', transforms=test_transforms)

    print("training dataset statistics")
    print(dataset_train)

    print("testing dataset statistics")
    print(dataset_test)

    dataloader_train = torch.utils.data.DataLoader(
        dataset_train,
        batch_size=args.batch_size,
        shuffle=True,
        num_workers=args.num_workers,
    )

    dataloader_test = torch.utils.data.DataLoader(
        dataset_test,
        batch_size=args.batch_size,
        shuffle=False,
        num_workers=args.num_workers,
    )

    ###############
    #             #
    # Model setup #
    #             #
    ###############

    criterion = torch.nn.BCEWithLogitsLoss()

    dset_class = getattr(datasets, CONFIG["dataset"]["name"])
    n_labels = dset_class.N_LABELS
    input_nc = dset_class.N_CHANNELS[CONFIG["dataset"]["input"]]
    model = models.unet.UNet(input_nc, n_labels).to(device)

    ############
    #          #
    # TRAINING #
    #          #
    ############

    optimizer = torch.optim.Adam(
        model.parameters(), lr=args.learning_rate, weight_decay=args.weight_decay,
    )

    train_and_eval(
        model,
        optimizer,
        criterion,
        dataloader_train,
        dataloader_test,
        num_epochs=args.epochs,
        device=device,
    )

    ##############
    #            #
    # save model #
    #            #
    ##############

    torch.save(model, OUT_DIR / "{}.pt".format(options.segment.args2str(args)))


import inflect

e = inflect.engine()

def main():
    names: list = []
    while True:
        try:
            n: str = input("Name: ")
            if len(n) > 0:
                n = n.title()
                names.append(n)
            else:
                exit(0)
        except EOFError:
            print(f"\nAdieu, adieu, to {e.join(names)}")
            break
        else:
            continue

if __name__ == "__main__":
    main()


import re

from gi.repository import Gdk
from gi.repository import Gtk
from gi.repository import GES
from gi.repository import Gio
from gi.repository import GObject

from gettext import gettext as _

from pitivi.timeline import elements
from pitivi.utils.loggable import Loggable
from pitivi.utils import ui
from pitivi.utils import timeline as timelineUtils

class BaseLayerControl(Gtk.Box, Loggable):

    """
    Base Layer control classes
    """

    __gtype_name__ = 'LayerControl'

    def __init__(self, layer, app, type_name):
        Gtk.Box.__init__(self, spacing=0)
        Loggable.__init__(self)

        self._app = app
        self.layer = layer
        self._selected = False
        self.__type_name = type_name
        self.__meta_name = type_name + "::name"
        self.props.no_show_all = True

        context = self.get_style_context()

        # get the default color for the current theme
        self.UNSELECTED_COLOR = context.get_background_color(
            Gtk.StateFlags.NORMAL)
        # use base instead of bg colors so that we get the lighter color
        # that is used for list items in TreeView.
        self.SELECTED_COLOR = context.get_background_color(
            Gtk.StateFlags.SELECTED)

        self.set_orientation(Gtk.Orientation.VERTICAL)

        table = Gtk.Table(n_rows=2, n_columns=2)
        table.set_border_width(ui.PADDING)
        table.set_row_spacings(3)
        table.set_col_spacings(3)

        self.pack_start(table, True, True, 0)

        self.name_entry = Gtk.Entry()
        self.name_entry.set_tooltip_text(
            _("Set a personalized name for this layer"))
        self.name_entry.set_property("secondary-icon-name", self._getIconName())
        self.name_entry.connect("key-press-event", self._keyPressCb)

        layer.bLayer.connect("notify::priority", self.__layerPriorityChangedCb)
        self.__resetLayerName()
        table.attach(self.name_entry, 0, 2, 0, 2)

        self.show_all()

    def __del__(self):
        self.layer.bLayer.disconnect_by_func(self.__layerPriorityChangedCb)

    def __layerPriorityChangedCb(self, bLayer, pspec):
        self.__resetLayerName()

    def __nameIsDefault(self, name):
        if name is None:
            return False

        return re.findall("%s [0-9]+$" % self.__type_name, name)

    def __resetLayerName(self):
        name = self.layer.bLayer.get_meta(self.__meta_name)
        if name is None or self.__nameIsDefault(name):
            name = '%s %d' % (self.__type_name, self.layer.bLayer.get_priority())
            self.layer.bLayer.set_meta(self.__meta_name, name)
        self.name_entry.set_text(name)

    def _getIconName(self):
        return None

    def getSelected(self):
        return self._selected

    def setSelected(self, selected):
        if selected != self._selected:
            self._selected = selected
            self._selectionChangedCb()

    def force_show_all(self):
        self.props.no_show_all = False
        self.show_all()
        self.props.no_show_all = True

    selected = property(getSelected, setSelected, None, "Selection state")

    def _selectionChangedCb(self):
        """
        Called when the selection state changes
        """
        if self.selected:
            self.name_entry.override_background_color(
                Gtk.StateType.NORMAL, self.SELECTED_COLOR)
        else:
            self.name_entry.override_background_color(
                Gtk.StateType.NORMAL, self.UNSELECTED_COLOR)

        # continue GTK signal propagation
        return True

    def _keyPressCb(self, unused_widget, event):
        self.layer.bLayer.set_meta(self.__meta_name, self.name_entry.get_text())
        self._app.project_manager.current_project.setModificationState(True)

    def getHeight(self):
        return self.get_allocation().height

    def getSeparatorHeight(self):
        return self.sep.get_allocation().height

    def getControlHeight(self):
        return self.getHeight() - self.getSeparatorHeight()

    def setSoloState(self, state):
        self.solo_button.set_active(state)

    def setSeparatorVisibility(self, visible):
        if visible:
            self.sep.show()
        else:
            self.sep.hide()

class VideoLayerControl(BaseLayerControl):
    """
    Layer control class for video layers
    """

    __gtype_name__ = 'VideoLayerControl'

    def __init__(self, layer, app):
        BaseLayerControl.__init__(self, layer, app, "video")

    def _getIconName(self):
        return "video-x-generic"

class AudioLayerControl(BaseLayerControl):
    """
    Layer control class for audio layers
    """

    __gtype_name__ = 'AudioLayerControl'

    def __init__(self, layer, app):
        BaseLayerControl.__init__(self, layer, app, "audio")

    def _getIconName(self):
        return "audio-x-generic"

class TwoStateButton(Gtk.Button):
    """
    Button with two states and according labels/images
    """

    __gsignals__ = {
        "changed-state": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT,),)
    }

    def __init__(self, state1="", state2=""):
        Gtk.Button.__init__(self)
        self.set_relief(Gtk.ReliefStyle.NONE)
        self.connect("clicked", self._clickedCb)

        self.set_states(state1, state2)
        self._state = True

        self.set_label(self.states[self._state])

    def set_states(self, state1, state2):
        self.states = {True: state1, False: state2}

    def _clickedCb(self, unused_widget):
        self._state = not self._state

        self.set_label(self.states[self._state])
        self.emit("changed-state", self._state)

class SpacedSeparator(Gtk.EventBox):
    """
    A Separator with vertical spacing

    Inherits from EventBox since we want to change background color
    """

    def __init__(self, position):
        Gtk.EventBox.__init__(self)

        self.box = Gtk.Box()
        self.box.set_orientation(Gtk.Orientation.VERTICAL)
        self.add(self.box)
        self.__position = position

        self.get_style_context().add_class("SpacedSeparator")
        self.box.get_style_context().add_class("SpacedSeparator")
        self.props.height_request = 1
        self.props.margin_bottom = 4
        self.props.margin_top = 4

    def do_state_flags_changed(self, old_flags):
        HIGLIGHTED_PADDING = 3
        total_height = ui.PADDING + HIGLIGHTED_PADDING
        if not self.get_state_flags() & Gtk.StateFlags.PRELIGHT:
            self.props.height_request = 1
            self.props.margin_bottom = (total_height - 1) / 2
            self.props.margin_top = (total_height - 1) / 2
        else:
            self.props.height_request = ui.PADDING
            if self.__position == Gtk.PositionType.TOP:
                self.props.margin_bottom = HIGLIGHTED_PADDING
                self.props.margin_top = 0
            else:
                self.props.margin_bottom = 0
                self.props.margin_top = HIGLIGHTED_PADDING
        Gtk.EventBox.do_state_flags_changed(self, old_flags)

class LayerControls(Gtk.EventBox, Loggable):

    __gtype_name__ = 'PitiviLayerControls'

    def __init__(self, bLayer, app):
        Gtk.EventBox.__init__(self)
        Loggable.__init__(self)

        self.bLayer = bLayer
        self.bTimeline = self.bLayer.get_timeline()
        self.app = app

        self.props.width_request = ui.CONTROL_WIDTH
        # Half the height because we display only the video strip when empty.
        self.props.height_request = ui.LAYER_HEIGHT / 2
        self.props.hexpand = True

        content = Gtk.Grid()
        self.add(content)

        self.before_sep = SpacedSeparator(Gtk.PositionType.TOP)
        content.attach(self.before_sep, 0, 0, 2, 1)

        self.video_control = VideoLayerControl(self, self.app)
        self.video_control.force_show_all()
        self.video_control.props.height_request = ui.LAYER_HEIGHT / 2
        self.video_control.props.hexpand = True
        content.attach(self.video_control, 0, 1, 1, 1)

        self.audio_control = AudioLayerControl(self, self.app)
        self.audio_control.hide()
        self.audio_control.props.height_request = ui.LAYER_HEIGHT / 2
        self.audio_control.props.hexpand = True
        content.attach(self.audio_control, 0, 2, 1, 1)

        menubutton = Gtk.MenuButton.new()
        menubutton.props.valign = Gtk.Align.START
        menubutton.props.margin_top = 3 * ui.PADDING
        menubutton.props.relief = Gtk.ReliefStyle.NONE
        menubutton.props.direction = Gtk.ArrowType.RIGHT
        menubutton.props.margin_end = ui.PADDING
        model, action_group = self.__createMenuModel()
        popover = Gtk.Popover.new_from_model(menubutton, model)
        popover.insert_action_group("layer", action_group)
        popover.props.position = Gtk.PositionType.LEFT
        menubutton.set_popover(popover)
        content.attach(menubutton, 1, 1, 1, 2)

        self.after_sep = SpacedSeparator(Gtk.PositionType.BOTTOM)
        content.attach(self.after_sep, 0, 3, 2, 1)

        sep = Gtk.Separator.new(Gtk.Orientation.VERTICAL)
        sep.props.margin_top = ui.PADDING / 2
        sep.props.margin_bottom = ui.PADDING / 2
        content.attach(sep, 2, 0, 1, 4)

        self.bLayer.connect("notify::priority", self.__layerPriorityChangedCb)
        self.bTimeline.connect("layer-added", self.__timelineLayerAddedCb)
        self.bTimeline.connect("layer-removed", self.__timelineLayerRemovedCb)
        self.__updateActions()

        # When the window property is set, specify the mouse cursor.
        self.connect("notify::window", self.__windowSetCb)

    def __windowSetCb(self, unused_window, unused_pspec):
        self.props.window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.HAND1))

    def __del__(self):
        self.bLayer.disconnect_by_func(self.__layerPriorityChangedCb)
        self.bTimeline.disconnect_by_func(self.__timelineLayerAddedCb)
        self.bTimeline.disconnect_by_func(self.__timelineLayerRemovedCb)
        super(LayerControls, self).__del__()

    def __layerPriorityChangedCb(self, unused_bLayer, unused_pspec):
        self.__updateActions()

    def __timelineLayerAddedCb(self, unused_timeline, unused_bLayer):
        self.__updateActions()

    def __timelineLayerRemovedCb(self, unused_timeline, unused_bLayer):
        self.__updateActions()

    def __updateActions(self):
        priority = self.bLayer.get_priority()
        first = priority == 0
        self.__move_layer_up_action.props.enabled = not first
        self.__move_layer_top_action.props.enabled = not first
        layers_count = len(self.bTimeline.get_layers())
        last = priority == layers_count - 1
        self.__move_layer_down_action.props.enabled = not last
        self.__move_layer_bottom_action.props.enabled = not last
        self.__delete_layer_action.props.enabled = layers_count > 1

    def __createMenuModel(self):
        action_group = Gio.SimpleActionGroup()
        menu_model = Gio.Menu()

        self.__move_layer_top_action = Gio.SimpleAction.new("move_layer_to_top", None)
        action = self.__move_layer_top_action
        action.connect("activate", self._moveLayerCb, -2)
        action_group.insert(action)
        menu_model.append(_("Move layer to top"), "layer.%s" % action.get_name().replace(" ", "."))

        self.__move_layer_up_action = Gio.SimpleAction.new("move_layer_up", None)
        action = self.__move_layer_up_action
        action.connect("activate", self._moveLayerCb, -1)
        action_group.insert(action)
        menu_model.append(_("Move layer up"), "layer.%s" % action.get_name().replace(" ", "."))

        self.__move_layer_down_action = Gio.SimpleAction.new("move_layer_down", None)
        action = self.__move_layer_down_action
        action.connect("activate", self._moveLayerCb, 1)
        action_group.insert(action)
        menu_model.append(_("Move layer down"), "layer.%s" % action.get_name().replace(" ", "."))

        self.__move_layer_bottom_action = Gio.SimpleAction.new("move_layer_to_bottom", None)
        action = self.__move_layer_bottom_action
        action.connect("activate", self._moveLayerCb, 2)
        action_group.insert(action)
        menu_model.append(_("Move layer to bottom"), "layer.%s" % action.get_name().replace(" ", "."))

        self.__delete_layer_action = Gio.SimpleAction.new("delete_layer", None)
        action = self.__delete_layer_action
        action.connect("activate", self._deleteLayerCb)
        action_group.insert(action)
        menu_model.append(_("Delete layer"), "layer.%s" % action.get_name())

        return menu_model, action_group

    def _deleteLayerCb(self, unused_action, unused_parametter):
        self.app.action_log.begin("delete layer")
        bLayer = self.bLayer
        bTimeline = bLayer.get_timeline()
        bTimeline.remove_layer(bLayer)
        bTimeline.get_asset().pipeline.commit_timeline()
        self.app.action_log.commit()

    def _moveLayerCb(self, unused_simple_action, unused_parametter, step):
        index = self.bLayer.get_priority()
        if abs(step) == 1:
            index += step
        elif step == -2:
            index = 0
        else:
            index = len(self.bLayer.get_timeline().get_layers()) - 1
            # if audio, set last position
        self.bLayer.get_timeline().ui.moveLayer(self.bLayer, index)
        self.app.project_manager.current_project.pipeline.commit_timeline()

class LayerLayout(Gtk.Layout, Loggable):
    """
    A GtkLayout that exclusivly container Clips.
    This allows us to properly handle the z order of
    """
    __gtype_name__ = "PitiviLayerLayout"

    def __init__(self, timeline):
        super(LayerLayout, self).__init__()
        Loggable.__init__(self)

        self._children = []
        self._changed = False
        self.timeline = timeline

        self.props.hexpand = True
        self.get_style_context().add_class("LayerLayout")

    def do_add(self, widget):
        self._children.append(widget)
        self._children.sort(key=lambda clip: clip.z_order)
        Gtk.Layout.do_add(self, widget)
        self._changed = True

        for child in self._children:
            if isinstance(child, elements.TransitionClip):
                window = child.get_window()
                if window is not None:
                    window.raise_()

    def do_remove(self, widget):
        self._children.remove(widget)
        self._changed = True
        Gtk.Layout.do_remove(self, widget)

    def put(self, child, x, y):
        self._children.append(child)
        self._children.sort(key=lambda clip: clip.z_order)
        Gtk.Layout.put(self, child, x, y)
        self._changed = True

    def do_draw(self, cr):
        if self._changed:
            self._children.sort(key=lambda clip: clip.z_order)
            for child in self._children:

                if isinstance(child, elements.TransitionClip):
                    window = child.get_window()
                    window.raise_()
            self._changed = False

        self.props.width = max(self.timeline.layout.get_allocation().width,
                               timelineUtils.Zoomable.nsToPixel(self.timeline.bTimeline.props.duration))
        self.props.width_request = max(self.timeline.layout.get_allocation().width,
                                       timelineUtils.Zoomable.nsToPixel(self.timeline.bTimeline.props.duration))

        for child in self._children:
            self.propagate_draw(child, cr)

class Layer(Gtk.EventBox, timelineUtils.Zoomable, Loggable):

    __gtype_name__ = "PitiviLayer"

    __gsignals__ = {
        "remove-me": (GObject.SignalFlags.RUN_LAST, None, (),)
    }

    def __init__(self, bLayer, timeline):
        super(Layer, self).__init__()
        Loggable.__init__(self)

        self.bLayer = bLayer
        self.bLayer.ui = self
        self.timeline = timeline
        self.app = timeline.app

        self.bLayer.connect("clip-added", self._clipAddedCb)
        self.bLayer.connect("clip-removed", self._clipRemovedCb)

        # FIXME Make the layer height user setable with 'Paned'
        self.props.height_request = ui.LAYER_HEIGHT / 2
        self.props.valign = Gtk.Align.START

        self._layout = LayerLayout(self.timeline)
        self._layout.connect("remove", self.__childWidgetRemovedCb)
        self.add(self._layout)

        self.media_types = GES.TrackType(0)
        for clip in bLayer.get_clips():
            self._addClip(clip)

        self.before_sep = SpacedSeparator(Gtk.PositionType.TOP)
        self.after_sep = SpacedSeparator(Gtk.PositionType.BOTTOM)

    def release(self):
        for clip in self.bLayer.get_clips():
            self._removeClip(clip)
        self.bLayer.disconnect_by_func(self._clipAddedCb)
        self.bLayer.disconnect_by_func(self._clipRemovedCb)

    def checkMediaTypes(self):
        if self.timeline.editing_context:
            self.info("Not updating media types as"
                      " we are editing the timeline")
            return
        old_media_types = self.media_types
        self.media_types = GES.TrackType(0)
        bClips = self.bLayer.get_clips()

        """
        FIXME: That produces segfault in GES/GSequence
        if not bClips:
            self.emit("remove-me")
            return
        """

        for bClip in bClips:
            for child in bClip.get_children(False):
                self.media_types |= child.get_track().props.track_type
                if self.media_types == (GES.TrackType.AUDIO | GES.TrackType.VIDEO):
                    break

        if not (self.media_types & GES.TrackType.AUDIO) and not (self.media_types & GES.TrackType.VIDEO):
            # An empty layer only shows the video strip.
            self.media_types = GES.TrackType.VIDEO

        height = 0
        if self.media_types & GES.TrackType.AUDIO:
            height += ui.LAYER_HEIGHT / 2
            self.bLayer.control_ui.audio_control.force_show_all()
        else:
            self.bLayer.control_ui.audio_control.hide()

        if self.media_types & GES.TrackType.VIDEO:
            self.bLayer.control_ui.video_control.force_show_all()
            height += ui.LAYER_HEIGHT / 2
        else:
            self.bLayer.control_ui.video_control.hide()

        self.props.height_request = height
        self.bLayer.control_ui.props.height_request = height

        if old_media_types != self.media_types:
            self.updatePosition()

    def move(self, child, x, y):
        self._layout.move(child, x, y)

    def _childAddedCb(self, bClip, child):
        self.checkMediaTypes()

    def _childRemovedCb(self, bClip, child):
        self.checkMediaTypes()

    def _clipAddedCb(self, layer, bClip):
        self._addClip(bClip)

    def _addClip(self, bClip):
        ui_type = elements.GES_TYPE_UI_TYPE.get(bClip.__gtype__, None)
        if ui_type is None:
            self.error("Implement UI for type %s?" % bClip.__gtype__)
            return

        if not hasattr(bClip, "ui") or bClip.ui is None:
            clip = ui_type(self, bClip)
        else:
            clip = bClip.ui

        self._layout.put(clip, self.nsToPixel(bClip.props.start), 0)
        self.show_all()
        bClip.connect_after("child-added", self._childAddedCb)
        bClip.connect_after("child-removed", self._childRemovedCb)
        self.checkMediaTypes()

    def _clipRemovedCb(self, bLayer, bClip):
        self._removeClip(bClip)

    def _removeClip(self, bClip):
        if not bClip.ui:
            return

        ui_type = elements.GES_TYPE_UI_TYPE.get(bClip.__gtype__, None)
        if ui_type is None:
            self.error("Implement UI for type %s?" % bClip.__gtype__)
            return

        bClip.ui.release()
        self._layout.remove(bClip.ui)

    def __childWidgetRemovedCb(self, layout, clip):
        bClip = clip.bClip
        bClip.ui.layer = None
        if self.timeline.draggingElement is None:
            bClip.ui.release()
            bClip.ui = None

        bClip.disconnect_by_func(self._childAddedCb)
        bClip.disconnect_by_func(self._childRemovedCb)
        self.checkMediaTypes()

    def updatePosition(self):
        for bClip in self.bLayer.get_clips():
            if hasattr(bClip, "ui"):
                bClip.ui.updatePosition()

    def do_draw(self, cr):
        Gtk.Box.do_draw(self, cr)


from django.urls import path
from . import views

app_name = 'blog'

urlpatterns = [
    path('', views.PostList.as_view(), name='list'),
    path('write/', views.PostWrite.as_view(), name='write'),
    path('<int:pk>/', views.PostDetail.as_view(), name='detail'),
    path('edit/<int:pk>/', views.PostUpdate.as_view(), name='edit'),
    path('delete/<int:pk>', views.PostDelete.as_view(), name='delete'),
    path('<int:post_id>/comment/write/',
         views.CommentWrite.as_view(), name='cmt-write'),
    path('<int:comment_id>/comment/delete/',
         views.CommentDelete.as_view(), name='cmt-delete'),
    path('<int:post_id>/hashtag/write/',
         views.HashtagWrite.as_view(), name='tag-write'),
    path('<int:hashtag_id>/hashtag/delete/',
         views.HashtagDelete.as_view(), name='tag-delete'),
    #     path("search/<str:tag>/", views.PostSearch.as_view(), name='post-search'),
    path('<int:comment_id>/reply/write/',
         views.ReplyWrite.as_view(), name='reply-write'),
    path('<int:reply_id>/reply/delete/',
         views.ReplyDelete.as_view(), name='reply-delete'),
]


import pytest
from unittest.mock import Mock
from GEMEditor.database.model import *
from GEMEditor.model.classes.cobra import Model, Metabolite, Reaction
from GEMEditor.model.classes.annotation import Annotation
from GEMEditor.database.test.fixtures import database
from PyQt5.QtWidgets import QApplication

# Make sure to only start an application
# if there is no active one. Opening multiple
# applications will lead to a crash.
app = QApplication.instance()
if app is None:
    app = QApplication([])

@pytest.fixture()
def progress():
    mock = Mock()
    mock.wasCanceled = Mock(return_value=False)
    return mock

#Todo: Reimplement test case to not edit settings
# class TestAnnotationSettingsDialog:
#
#     @pytest.mark.parametrize("check_state", (True, False))
#     def test_get_settings(self, check_state):
#         dialog = AnnotationSettingsDialog()
#
#         # Check states
#         dialog.checkBox_charge.setChecked(check_state)
#         dialog.checkBox_formula.setChecked(check_state)
#
#         # Check getting the settings
#         settings = dialog.get_settings()
#         assert settings["formula"] == dialog.checkBox_formula.isChecked()
#         assert settings["charge"] == dialog.checkBox_charge.isChecked()
#
#     @pytest.mark.parametrize("check_state", (True, False))
#     def test_get_settings_resources(self, check_state):
#         metabolite_resources = {"a": 1, "b": 2}
#         reaction_resources = {"c": 3, "d": 4}
#         dialog = AnnotationSettingsDialog(metabolite_resources, reaction_resources)
#
#         # Set state for metabolite checkboxes
#         for checkbox in dialog.metabolite_checkboxes:
#             checkbox.setChecked(check_state)
#
#         # Set state for reaction checkboxes
#         for checkbox in dialog.reaction_checkboxes:
#             checkbox.setChecked(check_state)
#
#         settings = dialog.get_settings()
#         if check_state:
#             assert set(settings["reaction_resources"]) == set(reaction_resources.values())
#             assert set(settings["metabolite_resources"]) == set(metabolite_resources.values())
#         else:
#             assert not settings["reaction_resources"]
#             assert not settings["metabolite_resources"]

class Test_get_reactions_with_same_signature:

    def test_get_entry_matching_signature(self, database):
        signature = set([1, 2, 3, 4])
        entries = set([1])
        result = get_reactions_with_same_signature(database, entries,
                                                   signature, set())
        assert result == set([1])

    def test_dont_get_reactions_matching_signature_not_in_entries(self, database):
        signature = set([1, 2, 3, 4])
        entries = set()
        result = get_reactions_with_same_signature(database, entries,
                                                   signature, set())
        assert result == set()

    def test_not_matching_when_one_metabolite_missing(self, database):
        signature = set([1, 2, 3])
        entries = set([1])
        result = get_reactions_with_same_signature(database, entries,
                                                   signature, set())
        assert result == set()

    def test_not_matching_if_additional_metabolite(self, database):
        signature = set([1, 2, 3, 4, 5])
        entries = set([1])
        result = get_reactions_with_same_signature(database, entries,
                                                   signature, set())
        assert result == set()

    def test_match_if_additional_metabolite_is_ignored(self, database):
        signature = set([1, 2, 3])
        entries = set([1])
        result = get_reactions_with_same_signature(database, entries,
                                                   signature, set([4]))
        assert result == set([1])

class Test_map_by_annotation:

    def test_map_metabolites(self, database):
        metabolite = Metabolite("m1")
        metabolite.annotation.add(Annotation(identifier="MNXM2", collection="metanetx.chemical"))
        metabolite.annotation.add(Annotation(identifier="MNXM215", collection="metanetx.chemical"))

        assert map_by_annotation(database, metabolite) == set([1, 2])

    def test_empty_result_if_not_in_db(self, database):
        metabolite = Metabolite("m1")
        metabolite.annotation.add(Annotation(identifier="MNXM2000", collection="metanetx.chemical"))

        assert map_by_annotation(database, metabolite) == set()

class Test_update_metabolite_database_mapping:

    def test_map_metabolite_by_annotation(self, database, progress):
        model = Model()
        met1 = Metabolite("m1")
        model.add_metabolites([met1])
        met1.annotation.add(Annotation(identifier="MNXM2", collection="metanetx.chemical"))

        update_metabolite_database_mapping(database, model, progress)
        assert model.database_mapping[met1] == 1

    def test_map_metabolite_by_name(self, database, progress):
        model = Model()
        met1 = Metabolite("m1", name="Water")
        model.add_metabolites([met1])

        update_metabolite_database_mapping(database, model, progress)
        assert model.database_mapping[met1] == 1

    def test_not_mapped_for_name_substring(self, database, progress):
        model = Model()
        met1 = Metabolite("m1", name="ater")
        model.add_metabolites([met1])

        update_metabolite_database_mapping(database, model, progress)
        assert model.database_mapping[met1] is None

    def test_map_metabolite_by_formula(self, database, progress):
        model = Model()
        met1 = Metabolite("m1", formula="H2O")
        model.add_metabolites([met1])

        update_metabolite_database_mapping(database, model, progress)
        assert model.database_mapping[met1] == 1

class Test_check_ambiguous_mappings:

    def test_do_nothing_if_no_ambiguous_maps(self):
        model = Model()
        metabolite = Metabolite()
        model.database_mapping[metabolite] = 1
        check_ambiguous_mappings(model, None)

        assert model.database_mapping[metabolite] == 1

    def test_ambiguous_maps_present(self):
        # Todo: Implement test
        assert True

class Test_update_reaction_database_mapping:

    def test_map_reaction_by_stoichiometry(self, database, progress):
        model = Model()
        met1 = Metabolite("m1")
        met2 = Metabolite("m2")
        met3 = Metabolite("m3")
        met4 = Metabolite("m4")
        model.add_metabolites((met1, met2,
                               met3, met4))
        model.database_mapping.update({met1: 1,
                                       met2: 2,
                                       met3: 3,
                                       met4: 4})
        reaction = Reaction("r1")
        reaction.add_metabolites({met1: -1, met2: -1,
                                  met3: 1, met4: 1})
        model.add_reactions([reaction])

        update_reaction_database_mapping(database, model, progress)

        assert model.database_mapping[reaction] == 1

    def test_map_reaction_by_annotation(self, database, progress):
        model = Model()
        met1 = Metabolite("m1")
        met2 = Metabolite("m2")
        model.add_metabolites([met1, met2])

        reaction = Reaction("r1")
        reaction.add_metabolites({met1: -1, met2: 1})
        reaction.annotation.add(Annotation(identifier="MNXR14892",
                                           collection="metanetx.reaction"))
        model.add_reactions([reaction])

        update_reaction_database_mapping(database, model, progress)

        assert model.database_mapping[reaction] == 1

    def test_no_map_by_stoichiometry_if_any_metabolite_not_mapped(self, database, progress):
        model = Model()
        met1 = Metabolite("m1")
        met2 = Metabolite("m2")
        model.add_metabolites((met1, met2))
        model.database_mapping.update({met1: 1})

        reaction = Reaction("r1")
        reaction.add_metabolites({met1: -1, met2: -1})
        model.add_reactions([reaction])

        update_reaction_database_mapping(database, model, progress)
        assert reaction not in model.database_mapping


import torch
from torch import nn
import numpy as np
import matplotlib
import matplotlib.pyplot as plt

import sklearn
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split
from helper_functions import accuracy_fn, plot_predictions, plot_decision_boundary

X_blob, y_blob = make_blobs(n_samples=1000,
                            n_features=2,
                            centers=4,
                            cluster_std=1.5,
                            random_state=42)

X_blob = torch.from_numpy(X_blob).type(torch.float32)
y_blob = torch.from_numpy(y_blob).type(torch.LongTensor)

X_blob_train, X_blob_test, y_blob_train, y_blob_test = train_test_split(X_blob,
                                                                        y_blob,
                                                                        test_size=0.2,
                                                                        random_state=42)

print(X_blob_train.shape, y_blob_train.shape)
plt.figure(figsize=(10, 7))
plt.scatter(X_blob[:, 0], X_blob[:, 1], c=y_blob, cmap=plt.cm.RdYlBu)
plt.show()

class BlobModel(nn.Module):
    def __init__(self, input_features, output_features, hidden_units=8):
        super().__init__()
        self.linear_layer_stack = nn.Sequential(
            nn.Linear(in_features=input_features, out_features=hidden_units),
            nn.ReLU(),
            nn.Linear(in_features=hidden_units, out_features=hidden_units),
            nn.ReLU(),
            nn.Linear(in_features=hidden_units, out_features=output_features)
        )

    def forward(self, x) -> torch.tensor:
        return self.linear_layer_stack(x)

torch.manual_seed(42)
model = BlobModel()


#!/usr/bin/env python
"""
File: task_manager.py
Description: Instance a TaskManager.
CreateDate: 2023/9/8
Author: xuwenlin
E-mail: wenlinxu.njfu@outlook.com
"""
from typing import Union, Iterable, Callable
from io import TextIOWrapper
from os import system
from datetime import datetime
from getpass import getuser
from socket import gethostname
from multiprocessing import Pool
from click import echo

class TaskManager:
    def __init__(self,
                 commands: Iterable[str] = None,
                 num_processing: int = None,
                 params: Iterable[tuple] = None,
                 log_file: Union[str, TextIOWrapper] = None):
        try:
            self.task = list(commands)
        except TypeError:
            self.task = []
        self.params = params
        self.num_processing = num_processing
        if isinstance(log_file, str):
            self.loger = open(log_file, 'w')
        else:
            self.loger = log_file

    def add_task(self, command: Union[str, Iterable[str]]):
        if isinstance(command, str):
            self.task.append(command)
        else:
            command = list(command)
            self.task.extend(command)

    def del_task(self, index: Union[int, str] = None):
        if isinstance(index, int):
            del self.task[index]
        elif isinstance(index, str):
            self.task.remove(index)
        else:
            self.task.pop()

    def clear_task(self):
        self.task = []

    def echo_and_exec_cmd(self, cmd: str):
        """
        NOTICE: This method cannot run normally when it is called by multiprocessing.
                Because different subprocess will share same TaskManager.loger attribution.
        """
        echo(f'\033[33m[{getuser()}@{gethostname()}: '
             f'{datetime.now().replace(microsecond=0)}]\n$ '
             f'\033[0m\033[36m{cmd}\033[0m', self.loger, err=True)
        system(cmd)

    def serial_run_cmd(self):
        for cmd in self.task:
            echo(f'\033[33m[{getuser()}@{gethostname()}: {datetime.now().replace(microsecond=0)}]\n'
                 f'$ \033[0m\033[36m{cmd}\033[0m', self.loger, err=True)
            system(cmd)

    def parallel_run_cmd(self):
        if not self.task:
            echo('\033[31mError: TaskManager has no task.\033[0m', err=True)
            exit()
        pool = Pool(self.num_processing)
        for cmd in self.task:
            pool.apply_async(self.echo_and_exec_cmd, args=(cmd,))
        pool.close()
        pool.join()

    def parallel_run_func(self, func: Callable, call_back_func: Callable = None):
        results = []
        with Pool(self.num_processing) as pool:
            for param in self.params:
                ret = pool.apply_async(func, args=param, callback=call_back_func)
                results.append(ret)
            pool.close()
            pool.join()
        return results

if __name__ == '__main__':
    tkm = TaskManager()
    cmds = [f'echo Hello World x {i}' for i in range(10)]
    tkm.add_task(cmds)
    tkm.serial_run_cmd()


from django.core.validators import ValidationError
from django.utils.translation import gettext_lazy as _
import doctest
doctest.IGNORE_EXCEPTION_DETAIL = True

def validate_starts(letter, word, field=None):
    if not word.lower().startswith(letter.lower()) and word:
        err = ValidationError(
            _("%(word)s does not start with %(letter)s"),
            params={
                "word": word,
                "letter": letter,
            }
        )
        if not field:
            raise err
        raise ValidationError({
                field: err
            })


from django.contrib.auth.models import AbstractUser
from django.db.models.fields import FilePathField

class User(AbstractUser):
    """
    User object.
    """

    # Subdirectory under their `data` folder where photos belong.
    # We assume that the `data` folder is bind-mounted in using Docker
    # (or, in a development environment, just exists) at `/data`.
    # Each user has a folder in `/data`.
    subdirectory = FilePathField(
        path="/data",
        null=False,
        blank=False,
        default="/data/",
        recursive=True,
        allow_folders=True,
        allow_files=False,
    )


import os
import streamlit as st
import pdfplumber
import openai

# 设置你的 OpenAI 密钥
openai.api_key = os.getenv("API_KEY")
st.header("虚拟面试官")
st.subheader( "根据上传的简历来分析您的优势")
st.subheader( "同时为您提供面试题，来模拟面试")

def read_pdf(file):
    with pdfplumber.open(file) as pdf:
        text = ''
        for page in pdf.pages:
            text += page.extract_text()
    return text

def summarize_text(text):
    messages = [
            {"role": "system", "content": "你现在来辅助帮助用户发现用户简历中的优势，和你认为可以优化的内容，语言干练简洁"},
            {"role": "user", "content": text},
        ]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-16k",
        messages=messages
    )
    return response['choices'][0]['message']['content']
def summarize_question(text):
    messages = [
            {"role": "system", "content": "你现在扮演面试官，阅读分隔符 #### 之间的用户简历,按照用户的专业给用户出几个专业度高的面试题,####"+text+"#### "},
           #{"role": "user", "content": text},
        ]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-16k",
        messages=messages
    )
    return response['choices'][0]['message']['content']
if 'summarized' not in st.session_state:
    st.session_state.summarized = False
    st.session_state.summary = None
    st.session_state.text = None
uploaded_file = st.file_uploader("上传pdf格式的简历", type='pdf')

if uploaded_file is not None and not st.session_state.summarized:
    with st.spinner('正在读取PDF...'):

        st.session_state.text = read_pdf(uploaded_file)
    with st.spinner('正在挖掘闪光点并提供一些优化建议...'):
        st.session_state.summary = summarize_text(st.session_state.text)
        st.session_state.summarized = True
        st.write( st.session_state.summary)
        # 添加一个按钮
if st.session_state.summarized:
    if st.button('我是面试官，我来提出几个问题吧！'):
        st.write("")
        with st.spinner('正在准备实战题目...'):
            st.session_state.summary = summarize_question(st.session_state.text)
        st.write(st.session_state.summary)


# from Strusion import IO
import IO
from math import floor
from tqdm import tqdm
#  Default values
x_axis = 192 			# x axis for second sub
y_axis = 48				# y axis for second sub
y_axis_bottom = 268		# y axis for second sub

default_sub_color = "ffffff"

def merge_two_subtitles(path_sub_1, path_sub_2, color=None,
                        x_axis=None, y_axis=None):
    sub1 = IO.load(path_sub_1)  # loading file
    sub2 = IO.load(path_sub_2)  # ''

    sub_position_str = set_position(
        axis_x=x_axis, axis_y=y_axis, one_subtitle=False)
    color_str = set_color(color)
    control = False  # control var to indicates that is a new sub block
    sub1.append('')

    for i in tqdm(range(len(sub2))):
        if 'ï»¿' in sub2[i]:
            sub2[i] = sub2[i][len(sub2[i]) - 1]

        if control:  # goes into because is the firstline without '-->'
            # add the first line
            sub1.append(sub_position_str + color_str + sub2[i])
            control = False

        elif sub2[i] != '':
            sub1.append(sub2[i])  # add the subsequent lines

        else:
            sub1.append("")  # add the last line
            sub1.append("")

        if '-->' in sub2[i]:  # from here, the code goes to a new sub block
            control = True
    return sub1

def change_one_subtitle(path_sub, color=None, x_axis=None, y_axis=None):
    sub1 = IO.load(path_sub)
    sub_out = list()

    sub_position_str = set_position(
        axis_x=x_axis,
        axis_y=y_axis,
        one_subtitle=True)
    color_str = set_color(color)
    control = False
    sub1.append('')
    for i in tqdm(range(len(sub1))):
        if 'ï»¿' in sub1[i]:
            sub1[i] = sub1[i][len(sub1[i]) - 1]

        if control:
            sub_out.append(sub_position_str + color_str + sub1[i])
            control = False

        elif sub1[i] != '':

            sub_out.append(sub1[i])  # add the subsequent lines

        else:
            sub_out.append("")  # add the last line
            sub_out.append("")

        if '-->' in sub1[i]:  # from here, the code goes to a new sub block
            control = True
    return sub_out

def change_subtitle_delay(millis, path_sub):
    millisecs = int(millis)
    sub = IO.load(path_sub)
    for i in tqdm(range(len(sub))):
        if '-->' in sub[i]:
            slices = sub[i].split(" --> ")
            ini = format_string_to_millisecs(slices[0])
            end = format_string_to_millisecs(slices[1])
            modification = "{} --> {}".format(
                format_millisecs_to_string(ini + millisecs),
                format_millisecs_to_string(end + millisecs))
            sub[i] = modification
    return sub

def set_position(one_subtitle, axis_x=None, axis_y=None):  # axis
    """
    Define the subtitle position on top
    :param axis_x, axis_y:
    :return:
    """

    # two different position exists for the y axis,
    # that's why the extra 'if' in y,
    x = axis_x if axis_x else x_axis  # se false usa o default
    y = axis_y if axis_y else (y_axis_bottom if one_subtitle else y_axis)
    return "{\\pos(" + str(x) + "," + str(y) + ")}"

def set_color(color):
    return ""

def format_millisecs_to_string(millis):
    millis = str(millis)
    millisecs = int(millis[-3:])
    millis = int(millis)
    seconds = (millis / 1000) % 60
    seconds = int(seconds)
    minutes = (millis / (1000 * 60)) % 60
    minutes = int(minutes)
    hours = (millis / (1000 * 60 * 60)) % 24
    string_formated = "{:02d}:{:02d}:{:02d},{:03d}"\
        .format(floor(hours), minutes, seconds, millisecs)
    return string_formated

def format_string_to_millisecs(string):
    # all the vars are in millisecs
    slices = string.split(':')
    hour = int(slices[0]) * (1000 * 60 * 60)
    minutes = int(slices[1]) * (1000 * 60)
    slices2 = slices[2].split(',')
    seconds = int(slices2[0]) * 1000
    millisecs = int(slices2[1])
    total = hour + minutes + seconds + millisecs
    return total


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

import math
import numpy as np
import networkx as nx
import scipy.sparse as sps
from sklearn.manifold import TSNE

def setup_layout_distances(nw, nodesdf, dists, maxdist, cluster):
    def computeShortPathUpToMax(adj, maxlen):
        dist = np.empty(adj.shape)
        dist.fill(-1)   # initialize to -1 - any element with -1 hasn't been filled yet
        np.fill_diagonal(dist, 0)
        cc = sps.identity(dist.shape[0])
        for idx in range(1, maxlen + 1):
            cc = cc.dot(adj)
            dist[(dist == -1) & (cc > 0).toarray()] = math.log(1 + idx)   # fill as yet unfilled path lengths
        dist[dist == -1] = 2.0 * maxlen
        return dist

    # compute network shortest path lengths up to a maximum threshold - beyond that things are far away
    if dists is None:
        print("Computing shortest paths")
        dists = computeShortPathUpToMax(nx.adjacency_matrix(nw), maxdist)
    # reduce path length if the nodes are in the same cluster
    if nodesdf is not None and cluster in nodesdf:
        node_idx = {idx: list(nw.nodes).index(idx) for idx in nw.nodes}
        clus = nodesdf.loc[list(nw.nodes)][cluster].sort_index().to_numpy()
        adj = nx.adjacency_matrix(nw, nodelist=nw.nodes).todense()
        for edge in nw.edges:
            a_edge = (node_idx[edge[0]], node_idx[edge[1]])
            adj[a_edge] = clus[a_edge[0]] == clus[a_edge[1]]
        dists = np.clip(dists - (adj / 1.5), 0, None)
    else:
        clus = None
    return dists, clus

# run tSNE to layout the nodes in 2D space
# dist is a distance matrix.  If None, distances are computed using shortest paths
# paths longer then maxdist are assumed to be "long" and set to 2*maxdist
# returns dict of {nodeid: [x,y]}
# offset increases minimum and so decreases relative distance between nodes, to hopefully spread tight clusters
def runTSNELayout(nw, nodesdf=None, dists=None, maxdist=5, cluster=None):
    # adj is adjacency matrix
    # compute shortest paths up to a max path length
    # fill all longer paths with twice the max
    def initial_positions(all_clus):
        r = 10
        clus = np.unique(all_clus)
        n_clus = len(clus)
        d_phi = 2 * np.pi / n_clus
        clus_idx = dict(zip(clus, np.arange(n_clus)))
        phi = np.array([d_phi * clus_idx[cl] for cl in all_clus])
        pos = r * np.random.rand(len(all_clus))
        x_pos = pos * np.cos(phi)
        y_pos = pos * np.sin(phi)
        return np.stack([x_pos, y_pos]).T

    print("Running tSNE layout")
    dists, clus = setup_layout_distances(nw, nodesdf, dists, maxdist, cluster)
    perp = min(50, nw.number_of_nodes()/10)
    # compute tSNE
    print("Computing tSNE")
    layout = TSNE(n_components=2, metric='precomputed', init=initial_positions(clus),
                  early_exaggeration=5, perplexity=perp).fit_transform(np.asarray(dists))
    # build the output data structure
    nodes = nw.nodes()
    nodeMap = dict(zip(nodes, range(len(nodes))))
    layout_dict = {node: layout[nodeMap[node]] for node in nodes}
    print("Done running tSNE layout")
    # return both networkx style dict and array of positions
    return layout_dict, layout


from matplotlib import pyplot as plt
import serial
import sys
import time
import struct
import os
import math as m
import statistics as st
import numpy as np
import pickle as pkl
from copy import deepcopy
from multiprocessing import Process, Manager
import pyaudio
import random as r

import pyFuncs.AudioFuncs as af

plot_selection = 'peaks'
# plot_selection = 'heatmap'
# plot_selection = '3d'

readFilePath = 'MusicData/Instruments/Tenor/noteRec.pkl'
# readFilePath = 'MusicData/Instruments/Alto/noteRec.pkl'

# readFilePath = 'pickle/noteRec_'
# ii = 0
# while os.path.exists(readFilePath + str(ii) + '.pkl'): ii += 1 # Loop until filename ii is not taken
# readFilePath = readFilePath + str(ii-1) + '.pkl'

print(f'Opening {readFilePath}')

pklFile = open(readFilePath, 'rb')
pklDict = pkl.load(pklFile)
pklFile.close()

for foo in pklDict: print(foo)

Right = np.where(np.array(pklDict['solenoid_played']) == 'Right')[0]
Left = np.where(np.array(pklDict['solenoid_played']) == 'Left')[0]

calc_pitch = np.array( pklDict['calc_pitch'] )
calc_confidence = np.array( pklDict['calc_confidence'] )
stepper_position = np.array( pklDict['stepper_position'] )

RATE = pklDict['FS_RATE']

def loadPeaks(fooDict):
    outData = []
    ii = 0

    frqs = []
    pos = []
    signi = []
    while fooDict['stepper_position'][ii] <= fooDict['stepper_position'][ii+1]:
        # if ii > 100: break
        fooSig = fooDict['signal'][ii]
        fooPos = fooDict['stepper_position'][ii]

        print(f"{len(pos)}\033[1A")
        freqs, amps = af.getHarmonic(RATE, fooSig)
        foo_frqs, foo_amps = af.FFT_Peaks(freqs, amps)
        frqs += list(foo_frqs)
        signi += [foo/max(foo_amps) for foo in foo_amps]
        pos += [fooPos for foo in foo_frqs]
        ii += 1
    outData.append( [pos, frqs, signi] )
    print(f"frqs:{len(frqs)}")
    print(f"pos:{len(pos)}")
    print(f"signi:{len(signi)}")

    return(outData)

    frqs = []
    pos = []
    signi = []
    while ii < len(fooDict['stepper_position']):
        fooSig = fooDict['signal'][ii]
        fooPos = fooDict['stepper_position'][ii]

        print(f"{len(pos)}\033[1A")
        freqs, amps = af.getHarmonic(RATE, fooSig)
        foo_frqs, foo_amps = af.FFT_Peaks(freqs, amps)
        frqs += foo_frqs
        signi += [foo/max(foo_amps) for foo in foo_amps]
        pos += [fooPos for foo in foo_frqs]
        ii += 1
    outData.append( [pos, frqs, signi] )
    print(f"frqs:{len(frqs)}")
    print(f"pos:{len(pos)}")
    print(f"signi:{len(signi)}")

    return(outData)

if plot_selection == 'heatmap':
    FREQS_H = None
    AMPS_H = []
    for fooSig in pklDict['signal']:
        # freqs_h, amps_h = af.FFT_Both(RATE, fooSig)
        # freqs_h, amps_h = af.getHarmonic(RATE, fooSig, harmonicCount=2)
        freqs_h, amps_h = af.getHarmonic(RATE, fooSig)
        # freqs_h, amps_h = af.getHarmonic(RATE, fooSig, harmonicCount=4)
        FREQS_H = freqs_h
        AMPS_H.append(amps_h)

    fig, ax = plt.subplots()
    freqCutoff = 1000
    maxInd = np.where(FREQS_H < freqCutoff)[0][-1]
    ax.matshow([fooAmps[:maxInd]/sum(fooAmps[:maxInd]) for fooAmps in AMPS_H], aspect='auto')
    ax.set_xticks(FREQS_H[:maxInd][::m.floor(maxInd/15)][:-1])
    plt.show()

if plot_selection == 'peaks':
    peakData = loadPeaks(pklDict)
    for foo in peakData:
        plt.scatter(foo[0], foo[1], alpha=foo[2])

    outputPickle_fileName = "tmp/notePeaks.pkl"
    outPkl = open(outputPickle_fileName, 'wb')
    pkl.dump(peakData, outPkl)
    outPkl.close()

    plt.show()

if plot_selection == '3d':
    fig = plt.figure()
    ax = plt.axes(projection='3d')

    peakData = loadPeaks(pklDict)
    for ii in range(len(peakData)):
        netIndex = sum([len(peakData[jj]) for jj in range(ii)])
        foo = peakData[ii]
        print(f"foo[0]   len:{len(foo[0])}")
        print(f"foo[1]   len:{len(foo[1])}")
        print(f"pklDict['solenoid_time'][netIndex:netIndex+len(peakData)]   len:{len(pklDict['solenoid_time'][netIndex:netIndex+len(peakData)])}")
        ax.scatter(
            foo[0],
            foo[1],
            pklDict['solenoid_time'][netIndex:netIndex+len(foo[0])],
            alpha=np.array(foo[2])/5,
        )

    ax.set_xlabel("Stepper Position")
    ax.set_ylabel("Frequency (Hz)")
    ax.set_zlabel("Solenoid Strike Time")
    plt.show()

# plt.scatter(range(len(Right)), calc_pitch[Right], alpha = calc_confidence[Right] )
# plt.scatter(range(len(Left)), calc_pitch[Left], alpha = calc_confidence[Left] )

# plt.scatter(abs(stepper_position[Right]), calc_pitch[Right], alpha = calc_confidence[Right] )
# plt.scatter(abs(stepper_position[Left]), calc_pitch[Left], alpha = calc_confidence[Left] )

# plt.scatter(stepper_position[Right], calc_pitch[Right] )
# plt.scatter(stepper_position[Left], calc_pitch[Left] )

# plt.scatter(stepper_position[Right], calc_pitch[Right], alpha = calc_confidence[Right] )
# plt.scatter(stepper_position[Left], calc_pitch[Left], alpha = calc_confidence[Left] )

# plt.plot(range(len(Right)), calc_pitch[Right] )
# plt.plot(range(len(Left)), calc_pitch[Left] )

# plt.scatter(pklDict['calc_pitch'], pklDict['calc_confidence'])

plt.show()


import uuid

from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from django.conf import settings
from django.utils.html import mark_safe

from cuser.middleware import CuserMiddleware

COLORS_CHOICES = (
    ('info', _('Light blue')),
    ('primary', _('Blue')),
    ('danger', _('Red')),
    ('warning', _('Yellow')),
    ('success', _('Green')),
    ('secondary', _('Gray')),
    ('dark', _('Black')),
    ('light', _('White')),
)

class TimeStampedModel(models.Model):
    """
    An abstract base class model that provides self-updating
    ``created`` and ``modified`` field.
    """
    created = models.DateTimeField(auto_now_add=True, verbose_name=_('created'))
    modified = models.DateTimeField(auto_now=True, verbose_name=_('modified'))

    class Meta:
        abstract = True

class PublishableModelQuerySet(models.QuerySet):

    # Get the list of published objects
    def published(self):
        """
        We show every objects to staff as a preview
        even if they are not published, yet.
        """
        user = CuserMiddleware.get_user()
        qs = self
        if user and not user.is_staff:
            qs = qs.filter(published=True)
        return qs

class PublishableModelManager(models.Manager):

    def get_queryset(self):
        return PublishableModelQuerySet(self.model, using=self._db)

    def published(self):
        return self.get_queryset().published()

class PublishableModel(models.Model):
    """
    A concrete base class model that updates the publication
    date as soon as it becomes published.
    """
    published = models.BooleanField(default=False, verbose_name=_('published'))
    publication_date = models.DateTimeField(blank=True, null=True, verbose_name=_('publication_date'))

    objects = PublishableModelManager()

    # Pubblication date is updated if published has been modified from False to True
    def __init__(self, *args, **kwargs):
        super(PublishableModel, self).__init__(*args, **kwargs)
        self.old_published = self.published

    def save(self, *args, **kwargs):
        if self.old_published != self.published and self.published:
            self.publication_date = timezone.now()
        super(PublishableModel, self).save(*args, **kwargs)

class PromotableModel(models.Model):
    """
    An abstract base class model that enables a promotion feature
    similar to a facebook like on any model.
    """
    promotions = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, verbose_name=_('promotions'))

    def user_has_promoted(self):
        # Fetch the logged user thanks to a dedicated middleware
        user = CuserMiddleware.get_user()
        if user in self.promotions.all():
            return True
        else:
            return False

    class Meta:
        abstract = True

class Element(models.Model):
    """
    An abstract base class model that represents a single piece of content.
    """
    title = models.CharField(
        max_length = 80,
        verbose_name = _('title'),
    )
    icon = models.CharField(
        blank = True,
        max_length = 30,
        verbose_name = _('icon'),
    )
    ICON_STYLE_CHOICES = (
        ('r', 'r - regular'),
        ('s', 's - solid'),
        ('l', 'l - light'),
        ('d', 'd - duotone'),
        ('b', 'b - brand'),

    )
    ICON_STYLE_DEFAULT = 'r'
    icon_style = models.CharField(
        blank = True,
        choices = ICON_STYLE_CHOICES,
        default = ICON_STYLE_DEFAULT,
        max_length = 1,
        verbose_name = _('icon style')
    )
    description = models.TextField(blank=True, verbose_name=_('description'))
    color = models.CharField(blank=True, choices=COLORS_CHOICES, max_length=30, default='default', verbose_name=_('color'))

    def __str__(self):
        return self.title

    def icon_tag(self):
        if self.icon:
            return mark_safe(''.format(self.icon))
        else:
            return _('No icon')
    icon_tag.short_description = _('Icon')

    def color_tag(self):
        if self.color:
            return mark_safe('{1}'.format(self.color, self.get_color_display()))
        else:
            return _('No color')
    color_tag.short_description = _('Color')

    class Meta:
        abstract = True

class Category(models.Model):
    """
    An abstract base class model that defines a specific type of object.
    """
    title = models.CharField(max_length=60, unique=True)
    default = models.BooleanField(default=False)

    def __str__(self):
        return self.title

    class Meta:
        verbose_name_plural = _("categories")
        abstract = True

class DiventiImageModel(models.Model):
    """
    An abstract base class that manages models based on images uploaded on the internet.
    """
    image = models.URLField(blank=True, verbose_name=_('image'))
    label = models.CharField(max_length=50, blank=True, verbose_name=_('label'))

    def image_tag(self, image_url=0):
        if image_url:
            return mark_safe(''.format(image_url))
        elif self.image:
            return mark_safe(''.format(self.image))
        else:
            return _('No image')
    image_tag.short_description = _('Image')

    class Meta:
        abstract = True

    def __str__(self):
        return u'{0}'.format(self.label)

class DiventiCoverQuerySet(models.QuerySet):

    # Get the active cover or returns nothing
    def active(self):
        try:
            cover = self.model.objects.get(active=True)
        except self.model.DoesNotExist:
            cover = self.model.objects.none()
        except self.model.MultipleObjectsReturned:
            msg = _("There must be only one object at a time. Please fix!")
            raise self.model.MultipleObjectsReturned(msg)
        return cover

class DiventiCoverManager(models.Manager):

    def get_queryset(self):
        return DiventiCoverQuerySet(self.model, using=self._db)

    def active(self):
        return self.get_queryset().active()

class DiventiCoverModel(DiventiImageModel):
    """
    An abstract base class that helps to implement an image that can be activated.
    """

    active = models.BooleanField(default=False, verbose_name=_('active'))

    objects = DiventiCoverManager()

    class Meta:
        abstract = True

class FeaturedModelQuerySet(PublishableModelQuerySet):

    # Get the featured object that can be selected to appear on the landing page
    # Even super users should not see featured objects if they are not strictly published
    def featured(self):
        try:
            featured_model = self.published().get(featured=True)
        except self.model.DoesNotExist:
            # Fail silently, return nothing
            featured_model = self.none()
        except self.model.MultipleObjectsReturned:
            msg = _('Multiple featured objects returned. Please fix!')
            raise self.model.MultipleObjectsReturned(msg)
        return featured_model

    # Get the not featured object that can be selected to appear on the landing page
    def not_featured(self):
        not_featured_models = self.published().filter(featured=False)
        return not_featured_models

    # Returns the first pinned objects
    # It assumes that the model has a "publication_date" field
    def pinned(self):
        featured_model = self.published().filter(pinned=True)
        try:
            featured_model = featured_model.get()
        except self.model.MultipleObjectsReturned:
            featured_model = featured_model.order_by('-publication_date').first()
        except self.model.DoesNotExist:
            featured_model = featured_model.first()
        return featured_model

    # Returns the list of pinned objects
    def pinned_list(self):
        featured_model = self.published().filter(pinned=True)
        return featured_model

class FeaturedModelManager(models.Manager):

    def get_queryset(self):
        return FeaturedModelQuerySet(self.model, using=self._db)

    def published(self):
        return self.get_queryset().published()

    def featured(self):
        return self.get_queryset().featured()

    def not_featured(self):
        return self.get_queryset().not_featured()

    def pinned(self):
        return self.get_queryset().pinned()

    def pinned_list(self):
        return self.get_queryset().pinned_list()

class FeaturedModel(PublishableModel):
    """
    An abstract base class that includes a featured boolean field

    """
    pinned = models.BooleanField(
        default = False,
        verbose_name = _('pinned'),
        help_text = _('Pinned objects appear on the navbar and on the landing page')
    )
    featured = models.BooleanField(
        default=False,
        verbose_name=_('featured'),
        help_text = _('Featured objects are displayed on the top of their page. If pinned, they are also displayed on the top of the landing page')
    )

    objects = FeaturedModelManager()

    class Meta:
        abstract = True

class HighlightedModelQuerySet(models.QuerySet):

    # Get the highlighted object or the first item of the queryset
    def highlighted_or_first(self):
        try:
            highlighted_model = self.get(highlighted=True)
        except self.model.DoesNotExist:
            # Fail silently and return the first item
            highlighted_model = self.first()
        except self.model.MultipleObjectsReturned:
            msg = _('Multiple highlighted objects returned. Please fix!')
            raise self.model.MultipleObjectsReturned(msg)
        return highlighted_model

class HighlightedModelManager(models.Manager):

    def get_queryset(self):
        return HighlightedModelQuerySet(self.model, using=self._db)

    def highlighted_or_first(self):
        return self.get_queryset().highlighted_or_first()

class HighlightedModel(models.Model):
    """
        An abstract bae class that includes a featured boolean field
        without the publishable functionality.
    """
    highlighted = models.BooleanField(default=False, verbose_name=_('highlighted'))

    objects = HighlightedModelManager()

    class Meta:
        abstract = True

class DiventiColModel(models.Model):
    COL_CHOICES = [
        (12, _('Full (12)')),
        (8, _('Two thirds (8)')),
        (6, _('Half (6)')),
        (4, _('One third (4)')),
        (3, _('One fourth (3)')),
    ]
    col_lg = models.PositiveIntegerField(default=12, choices=COL_CHOICES, verbose_name=_('lg column'))
    order_lg = models.PositiveIntegerField(default=1, verbose_name=_('lg order'))
    col_md = models.PositiveIntegerField(default=12, choices=COL_CHOICES, verbose_name=_('md column'))
    order_md = models.PositiveIntegerField(default=1, verbose_name=_('md order'))
    col_sm = models.PositiveIntegerField(default=12, choices=COL_CHOICES, verbose_name=_('sm column'))
    order_sm = models.PositiveIntegerField(default=1, verbose_name=_('sm order'))

    class Meta:
        abstract = True

class SectionModel(models.Model):
    """ Includes utility methods for content areas such as sections. """
    ALIGNMENT_CHOICES = (
        ('left', _('left')),
        ('centered', _('centered')),
        ('right', _('right')),
    )
    alignment = models.CharField(
        default='centered',
        choices=ALIGNMENT_CHOICES,
        max_length=50,
        verbose_name=_('alignment')
    )
    POSITION_CHOICES = (
        (1, _('text first')),
        (3, _('text second')),
    )
    position = models.PositiveIntegerField(
        default=1,
        choices=POSITION_CHOICES,
        verbose_name=_('text position')
    )

    class Meta:
        abstract = True


import numpy as np
import cv2
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from geometry_msgs.msg import Twist
from std_msgs.msg import Int32

class ImageSubscriber(Node):
    def __init__(self):
        super().__init__('image_subscriber')
        self.bridge = CvBridge()
        self.subscription = self.create_subscription(
            Image,
            '/oakd/rgb/preview/image_raw',
            self.image_callback,
            10)
        ###############
        self.publisher = self.create_publisher(Twist, '/cmd_vel', 10)
        self.button_subscriber = self.create_subscription(Int32,"number_topic", self.number_callback, 10)
        self.speed=0
        #self.timer = self.create_timer(0.1, self.publish_twist)
        #self.activate() ##
        #########

    def number_callback(self, msg): #button노드에서 넘겨받게된다.
        number = msg.data
        # 받은 숫자를 처리하는 로직 작성
        print("Received number:", number)
        self.speed=number

    def image_callback(self, msg):
        # Convert the ROS Image message to a numpy array with CvBridge
        cv_image = self.bridge.imgmsg_to_cv2(msg, desired_encoding='bgr8')
        # Now you have a cv2 (OpenCV) image and you can process it as you like
        # For instance, you can display it
        cv2.imshow("Image window", cv_image)
        self.publish_twist()
        cv2.waitKey(3)  # You need this to actually display the image

    def publish_twist(self):
        #print("run_0.05")
        msg = Twist()
        msg.linear.x = self.speed*0.1
        msg.linear.y = 0.0
        msg.linear.z = 0.0
        msg.angular.x = 0.0
        msg.angular.y = 0.0
        msg.angular.z = 0.0
        self.publisher.publish(msg)

def main(args=None):
    print("as")
    rclpy.init(args=args)

    ##########go#############
    # node = rclpy.create_node('turtlebot_controller')
    # publisher = node.create_publisher(Twist, '/cmd_vel', 0.1)
    # msg = Twist()
    # msg.linear.x = 0.2
    # msg.angular.z = 0.0
    # publisher.publish(msg)
    #####################

    image_subscriber = ImageSubscriber()

    rclpy.spin(image_subscriber)

    image_subscriber.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()


from PIL import Image
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
import os
import matplotlib.pyplot as plt

class SmilesDataset(Dataset):
    def __init__(self, dataset_path):
        self.data = []
        # Positive examples
        dir = os.fsencode(dataset_path + '/positives/positives7/')
        for file in os.listdir(dir):
            image = Image.open(dataset_path + '/positives/positives7/' + (file.strip()).decode("utf-8"))
            transform = transforms.Compose(
                        [transforms.RandomHorizontalFlip(),
                        transforms.ColorJitter(brightness = 0.5),
                        transforms.RandomCrop((64, 64)),
                        transforms.ToTensor()])
            tensor = transform(image)

            self.data.append((tensor, 1))

        num_positives = len(self.data)
        num_negatives = 0
        # Negative examples
        with open(dataset_path + '/negatives/smiles_01_neg.idx') as file:
            for line in file:
                if num_negatives > num_positives:
                    break

                image = Image.open(dataset_path + '/negatives/' + line.strip())
                transform = transforms.ToTensor()
                tensor = transform(image)

                self.data.append((tensor, 0))
                num_negatives += 1

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

    def __getitem__(self, idx):
        return self.data[idx]

def load_data(dataset_path, num_workers=0, batch_size=64):
    dataset = SmilesDataset(dataset_path)
    return DataLoader(dataset, num_workers=num_workers, batch_size=batch_size, shuffle=True, drop_last=False)

def viz_data(dataloader):
    data = next(iter(dataloader))
    f, axarr = plt.subplots(8,8)
    im = 0
    for r in range(8):
        for c in range(8):
            axarr[r][c].axis('off')
            axarr[r,c].imshow(data[0][im].squeeze(), cmap = 'gray')
            im += 1
    plt.show()

obj = SmilesDataset('./data/SMILEs')
assert len(obj) > 0, "Dataset is empty!"
# viz_data(load_data('./data/SMILEs'))


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

plt.style.use('ggplot')
# 中文和负号的正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

titanic = pd.read_csv('titanic_train.csv')
titanic.dropna(subset=['Age'], inplace=True)

# 提取不同性别的年龄数据
age_female = titanic.Age[titanic.Sex == 'female']
age_male = titanic.Age[titanic.Sex == 'male']

plt.hist(age_female, bins=np.arange(titanic.Age.min(), titanic.Age.max(), 2), label='女性', color='blue', edgecolor='k')
plt.hist(age_male, bins=np.arange(titanic.Age.min(), titanic.Age.max(), 2), label='男性', color='steelblue',
         edgecolor='k', alpha=0.6)

plt.title('乘客年龄直方图')
plt.xlabel('年龄')
plt.ylabel('人数')

plt.tick_params(top='off', right='off')

plt.legend(loc='best')

plt.show()


# -*- coding: utf-8 -*-
"""
hpack/hpack
~~~~~~~~~~~

Implements the HPACK header compression algorithm as detailed by the IETF.
"""
import logging

from .table import HeaderTable, table_entry_size
from .compat import to_byte, to_bytes
from .exceptions import (
    HPACKDecodingError, OversizedHeaderListError, InvalidTableSizeError
)
from .huffman import HuffmanEncoder
from .huffman_constants import (
    REQUEST_CODES, REQUEST_CODES_LENGTH
)
from .huffman_table import decode_huffman
from .struct import HeaderTuple, NeverIndexedHeaderTuple

log = logging.getLogger(__name__)

INDEX_NONE = b'\x00'
INDEX_NEVER = b'\x10'
INDEX_INCREMENTAL = b'\x40'

# Precompute 2^i for 1-8 for use in prefix calcs.
# Zero index is not used but there to save a subtraction
# as prefix numbers are not zero indexed.
_PREFIX_BIT_MAX_NUMBERS = [(2 ** i) - 1 for i in range(9)]

try:  # pragma: no cover
    str = str
except NameError:  # pragma: no cover
    str = (str, bytes)

# We default the maximum header list we're willing to accept to 64kB. That's a
# lot of headers, but if applications want to raise it they can do.
DEFAULT_MAX_HEADER_LIST_SIZE = 2 ** 16

def _unicode_if_needed(header, raw):
    """
    Provides a header as a unicode string if raw is False, otherwise returns
    it as a bytestring.
    """
    name = to_bytes(header[0])
    value = to_bytes(header[1])
    if not raw:
        name = name.decode('utf-8')
        value = value.decode('utf-8')
    return header.__class__(name, value)

def encode_integer(integer, prefix_bits):
    """
    This encodes an integer according to the wacky integer encoding rules
    defined in the HPACK spec.
    """
    log.debug("Encoding %d with %d bits", integer, prefix_bits)

    if integer < 0:
        raise ValueError(
            "Can only encode positive integers, got %s" % integer
        )

    if prefix_bits < 1 or prefix_bits > 8:
        raise ValueError(
            "Prefix bits must be between 1 and 8, got %s" % prefix_bits
        )

    max_number = _PREFIX_BIT_MAX_NUMBERS[prefix_bits]

    if integer < max_number:
        return bytearray([integer])  # Seriously?
    else:
        elements = [max_number]
        integer -= max_number

        while integer >= 128:
            elements.append((integer & 127) + 128)
            integer >>= 7

        elements.append(integer)

        return bytearray(elements)

def decode_integer(data, prefix_bits):
    """
    This decodes an integer according to the wacky integer encoding rules
    defined in the HPACK spec. Returns a tuple of the decoded integer and the
    number of bytes that were consumed from ``data`` in order to get that
    integer.
    """
    if prefix_bits < 1 or prefix_bits > 8:
        raise ValueError(
            "Prefix bits must be between 1 and 8, got %s" % prefix_bits
        )

    max_number = _PREFIX_BIT_MAX_NUMBERS[prefix_bits]
    index = 1
    shift = 0
    mask = (0xFF >> (8 - prefix_bits))

    try:
        number = to_byte(data[0]) & mask
        if number == max_number:
            while True:
                next_byte = to_byte(data[index])
                index += 1

                if next_byte >= 128:
                    number += (next_byte - 128) << shift
                else:
                    number += next_byte << shift
                    break
                shift += 7

    except IndexError:
        raise HPACKDecodingError(
            "Unable to decode HPACK integer representation from %r" % data
        )

    log.debug("Decoded %d, consumed %d bytes", number, index)

    return number, index

def _dict_to_iterable(header_dict):
    """
    This converts a dictionary to an iterable of two-tuples. This is a
    HPACK-specific function becuase it pulls "special-headers" out first and
    then emits them.
    """
    assert isinstance(header_dict, dict)
    keys = sorted(
        list(header_dict.keys()),
        key=lambda k: not _to_bytes(k).startswith(b':')
    )
    for key in keys:
        yield key, header_dict[key]

def _to_bytes(string):
    """
    Convert string to bytes.
    """
    if isinstance(string, bytes):
        return string
    if not isinstance(string, str):  # pragma: no cover
        string = str(string)

    return string if isinstance(string, bytes) else string.encode('utf-8')

class Encoder(object):
    """
    An HPACK encoder object. This object takes HTTP headers and emits encoded
    HTTP/2 header blocks.
    """

    def __init__(self):
        self.header_table = HeaderTable()
        self.huffman_coder = HuffmanEncoder(
            REQUEST_CODES, REQUEST_CODES_LENGTH
        )
        self.table_size_changes = []

    @property
    def header_table_size(self):
        """
        Controls the size of the HPACK header table.
        """
        return self.header_table.maxsize

    @header_table_size.setter
    def header_table_size(self, value):
        self.header_table.maxsize = value
        if self.header_table.resized:
            self.table_size_changes.append(value)

    def encode(self, headers, huffman=True):
        """
        Takes a set of headers and encodes them into a HPACK-encoded header
        block.

        :param headers: The headers to encode. Must be either an iterable of
                        tuples, an iterable of :class:`HeaderTuple
                        <hpack.struct.HeaderTuple>`, or a ``dict``.

                        If an iterable of tuples, the tuples may be either
                        two-tuples or three-tuples. If they are two-tuples, the
                        tuples must be of the format ``(name, value)``. If they
                        are three-tuples, they must be of the format
                        ``(name, value, sensitive)``, where ``sensitive`` is a
                        boolean value indicating whether the header should be
                        added to header tables anywhere. If not present,
                        ``sensitive`` defaults to ``False``.

                        If an iterable of :class:`HeaderTuple
                        <hpack.struct.HeaderTuple>`, the tuples must always be
                        two-tuples. Instead of using ``sensitive`` as a third
                        tuple entry, use :class:`NeverIndexedHeaderTuple
                        <hpack.struct.NeverIndexedHeaderTuple>` to request that
                        the field never be indexed.

                        .. warning:: HTTP/2 requires that all special headers
                            (headers whose names begin with ``:`` characters)
                            appear at the *start* of the header block. While
                            this method will ensure that happens for ``dict``
                            subclasses, callers using any other iterable of
                            tuples **must** ensure they place their special
                            headers at the start of the iterable.

                            For efficiency reasons users should prefer to use
                            iterables of two-tuples: fixing the ordering of
                            dictionary headers is an expensive operation that
                            should be avoided if possible.

        :param huffman: (optional) Whether to Huffman-encode any header sent as
                        a literal value. Except for use when debugging, it is
                        recommended that this be left enabled.

        :returns: A bytestring containing the HPACK-encoded header block.
        """
        # Transforming the headers into a header block is a procedure that can
        # be modeled as a chain or pipe. First, the headers are encoded. This
        # encoding can be done a number of ways. If the header name-value pair
        # are already in the header table we can represent them using the
        # indexed representation: the same is true if they are in the static
        # table. Otherwise, a literal representation will be used.
        log.debug("HPACK encoding %s", headers)
        header_block = []

        # Turn the headers into a list of tuples if possible. This is the
        # natural way to interact with them in HPACK. Because dictionaries are
        # un-ordered, we need to make sure we grab the "special" headers first.
        if isinstance(headers, dict):
            headers = _dict_to_iterable(headers)

        # Before we begin, if the header table size has been changed we need
        # to signal all changes since last emission appropriately.
        if self.header_table.resized:
            header_block.append(self._encode_table_size_change())
            self.header_table.resized = False

        # Add each header to the header block
        for header in headers:
            sensitive = False
            if isinstance(header, HeaderTuple):
                sensitive = not header.indexable
            elif len(header) > 2:
                sensitive = header[2]

            header = (_to_bytes(header[0]), _to_bytes(header[1]))
            header_block.append(self.add(header, sensitive, huffman))

        header_block = b''.join(header_block)

        log.debug("Encoded header block to %s", header_block)

        return header_block

    def add(self, to_add, sensitive, huffman=False):
        """
        This function takes a header key-value tuple and serializes it.
        """
        log.debug("Adding %s to the header table", to_add)

        name, value = to_add

        # Set our indexing mode
        indexbit = INDEX_INCREMENTAL if not sensitive else INDEX_NEVER

        # Search for a matching header in the header table.
        match = self.header_table.search(name, value)

        if match is None:
            # Not in the header table. Encode using the literal syntax,
            # and add it to the header table.
            encoded = self._encode_literal(name, value, indexbit, huffman)
            if not sensitive:
                self.header_table.add(name, value)
            return encoded

        # The header is in the table, break out the values. If we matched
        # perfectly, we can use the indexed representation: otherwise we
        # can use the indexed literal.
        index, name, perfect = match

        if perfect:
            # Indexed representation.
            encoded = self._encode_indexed(index)
        else:
            # Indexed literal. We are going to add header to the
            # header table unconditionally. It is a future todo to
            # filter out headers which are known to be ineffective for
            # indexing since they just take space in the table and
            # pushed out other valuable headers.
            encoded = self._encode_indexed_literal(
                index, value, indexbit, huffman
            )
            if not sensitive:
                self.header_table.add(name, value)

        return encoded

    def _encode_indexed(self, index):
        """
        Encodes a header using the indexed representation.
        """
        field = encode_integer(index, 7)
        field[0] |= 0x80  # we set the top bit
        return bytes(field)

    def _encode_literal(self, name, value, indexbit, huffman=False):
        """
        Encodes a header with a literal name and literal value. If ``indexing``
        is True, the header will be added to the header table: otherwise it
        will not.
        """
        if huffman:
            name = self.huffman_coder.encode(name)
            value = self.huffman_coder.encode(value)

        name_len = encode_integer(len(name), 7)
        value_len = encode_integer(len(value), 7)

        if huffman:
            name_len[0] |= 0x80
            value_len[0] |= 0x80

        return b''.join(
            [indexbit, bytes(name_len), name, bytes(value_len), value]
        )

    def _encode_indexed_literal(self, index, value, indexbit, huffman=False):
        """
        Encodes a header with an indexed name and a literal value and performs
        incremental indexing.
        """
        if indexbit != INDEX_INCREMENTAL:
            prefix = encode_integer(index, 4)
        else:
            prefix = encode_integer(index, 6)

        prefix[0] |= ord(indexbit)

        if huffman:
            value = self.huffman_coder.encode(value)

        value_len = encode_integer(len(value), 7)

        if huffman:
            value_len[0] |= 0x80

        return b''.join([bytes(prefix), bytes(value_len), value])

    def _encode_table_size_change(self):
        """
        Produces the encoded form of all header table size change context
        updates.
        """
        block = b''
        for size_bytes in self.table_size_changes:
            size_bytes = encode_integer(size_bytes, 5)
            size_bytes[0] |= 0x20
            block += bytes(size_bytes)
        self.table_size_changes = []
        return block

class Decoder(object):
    """
    An HPACK decoder object.

    .. versionchanged:: 2.3.0
       Added ``max_header_list_size`` argument.

    :param max_header_list_size: The maximum decompressed size we will allow
        for any single header block. This is a protection against DoS attacks
        that attempt to force the application to expand a relatively small
        amount of data into a really large header list, allowing enormous
        amounts of memory to be allocated.

        If this amount of data is exceeded, a `OversizedHeaderListError
        <hpack.OversizedHeaderListError>` exception will be raised. At this
        point the connection should be shut down, as the HPACK state will no
        longer be useable.

        Defaults to 64kB.
    :type max_header_list_size: ``int``
    """
    def __init__(self, max_header_list_size=DEFAULT_MAX_HEADER_LIST_SIZE):
        self.header_table = HeaderTable()

        #: The maximum decompressed size we will allow for any single header
        #: block. This is a protection against DoS attacks that attempt to
        #: force the application to expand a relatively small amount of data
        #: into a really large header list, allowing enormous amounts of memory
        #: to be allocated.
        #:
        #: If this amount of data is exceeded, a `OversizedHeaderListError
        #: <hpack.OversizedHeaderListError>` exception will be raised. At this
        #: point the connection should be shut down, as the HPACK state will no
        #: longer be usable.
        #:
        #: Defaults to 64kB.
        #:
        #: .. versionadded:: 2.3.0
        self.max_header_list_size = max_header_list_size

        #: Maximum allowed header table size.
        #:
        #: A HTTP/2 implementation should set this to the most recent value of
        #: SETTINGS_HEADER_TABLE_SIZE that it sent *and has received an ACK
        #: for*. Once this setting is set, the actual header table size will be
        #: checked at the end of each decoding run and whenever it is changed,
        #: to confirm that it fits in this size.
        self.max_allowed_table_size = self.header_table.maxsize

    @property
    def header_table_size(self):
        """
        Controls the size of the HPACK header table.
        """
        return self.header_table.maxsize

    @header_table_size.setter
    def header_table_size(self, value):
        self.header_table.maxsize = value

    def decode(self, data, raw=False):
        """
        Takes an HPACK-encoded header block and decodes it into a header set.

        :param data: A bytestring representing a complete HPACK-encoded header
                     block.
        :param raw: (optional) Whether to return the headers as tuples of raw
                    byte strings or to decode them as UTF-8 before returning
                    them. The default value is False, which returns tuples of
                    Unicode strings
        :returns: A list of two-tuples of ``(name, value)`` representing the
                  HPACK-encoded headers, in the order they were decoded.
        :raises HPACKDecodingError: If an error is encountered while decoding
                                    the header block.
        """
        log.debug("Decoding %s", data)

        if not isinstance(data, memoryview):
            data_mem = memoryview(data)
        else:
            data_mem = data
        headers = []
        data_len = len(data)
        inflated_size = 0
        current_index = 0

        while current_index < data_len:
            # Work out what kind of header we're decoding.
            # If the high bit is 1, it's an indexed field.
            current = to_byte(data[current_index])
            indexed = True if current & 0x80 else False

            # Otherwise, if the second-highest bit is 1 it's a field that does
            # alter the header table.
            literal_index = True if current & 0x40 else False

            # Otherwise, if the third-highest bit is 1 it's an encoding context
            # update.
            encoding_update = True if current & 0x20 else False

            if indexed:
                header, consumed = self._decode_indexed(
                    data_mem[current_index:]
                )
            elif literal_index:
                # It's a literal header that does affect the header table.
                header, consumed = self._decode_literal_index(
                    data_mem[current_index:]
                )
            elif encoding_update:
                # It's an update to the encoding context. These are forbidden
                # in a header block after any actual header.
                if headers:
                    raise HPACKDecodingError(
                        "Table size update not at the start of the block"
                    )
                consumed = self._update_encoding_context(
                    data_mem[current_index:]
                )
                header = None
            else:
                # It's a literal header that does not affect the header table.
                header, consumed = self._decode_literal_no_index(
                    data_mem[current_index:]
                )

            if header:
                headers.append(header)
                inflated_size += table_entry_size(*header)

                if inflated_size > self.max_header_list_size:
                    raise OversizedHeaderListError(
                        "A header list larger than %d has been received" %
                        self.max_header_list_size
                    )

            current_index += consumed

        # Confirm that the table size is lower than the maximum. We do this
        # here to ensure that we catch when the max has been *shrunk* and the
        # remote peer hasn't actually done that.
        self._assert_valid_table_size()

        try:
            return [_unicode_if_needed(h, raw) for h in headers]
        except UnicodeDecodeError:
            raise HPACKDecodingError("Unable to decode headers as UTF-8.")

    def _assert_valid_table_size(self):
        """
        Check that the table size set by the encoder is lower than the maximum
        we expect to have.
        """
        if self.header_table_size > self.max_allowed_table_size:
            raise InvalidTableSizeError(
                "Encoder did not shrink table size to within the max"
            )

    def _update_encoding_context(self, data):
        """
        Handles a byte that updates the encoding context.
        """
        # We've been asked to resize the header table.
        new_size, consumed = decode_integer(data, 5)
        if new_size > self.max_allowed_table_size:
            raise InvalidTableSizeError(
                "Encoder exceeded max allowable table size"
            )
        self.header_table_size = new_size
        return consumed

    def _decode_indexed(self, data):
        """
        Decodes a header represented using the indexed representation.
        """
        index, consumed = decode_integer(data, 7)
        header = HeaderTuple(*self.header_table.get_by_index(index))
        log.debug("Decoded %s, consumed %d", header, consumed)
        return header, consumed

    def _decode_literal_no_index(self, data):
        return self._decode_literal(data, False)

    def _decode_literal_index(self, data):
        return self._decode_literal(data, True)

    def _decode_literal(self, data, should_index):
        """
        Decodes a header represented with a literal.
        """
        total_consumed = 0

        # When should_index is true, if the low six bits of the first byte are
        # nonzero, the header name is indexed.
        # When should_index is false, if the low four bits of the first byte
        # are nonzero the header name is indexed.
        if should_index:
            indexed_name = to_byte(data[0]) & 0x3F
            name_len = 6
            not_indexable = False
        else:
            high_byte = to_byte(data[0])
            indexed_name = high_byte & 0x0F
            name_len = 4
            not_indexable = high_byte & 0x10

        if indexed_name:
            # Indexed header name.
            index, consumed = decode_integer(data, name_len)
            name = self.header_table.get_by_index(index)[0]

            total_consumed = consumed
            length = 0
        else:
            # Literal header name. The first byte was consumed, so we need to
            # move forward.
            data = data[1:]

            length, consumed = decode_integer(data, 7)
            name = data[consumed:consumed + length]
            if len(name) != length:
                raise HPACKDecodingError("Truncated header block")

            if to_byte(data[0]) & 0x80:
                name = decode_huffman(name)
            total_consumed = consumed + length + 1  # Since we moved forward 1.

        data = data[consumed + length:]

        # The header value is definitely length-based.
        length, consumed = decode_integer(data, 7)
        value = data[consumed:consumed + length]
        if len(value) != length:
            raise HPACKDecodingError("Truncated header block")

        if to_byte(data[0]) & 0x80:
            value = decode_huffman(value)

        # Updated the total consumed length.
        total_consumed += length + consumed

        # If we have been told never to index the header field, encode that in
        # the tuple we use.
        if not_indexable:
            header = NeverIndexedHeaderTuple(name, value)
        else:
            header = HeaderTuple(name, value)

        # If we've been asked to index this, add it to the header table.
        if should_index:
            self.header_table.add(name, value)

        log.debug(
            "Decoded %s, total consumed %d bytes, indexed %s",
            header,
            total_consumed,
            should_index
        )

        return header, total_consumed


# for spawning berries on tree
# can be clicked on to be collected -> inventory
# used to feed birds to have them fly off-screen

import pygame
import random

from interaction import *

class Berry(Interactable):
    def __init__(self, world, x, y):
        super().__init__()
        self.radius = 5
        self.world = world
        self.x, self.y = x, y
        self.rect = pygame.Rect(x - self.radius, y - self.radius,
                                2 * self.radius, 2 * self.radius)
        self.image = pygame.Surface((2 * self.radius, 2 * self.radius),
                                    pygame.SRCALPHA)
        self.image = self.image.convert_alpha()
        self.color = [(28, 59, 163, 190),
                      (230, 57, 57, 190),
                      (255, 156, 207, 190),
                      (255, 145, 0, 190),
                      (0, 138, 145, 190),
                      (0, 148, 222, 190),
                      (191, 34, 134, 190)]  # color options
        pygame.draw.circle(self.image, random.choice(self.color),
                           (self.radius, self.radius), self.radius)
        self.click = True
        self.priority = -1
        world.interactionHandler.register(self)

    def onClick(self, x, y):
        self.world.inventory.berryAmount += 1
        self.kill()
        self.world.ui.inventoryView.updateAmounts()

    def getRect(self):
        self.rect = pygame.Rect(self.x - self.radius, self.y - self.radius,
                                2 * self.radius, 2 * self.radius)

    def update(self, screenWidth, screenHeight):
        self.getRect()