text:
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import uic
import numpy as np
import datetime
import json
from matplotlib import pyplot
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas

import achievements
import gscreen
import saves
from towns import Town, Service
import logging
#import clipboard
import webbrowser
logger = logging.Logger(name="main")

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self, scr_size, *args, **kwargs):
        """ A lot of boilerplate stuff here"""
        super().__init__(*args, **kwargs)
        self.screen_size = scr_size
        self.showFullScreen()  # the map image size is set based on the startup screen size, so don't resize!
        self.intermediate_towns = []
        self.towns = []
        self.create_towns()  # loads the town data from a json file
        uic.loadUi('main_window.ui', self)  # loads the ui from Qt Designer
        self.wallet = gscreen.Wallet()
        self.score = gscreen.Score()
        self.mode_show_map = True
        self.gr_left = QtWidgets.QGridLayout(self.frm_map)
        self.gr_left.setAlignment(QtCore.Qt.AlignTop)
        self.map_image = None
        ''' Now we are connecting signals with slots'''
        self.btn_new_route.clicked.connect(self.clicked_new_route)
        self.frm_new_route.setVisible(False)
        self.gr_intermediate_stops = QtWidgets.QGridLayout(self.frm_intermediate_stops)
        self.frmscrl_route_select = QtWidgets.QFrame()
        self.frmscrl_route_select.setMinimumHeight(200)
        self.gr_list_of_routes = QtWidgets.QGridLayout(self.frmscrl_route_select)
        self.gr_list_of_routes.setAlignment(QtCore.Qt.AlignTop)
        self.scr_route_select.setWidget(self.frmscrl_route_select)
        self.colours = gscreen.ServiceColours()
        for town in self.towns:
            self.cmb_from.addItem(town.get_name())
        self.cmb_from_selection_changed(self.cmb_from.currentText())
        self.cmb_from.currentTextChanged.connect(self.cmb_from_selection_changed)
        self.cmb_to.currentTextChanged.connect(self.cmb_to_selection_changed)
        ''' Image stuff '''
        pix_engine = QtGui.QPixmap()
        pix_engine.load("assets/engine_thb.png")
        self.lbl_engine.setPixmap(pix_engine)
        pix_passenger = QtGui.QPixmap()
        pix_passenger.load("assets/passenger_thb.png")
        self.lbl_passenger_car.setPixmap(pix_passenger)
        pix_sleeper = QtGui.QPixmap()
        pix_sleeper.load("assets/sleeper_thm.png")
        self.lbl_sleeper.setPixmap(pix_sleeper)
        # map image
        self.img_map = gscreen.Map(int(self.screen_size.width()*0.5), self.screen_size.height(), self.towns, self.wallet, self.score, self.colours)
        self.update_map_image()
        ''' Services are train services between two towns (with possible intermediate stops). The service Objects holds
            all information about a service, such as what the carriage setup is etc. The service object starts as
            `unconfirmed` meaning the train doesn't actually run until the status is changed to `confirmed`
            One unconfirmed service always exists on the tail of the self.services, which is the one altered by the
            route/service planner menu'''
        self.services = [Service()]
        self.unconfirmed_service = self.services[0]
        self.fill_intermediate_towns(self.get_town_by_name(self.cmb_from.currentText()),
                                     self.get_town_by_name(self.cmb_to.currentText()))
        '''More boilerplate signal connection, to update the unconfirmed service whenever a change is made.'''
        self.ckb_return.stateChanged.connect(self.update_unconfirmed_service)
        self.departure_time_edit.timeChanged.connect(self.update_unconfirmed_service)
        self.ckb_run_every_x_hour.stateChanged.connect(self.update_unconfirmed_service)
        self.dbl_run_every_x_hour.valueChanged.connect(self.update_unconfirmed_service)
        self.ckb_mon.stateChanged.connect(self.update_unconfirmed_service)
        self.ckb_tue.stateChanged.connect(self.update_unconfirmed_service)
        self.ckb_wed.stateChanged.connect(self.update_unconfirmed_service)
        self.ckb_thu.stateChanged.connect(self.update_unconfirmed_service)
        self.ckb_fri.stateChanged.connect(self.update_unconfirmed_service)
        self.ckb_sat.stateChanged.connect(self.update_unconfirmed_service)
        self.ckb_sun.stateChanged.connect(self.update_unconfirmed_service)
        self.sb_engines.valueChanged.connect(self.update_unconfirmed_service)
        self.sb_passenger_car.valueChanged.connect(self.update_unconfirmed_service)
        self.sb_sleeper_car.valueChanged.connect(self.update_unconfirmed_service)
        #self.sb_open_air.valueChanged.connect(self.update_unconfirmed_service)
        #self.sb_baggage.valueChanged.connect(self.update_unconfirmed_service)
        self.dsb_sleeper_fare.valueChanged.connect(self.update_unconfirmed_service)
        self.dsb_seat_fare.valueChanged.connect(self.update_unconfirmed_service)
        self.btn_confirm.clicked.connect(self.click_confirm_new_route)
        self.timer = QtCore.QTimer()
        self.tick_rate = 1  # number of updates every second
        self.timer.setInterval(int(self.tick_rate*1000))
        self.timer.setTimerType(QtCore.Qt.CoarseTimer)
        self.timer.timeout.connect(self.tick)
        self.btn_toggle_speed.clicked.connect(self.img_map.change_speed)
        self.btn_bounding_nz.clicked.connect(lambda: self.set_view("nz"))
        self.btn_bounding_n.clicked.connect(lambda: self.set_view("north"))
        self.btn_bounding_s.clicked.connect(lambda: self.set_view("south"))
        self.achievements = achievements.Achievements()
        self.btn_achievements.clicked.connect(self.display_achievements)
        self.save_manager = saves.SaveManager()
        self.towns_with_services = []  # this allows tracking progress to have 90% towns connected.
        self.show_menu()
        self.btn_exit.clicked.connect(self.save_and_exit)
        self.btn_skip_year.clicked.connect(self.skip_year)
        self.company_reputation = 0.5

    def set_view(self, id):
        """
        For selecting which island to show on the map screen
        :param id: either nz, north or south
        :return: None
        """
        self.img_map.change_bounding_box(id)
        self.img_map.redraw()
        self.update_map_image()
        if id == "nz":
            self.btn_bounding_nz.setChecked(True)
            self.btn_bounding_n.setChecked(False)
            self.btn_bounding_s.setChecked(False)
        elif id == "north":
            self.btn_bounding_nz.setChecked(False)
            self.btn_bounding_n.setChecked(True)
            self.btn_bounding_s.setChecked(False)
        elif id == "south":
            self.btn_bounding_nz.setChecked(False)
            self.btn_bounding_n.setChecked(False)
            self.btn_bounding_s.setChecked(True)

    def display_achievements(self):
        """
        Shows all the achievements on the left panel (instead of the default map). Achievements that are complete
        will have their title crossed out to indicate they are done
        :return: None
        """
        ach_all = self.achievements.get_all_achievements()
        ach_done = self.achievements.get_completed_achievements(self.services[:len(self.services)-1])
        self.close_report()
        if self.mode_show_map:
            self.mode_show_map = False
            if self.map_image is not None:
                self.gr_left.removeWidget(self.map_image)
                self.map_image = None
        for key in ach_all:
            lbl = QtWidgets.QLabel(f"
{key}
")
            if key in ach_done:
                lbl.setText(f"<s>
{key}
</s>")
            lbl_descript = QtWidgets.QLabel(ach_all[key])
            self.gr_left.addWidget(lbl)
            self.gr_left.addWidget(lbl_descript)
        btn_close = QtWidgets.QPushButton("Close")
        btn_close.clicked.connect(self.close_report)
        self.gr_left.addWidget(btn_close)

    def skip_year(self):
        """
        This should skip one year ahead, but I don't think all the services, passenger numbers and revenue are
        updated properly when this is run so the skip year button is disabled (27 jan 22) todo: fix
        :return: None
        """
        new_year = self.img_map.skip_year()
        self.btn_skip_year.setText(f"Skip to {new_year+1}")

    def start_game(self, rb1, rb2, rb3):
        """
        Starts the game. This method is called when the start game button is pressed on the menu screen. It
        sets the save slot, enables all the buttons, removes the menu from the screen and starts the game
        timer.
        :param: rb1: the radio button that indicates if slot 1 is selected.
        :param: rb2: the radio button that indicates if slot 2 is selected.
        :param: rb3: the radio button that indicates if slot 3 is selected.
        :return: None
        """
        self.btn_bounding_nz.setChecked(True)
        slot = None
        if rb1.isChecked():
            slot = 1
        elif rb2.isChecked():
            slot = 2
        elif rb3.isChecked():
            slot = 3
        self.save_manager.set_save_slot(slot)
        self.wallet.set_save_dir(self.save_manager.get_dir())
        load_data = self.save_manager.load()
        if load_data is not None:  # returns None if there is no save in the slot
            logger.info("Loading game state from file")
            self.wallet, self.score, self.towns, self.services, self.img_map = load_data
            self.unconfirmed_service = self.services[len(self.services)-1]
            self.img_map.load_wallet_score(self.wallet, self.score)
            for i, service in enumerate(self.services):
                if i == len(self.services)-1:
                    self.unconfirmed_service = service
                else:
                    for town in service.stations:
                        if town not in self.towns_with_services:
                            self.towns_with_services.append(town)
                    self.update_services_panel(service)
            self.img_map.update_percent_connected(len(self.towns_with_services) / len(self.towns))
        self.timer.start()
        self.btn_new_route.setEnabled(True)
        self.btn_skip_year.setEnabled(False)  # disabled because it doesn't work properly
        self.btn_pause.setEnabled(True)
        self.btn_toggle_speed.setEnabled(True)
        self.btn_bounding_nz.setEnabled(True)
        self.btn_bounding_n.setEnabled(True)
        self.btn_bounding_s.setEnabled(True)
        self.btn_achievements.setEnabled(True)
        self.close_report()

    def delete_save(self, slot, radiobutton):
        self.save_manager.delete_save(slot)
        radiobutton.setText(f"Slot {slot} - new")

    def save_and_exit(self):
        if self.save_manager.save_slot is not None:
            self.save_manager.save(self.wallet, self.score, self.towns, self.services, self.img_map)
        self.close()

    def get_emissions_plot(self):
        """
        Makes the emissions plot seen in the introduction email on the menu screen.
        :return: None
        """
        with open(os.path.join("assets", "emissions_data.json"), encoding='utf-8') as f:
            data = json.load(f)
        labels = []
        x = []
        explode = []
        for key in data:
            if key != "units" and key != "source":
                labels.append(key)
                x.append(data[key])
                if key == "Transport":
                    explode.append(0.1)
                else:
                    explode.append(0)
        pyplot.rcParams.update({'font.size': 5})
        fig1, ax1 = pyplot.subplots(figsize=(4, 1.5), dpi=130)
        canvas = FigureCanvas(fig1)
        ax1.pie(x, explode=explode, labels=labels)
        ax1.axis('equal')
        canvas.draw()
        width, height = canvas.get_width_height()
        im = QtGui.QImage(canvas.buffer_rgba(), width, height, QtGui.QImage.Format_ARGB32)
        return QtGui.QPixmap.fromImage(im)

    def share(self, btn, message, original_text):
        """
        Copies a message to the clipboard. It changes the button to read "copied to clipboard" then changes the
        text back to the original 1-second later.
        :param btn: button that called this function
        :param message: message to copy
        :param original_text: the original text of the button (what it will be set back to)
        :return: None
        """
        #clipboard.copy(message)
        btn.setText("Copied to clipboard")
        t = QtCore.QTimer()
        t.singleShot(1000, lambda: btn.setText(original_text))

    def show_menu(self):
        """
        Shows the start of game menu, where the user can select which save slot to use and see the instructions
        Note: this reuses the report_widgets array
        :return: None
        """
        if self.mode_show_map:
            self.mode_show_map = False
            if self.map_image is not None:
                self.gr_left.removeWidget(self.map_image)
                self.map_image = None
        frm_menu = QtWidgets.QFrame()
        frm_menu.setMinimumSize(int(self.screen_size.width()*0.5) - 50, self.screen_size.height() - 50)
        gr_frm_menu = QtWidgets.QGridLayout(frm_menu)
        #gr_frm_menu.setAlignment(QtCore.Qt.AlignTop)
        scroll_area = QtWidgets.QScrollArea()
        scroll_area.setWidget(frm_menu)
        scroll_area.setObjectName("a")
        lbl_title = QtWidgets.QLabel("TIMETABLES! \n(The train scheduling game)")
        font_id1 = QtGui.QFontDatabase.addApplicationFont(os.path.join('assets', 'fonts', 'Arvo-Bold.ttf'))
        font_id2 = QtGui.QFontDatabase.addApplicationFont(os.path.join('assets', 'fonts', 'RobotoMono-VariableFont_wght.ttf'))
        font_string1 = QtGui.QFontDatabase.applicationFontFamilies(font_id1)[0]
        font_string2 = QtGui.QFontDatabase.applicationFontFamilies(font_id2)[0]
        lbl_title.setFont(QtGui.QFont(font_string1, 20))
        rb_slot1 = QtWidgets.QRadioButton("Slot 1 - "+self.save_manager.get_save_time(1))
        rb_slot1.setChecked(True)
        rb_slot2 = QtWidgets.QRadioButton("Slot 2 - "+self.save_manager.get_save_time(2))
        rb_slot3 = QtWidgets.QRadioButton("Slot 3 - "+self.save_manager.get_save_time(3))
        btn_slot1_clear = QtWidgets.QPushButton("Delete Saved Data")
        btn_slot1_clear.clicked.connect(lambda: self.delete_save(1, rb_slot1))
        btn_slot2_clear = QtWidgets.QPushButton("Delete Saved Data")
        btn_slot2_clear.clicked.connect(lambda: self.delete_save(2, rb_slot2))
        btn_slot3_clear = QtWidgets.QPushButton("Delete Saved Data")
        btn_slot3_clear.clicked.connect(lambda: self.delete_save(3, rb_slot3))
        with open(os.path.join("assets", "welcome_email.txt"), "r", encoding='utf-8') as f:
            intro_txt1, intro_txt2 = f.read().split("^")  # this is where the plot goes
        lbl_message1 = QtWidgets.QLabel(intro_txt1)
        lbl_message1.setFont(QtGui.QFont(font_string2, 8))
        lbl_message1.setWordWrap(True)
        lbl_plot = QtWidgets.QLabel("")
        lbl_plot.setPixmap(self.get_emissions_plot())
        lbl_message2 = QtWidgets.QLabel(intro_txt2)
        lbl_message2.setFont(QtGui.QFont(font_string2, 8))
        lbl_message2.setWordWrap(True)
        cmb_difficulty = QtWidgets.QComboBox()
        cmb_difficulty.addItems(["Normal difficulty"])
        btn_begin = QtWidgets.QPushButton("Start Game")
        btn_begin.clicked.connect(lambda: self.start_game(rb_slot1, rb_slot2, rb_slot3))
        ''' If release, this will go to a highscores webpage, but for now I will use it to get feedback'''
        btn_highscore = QtWidgets.QPushButton("Send Feedback")
        btn_highscore.clicked.connect(lambda: webbrowser.open("https://docs.google.com/forms/d/e/1FAIpQLSdnpQeyxYQPsScqqeVxJuE9IL74KrecaWQhIOkMUz5ov5wKCA/viewform?usp=sf_link"))
        btn_share = QtWidgets.QPushButton("Share with friend")
        share_text = "Hey friend! I'm playing a game about scheduling trains, you should get it too! https://timetablesgame.nz"
        btn_share.clicked.connect(lambda: self.share(btn_share, share_text, "Share with friend"))
        share_mp_text = """Dear Member of Parliament,

I'm writing to tell you about a political video game I think you should try. It is about scheduling trains to avoid the worst effects of climate change.
I think you could use it for both some light entertainment and as a first step in informing public transport policy!

You can find out more about it at https://timetablesgame.nz"""
        btn_share_mp = QtWidgets.QPushButton("Share with your MP")
        btn_share_mp.clicked.connect(lambda: self.share(btn_share_mp, share_mp_text, "Share with your MP"))
        gr_frm_menu.addWidget(lbl_title, 0, 0)
        gr_frm_menu.addWidget(rb_slot1, 1, 0)
        gr_frm_menu.addWidget(rb_slot2, 2, 0)
        gr_frm_menu.addWidget(rb_slot3, 3, 0)
        gr_frm_menu.addWidget(btn_slot1_clear, 1, 1)
        gr_frm_menu.addWidget(btn_slot2_clear, 2, 1)
        gr_frm_menu.addWidget(btn_slot3_clear, 3, 1)
        gr_frm_menu.addWidget(rb_slot2, 2, 0)
        gr_frm_menu.addWidget(rb_slot3, 3, 0)
        gr_frm_menu.addWidget(lbl_message1, 4, 0, 1, 2)
        gr_frm_menu.addWidget(lbl_plot,  5, 0, 1, 2)
        gr_frm_menu.addWidget(lbl_message2, 6, 0, 1, 2)
        gr_frm_menu.addWidget(cmb_difficulty, 7, 0, 1, 2)
        gr_frm_menu.addWidget(btn_begin, 8, 0)
        gr_frm_menu.addWidget(btn_highscore, 8, 1)
        gr_frm_menu.addWidget(btn_share, 9, 0)
        gr_frm_menu.addWidget(btn_share_mp, 9, 1)
        self.gr_left.addWidget(scroll_area, 1, 0)

    def show_win_screen(self):
        """
        This screen should be shown when the player wins the game (gets to 2050 and passes all the checks)
        :return: None
        """
        self.timer.stop()  # halt game progress
        if self.mode_show_map:
            self.mode_show_map = False
            if self.map_image is not None:
                self.gr_left.removeWidget(self.map_image)
                self.map_image = None
        font_id1 = QtGui.QFontDatabase.addApplicationFont(os.path.join('assets', 'fonts', 'Arvo-Bold.ttf'))
        font_string1 = QtGui.QFontDatabase.applicationFontFamilies(font_id1)[0]
        lbl_game_over = QtWidgets.QLabel("SUCCESS!")
        lbl_game_over.setFont(QtGui.QFont(font_string1, 20))
        lbl = QtWidgets.QLabel("You won! Ngā mihi nui for building our public transport network!")
        btn = QtWidgets.QPushButton("Close")
        btn.clicked.connect(self.close)
        self.gr_left.addWidget(lbl_game_over)
        self.gr_left.addWidget(lbl)
        self.gr_left.addWidget(btn)

    def show_fail_screen(self, message):
        """
        This screen should be shown if the player fails to meet the 2030 or 2050 requirements or if they run go
        bankrupt.
        :param message: The reason the failed the game - this is shown to the play
        :return: None
        """
        self.timer.stop()  # halt game progress
        if self.mode_show_map:
            self.mode_show_map = False
            if self.map_image is not None:
                self.gr_left.removeWidget(self.map_image)
                self.map_image = None
        font_id1 = QtGui.QFontDatabase.addApplicationFont(os.path.join('assets', 'fonts', 'Arvo-Bold.ttf'))
        font_string1 = QtGui.QFontDatabase.applicationFontFamilies(font_id1)[0]
        lbl_game_over = QtWidgets.QLabel("GAME OVER!")
        lbl_game_over.setFont(QtGui.QFont(font_string1, 20))
        lbl = QtWidgets.QLabel(message)
        btn = QtWidgets.QPushButton("Close")
        btn.clicked.connect(self.close)
        self.gr_left.addWidget(lbl_game_over)
        self.gr_left.addWidget(lbl)
        self.gr_left.addWidget(btn)

    def show_caution(self, message):
        """
        Shows a warning to the player, e.g. if they can't afford a new train then use this to show a "not enough money"
        screen. Unlike the fail and win screens, the player can dismiss the message and it doesn't effect the game.
        :param message: message to show the player
        :return: None
        """
        if self.mode_show_map:
            self.mode_show_map = False
            if self.map_image is not None:
                self.gr_left.removeWidget(self.map_image)
                self.map_image = None
        lbl = QtWidgets.QLabel(message[2:])
        btn = QtWidgets.QPushButton("Close")
        btn.clicked.connect(self.close_report)
        self.gr_left.addWidget(lbl)
        self.gr_left.addWidget(btn)

    def tick(self):
        """
        This is called every second and updates the map, tests for win conditions, and runs all the services that
        occured in the last second (which is 1 day in game-time if not on fast-mode)
        :return:
        """
        if not self.btn_pause.isChecked():
            win = self.img_map.update_time(self.tick_rate)
            """win will be of form [P/W/F] REASON where P = PASS/PROCEED (do nothing), W = WIN, F = FAIL
                There is also the code C = CAUTION, used when the player is unable to afford a new service."""
            if win[0] == "W":
                self.show_win_screen()
            elif win[0] == "F":
                self.show_fail_screen(win[2:])
            for service in self.services:
                response = service.run(self.img_map.get_increment(), self.img_map.get_time(), self.wallet, self.score, self.company_reputation)
                if response[0] == "F":
                    self.show_fail_screen(response[2:])
        self.update_map_image()

    def update_map_image(self):
        """
        This gets the map image from gscreen.Map and sets it to self.map_image
        :return: None
        """
        if self.mode_show_map:
            if self.map_image is None:
                self.map_image = QtWidgets.QLabel("")
                self.gr_left.addWidget(self.map_image)
                self.map_image.show()
            qim = self.img_map.get_image_qt()
            pix_map_img = QtGui.QPixmap.fromImage(qim)
            self.map_image.setPixmap(pix_map_img)

    def update_unconfirmed_service(self):
        """
        This methods is called whenever something in the New Route panel is changed. It updates the work-in-progress
        service to reflect the changes. It then called the method update_service_dependant_widgets
        :return:
        """
        total_car_allowed = self.sb_engines.value() * 10
        self.sb_sleeper_car.setMaximum(total_car_allowed - self.sb_passenger_car.value())
        self.sb_passenger_car.setMaximum(total_car_allowed - self.sb_sleeper_car.value())
        stations = []
        for station in self.intermediate_towns:
            if station.isChecked():
                stations.append(self.get_town_by_name(station.text()))
        returns = self.ckb_return.isChecked()
        fmt = "%H:%M"
        departure_times = [datetime.datetime.strptime(self.departure_time_edit.time().toString("HH:mm"), fmt)]
        if self.ckb_run_every_x_hour.isChecked():
            start_time = departure_times[0]
            day = start_time.day
            while start_time.day == day:
                start_time += datetime.timedelta(hours=self.dbl_run_every_x_hour.value())
                departure_times.append(start_time)
            departure_times.pop()
        days = [self.ckb_mon.isChecked(), self.ckb_tue.isChecked(), self.ckb_wed.isChecked(), self.ckb_thu.isChecked(),
                self.ckb_fri.isChecked(), self.ckb_sat.isChecked(), self.ckb_sun.isChecked()]
        config = [self.sb_engines.value(), self.sb_passenger_car.value(), self.sb_sleeper_car.value(),
                  0, 0]
        fares = [self.dsb_seat_fare.value(), self.dsb_sleeper_fare.value()]
        self.unconfirmed_service.update(stations, returns, departure_times, days, config, fares)
        self.update_service_dependant_widgets()
        self.txt_service_name.setPlaceholderText(self.unconfirmed_service.create_name())

    def update_service_dependant_widgets(self):
        self.lbl_feedback_1.setText(f"This train will be able to carry a maximum of {self.unconfirmed_service.get_capacity()} passengers, cost ${self.unconfirmed_service.get_up_front_cost()} to build and ${self.unconfirmed_service.get_running_cost()}/journey to run")
        self.lbl_feedback_2.setText(f"Expected Revenue per journey at 70% full is ${np.round(self.unconfirmed_service.get_estimated_revenue(),2)}, giving an expected profit of ${np.round(self.unconfirmed_service.get_estimated_profit(),2)} before tax")
        self.lcd_arrival_time.display(self.unconfirmed_service.get_arrival_time())
        self.lcd_return_time.display(self.unconfirmed_service.get_return_time())

    def create_towns(self):
        """
        This imports the towns.json file and sets up the towns tree structure. It is called on __init__
        :return: None
        """
        file = "towns.json"
        with open(file, "r", encoding='utf-8') as f:
            towns_data = json.load(f)
        connections = []
        for town in towns_data:
            name = town
            connections.append(towns_data[name]['connections'])
            population = towns_data[name]['population']
            location = towns_data[name]['location']
            new_town = Town(name, population, location)
            self.towns.append(new_town)
        for conns, town in zip(connections, self.towns):
            for conn in conns:
                if conn[0] != "":
                    try:
                        town.add_link(self.get_town_by_name(conn[0]), float(conn[1]))
                    except:
                        print(conn[0])
        for town in towns_data:
            try:
                self.get_town_by_name(town).add_economic_partner(self.get_town_by_name(towns_data[town]["economic "
                                                                                + "partner"]))
            except KeyError:
                pass  # not all towns have economic partners and this is OK!

    def get_town_by_name(self, name):
        """
        Returns the town object associated with the given name. E.g. get_town_by_name("Ōtaki") will return the
        towns.Town object representing Ōtaki
        :param name: name of town (case and macro sensitive)
        :return: towns.Town object representing the named town or None if not found.
        """
        for town in self.towns:
            if town.get_name() == name:
                return town

    def fill_intermediate_towns(self, departure_town, arrival_town):
        """
        This finds all towns on a train line between two endpoint towns and places them on the intermediate stops
        panel. The endpoint towns are also placed on the panel pre-ticked and non-changeable.
        :param departure_town: 1st endpoint
        :param arrival_town: 2nd endpoint
        :return: None
        """
        path = departure_town.getNodesOnPath(arrival_town)
        for town in self.intermediate_towns:
            self.gr_intermediate_stops.removeWidget(town)
            town.destroy()
        self.intermediate_towns = []
        j = 0
        i = 0
        for node in path:
            i += 1
            if i > 5:
                i = 0
                j += 1
            ckb = QtWidgets.QCheckBox(node.get_name(), parent=self.frm_intermediate_stops)
            ckb.stateChanged.connect(self.update_unconfirmed_service)
            # todo: rotate ckb, see -> https://stackoverflow.com/questions/43388464/rotate-whole-qwidget-by-angle
            self.gr_intermediate_stops.addWidget(ckb, j, i)
            if node is departure_town or node is arrival_town:
                ckb.setChecked(True)
                ckb.setEnabled(False)
            ckb.show()
            self.intermediate_towns.append(ckb)
        self.update_unconfirmed_service()

    def cmb_from_selection_changed(self, text):
        """
        Called when the combo-box for the departure town is changed. When this happens we need to reassess which towns
        can be connected to the departure town and update the arrival town combo-box.
        :param text: text of the combo box, which is just the name of the town
        :return: None
        """
        for town in self.towns:
            if town.get_name() == text:
                all_connected = town.getAllNodes()
                all_connected.remove(town)
                self.cmb_to.clear()
                for ac in all_connected:
                    self.cmb_to.addItem(ac.get_name())

    def cmb_to_selection_changed(self, text):
        if text != "":  # while the updates occurs it sometimes trigger this with empty text.
            self.fill_intermediate_towns(self.get_town_by_name(self.cmb_from.currentText()), self.get_town_by_name(text))

    def clicked_new_route(self, toggled):
        self.frm_new_route.setVisible(toggled)

    def close_report(self):
        """
        Delete everything from the left panel, then sets the flag to show the map (which is the default for when nothing
        else is using the panel.
        :return: None
        """
        for i in reversed(range(self.gr_left.count())):
            self.gr_left.itemAt(i).widget().setParent(None)
        self.mode_show_map = True
        self.update_map_image()

    def fill_report_table(self, table, stations, passenger_numbers, earnings):
        col_num = len(passenger_numbers[0][0])
        current_row = 0
        for i, station in enumerate(stations):
            table.setItem(current_row, 0, QtWidgets.QTableWidgetItem("Time"))
            table.setItem(current_row, 1, QtWidgets.QTableWidgetItem("Profit"))
            table.setItem(current_row, i + 2, QtWidgets.QTableWidgetItem(station.get_name()))
        current_row += 1
        for (numbers, earn) in zip(passenger_numbers, earnings):
            table.setItem(current_row, 0, QtWidgets.QTableWidgetItem(earn[1].strftime('%H:%M %d/%m/%Y')))
            table.setItem(current_row, 1, QtWidgets.QTableWidgetItem(f"{earn[0]}nz$"))
            table.setItem(current_row, 2, QtWidgets.QTableWidgetItem("Departures: (seat/sleep)"))
            table.setSpan(current_row, 2, 1, col_num)
            current_row += 1
            for i in range(len(numbers[0])):
                table.setItem(current_row, i + 2,
                              QtWidgets.QTableWidgetItem(f"{int(numbers[0][i])}/{int(numbers[2][i])}"))
            current_row += 1
            table.setItem(current_row, 2, QtWidgets.QTableWidgetItem("Arrivals: (seat/sleep)"))
            table.setSpan(current_row, 2, 1, col_num)
            current_row += 1
            for i in range(len(numbers[1])):
                table.setItem(current_row, i + 2,
                              QtWidgets.QTableWidgetItem(f"{int(numbers[1][i])}/{int(numbers[3][i])}"))
            current_row += 1

    def display_report(self, service):
        self.close_report()
        if self.mode_show_map:
            self.mode_show_map = False
            if self.map_image is not None:
                self.gr_left.removeWidget(self.map_image)
                self.map_image = None
        passenger_numbers = service.get_passenger_numbers_report()
        earnings = service.get_earnings_report()
        if len(passenger_numbers) == 0:
            lbl_title = QtWidgets.QLabel(f"Service Report for {service.get_name()}")
            self.gr_left.addWidget(lbl_title, 0, 0)
            lbl_404 = QtWidgets.QLabel("Report not found :( maybe the train hasn't completed any journeys yet?")
            self.gr_left.addWidget(lbl_404, 1, 0)
            close = QtWidgets.QPushButton("Close")
            close.clicked.connect(self.close_report)
            self.gr_left.addWidget(close, 2, 0)
            return
        col_num = len(passenger_numbers[0][0])
        lbl_title = QtWidgets.QLabel(f"Service Report for {service.get_name()}")
        self.gr_left.addWidget(lbl_title, 0, 0)
        table = QtWidgets.QTableWidget(5*len(passenger_numbers), col_num+2)
        self.gr_left.addWidget(table, 1, 0)
        if service.returns:
            table_return = QtWidgets.QTableWidget(5 * len(passenger_numbers), col_num + 2)
            self.gr_left.addWidget(table_return, 2, 0)
            stations = service.get_stations()
            print(stations)
            stations.reverse()
            print(stations)
            self.fill_report_table(table_return, stations, service.get_passenger_numbers_report(returns_report=True),
                                   service.get_earnings_report(returns_report=True))
        close = QtWidgets.QPushButton("Close")
        close.clicked.connect(self.close_report)
        self.gr_left.addWidget(close, 3, 0)
        self.fill_report_table(table, service.get_stations(), passenger_numbers, earnings)

    def delete_service(self, service, widgets):
        """
        Removes a train service
        :param service: the service to remove (towns.Service object)
        :param widgets: the qtwidget representing that service in the list of services panel
        :return: None
        """
        self.company_reputation = self.company_reputation * 0.8  # decrease by 20%
        widgets[0].removeWidget(widgets[1])
        widgets[0].removeWidget(widgets[2])
        widgets[0].removeWidget(widgets[3])
        self.gr_list_of_routes.removeWidget(widgets[0].parentWidget())
        self.colours.remove(service)
        # we have to completely redo, because if we just delete to towns that this service services, then we may miss
        # a town that is also serviced by another route.
        for i, candidate in enumerate(self.services):
            if candidate is service:
                self.services.pop(i)
                self.img_map.update_connection_ids()
                break
        self.towns_with_services = []
        for i, service in enumerate(self.services):
            if i == len(self.services) - 1:
                pass
            else:
                for town in service.stations:
                    if town not in self.towns_with_services:
                        self.towns_with_services.append(town)
        self.img_map.update_percent_connected(len(self.towns_with_services) / len(self.towns))

    def marketing(self, service):
        """
        Shows the marketing screen, so that the user can make promotes for a particular service, or for train transport
        generally. Types of marketing should be: TV ads, social media ads, posters, print ads.
        todo: actually make this
        :param service: The service to adverise
        :return:
        """
        pass

    def update_services_panel(self, service):
        """
        Adds a new service to the list of services panel
        :param service: The new service to add (towns.Service)
        :return: None
        """
        frm_service_panel = QtWidgets.QFrame()
        frm_service_panel.setObjectName(f"frm_service_panel{self.colours.get_colour_number(service)}")
        self.img_map.update_connection_ids()
        self.update_map_image()
        frm_service_panel.setMaximumHeight(50)
        self.gr_list_of_routes.addWidget(frm_service_panel)
        gr_service_panel = QtWidgets.QGridLayout(frm_service_panel)
        service_panel = QtWidgets.QLabel(service.get_name())
        service_report = QtWidgets.QPushButton("Service Report")
        service_report.clicked.connect(lambda: self.display_report(service))
        btn_promote = QtWidgets.QPushButton("Promote")
        btn_promote.clicked.connect(lambda: self.marketing(service))
        service_remove = QtWidgets.QPushButton("Delete")
        service_remove.clicked.connect(lambda: self.delete_service(service, [gr_service_panel, service_panel, service_report, service_remove]))
        gr_service_panel.addWidget(service_panel, len(self.services), 0)
        gr_service_panel.addWidget(service_report, len(self.services), 1)
        gr_service_panel.addWidget(btn_promote, len(self.services), 2)
        gr_service_panel.addWidget(service_remove, len(self.services), 3)
        service_panel.show()

    def click_confirm_new_route(self):
        self.company_reputation = self.company_reputation * (1.0 + 0.1 * (self.unconfirmed_service.get_capacity()/486))
        name = self.txt_service_name.text()
        self.update_unconfirmed_service()
        response = self.unconfirmed_service.confirm_service(name, self.wallet, self.img_map.get_time().strftime("%d/%m/%y"))
        if response[0] == "C":
            self.show_caution(response)
        else:
            new_achieves = self.achievements.check_for_new_achievement(self.unconfirmed_service)
            self.img_map.display_new_achievement(new_achieves)
            for town in self.unconfirmed_service.stations:
                if town not in self.towns_with_services:
                    self.towns_with_services.append(town)
            self.img_map.update_percent_connected(len(self.towns_with_services) / len(self.towns))
            self.update_services_panel(self.unconfirmed_service)
            self.unconfirmed_service = Service()
            self.services.append(self.unconfirmed_service)
            self.btn_new_route.setChecked(False)
            self.clicked_new_route(False)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    size = app.primaryScreen().size()
    with open("style.css", "r", encoding='utf-8') as f:
        app.setStyleSheet(f.read())
    window = MainWindow(scr_size=size)
    window.show()
    app.exec_()

max_stars_repo_name: pjamessteven/timetables

max_issues_repo_name: pjamessteven/timetables

max_forks_repo_name: pjamessteven/timetables


text:
from typing import List

import tensorflow as tf
import math
import sys
import cv2
import numpy as np
from pathlib import Path

sys.path.insert(0, './')
import libs.utils as utils

TFRECORD_DATASET_FILE_NAME = "TFRecord_dataset"
DATA_NUM_FILE_NAME = 'dataset_num'

class TFRecordDataset:
    def __init__(self, train_dir,
                 converter,
                 batch_size,
                 shuffle_batch_size=1,
                 num_parallel_calls=6,
                 da=None,
                 filter_labels=True):
        self.filter_labels = filter_labels
        self.da = da
        self.num_parallel_calls = num_parallel_calls
        self.batch_size = batch_size
        self.train_dir = train_dir
        self.converter = converter
        self.da = da

        dataset_file_paths = self.get_TFRecord_filepath(train_dir)
        self.size = self.get_data_size(train_dir)

        self.num_batches = math.ceil(self.size / self.batch_size)

        self.dataset = tf.data.TFRecordDataset(dataset_file_paths)
        self.dataset = self.dataset.shuffle(shuffle_batch_size)
        self.dataset = self.dataset.map(self._input_parser, num_parallel_calls=self.num_parallel_calls)
        self.dataset = self.dataset.padded_batch(self.batch_size,
                                                 padded_shapes=(
                                                     [None], [None], [None]),
                                                 padding_values=(
                                                     np.uint8(32), np.uint8(0), np.int32(0)))  # 32 空格的unicode编码
        self.dataset = self.dataset.prefetch(buffer_size=self.batch_size * 2)
        iterator = self.dataset.make_initializable_iterator()
        self.next_batch = iterator.get_next()
        self.init_op = iterator.make_initializer(self.dataset)

    def get_next_batch(self, sess):
        label_batch, image_raw_batch, image_raw_length_batch = sess.run(self.next_batch)

        label_batch = [x.tostring().decode() for x in label_batch]
        label_batch = utils.str_Q2B(label_batch, self.converter.chars)
        if self.filter_labels:
            label_batch = self.converter.filter_labels(label_batch)
        label_batch = utils.strip_space(label_batch)

        encoded_label_batch = self.converter.encode_list(label_batch)
        sparse_label_batch = self._sparse_tuple_from_label(encoded_label_batch)

        np_img_batch, width_batch = self._decode_raw_imgs(image_raw_batch, image_raw_length_batch)

        tmp_img_batch = []
        tmp_width_batch = []
        for np_img in np_img_batch:
            if self.da is not None:
                np_img = self.da.run(np_img)
            np_img = self.image_pre_process(np_img)
            tmp_img_batch.append(np_img)
            tmp_width_batch.append(np_img.shape[1])

        np_img_batch = tmp_img_batch
        width_batch = tmp_width_batch

        max_width = max(width_batch)

        image_padded_batch = []
        for np_img in np_img_batch:
            image_padded = self.pad_image(np_img, max_width, (255.0 - 128.0) / 128.0)
            image_padded_batch.append(image_padded)

        # 生成小文件时，文件名就是label,方便人工查看
        return image_padded_batch, width_batch, sparse_label_batch, label_batch, label_batch

    def _decode_raw_imgs(self, image_raw_batch, image_raw_length_batch) -> (List[np.ndarray], List[int]):
        """
        把 TFRecord 的 raw 数据转成 numpy 图像
        """
        np_imgs = []
        widths = []
        for image_raw, image_raw_length in zip(image_raw_batch, image_raw_length_batch):
            np_img = cv2.imdecode(np.fromstring(image_raw.tostring()[0:image_raw_length[0]], dtype=np.uint8),
                                  cv2.IMREAD_GRAYSCALE)

            np_imgs.append(np_img)
            widths.append(np_img.shape[1])
        return np_imgs, widths

    def image_pre_process(self, img_padded):
        image = img_padded[:, :, np.newaxis]
        if image.shape[0] != 32:
            scale = 32. / image.shape[0]
            scaled_width = int(image.shape[1] * scale)
            image = cv2.resize(image, (scaled_width, 32), interpolation=cv2.INTER_LINEAR)
            image = image[:, :, np.newaxis]
        image = image.astype(np.float32)
        image = (image - 128.0) / 128.0

        return image

    def pad_image(self, image, max_width, pad_value):
        res = np.tile(pad_value, (32, max_width, 1))
        w = image.shape[1]
        res[:, 0:w, :] = image
        return res

    def _input_parser(self, serialized_tfrecord):
        features = {
            'label': tf.FixedLenFeature([], tf.string),
            'image_raw': tf.FixedLenFeature([], tf.string),
            'image_raw_length': tf.FixedLenFeature([], tf.int64),
        }

        feature = tf.parse_single_example(serialized_tfrecord, features)

        image_raw = tf.decode_raw(feature['image_raw'], tf.uint8)

        label = tf.decode_raw(feature['label'], tf.uint8)

        image_raw_length = tf.cast(feature['image_raw_length'], tf.int32)

        return label, image_raw, [image_raw_length]

    def _sparse_tuple_from_label(self, sequences, default_val=-1, dtype=np.int32):
        """Create a sparse representention of x.
        Args:
            sequences: a list of lists of type dtype where each element is a sequence
                      encode label, e.g: [2,44,11,55]
            default_val: value should be ignored in sequences
        Returns:
            A tuple with (indices, values, shape)
        """
        indices = []
        values = []

        for n, seq in enumerate(sequences):
            seq_filtered = list(filter(lambda x: x != default_val, seq))
            indices.extend(zip([n] * len(seq_filtered), range(len(seq_filtered))))
            values.extend(seq_filtered)

        indices = np.asarray(indices, dtype=np.int64)
        values = np.asarray(values, dtype=dtype)

        if len(indices) == 0:
            shape = np.asarray([len(sequences), 0], dtype=np.int64)
        else:
            shape = np.asarray([len(sequences), np.asarray(indices).max(0)[1] + 1], dtype=np.int64)

        return indices, values, shape

    def get_data_size(self, dir_name):
        p = Path(dir_name)
        dataset_nums_paths = list(p.glob('**/%s' % DATA_NUM_FILE_NAME))
        total_size = sum([int(it.read_text()) for it in dataset_nums_paths])
        return total_size

    def get_TFRecord_filepath(self, dir_name):
        p = Path(dir_name)
        dataset_paths = list(p.glob('**/%s' % TFRECORD_DATASET_FILE_NAME))
        dataset_paths = [str(it) for it in dataset_paths]
        return dataset_paths

if __name__ == '__main__':
    import sys

    sys.path.insert(0, './')
    from libs.label_converter import LabelConverter
    from libs.data_augumenter import DataAugumenter
    from libs.config import load_config

    converter = LabelConverter(chars_file='/Users/cwq/code/tf_crnn/data/ocr_chars/num_and_big_eng.txt')

    cfg = load_config('raw8_one_lstm')

    da = DataAugumenter(cfg)
    da = None

    ds = TFRecordDataset(train_dir='/Users/cwq/data/TFRecord/random0_val',
                         converter=converter,
                         batch_size=20, da=da,
                         num_parallel_calls=1)
    with tf.Session() as sess:
        ds.init_op.run()
        image_padded_batch, width_batch, sparse_label_batch, label_batch, _ = ds.get_next_batch(sess)

        for i, img in enumerate(image_padded_batch):
            print(label_batch[i])
            print(np.count_nonzero(img != 0))
            img = img * 128 + 128
            cv2.imshow('debug', img.astype(np.uint8))
            cv2.waitKey()

ext: py

reason: import numpy


text:
# -*- coding: utf-8 -*-
"""
"""
import pytest

import numpy as np
import pandas as pd
import scipy.sparse as sps

from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering
from sklearn.datasets.samples_generator import make_blobs

from aikit.models import DBSCANWrapper, KMeansWrapper, AgglomerativeClusteringWrapper

def test_KMeansWrapper():
    Xtrain, cl = make_blobs(n_samples=1000, n_features=10, centers=5, random_state=123)

    kmeans_wrapper = KMeansWrapper(n_clusters=5, random_state=123)
    kmeans_wrapper.fit(Xtrain)

    kmeans = KMeans(n_clusters=5, random_state=123)
    kmeans.fit(Xtrain)

    assert kmeans_wrapper.n_clusters == kmeans.n_clusters

    diff_cluster_centers = np.abs(kmeans_wrapper.cluster_centers_ - kmeans.cluster_centers_)

    assert np.array_equal(kmeans_wrapper.labels_, kmeans.labels_)
    assert np.sum(diff_cluster_centers) <= 10 ** (-10)

    # check that n_clusters is < n_features
    Xtrain, cl = make_blobs(n_samples=10, n_features=5, centers=5)

    kmeans_wrapper = KMeansWrapper(n_clusters=15, random_state=123)
    kmeans_wrapper.fit(Xtrain)

    assert kmeans_wrapper.n_clusters == 9

def test_AgglomerativeClusteringWrapper():
    Xtrain, cl = make_blobs(n_samples=1000, n_features=10, centers=5, random_state=123)

    agg_wrapper = AgglomerativeClusteringWrapper(n_clusters=5)
    agg_wrapper.fit(Xtrain)

    agg = AgglomerativeClustering(n_clusters=5)
    agg.fit(Xtrain)

    assert agg.n_clusters == agg_wrapper.n_clusters
    assert np.array_equal(agg.labels_, agg_wrapper.labels_)

    # check that n_clusters is < n_features
    Xtrain, cl = make_blobs(n_samples=10, n_features=5, centers=5)

    agg_wrapper = AgglomerativeClusteringWrapper(n_clusters=15)
    agg_wrapper.fit(Xtrain)

    assert agg_wrapper.n_clusters <= 10

def test_DBSCANWrapper():
    Xtrain, cl = make_blobs(n_samples=1000, n_features=10, centers=5, random_state=123)

    dbscan_wrapper = DBSCANWrapper(eps=0.5, scale_eps=False)
    dbscan_wrapper.fit(Xtrain)

    dbscan = DBSCAN(eps=0.5)
    dbscan.fit(Xtrain)

    assert np.array_equal(dbscan.labels_, dbscan_wrapper.labels_)

    Xtrain = np.mgrid[-1:1.2:0.2, -1:1.2:0.2].reshape(2, -1).T
    dbscan_wrapper = DBSCANWrapper(eps=0.5, scale_eps=True)
    dbscan_wrapper.fit(Xtrain)

    eps_to_find = 0.5 * (2.0 * np.sqrt(2.0) - 0.2) + 0.2

    assert np.abs(dbscan_wrapper.eps - eps_to_find) <= 10 ** (-5)

max_stars_repo_name: gfournier/aikit

max_issues_repo_name: gfournier/aikit

max_forks_repo_name: gfournier/aikit

reason: import numpy,import scipy


text:
from typing import List

import numpy

from Base.bp2DBin import Bin
from Base.bp2DBox import Box

class State:
    def __init__(self, nbins: int, bin_size: (int, int), boxes_open: List[Box]):
        self.bin_size = bin_size
        self.bins = [Bin(*self.bin_size) for _ in range(nbins)]
        self.boxes_open = boxes_open
        self.solution_runtime = None

    def has_open_boxes(self):
        return len(self.boxes_open) > 0

    def place_box_in_bin_at_pnt(self, box, i: int, pnt):
        # box says if object can be placed there
        # "logic" checks if path to point is reachable
        # TODO: here we can add constraints on the placement, eg check for "gravity" constraints
        return self.bins[i].place_box_at_pnt(box, pnt)

    def place_box_in_bin(self, box: Box, i: int):
        '''
        places box in bin i at the first feasible position
        '''
        pnts_open = self.get_open_pnts_of_bin_i(i)
        for pnt in pnts_open:
            if self.place_box_in_bin_at_pnt(box, i, pnt):
                return True  # placement successful

        return False  # box couldn't be placed

    def check_if_fits_somewhere_in_box(self, box: Box, i: int):
        box_old_bl = box.bl.copy()
        if self.place_box_in_bin(box, i):
            self.remove_box_from_bin(box, i)
            box.move(box_old_bl)
            return True

        return False

    def remove_box_from_bin(self, box: Box, i: int):
        return self.bins[i].remove_box(box)

    def open_new_bin(self):
        self.bins.append(Bin(*self.bin_size))

    def get_open_pnts_of_bin_i(self, i: int):
        return self.bins[i].pnts_open

    def get_next_open_box(self):
        return self.boxes_open.pop(0)

    def insert_open_box(self, box: Box, i=0):
        self.boxes_open.insert(i, box)

    def append_open_box(self, box: Box):
        self.boxes_open.append(box)

    def get_bin_i(self, i: int):
        return self.bins[i]

    def get_all_boxes(self) -> List[Box]:
        all_boxes = [box for box in self.boxes_open]
        for b in self.bins:
            for box in b.boxes_stored:
                all_boxes.append(box)
        return all_boxes

    def compare_states(self, state):
        state1_boxes = state.get_all_boxes()
        state2_boxes = self.get_all_boxes()
        if len(state1_boxes) != len(state2_boxes):
            return False
        checked = numpy.zeros(len(state2_boxes), dtype=bool)
        for i, box1 in enumerate(state1_boxes):
            found = False
            for j, box2 in enumerate(state2_boxes):
                same_width = box1.get_w() == box2.get_w()
                same_height = box1.get_h() == box2.get_h()
                if not checked[i] and same_width and same_height:
                    checked[i] = True
                    found = True
                    break
            if not found:
                return False
        return numpy.all(checked)

    def box_overlap_check(self):
        for b in self.bins:
            for i, boxA in enumerate(b.boxes_stored):
                if not b.bounding_box.contains_rectangle(boxA):
                    return False
                for j, boxB in enumerate(b.boxes_stored):
                    if i != j and boxA.overlap(boxB):
                        return False
        return True

    def is_valid(self, state) -> bool:
        if len(self.boxes_open) > 0:
            print(f'Please pack the boxes {self.boxes_open} in some bin!')
            return False
        if not self.box_overlap_check():
            print(f'Some boxes are overlapping!')
            return False
        if not self.compare_states(state):
            print(f'The states are not equal')
            return False
        return True

class Action:

    def __init__(self, pnt, rct):
        self.rct = rct  # rectangle to be placed
        self.pnt = pnt  # point for rectangle to be placed at

    def __repr__(self):
        return 'action: r%d at (%f,%f)' % (self.rct.n, self.pnt[0], self.pnt[1])

    def complies_with_box(self, state):  # checks whether rct is in bounds
        test = self.rct.place_at(self.pnt)
        return state.area.contains_rectangle(test)

    def complies_with_box_content(self, state):  # checks that no rcts in box overlap
        test = self.rct.place_at(self.pnt)
        for rct in state.rcts_clsd:
            if test.overlap(rct) > 0: return False
        return True

    def is_feasible(self, state):
        return self.complies_with_box(state) and \
               self.complies_with_box_content(state)

    def apply_to(self, state):
        rcts_clsd = list(state.rcts_clsd)  # recall that list([...])
        rcts_open = list(state.rcts_open)  # creates a copy of [...]
        pnts_open = list(state.pnts_open)
        box = state.area

        rct = self.rct
        pnt = self.pnt

        rcts_open.remove(rct)  # works, because we overlaoded == in Rectangle2D
        pnts_open.remove(pnt)  # works, because we overlaoded == in Point2D

        rct_new = rct.place_at(pnt)

        pnts_open.extend(Action.new_placing_points(rct_new,
                                                   state))  # TODO: needed? not sure if blog entry code runs if this line is included
        rcts_clsd.append(rct_new)

        return Bin(rcts_clsd, rcts_open, pnts_open, box)

    def rot_rct(self):
        # forward method for 2DRct.rotate90()
        self.rct.rotate90()

    @staticmethod
    def new_placing_points(rct, state):
        box = state.area
        rcts_clsd = state.rcts_clsd

        pnt_br = rct.get_corner('br')
        pnt_tl = rct.get_corner('tl')

        pnts_new = []

        # test w.r.t. the 1st candidate point
        if pnt_br.get_x() < box.get_w():
            # test if bottom face of box contains candidate point
            if box.get_face('b').interior_contains_point(pnt_br):
                pnts_new.append(pnt_br)
            else:
                touches_tr = False
                touches_tl = False
                # iterate over all previously packed rectangles
                for r in rcts_clsd:
                    # test if top face of rectangle contains candidate
                    if r.get_face('t').interior_contains_point(pnt_br):
                        pnts_new.append(pnt_br)
                        break

                    if r.get_corner('tr') == pnt_br:
                        touches_tr = True
                    if r.get_corner('tl') == pnt_br:
                        touches_tl = True
                if touches_tr and touches_tl:
                    pnts_new.append(pnt_br)

        # test w.r.t. the 2nd candidate point
        if pnt_tl.get_y() < box.get_h():
            # test if left face of box contains candidate point
            if box.get_face('l').interior_contains_point(pnt_tl):
                pnts_new.append(pnt_tl)
            else:
                touches_br = False
                touches_tr = False
                # iterate over all previously packed rectangles
                for r in rcts_clsd:
                    # test if right face of rectangle contains candidate
                    if r.get_face('r').interior_contains_point(pnt_tl):
                        pnts_new.append(pnt_tl)
                        break

                    if r.get_corner('br') == pnt_tl:
                        touches_tr = True
                    if r.get_corner('tr') == pnt_tl:
                        touches_tl = True  ## TODO: bug? maybe this broke 2DRct.contains_point()?
                if touches_br and touches_tr:
                    pnts_new.append(pnt_tl)

        return pnts_new

if __name__ == '__main__':
    pass


text:
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
from random import uniform
from math import floor
import random
import json
import numpy as np
import time
from collections import deque
from keras.models import Sequential, load_model, model_from_json
from keras.layers import Dense, Flatten, BatchNormalization
from keras.optimizers import Adam, RMSprop

class AI:
    def __init__(self, state_size, gen_count, epsilon):
        print("AI Created.")
        print("-----")
        self.model_load_failed = False
        self.state_size = state_size
        self.availableActions = ['Left', 'None', 'Right']
        self.action_size = len(self.availableActions)

        self.gen_count = gen_count
        self.child_count = 0
        self.child_limit = 100
        self.child_rewards = 0
        self.child_current_score = 0
        self.child_best_score = 0
        self.action_limit = 1_000_000

        self.states = []
        self.train_targets = []

        self.gamma = 0.95
        self.learning_rate = 0.001

        self.epsilon = epsilon
        self.epsilon_decay = 0.999
        self.epsilon_min = 0.01

        self.model = self.build_model()
        if os.path.isfile("checkpoint.h5"):
            try:
                self.model.load_weights("checkpoint.h5")
            except:
                print("Failed to load weights. Exiting...")
                self.model_load_failed = True

    def on_closing(self):
        del self

    def __del__(self):
        print("-----")
        print("AI Closed.")
        print("---------------")

    def build_model(self):
        model = Sequential()
        model.add(Flatten(input_shape=self.state_size))
        model.add(BatchNormalization())
        model.add(Dense(20, activation="relu"))
        model.add(Dense(12, activation="relu"))
        model.add(Dense(self.action_size, activation="softmax"))
        model.compile(loss="mse", optimizer=Adam(lr=self.learning_rate))
        return model

    def remember(self, state, action, reward, next_state, done):
        self.child_rewards += reward
        if reward == 1:
            self.child_current_score += 1
            if self.child_current_score > self.child_best_score:
                self.child_best_score = self.child_current_score

        if done:
            self.child_count += 1

            print("Collecting actions for training... Generation : " + str(self.gen_count)
                  + " | Childs : " + str(self.child_count) + "/" + str(self.child_limit)
                  + " | Actions : " + str(len(self.states) + 1) + "/" + str(self.action_limit)
                  + " | Score : " + str(self.child_current_score)
                  + " | Best Score : " + str(self.child_best_score))

            self.child_current_score = 0
            target = reward
        else:
            target = reward + self.gamma * np.amax(self.model.predict(next_state)[0])
        train_target = self.model.predict(state)
        train_target[0][action] = target

        self.states.append(np.squeeze(state, axis=0))
        self.train_targets.append(np.squeeze(train_target, axis=0))

    def act(self, state):
        if np.random.rand() <= self.epsilon:
            return random.randrange(self.action_size)
        act_values = self.model.predict(state)
        return np.argmax(act_values[0])

    def replay(self):
        if self.child_count < self.child_limit and len(self.states) < self.action_limit:
            return

        generation_info = {
                            "Generation": self.gen_count,
                            "Childs": self.child_count,
                            "Actions": len(self.states),
                            "BestScore": self.child_best_score,
                            "AverageReward": round(self.child_rewards / self.child_count, 5),
                            "Epsilon": round(self.epsilon, 5)
                        }
        print("")
        print(generation_info)
        print("--------------------------------------------------")
        print("Training with collected actions...\n")
        self.model.fit(np.array(self.states), np.array(self.train_targets), verbose=1, epochs=1, shuffle=True)
        self.model.save_weights(filepath="checkpoint.h5")
        print("\nTraining completed...")
        print("--------------------------------------------------")
        self.states.clear()
        self.train_targets.clear()
        self.gen_count += 1
        self.child_count = 0
        self.child_rewards = 0
        self.child_best_score = 0
        self.adaptiveEGreedy()

        return generation_info

    def adaptiveEGreedy(self):
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay


text:
#
#  File:
#    nio04.py
#
#  Synopsis:
#    Shows how to use Nio to open an existing NetCDF file and append
#    data to a variable with an unlimited dimension.
#
#  Category:
#    Processing.
#
#  Author:
#    Dave Brown
#
#  Date of original publication:
#    August, 2007
#
#  Description:
#    This example creates a NetCDF file "nio04.nc" that has a
#    variable with an unlimited dimension. It then reads this
#    file back in and appends data to the unlimited dimension.
#
#  Effects illustrated:
#    o  Creating, reading, and appending to NetCDF files using Nio.
#
#  Output:
#    This example produces no graphic output, but it does
#    write to standard out.
#
#  Notes:
#

from __future__ import print_function
import numpy
import Nio
import os

#
#  Creating a NetCDF file named "nio04.nc".  If there is already
#  a file with that name, delete it first.
#
filename = "nio04.nc"

if (os.path.exists(filename)):
  os.remove(filename)

#
#  Open a NetCDF file for writing file and specify a
#  global history attribute.
#
file       = Nio.open_file(filename, "w")
file.title = "Unlimited dimension test file"

#
#  Create some dimensions.
#
file.create_dimension("lon",     3)
file.create_dimension("lat",     3)
file.create_dimension("time", None)     # unlimited dimension

print(file)

#
#  Create a variable of type double with three dimemsions.
#
var = file.create_variable("var", 'd', ("time", "lat","lon"))
var._FillValue = -999.0

for i in range(10):
# Initialize lat/lon grid to the timestep number for 10 timesteps
  var[i] = i

print("After assigning elements 0-9 of unlimited dimension:")
print(file)

print("Closing '{}' file...\n".format(filename))
file.close()

#
#  Reopen the file for writing
#
print("Reopening '{}' file...".format(filename))
file = Nio.open_file(filename, "w")

print(file)

var = file.variables['var']

for i in range(10,20):
  var[i] = i  # add ten more elements to the unlimited dimension

print("After assigning elements 10-19 of unlimited dimension:")
print(file)

var[25] = 25  # add ten more elements to the unlimited dimension

print("After assigning element 25 of unlimited dimension:")
print(file)

print("'print var'")
print(var)

print("'print var[23:]'")
print(var[23:])

file.close()


text:
"""Simulation of a flock of boids in a 3D box"""
import vedo
import numpy as np

########################################################################
class Boid:
    def __init__(self, pos, vel=(1,0,0), acc=(0,0,0), c='black'):
        self.xlim = (-3,3)
        self.ylim = (-3,3)
        self.zlim = (-3,3)
        self.max_speed = 0.075
        self.position = np.array(pos)
        self.acceleration = np.array(acc)
        self.velocity = np.array(vel) / np.linalg.norm(vel)
        self.color = c

    def update(self):
        x,y,z = self.position
        if x < self.xlim[0]: self.position[0] = self.xlim[1]
        if x > self.xlim[1]: self.position[0] = self.xlim[0]
        if y < self.ylim[0]: self.position[1] = self.ylim[1]
        if y > self.ylim[1]: self.position[1] = self.ylim[0]
        if z < self.zlim[0]: self.position[2] = self.zlim[1]
        if z > self.zlim[1]: self.position[2] = self.zlim[0]

        self.position += self.velocity * self.max_speed
        self.velocity += self.acceleration
        self.velocity = self.velocity / np.linalg.norm(self.velocity)

########################################################################
class Flock:
    def __init__(self, boids=()):
        self.neighbors  = 20
        self.cohesion   = 0.5
        self.separation = 0.3

        self.boids = list(boids)
        self.actor = None
        self.colors = [vedo.getColor(b.color) for b in boids]

        self.actor = vedo.Points([b.position for b in self.boids], r=8, c=self.colors)

    def positions(self):
        return np.array([b.position for b in self.boids])

    def velocities(self):
        return np.array([b.velocity for b in self.boids])

    def move(self):
        velos = self.velocities()
        coords = self.positions()
        for i,b in enumerate(self.boids):
            ids = self.actor.closestPoint(b.position, N=self.neighbors, returnPointId=True)[1:]

            # alignment: steer boid towards the average heading of local flockmates
            desired_vel = np.mean(velos[ids],  axis=0)
            b.acceleration = desired_vel/np.linalg.norm(desired_vel) - b.velocity

            # cohesion: steer boid to move toward the average position of local flockmates
            desired_pos = np.mean(coords[ids], axis=0)
            b.acceleration += (desired_pos - b.position) * self.cohesion

            # separation: steer boid to avoid crowding local flockmates
            dists = np.linalg.norm(coords[ids] - b.position, axis=1)
            idmin = np.argmin(dists)  # index of min distances in the list
            idpt = ids[idmin]         # index of the point
            b.acceleration += (b.position- coords[idpt]) * self.separation

            b.update()

        self.actor.points(self.positions()) # update all positions
        return self

################################################################################
if __name__=="__main__":

    vedo.settings.allowInteraction = True

    np.random.seed(6)
    boids = []
    for i in range(500):
        c = 'black' if i % 50 else 'red'
        boids.append( Boid(np.random.randn(3), np.random.randn(3), c=c) )
    flock = Flock(boids)

    plt = vedo.Plotter(bg2='lb', interactive=False)
    axes = vedo.Axes(xrange=(-3,3), yrange=(-3,3), zrange=(-3,3), yzGrid=True, zxGrid2=True)
    plt += [__doc__, flock.actor, axes]

    pb = vedo.ProgressBar(0, 100)
    for i in pb.range():
        flock.move()
        plt.show(resetcam=False, viewup='z')
        pb.print()

max_stars_repo_name: charliekind/vtkplotter

max_issues_repo_name: charliekind/vtkplotter

max_forks_repo_name: charliekind/vtkplotter


text:
import numpy as np
import regreg.api as rr

class optimal_tilt(rr.smooth_atom):

    """
    An objective used to find an
    approximately best tilt for a
    given affine constraint and a given
    direction of interest.

    We approximately solve the problem

    ..math::

        \text{min.}_{c,z:A(z + c\eta + \gamma) \leq b} \|z + c \eta\|^2_{\Sigma}

    where the objective is Mahalanobis distance
    for the constraint's covariance, $\gamma$ is
    the constraint's mean and the set
    $\{w:Aw \leq b\}$ is the affine constraint.

    """

    def __init__(self, affine_con,
                 direction_of_interest,
                 offset=None,
                 quadratic=None,
                 initial=None):

        rr.smooth_atom.__init__(self,
                                affine_con.linear_part.shape[1] + 1,
                                offset=offset,
                                quadratic=quadratic,
                                initial=initial)

        self.affine_con = affine_con
        self.direction_of_interest = eta = direction_of_interest

        design = self.design = np.hstack([np.identity(affine_con.dim),
                                          eta.reshape((-1,1))])

        sqrt_inv = affine_con.covariance_factors()[1]
        Si = np.dot(sqrt_inv.T, sqrt_inv)
        self.Q = np.dot(design.T, np.dot(Si, design))

        gamma = affine_con.mean

        linear_part = np.dot(affine_con.linear_part, design)
        offset = affine_con.offset - np.dot(affine_con.linear_part,
                                            affine_con.mean)

        scaling = np.sqrt((linear_part**2).sum(1))
        linear_part /= scaling[:,None]
        offset /= scaling

        self.linear_objective = 0.

        smoothing_quadratic = rr.identity_quadratic(1.e-2, 0, 0, 0)
        self.smooth_constraint = rr.nonpositive.affine(linear_part,
                                 -offset).smoothed(
                                 smoothing_quadratic)

    def smooth_objective(self, z, mode='both', check_feasibility=False):

        Qz = np.dot(self.Q, z)

        if mode == 'both':
            fc, gc = self.smooth_constraint.smooth_objective(z, mode='both')
            g = Qz + self.linear_objective + gc
            f = (z*Qz).sum() * 0.5 + (self.linear_objective*z).sum() + fc
            return f, g
        elif mode == 'grad':
            gc = self.smooth_constraint.smooth_objective(z, mode='grad')
            g = Qz + self.linear_objective + gc
            return g
        elif mode == 'func':
            fc = self.smooth_constraint.smooth_objective(z, mode='func')
            f = (z*Qz).sum() * 0.5 + (self.linear_objective*z).sum() + fc
            return f

    def fit(self, **regreg_args):
        soln = self.soln = self.solve(**regreg_args)
        self.z_soln = soln[:-1]
        self.c_soln = soln[-1]
        self.optimal_point = np.dot(self.design, self.soln)
        self.reweight_func = -self.affine_con.solve(self.optimal_point)
        return self.optimal_point

max_stars_repo_name: Xiaoying-Tian/selective-inference

max_issues_repo_name: Xiaoying-Tian/selective-inference

max_forks_repo_name: Xiaoying-Tian/selective-inference


text:
"""
A program that renders mono input as 3D, stereo output

:-a --azimuth evaluator 40*seconds
    Horizontal angle in degrees (0 = center). Can be expression like "90 * seconds"

:-e --elevation evaluator 0
    Vertical angle in degrees (0 = center). Can be expression like "30 * sin(0.1 * seconds))"')

:-d --distance evaluator 10
    Distance (10 = 100%% volume). Can be expression like "cos(seconds)"'

:-u --update-interval float 0.05
    Seconds between updating the position

:-c --chunk-size int 2048
    Samples per chunk (affects latency and cpu usage)

:-r --hrir-zip str {data_folder}/IRC_1013.zip
    ZIP file of HRIR data to use
"""
import inspect
import io
import math
import sys
from collections import namedtuple
from os.path import dirname, realpath, join
from time import sleep, monotonic
from traceback import format_exception_only
from typing import Callable, Tuple
from zipfile import ZipFile

import numpy as np
import pyaudio
from prettyparse import Usage

HrirData = namedtuple('HrirData', 'left_filters right_filters azimuths elevations')

class Processor:
    def __init__(self,
                 hrir: HrirData,
                 calc_azimuth: Callable[[], float],
                 calc_elevation: Callable[[], float],
                 calc_distance: Callable[[], float],
                 update_interval: float = 0.3):
        filters = np.stack([
            hrir.left_filters,
            hrir.right_filters
        ]).transpose((1, 0, 2))  # [direction][side][timestep]
        mag = (filters ** 2).transpose((2, 0, 1))  # Place timesteps first
        chop_index = find_index_to_running_sum(mag, 0.05 * mag.sum())
        self.filters = filters[:, :, chop_index:2 * chop_index]
        self.buffer = np.zeros((self.filters.shape[-1],))
        self.angles = np.dstack([hrir.azimuths, hrir.elevations])[0]
        self.calc_azimuth = calc_azimuth
        self.calc_elevation = calc_elevation
        self.calc_distance = calc_distance
        self.filter = self.calc_filter(self.calc_azimuth(), self.calc_elevation())
        self.distance = self.calc_distance()
        self.update_interval = update_interval
        self.last_update = monotonic()

    def calc_filter(self, azimuth, elevation) -> np.ndarray:
        """
        Calculates a left right convolution filter for a particular direction
        Works by taking a weighted average of the 4 closest filters
        """
        angle = np.array([azimuth, elevation])
        diffs = ((self.angles - angle) + 180) % 360 - 180
        x_is_positive = diffs[:, 0] >= 0
        y_is_positive = diffs[:, 1] >= 0

        def calc_closest_index(constraint):
            indices = np.where(constraint)
            ndiffs = diffs[indices]
            ndists = (ndiffs ** 2).sum(axis=-1)
            min_index = ndists.argmin()
            return indices[0][min_index], ndists[min_index]

        index_data = [calc_closest_index(i) for i in [
            x_is_positive & y_is_positive,
            x_is_positive & ~y_is_positive,
            ~x_is_positive & y_is_positive,
            ~x_is_positive & ~y_is_positive
        ]]
        weights = [1 / dist for index, dist in index_data]
        indices = [index for index, weight in index_data]
        return np.average(self.filters[indices], weights=weights, axis=0)

    def update(self):
        self.filter = self.calc_filter(self.calc_azimuth(), self.calc_elevation())
        self.distance = self.calc_distance()
        self.last_update = monotonic()

    def process(self, audio: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
        """Render positioned mono audio into 3D, stereo audio"""
        if monotonic() - self.last_update >= self.update_interval:
            self.update()
        full_audio = np.concatenate([self.buffer, audio]) * (10.0 / self.distance)
        self.buffer = audio[-len(self.buffer):]
        left = np.convolve(full_audio, self.filter[0], mode='valid')
        right = np.convolve(full_audio, self.filter[1], mode='valid')
        return left, right

def find_index_to_running_sum(arr: np.ndarray, amount: float) -> int:
    """Finds the index of arr that has a running sum at or above amount"""
    s = 0.0
    for i in range(len(arr)):
        s += arr[i].sum()
        if s >= amount:
            return i
    raise IndexError("No such index exists")

def hrir_data_from_mat(mat: dict):
    assert np.all(mat['l_hrir_S'][0][0]['azim_v'] == mat['r_hrir_S'][0][0]['azim_v'])
    assert np.all(mat['l_hrir_S'][0][0]['elev_v'] == mat['r_hrir_S'][0][0]['elev_v'])
    assert mat['l_hrir_S'][0][0]['sampling_hz'][0][0] == 44100
    assert mat['r_hrir_S'][0][0]['sampling_hz'][0][0] == 44100
    return HrirData(
        left_filters=mat['l_hrir_S'][0][0]['content_m'],
        right_filters=mat['r_hrir_S'][0][0]['content_m'],
        azimuths=mat['l_hrir_S'][0][0]['azim_v'][:, 0],
        elevations=mat['l_hrir_S'][0][0]['elev_v'][:, 0]
    )

def load_mat_from_zip(zip_filename: str) -> dict:
    from scipy.io import loadmat
    with ZipFile(zip_filename, 'r') as archive:
        mat_path = next(iter(
            [i for i in archive.namelist() if i.startswith('RAW/MAT/')] or
            [i for i in archive.namelist() if i.lower().endswith('.mat')]
        ))
        # noinspection PyTypeChecker
        return loadmat(io.BytesIO(archive.read(mat_path)))

def evaluator_type(expression: str) -> Callable[[], float]:
    def evaluator():
        return eval(expression, dict(inspect.getmembers(math)), dict(seconds=monotonic() - start_time))

    try:
        start_time = monotonic()
        evaluator()  # Verify no exceptions
    except Exception as e:
        msg = ''.join(format_exception_only(type(e), e)).strip()
        print(msg, file=sys.stderr)
        raise ValueError(msg)
    return evaluator

def main():
    Usage.types['evaluator'] = evaluator_type
    usage = Usage(__doc__)
    args = usage.parse()

    data_folder = join(dirname(realpath(__file__)), 'data')
    mat = load_mat_from_zip(args.hrir_zip.format(data_folder=data_folder))
    hrir = hrir_data_from_mat(mat)

    processor = Processor(
        hrir,
        calc_azimuth=args.azimuth,
        calc_elevation=args.elevation,
        calc_distance=args.distance,
        update_interval=args.update_interval
    )

    def callback(in_data, frame_count, time_info, status):
        audio = np.frombuffer(in_data, dtype=np.float32).reshape((-1, 2))[:, 0]
        left, right = processor.process(audio)
        out_data = np.vstack((left, right)).T.flatten().astype('float32').tobytes()
        return out_data, pyaudio.paContinue

    p = pyaudio.PyAudio()
    stream = p.open(
        format=pyaudio.paFloat32,
        channels=2,
        rate=44100,
        input=True,
        output=True,
        frames_per_buffer=args.chunk_size,
        stream_callback=callback
    )
    stream.start_stream()

    try:
        while stream.is_active():
            sleep(0.2)
    finally:
        stream.stop_stream()
        stream.close()
        p.terminate()

if __name__ == '__main__':
    main()

reason: import numpy,from scipy


text:
import pathlib
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk, ImageOps
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import cv2
from filters.notch_filters import IdealNotchFilter, ButterworthNotchFilter, GaussianNotchFilter
import os
from ctypes import *

if not os.path.exists('tmp'):
    os.makedirs('tmp')

def set_plot_title(title, fs = 16):
    plt.title(title, fontsize = fs)

class MainApp:
    def __init__(self):
        #Seeting up root
        windll.shcore.SetProcessDpiAwareness(1)
        self.root = tk.Tk()
        self.root.tk.call('tk', 'scaling', 1.5) # To get bigger window on higher resolution displays
        self.root.resizable(0, 0)
        self.root.title("Notch Filter")
        self.root.iconphoto(False, tk.PhotoImage(file = pathlib.Path("imgs/icon.png")))
        #setting up left side of GUI
        self.left_frame = tk.LabelFrame(text = "Original Image")
        self.left_frame.columnconfigure(0)
        self.left_frame.columnconfigure(1)
        self.left_frame.rowconfigure(0)
        self.left_frame.rowconfigure(1)
        self.left_frame.rowconfigure(2)
        self.left_frame.rowconfigure(3)
        self.left_frame.rowconfigure(4)
        self.left_frame.rowconfigure(5)
        self.original_img = tk.Label(self.left_frame, image = "", text = "Load an image \n to preview it here!", padx = 150, pady = 150)
        self.btn_browse_img = tk.Button(self.left_frame, text = "Browse Image", bg = "lightblue", command = self.browse_img)
        self.btn_apply_filter = tk.Button(self.left_frame, text = "Apply Filter", bg = "lightblue", command = self.apply_filter)
        self.select_filter_var = tk.StringVar(self.root)
        self.select_filter_var.set('Ideal')
        self.select_filter = tk.OptionMenu(self.left_frame, self.select_filter_var, *{'Ideal', 'Butterworth', 'Gaussian'})
        self.number_of_points = tk.Entry(self.left_frame)
        self.frequency = tk.Entry(self.left_frame)
        self.butterworth_order = tk.Entry(self.left_frame)
        self.original_img.grid(row = 0, column = 0, columnspan = 2)
        self.btn_browse_img.grid(row = 1, column = 0, sticky='nsew')
        self.btn_apply_filter.grid(row = 1, column = 1, sticky='nsew')
        tk.Label(self.left_frame, text = "Select type of Notch Filter: ").grid(row = 2, column = 0, sticky = "nsew")
        self.select_filter.grid(row = 2, column = 1, sticky = 'nsew')
        tk.Label(self.left_frame, text = "Number of Points: ").grid(row = 3, column = 0, sticky = 'nsew')
        self.number_of_points.grid(row = 3, column = 1, sticky = 'nsew')
        self.number_of_points.insert(tk.END, '6')
        tk.Label(self.left_frame, text = "Band Radius: ").grid(row = 4, column = 0, sticky = 'nsew')
        self.frequency.grid(row = 4, column = 1, sticky = 'nsew')
        self.frequency.insert(tk.END, '121.0')
        tk.Label(self.left_frame, text = "Order of \n Butterworth Filter").grid(row = 5, column = 0, sticky = 'nsew')
        self.butterworth_order.grid(row = 5, column = 1, sticky = 'nsew')
        self.butterworth_order.insert(tk.END, 1)
        self.left_frame.pack(side = "left", fill = tk.Y)
        #setting up Right side of GUI
        self.right_frame = tk.LabelFrame(text = "Filtered Image")
        self.filter_img = tk.Label(self.right_frame, image = "", text = "Apply filter to an image\nto view it here !", padx = 150, pady = 150)
        self.btn_save_img = tk.Button(self.right_frame, text = "Save this Image", bg = "lightblue", command = self.save_img)
        self.btn_summary = tk.Button(self.right_frame, text = "Show Summary",  bg = "lightblue", command = self.show_summary)
        self.info_lbl = tk.Label(self.right_frame, text = "READY")
        self.filter_img.pack()
        self.btn_save_img.pack(in_ = self.right_frame, fill = tk.X)
        self.btn_summary.pack(in_ = self.right_frame, fill = tk.X)
        self.info_lbl.pack(in_ = self.right_frame, fill = tk.BOTH, side = tk.LEFT)
        self.right_frame.pack(side = "right", fill = tk.Y)

    def browse_img(self):
        try:
            file = filedialog.askopenfilename(title = "Load Image", filetypes=[('Images', ['*jpeg','*png','*jpg'])])
            file = ImageOps.grayscale((Image.open(file)))
            file.save(pathlib.Path("tmp/original_img.png"))
            file = ImageTk.PhotoImage(file)
            self.original_img.configure(text = "", image = file)
            self.original_img.text = ""
            self.original_img.image = file
        except Exception as e:
            messagebox.showerror("An error occured !", e)

    def get_fshift_and_save_dft(self):
        img = Image.open(pathlib.Path("tmp/original_img.png"))
        img = np.asarray(img)
        f = np.fft.fft2(img)
        fshift = np.fft.fftshift(f)
        dft = 20 * np.log(np.abs(fshift))
        matplotlib.image.imsave(pathlib.Path("tmp/dft.png"), dft, cmap = "gray")
        return fshift, dft

    def apply_filter(self):
        try:
            self.info_lbl.configure(text = "BUSY")
            self.info_lbl.text = "BUSY"
            fshift, dft = self.get_fshift_and_save_dft()
            plt.clf()
            plt.imshow(Image.open(pathlib.Path("tmp/dft.png")), cmap = "gray")
            set_plot_title("Click on image to choose points. (Press any key to Start)")
            plt.waitforbuttonpress()
            set_plot_title(f'Select {self.number_of_points.get()} points with mouse click')
            points = np.asarray(plt.ginput(int(self.number_of_points.get()), timeout = -1))
            plt.close()
            #Applying filter
            if self.select_filter_var.get() == "Ideal":
                IdealNotchFilter().apply_filter(fshift, points, float(self.frequency.get()), pathlib.Path("tmp/filtered_img.png"))
            elif self.select_filter_var.get() == "Butterworth":
                ButterworthNotchFilter().apply_filter(fshift, points, float(self.frequency.get()), pathlib.Path("tmp/filtered_img.png"), order = int(self.butterworth_order.get()))
            elif self.select_filter_var.get() == "Gaussian":
                GaussianNotchFilter().apply_filter(fshift, points, float(self.frequency.get()), pathlib.Path("tmp/filtered_img.png"))
            self.info_lbl.configure(text = "READY")
            self.info_lbl.text = "READY"
            #Show filtered image
            filter_img = ImageTk.PhotoImage(ImageOps.grayscale((Image.open(pathlib.Path("tmp/filtered_img.png")))))
            self.filter_img.configure(image = filter_img)
            self.filter_img.image = filter_img
        except Exception as e:
            messagebox.showerror("An error occured!", e)

    def save_img(self):
        try:
            directory = filedialog.asksaveasfilename(title = "Save Image", filetypes=[('Images',['*jpeg','*png','*jpg'])])
            Image.open(pathlib.Path("tmp/filtered_img.png")).save(directory)
        except Exception as e:
            messagebox.showerror("An error occured!", e)

    def save_dft(self, path, save_path):
        img = ImageOps.grayscale((Image.open(path)))
        img = np.asarray(img)
        f = np.fft.fft2(img)
        fshift = np.fft.fftshift(f)
        dft = 20 * np.log(np.abs(fshift))
        matplotlib.image.imsave(save_path, dft, cmap = "gray")

    def show_summary(self):
        f, axarr = plt.subplots(2,2)
        axarr[0,0].imshow(Image.open(pathlib.Path("tmp/original_img.png")), cmap = "gray")
        axarr[0,1].imshow(Image.open(pathlib.Path("tmp/filtered_img.png")), cmap = "gray")
        axarr[1,0].imshow(Image.open(pathlib.Path("tmp/dft.png")), cmap = "gray")
        self.save_dft(pathlib.Path("tmp/filtered_img.png"), pathlib.Path("tmp/tdft.png"))
        axarr[1,1].imshow(Image.open(pathlib.Path("tmp/tdft.png")), cmap = "gray")
        plt.show()

    def run(self):
        self.root.mainloop()

if __name__ == "__main__":
    MainApp().run()


text:
import pandas as pd
import numpy as np
import warnings

from torch.utils.data.dataset import Dataset
from PIL import Image

Image.MAX_IMAGE_PIXELS = None
warnings.simplefilter('ignore', Image.DecompressionBombWarning)

class CustomDatasetFromImages(Dataset):
    def __init__(self, csv_path, transform):
        """
        Args:
            csv_path (string): path to csv file
            img_path (string): path to the folder where images are
            transform: pytorch transforms for transforms and tensor conversion
        """
        # Transforms
        self.transforms = transform
        # Read the csv file
        data_info = pd.read_csv(csv_path, header=None)
        # Second column is the image paths
        self.image_arr = np.asarray(data_info.iloc[:, 1])
        # First column is the image IDs
        self.label_arr = np.asarray(data_info.iloc[:, 0])
        # Calculate len
        self.data_len = len(data_info)

    def __getitem__(self, index):
        # Get image name from the pandas df
        single_image_name = self.image_arr[index]
        # Open image
        img_as_img = Image.open(single_image_name+'.jpg')
        # Transform the image
        img_as_tensor = self.transforms(img_as_img)
        # Get label(class) of the image based on the cropped pandas column
        single_image_label = self.label_arr[index]

        return (img_as_tensor, single_image_label)

    def __len__(self):
        return self.data_len


text:
import numpy as np
import soundfile as sf
from scipy import signal
import random
import os

def load_audio(path):
    sound, sample_rate = sf.read(path, dtype='int16')
    # TODO this should be 32768.0 to get twos-complement range.
    # TODO the difference is negligible but should be fixed for new models.
    sound = sound.astype('float32') / 32767  # normalize audio
    if len(sound.shape) > 1:
        if sound.shape[1] == 1:
            sound = sound.squeeze()
        else:
            sound = sound.mean(axis=1)  # multiple channels, average
    return sound

class Augment_wave(object):

    def __init__(self, fs, rir_path, split='train', shift_output=True, normalize=True):
        self.fs = fs
        self.shift_output = shift_output
        self.normalize = normalize
        assert split in ['train', 'dev', 'test']
        self.rir_path = rir_path
        self.rir = None
        self.init()

    def init(self):
        # construct rir dict
        self.rooms = ['ConferenceRoom2', 'C236', 'D105', 'E112', 'L207', 'L212', 'Q301']
        rir_all = {}
        for room in self.rooms:
            rir_all[room] = []
        for _, _, files in os.walk(self.rir_path):
            for rir in files:
                if rir.endswith('.wav'):
                    rir_room = rir.split('_')[2].split('-')[0]
                    assert rir_room in self.rooms
                    rir_all[rir_room].append(rir)
        for room in self.rooms:
            random.shuffle(rir_all[room])
        self.rir_dict = rir_all

    def compute_early_reverb_power(self, wave, rir):
        peak_index = rir.argmax()
        before_peak = int(0.001 * self.fs)
        after_peak = int(0.05 * self.fs)
        early_rir_start = max(0, peak_index - before_peak)
        early_rir_end = min(rir.shape[0], peak_index + after_peak)
        early_rir = rir[early_rir_start: early_rir_end]
        early_reverb = signal.fftconvolve(wave, early_rir, mode="full")
        early_power = np.dot(early_reverb, early_reverb) / early_reverb.shape[0]
        return early_power

    def do_reverb(self, wave, rir):
        rir = rir.astype("float32")
        rir = rir / np.max(np.abs(rir))
        early_power = self.compute_early_reverb_power(wave, rir)
        wave = signal.fftconvolve(wave, rir)
        return wave, early_power

    def augment(self, wave, rir=None):
        if rir is None:
            return wave
        wave = wave.astype("float32")
        if self.shift_output is True:
            dur2len = len(wave)
        else:
            dur2len = len(wave) + len(rir) - 1
        before_power = np.dot(wave, wave) / wave.shape[0]
        peak_index = 0
        early_power = before_power
        # reverberate the wave
        if rir is not None:
            wave, early_power = self.do_reverb(wave, rir)
            if self.shift_output is True:
                peak_index = rir.argmax()

        # normalize wave
        if self.normalize is True:
            # compute the power of wave after reverberation and possibly noise
            after_power = np.dot(wave, wave) / wave.shape[0]
            wave = wave * (np.sqrt(before_power / after_power))
        # extend wave if duration is larger than the length of wave
        if dur2len > wave.shape[0]:
            wave = np.pad(wave, pad_width=(0, dur2len - wave.shape[0]), mode="wrap")
        # shift the output wave by shift_output
        wave = wave[peak_index: peak_index + dur2len]
        return wave

    def inject(self, wave):
        # sample a room and a rir of the room based on P(r): uniform distribution
        room = np.random.choice(self.rooms)
        rir_name = np.random.choice(self.rir_dict[room])
        rir = load_audio(os.path.join(self.rir_path, rir_name))

        return self.augment(wave, rir=rir)


text:
import numpy as np

def sigmoid(x):
    """
    Compute the sigmoid of x

    Arguments:
    x -- A scalar or numpy array of any size

    Return:
    s -- sigmoid(x)
    """
    s = 1 / (1 + np.exp(-x))
    return s

def sigmoid_derivative(x):
    """
    Compute the gradient of the sigmoid function w.r.t x

    Arguments:
    x -- A scalar or numpy array

    Return:
    dx -- Computed gradient
    """

    s = sigmoid(x)
    dx = s * (1 - s)

    return dx

def normalizeRows(x):
    """
    Implement a function to normalizes each row of the matrix x (to have unit length)

    Argument:
    x -- A numpy matrix of shape (n, m)

    Returns:
    x -- The normalized (by row) numpy matrix
    """

    x_norm = np.linalg.norm(x, ord=2, axis=1, keepdims=True)
    x = x / x_norm

    return x

def softmax(x):
    """
    Calculates the softmax for each row of the input x

    Argument:
    x -- A numpy matrix of shape (n, m)

    Returns:
    s -- A numpy matrix equal to the softmax of x
    """

    x_exp = np.exp(x)
    x_sum = np.sum(x_exp, axis=1, keepdims=True)
    s = x_exp / x_sum

    return s