text:
"""Main module."""

# package(s) related to time, space and id
import json
import logging
import uuid

# you need these dependencies (you can get these from anaconda)
# package(s) related to the simulation
import simpy
import random
import networkx as nx
import numpy as np
import math

# spatial libraries
import pyproj
import shapely.geometry

# additional packages
import datetime, time

logger = logging.getLogger(__name__)

class SimpyObject:
    """General object which can be extended by any class requiring a simpy environment
    env: a simpy Environment
    """

    def __init__(self, env, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.env = env

class HasResource(SimpyObject):
    """Something that has a resource limitation, a resource request must be granted before the object can be used.
    nr_resources: nr of requests that can be handled simultaneously"""

    def __init__(self, nr_resources=1, priority=False, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.resource = (
            simpy.PriorityResource(self.env, capacity=nr_resources)
            if priority
            else simpy.Resource(self.env, capacity=nr_resources)
        )

class Identifiable:
    """Mixin class: Something that has a name and id
    name: a name
    id: a unique id generated with uuid"""

    def __init__(self, name, id=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.name = name
        # generate some id, in this case based on m
        self.id = id if id else str(uuid.uuid1())

class Locatable:
    """Mixin class: Something with a geometry (geojson format)
    geometry: can be a point as well as a polygon"""

    def __init__(self, geometry, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.geometry = geometry
        self.node = None

class Neighbours:
    """Can be added to a locatable object (list)
    travel_to: list of locatables to which can be travelled"""

    def ___init(self, travel_to, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.neighbours = travel_to

class HasDirection(SimpyObject):
    """Mixin class: Something with a storage capacity
    capacity: amount the container can hold
    level: amount the container holds initially
    container: a simpy object that can hold stuff"""

    def __init__(self, direction, total_requested=0, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.length = simpy.Container(self.env, capacity = direction, init=0)

class HasLength(SimpyObject):
    """Mixin class: Something with a storage capacity
    capacity: amount the container can hold
    level: amount the container holds initially
    container: a simpy object that can hold stuff"""

    def __init__(self, length, remaining_length=0, total_requested=0, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.length = simpy.Container(self.env, capacity = length, init=remaining_length)
        self.pos_length = simpy.Container(self.env, capacity = length, init=remaining_length)

class HasContainer(SimpyObject):
    """Mixin class: Something with a storage capacity
    capacity: amount the container can hold
    level: amount the container holds initially
    container: a simpy object that can hold stuff
    total_requested: a counter that helps to prevent over requesting"""

    def __init__(self, capacity, level=0, total_requested=0, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.container = simpy.Container(self.env, capacity, init=level)
        self.total_requested = total_requested

    @property
    def is_loaded(self):
        return True if self.container.level > 0 else False

    @property
    def filling_degree(self):
        return self.container.level / self.container.capacity

class Log(SimpyObject):
    """Mixin class: Something that has logging capability
    log: log message [format: 'start activity' or 'stop activity']
    t: timestamp
    value: a value can be logged as well
    geometry: value from locatable (lat, lon)"""

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.log = {"Message": [], "Timestamp": [], "Value": [], "Geometry": []}

    def log_entry(self, log, t, value, geometry_log):
        """Log"""
        self.log["Message"].append(log)
        self.log["Timestamp"].append(datetime.datetime.fromtimestamp(t))
        self.log["Value"].append(value)
        self.log["Geometry"].append(geometry_log)

    def get_log_as_json(self):
        json = []
        for msg, t, value, geometry_log in zip(
            self.log["Message"],
            self.log["Timestamp"],
            self.log["Value"],
            self.log["Geometry"],
        ):
            json.append(
                dict(message=msg, time=t, value=value, geometry_log=geometry_log)
            )
        return json

class VesselProperties:
    """Mixin class: Something that has vessel properties
    vessel_type: can contain info on vessel type (avv class, cemt_class or other)
    width: vessel width
    length: vessel length
    height_empty: vessel height unloaded
    height_full: vessel height loaded
    draught_empty: draught unloaded
    draught_full: draught loaded
    Add information on possible restrictions to the vessels, i.e. height, width, etc.
    """

    def __init__(
        self,
        vessel_type,
        width,
        length,
        height_empty,
        height_full,
        draught_empty,
        draught_full,
        *args,
        **kwargs
    ):
        super().__init__(*args, **kwargs)

        """Initialization"""
        self.vessel_type = vessel_type

        self.width = width
        self.length = length

        self.height_empty = height_empty
        self.height_full = height_full

        self.draught_empty = draught_empty
        self.draught_full = draught_full

    @property
    def current_height(self):
        """ Calculate current height based on filling degree """

        return (
            self.filling_degree * (self.height_full - self.height_empty)
            + self.height_empty
        )

    @property
    def current_draught(self):
        """ Calculate current draught based on filling degree """

        return (
            self.filling_degree * (self.draught_full - self.draught_empty)
            + self.draught_empty
        )

    def get_route(
        self,
        origin,
        destination,
        graph=None,
        minWidth=None,
        minHeight=None,
        minDepth=None,
        randomSeed=4,
    ):
        """ Calculate a path based on vessel restrictions """

        graph = graph if graph else self.env.FG
        minWidth = minWidth if minWidth else 1.1 * self.width
        minHeight = minWidth if minHeight else 1.1 * self.current_height
        minDepth = minWidth if minDepth else 1.1 * self.current_draught

        # Check if information on restrictions is added to the edges
        random.seed(randomSeed)
        edge = random.choice(list(graph.edges(data=True)))
        edge_attrs = list(edge[2].keys())

        # IMPROVE THIS TO CHECK ALL EDGES AND COMBINATIONS OF RESTRICTIONS

        if all(item in edge_attrs for item in ["Width", "Height", "Depth"]):
            edges = []
            nodes = []

            for edge in graph.edges(data=True):
                if (
                    edge[2]["Width"] >= minWidth
                    and edge[2]["Height"] >= minHeight
                    and edge[2]["Depth"] >= minDepth
                ):
                    edges.append(edge)

                    nodes.append(graph.nodes[edge[0]])
                    nodes.append(graph.nodes[edge[1]])

            subGraph = graph.__class__()

            for node in nodes:
                subGraph.add_node(
                    node["name"],
                    name=node["name"],
                    geometry=node["geometry"],
                    position=(node["geometry"].x, node["geometry"].y),
                )

            for edge in edges:
                subGraph.add_edge(edge[0], edge[1], attr_dict=edge[2])

            try:
                return nx.dijkstra_path(subGraph, origin, destination)
            except:
                raise ValueError(
                    "No path was found with the given boundary conditions."
                )

        # If not, return shortest path
        else:
            return nx.dijkstra_path(graph, origin, destination)

class HasEnergy:
    """Mixin class: Something that has energy usage.
    installed_power: installed engine power [kW]
    resistance: Rtot unloaded [N]
    resistance_empty: Rtot loaded [N]
    emissionfactor: emission factor [-]
    """

    def __init__(self, installed_power, resistance, resistance_empty, emissionfactor, *args, **kwargs):
        super().__init__(*args, **kwargs)

        """Initialization"""
        self.installed_power = installed_power
        self.resistance = resistance
        self.resistance_empty = resistance_empty
        self.emissionfactor = emissionfactor

class Routeable:
    """Mixin class: Something with a route (networkx format)
    route: a networkx path"""

    def __init__(self, route, complete_path=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.route = route
        self.complete_path = complete_path

class IsLockWaitingArea(HasResource, Identifiable, Log):
    """Mixin class: Something has lock object properties
    properties in meters
    operation in seconds
    """

    def __init__(
        self,
        node,
        *args,
        **kwargs
    ):
        super().__init__(*args, **kwargs)
        """Initialization"""

        waiting_area_resources = 100
        self.waiting_area = {
            node: simpy.PriorityResource(self.env, capacity=waiting_area_resources),
        }

        #departure_resources = 4
        #self.departure = {
        #    node: simpy.PriorityResource(self.env, capacity=departure_resources),
        #}

class IsLockLineUpArea(HasResource, HasLength, Identifiable, Log):
    """Mixin class: Something has lock object properties
    properties in meters
    operation in seconds
    """

    def __init__(
        self,
        node,
        lineup_length,
        *args,
        **kwargs
    ):
        super().__init__(length = lineup_length, remaining_length = lineup_length, *args, **kwargs)
        """Initialization"""

        self.lock_queue_length = 0

        # Lay-Out
        self.enter_line_up_area = {
            node: simpy.PriorityResource(self.env, capacity=1),
        }

        self.line_up_area = {
            node: simpy.PriorityResource(self.env, capacity=100),
        }

        self.converting_while_in_line_up_area = {
            node: simpy.PriorityResource(self.env, capacity=1),
        }

        self.pass_line_up_area = {
            node: simpy.PriorityResource(self.env, capacity=1),
        }

class HasLockDoors(SimpyObject):

     def __init__(
        self,
        node_1,
        node_3,
        *args,
        **kwargs
    ):
        super().__init__(*args, **kwargs)
        """Initialization"""

        self.doors_1 = {
            node_1: simpy.PriorityResource(self.env, capacity = 1),
        }
        self.doors_2 = {
            node_3: simpy.PriorityResource(self.env, capacity = 1),
        }

class IsLock(HasResource, HasLength, HasLockDoors, Identifiable, Log):
    """Mixin class: Something has lock object properties
    properties in meters
    operation in seconds
    """

    def __init__(
        self,
        node_1,
        node_2,
        node_3,
        lock_length,
        lock_width,
        lock_depth,
        doors_open,
        doors_close,
        wlev_dif,
        disch_coeff,
        grav_acc,
        opening_area,
        opening_depth,
        simulation_start,
        operating_time,
        *args,
        **kwargs
    ):

        """Initialization"""

        # Properties
        self.lock_length = lock_length
        self.lock_width = lock_width
        self.lock_depth = lock_depth
        self.wlev_dif = wlev_dif
        self.disch_coeff = disch_coeff
        self.grav_acc = grav_acc
        self.opening_area = opening_area
        self.opening_depth = opening_depth
        self.simulation_start = simulation_start.timestamp()
        self.operating_time = operating_time

        # Operating
        self.doors_open = doors_open
        self.doors_close = doors_close

        # Water level
        assert node_1 != node_3

        self.node_1 = node_1
        self.node_3 = node_3
        self.water_level = random.choice([node_1, node_3])

        super().__init__(length = lock_length, remaining_length = lock_length, node_1 = node_1, node_3 = node_3, *args, **kwargs)

    def operation_time(self, environment):
        operating_time = (2*self.lock_width*self.lock_length*abs(self.wlev_dif[1][np.abs(self.wlev_dif[0]-(environment.now-self.simulation_start)).argmin()]))/(self.disch_coeff*self.opening_area*math.sqrt(2*self.grav_acc*self.opening_depth))
        return operating_time

    def convert_chamber(self, environment, new_level):
        """ Convert the water level """

        # Close the doors
        self.log_entry("Lock doors closing start", environment.now, self.water_level, 0)
        yield environment.timeout(self.doors_close)
        self.log_entry("Lock doors closing stop", environment.now, self.water_level, 0)

        # Convert the chamber
        self.log_entry(
            "Lock chamber converting start", environment.now, self.water_level, 0
        )

        # Water level will shift
        self.change_water_level(new_level)
        yield environment.timeout(self.operation_time(environment))
        self.log_entry(
            "Lock chamber converting stop", environment.now, self.water_level, 0
        )
        # Open the doors
        self.log_entry("Lock doors opening start", environment.now, self.water_level, 0)
        yield environment.timeout(self.doors_open)
        self.log_entry("Lock doors opening stop", environment.now, self.water_level, 0)

    def change_water_level(self, side):
        """ Change water level and priorities in queue """

        self.water_level = side

        for request in self.resource.queue:
            request.priority = -1 if request.priority == 0 else 0

            if request.priority == -1:
                self.resource.queue.insert(
                    0, self.resource.queue.pop(self.resource.queue.index(request))
                )
            else:
                self.resource.queue.insert(
                    -1, self.resource.queue.pop(self.resource.queue.index(request))
                )

class Movable(Locatable, Routeable, Log):
    """Mixin class: Something can move
    Used for object that can move with a fixed speed
    geometry: point used to track its current location
    v: speed"""

    def __init__(self, v=1, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.v = v
        self.wgs84 = pyproj.Geod(ellps="WGS84")

    def move(self):
        """determine distance between origin and destination, and
        yield the time it takes to travel it
        Assumption is that self.path is in the right order - vessel moves from route[0] to route[-1].
        """
        self.distance = 0
        speed = self.v
        # Check if vessel is at correct location - if not, move to location
        if (
            self.geometry
            != nx.get_node_attributes(self.env.FG, "geometry")[self.route[0]]
        ):
            orig = self.geometry
            dest = nx.get_node_attributes(self.env.FG, "geometry")[self.route[0]]

            print("Origin", orig)
            print("Destination", dest)

            self.distance += self.wgs84.inv(
                shapely.geometry.asShape(orig).x,
                shapely.geometry.asShape(orig).y,
                shapely.geometry.asShape(dest).x,
                shapely.geometry.asShape(dest).y,
            )[2]

            yield self.env.timeout(self.distance / self.current_speed)
            self.log_entry("Sailing to start", self.env.now, self.distance, dest)

        # Move over the path and log every step
        for node in enumerate(self.route):
            self.node = node[1]

            if node[0] + 2 <= len(self.route):
                origin = self.route[node[0]]
                destination = self.route[node[0] + 1]

            if "Waiting area" in self.env.FG.nodes[destination].keys():
                locks = self.env.FG.nodes[destination]["Waiting area"]
                for lock in locks:
                    loc = self.route.index(destination)
                    for r in self.route[loc:]:
                        if 'Line-up area' in self.env.FG.nodes[r].keys():
                            wait_for_waiting_area = self.env.now
                            access_waiting_area = lock.waiting_area[destination].request()
                            yield access_waiting_area

                            if wait_for_waiting_area != self.env.now:
                                waiting = self.env.now - wait_for_waiting_area
                                self.log_entry("Waiting to enter waiting area start", wait_for_waiting_area, 0, nx.get_node_attributes(self.env.FG, "geometry")[origin],)
                                self.log_entry("Waiting to enter waiting area stop", self.env.now, waiting, nx.get_node_attributes(self.env.FG, "geometry")[origin],)

            if "Waiting area" in self.env.FG.nodes[origin].keys():
                locks = self.env.FG.nodes[origin]["Waiting area"]
                for lock in locks:
                    loc = self.route.index(origin)
                    for r in self.route[loc:]:
                        if 'Line-up area' in self.env.FG.nodes[r].keys():
                            locks2 = self.env.FG.nodes[r]["Line-up area"]
                            for r2 in self.route[loc:]:
                                if 'Lock' in self.env.FG.nodes[r2].keys():
                                    locks3 = self.env.FG.nodes[r2]["Lock"]
                                    break
                            print(self.id,self.env.now,'wa')
                            self.lock_name = []
                            for lock3 in locks3:
                                if lock3.water_level == self.route[self.route.index(r2)-1]:
                                    for lock2 in locks2:
                                        if lock2.name == lock3.name:
                                            if lock2.lock_queue_length == 0:
                                                self.lock_name = lock3.name
                                        break

                            lock_queue_length = [];
                            if self.lock_name == []:
                                for lock2 in locks2:
                                    lock_queue_length.append(lock2.lock_queue_length)

                                self.lock_name = locks2[lock_queue_length.index(min(lock_queue_length))].name

                            for lock2 in locks2:
                                if lock2.name == self.lock_name:
                                    lock2.lock_queue_length += 1

                            for lock2 in locks2:
                                if lock2.name == self.lock_name:
                                    self.v = 0.5*speed
                                    break

                            wait_for_lineup_area = self.env.now
                            lock.waiting_area[origin].release(access_waiting_area)

                            access_lineup_length = lock2.length.get(self.length)
                            if len(lock2.length.get_queue) != 0:
                                lock2.length.get_queue[-1].id = self.id
                                lock2.length.get_queue[-1].length = self.length
                                lock2.length.get_queue[-1].k = 0
                                total_length_vessels_in_line_up_area = 0
                                k = 0
                                for j in range(len(lock2.length.get_queue)):
                                    if lock2.length.get_queue[j].k == 1:
                                        total_length_vessels_in_line_up_area += lock2.length.get_queue[j].amount-lock2.length.capacity+lock2.length.get_queue[j].length
                                    else:
                                        total_length_vessels_in_line_up_area += lock2.length.get_queue[j].amount

                                    if lock2.length.get_queue[j].id == self.id and total_length_vessels_in_line_up_area > k*lock2.length.capacity:
                                        k += 1
                                        lock2.length.get_queue.remove(lock2.length.get_queue[j])
                                        access_lineup_length = lock2.length.get(lock2.length.capacity)
                                        lock2.length.get_queue[j].id = self.id
                                        lock2.length.get_queue[-1].length = self.length
                                        lock2.length.get_queue[-1].k = 1
                                        yield access_lineup_length
                                        k -= 1
                                        access_lineup_length = lock2.length.put(lock2.length.capacity-self.length)
                                    elif total_length_vessels_in_line_up_area > k*lock2.length.capacity:
                                        k += 1

                                if lock2.length.get_queue != [] and lock2.length.get_queue[-1].k == 0:
                                    yield access_lineup_length

                            else:
                                yield access_lineup_length

                            access_lineup_pos_length = lock2.pos_length.get(self.length)
                            self.lineup_dist = lock2.pos_length.level + 0.5*self.length

                            self.wgs84 = pyproj.Geod(ellps="WGS84")
                            [lineup_area_start_lat, lineup_area_start_lon, lineup_area_stop_lat, lineup_area_stop_lon] = [self.env.FG.nodes[self.route[self.route.index(r)]]['geometry'].x, self.env.FG.nodes[self.route[self.route.index(r)]]['geometry'].y,
                                                                                self.env.FG.nodes[self.route[self.route.index(r)+1]]['geometry'].x, self.env.FG.nodes[self.route[self.route.index(r)+1]]['geometry'].y]
                            fwd_azimuth,_,_ = self.wgs84.inv(lineup_area_start_lat, lineup_area_start_lon, lineup_area_stop_lat, lineup_area_stop_lon)
                            [self.lineup_pos_lat,self.lineup_pos_lon,_] = self.wgs84.fwd(self.env.FG.nodes[self.route[self.route.index(r)]]['geometry'].x,
                                                                                self.env.FG.nodes[self.route[self.route.index(r)]]['geometry'].y,
                                                                                fwd_azimuth,self.lineup_dist)

                            yield access_lineup_pos_length
                            enter_lineup_length = lock2.enter_line_up_area[r].request()
                            yield enter_lineup_length
                            lock2.enter_line_up_area[r].users[0].id = self.id

                            access_lineup_area = lock2.line_up_area[r].request()
                            lock2.line_up_area[r].users[-1].length = self.length
                            lock2.line_up_area[r].users[-1].id = self.id
                            lock2.line_up_area[r].users[-1].lineup_pos_lat = self.lineup_pos_lat
                            lock2.line_up_area[r].users[-1].lineup_pos_lon = self.lineup_pos_lon
                            lock2.line_up_area[r].users[-1].n = len(lock2.line_up_area[r].users)
                            lock2.line_up_area[r].users[-1].v = 0.25*speed
                            lock2.line_up_area[r].users[-1].wait_for_next_cycle = False
                            yield access_lineup_area

                            if wait_for_lineup_area != self.env.now:
                                self.v = 0.25*speed
                                waiting = self.env.now - wait_for_lineup_area
                                self.log_entry("Waiting in waiting area start", wait_for_lineup_area, 0, nx.get_node_attributes(self.env.FG, "geometry")[origin])
                                self.log_entry("Waiting in waiting area stop", self.env.now, waiting, nx.get_node_attributes(self.env.FG, "geometry")[origin])

                            break

            if "Line-up area" in self.env.FG.nodes[destination].keys():
                locks = self.env.FG.nodes[destination]["Line-up area"]
                for lock in locks:
                    if lock.name == self.lock_name:
                        loc = self.route.index(destination)
                        orig = shapely.geometry.Point(self.lineup_pos_lat,self.lineup_pos_lon)
                        for r in self.route[loc:]:
                            if 'Lock' in self.env.FG.nodes[r].keys():
                                locks = self.env.FG.nodes[r]["Lock"]
                                for lock2 in locks:
                                    for q in range(len(lock.line_up_area[destination].users)):
                                        if lock.line_up_area[destination].users[q].id == self.id:
                                            if lock.line_up_area[destination].users[q].n != len(lock.line_up_area[destination].users):
                                                for q2 in range(len(lock2.resource.users)):
                                                    if q2 == lock.line_up_area[destination].users[q].n - len(lock.line_up_area[destination].users):
                                                        break
                                                    else:
                                                        self.lineup_dist += lock2.resource.users[q2].length
                                                [self.lineup_pos_lat,self.lineup_pos_lon,_] = self.wgs84.fwd(self.env.FG.nodes[self.route[self.route.index(destination)]]['geometry'].x,
                                                                                self.env.FG.nodes[self.route[self.route.index(destination)]]['geometry'].y,
                                                                                fwd_azimuth,self.lineup_dist)
                                                lock.line_up_area[destination].users[q].lineup_pos_lat = self.lineup_pos_lat
                                                lock.line_up_area[destination].users[q].lineup_pos_lon = self.lineup_pos_lon
                                break

            if "Line-up area" in self.env.FG.nodes[origin].keys():
                locks = self.env.FG.nodes[origin]["Line-up area"]
                for lock in locks:
                    if lock.name == self.lock_name:
                        loc = self.route.index(origin)
                        orig = shapely.geometry.Point(self.lineup_pos_lat,self.lineup_pos_lon)
                        for r in self.route[loc:]:
                            if 'Lock' in self.env.FG.nodes[r].keys():
                                locks = self.env.FG.nodes[r]["Lock"]
                                lock.enter_line_up_area[origin].release(enter_lineup_length)
                                for q in range(len(lock.line_up_area[origin].users)):
                                    if lock.line_up_area[origin].users[q].id == self.id:
                                        if q > 0:
                                            _,_,distance = self.wgs84.inv(orig.x,
                                                                          orig.y,
                                                                          lock.line_up_area[origin].users[0].lineup_pos_lat,
                                                                          lock.line_up_area[origin].users[0].lineup_pos_lon)
                                            yield self.env.timeout(distance/self.v)
                                            break

                                for lock2 in locks:
                                    if lock2.name == self.lock_name:
                                        self.v = 0.25*speed
                                        wait_for_lock_entry = self.env.now

                                        for r2 in self.route[(loc+1):]:
                                            if 'Line-up area' in self.env.FG.nodes[r2].keys():
                                                locks = self.env.FG.nodes[r2]["Line-up area"]
                                                for lock3 in locks:
                                                    if lock3.name == self.lock_name:
                                                        break
                                                break

                                        if self.route[self.route.index(r)-1] == lock2.node_1:
                                            if len(lock2.doors_2[lock2.node_3].users) != 0:
                                                if lock2.doors_2[lock2.node_3].users[0].priority == -1:
                                                    if self.length > lock2.resource.users[-1].lock_dist or (lock.line_up_area[origin].users != [] and lock3.pass_line_up_area[r2].queue != [] and lock3.pass_line_up_area[r2].queue[-1].priority == 0):
                                                        wait_for_next_cycle = lock3.pass_line_up_area[r2].request()
                                                        yield wait_for_next_cycle
                                                        lock3.pass_line_up_area[r2].release(wait_for_next_cycle)

                                                    if lock.converting_while_in_line_up_area[origin].users != []:
                                                        waiting_during_converting = lock.converting_while_in_line_up_area[origin].request(priority = -1)
                                                        yield waiting_during_converting
                                                        lock.converting_while_in_line_up_area[origin].release(waiting_during_converting)

                                                    elif (len(lock2.doors_1[lock2.node_1].users) == 0 or (len(lock2.doors_1[lock2.node_1].users) != 0 and lock2.doors_1[lock2.node_1].users[0].priority != -1)) and self.route[self.route.index(r)-1] != lock2.water_level:
                                                        waiting_during_converting = lock.converting_while_in_line_up_area[origin].request()
                                                        yield waiting_during_converting
                                                        yield from lock2.convert_chamber(self.env, self.route[self.route.index(r)-1])
                                                        lock.converting_while_in_line_up_area[origin].release(waiting_during_converting)

                                                    access_lock_door1 = lock2.doors_1[lock2.node_1].request()
                                                    yield access_lock_door1

                                                    if lock2.doors_2[lock2.node_3].users != [] and lock2.doors_2[lock2.node_3].users[0].priority == -1:
                                                        access_lock_door2 = lock2.doors_2[lock2.node_3].request(priority = -1)
                                                        lock2.doors_2[lock2.node_3].release(lock2.doors_2[lock2.node_3].users[0])
                                                        yield access_lock_door2
                                                        lock2.doors_2[lock2.node_3].users[0].id = self.id
                                                    else:
                                                        access_lock_door2 = lock2.doors_2[lock2.node_3].request(priority = -1)
                                                        yield access_lock_door2
                                                        lock2.doors_2[lock2.node_3].users[0].id = self.id

                                                else:
                                                    if lock3.converting_while_in_line_up_area[r2].users != []:
                                                        waiting_during_converting = lock3.converting_while_in_line_up_area[r2].request()
                                                        yield waiting_during_converting
                                                        lock3.converting_while_in_line_up_area[r2].release(waiting_during_converting)

                                                    access_lock_door1 = lock2.doors_1[lock2.node_1].request()
                                                    yield access_lock_door1

                                                    if lock2.doors_2[lock2.node_3].users != [] and lock2.doors_2[lock2.node_3].users[0].priority == -1:
                                                        access_lock_door2 = lock2.doors_2[lock2.node_3].request(priority = -1)
                                                        lock2.doors_2[lock2.node_3].release(lock2.doors_2[lock2.node_3].users[0])
                                                        yield access_lock_door2
                                                        lock2.doors_2[lock2.node_3].users[0].id = self.id
                                                    else:
                                                        access_lock_door2 = lock2.doors_2[lock2.node_3].request(priority = -1)
                                                        yield access_lock_door2
                                                        lock2.doors_2[lock2.node_3].users[0].id = self.id
                                            else:
                                                access_lock_door1 = lock2.doors_1[lock2.node_1].request()
                                                yield access_lock_door1

                                                if lock2.doors_2[lock2.node_3].users != [] and lock2.doors_2[lock2.node_3].users[0].priority == -1:
                                                    access_lock_door2 = lock2.doors_2[lock2.node_3].request(priority = -1)
                                                    lock2.doors_2[lock2.node_3].release(lock2.doors_2[lock2.node_3].users[0])
                                                    yield access_lock_door2
                                                    lock2.doors_2[lock2.node_3].users[0].id = self.id

                                                elif lock2.doors_2[lock2.node_3].users != [] and lock2.doors_2[lock2.node_3].users[0].priority == 0:
                                                    access_lock_door2 = lock2.doors_2[lock2.node_3].request(priority = -1)
                                                    yield access_lock_door2
                                                    lock2.doors_2[lock2.node_3].users[0].id = self.id

                                                else:
                                                    if self.route[self.route.index(r)-1] != lock2.water_level:
                                                        waiting_during_converting = lock.converting_while_in_line_up_area[origin].request()
                                                        yield waiting_during_converting
                                                        yield from lock2.convert_chamber(self.env, self.route[self.route.index(r)-1])
                                                        lock.converting_while_in_line_up_area[origin].release(waiting_during_converting)

                                                    access_lock_door2 = lock2.doors_2[lock2.node_3].request(priority = -1)
                                                    yield access_lock_door2
                                                    lock2.doors_2[lock2.node_3].users[0].id = self.id

                                        elif self.route[self.route.index(r)-1] == lock2.node_3:
                                            if len(lock2.doors_1[lock2.node_1].users) != 0:
                                                if lock2.doors_1[lock2.node_1].users[0].priority == -1:
                                                    if self.length > lock2.resource.users[-1].lock_dist or (lock.line_up_area[origin].users != [] and lock3.pass_line_up_area[r2].queue != [] and lock3.pass_line_up_area[r2].queue[-1].priority == 0):
                                                        wait_for_next_cycle = lock3.pass_line_up_area[r2].request()
                                                        yield wait_for_next_cycle
                                                        lock3.pass_line_up_area[r2].release(wait_for_next_cycle)

                                                    if lock.converting_while_in_line_up_area[origin].users != []:
                                                        waiting_during_converting = lock.converting_while_in_line_up_area[origin].request(priority = -1)
                                                        yield waiting_during_converting
                                                        lock.converting_while_in_line_up_area[origin].release(waiting_during_converting)

                                                    elif (len(lock2.doors_2[lock2.node_3].users) == 0 or (len(lock2.doors_2[lock2.node_3].users) != 0 and lock2.doors_2[lock2.node_3].users[0].priority != -1)) and self.route[self.route.index(r)-1] != lock2.water_level:
                                                        waiting_during_converting = lock.converting_while_in_line_up_area[origin].request()
                                                        yield waiting_during_converting
                                                        yield from lock2.convert_chamber(self.env, self.route[self.route.index(r)-1])
                                                        lock.converting_while_in_line_up_area[origin].release(waiting_during_converting)

                                                    access_lock_door2 = lock2.doors_2[lock2.node_3].request()
                                                    yield access_lock_door2

                                                    if lock2.doors_1[lock2.node_1].users != [] and lock2.doors_1[lock2.node_1].users[0].priority == -1:
                                                        access_lock_door1 = lock2.doors_1[lock2.node_1].request(priority = -1)
                                                        lock2.doors_1[lock2.node_1].release(lock2.doors_1[lock2.node_1].users[0])
                                                        yield access_lock_door1
                                                        lock2.doors_1[lock2.node_1].users[0].id = self.id

                                                    else:
                                                        access_lock_door1 = lock2.doors_1[lock2.node_1].request(priority = -1)
                                                        yield access_lock_door1
                                                        lock2.doors_1[lock2.node_1].users[0].id = self.id

                                                else:
                                                    if lock3.converting_while_in_line_up_area[r2].users != []:
                                                        waiting_during_converting = lock3.converting_while_in_line_up_area[r2].request()
                                                        yield waiting_during_converting
                                                        lock3.converting_while_in_line_up_area[r2].release(waiting_during_converting)

                                                    access_lock_door2 = lock2.doors_2[lock2.node_3].request()
                                                    yield access_lock_door2

                                                    if lock2.doors_1[lock2.node_1].users != [] and lock2.doors_1[lock2.node_1].users[0].priority == -1:
                                                        access_lock_door1 = lock2.doors_1[lock2.node_1].request(priority = -1)
                                                        lock2.doors_1[lock2.node_1].release(lock2.doors_1[lock2.node_1].users[0])
                                                        yield access_lock_door1
                                                        lock2.doors_1[lock2.node_1].users[0].id = self.id
                                                    else:
                                                        access_lock_door1 = lock2.doors_1[lock2.node_1].request(priority = -1)
                                                        yield access_lock_door1
                                                        lock2.doors_1[lock2.node_1].users[0].id = self.id

                                            else:
                                                access_lock_door2 = lock2.doors_2[lock2.node_3].request()
                                                yield access_lock_door2

                                                if lock2.doors_1[lock2.node_1].users != [] and lock2.doors_1[lock2.node_1].users[0].priority == -1:
                                                    access_lock_door1 = lock2.doors_1[lock2.node_1].request(priority = -1)
                                                    lock2.doors_1[lock2.node_1].release(lock2.doors_1[lock2.node_1].users[0])
                                                    yield access_lock_door1
                                                    lock2.doors_1[lock2.node_1].users[0].id = self.id
                                                elif lock2.doors_1[lock2.node_1].users != [] and lock2.doors_1[lock2.node_1].users[0].priority == 0:
                                                    access_lock_door1 = lock2.doors_1[lock2.node_1].request(priority = -1)
                                                    yield access_lock_door1
                                                    lock2.doors_1[lock2.node_1].users[0].id = self.id
                                                else:
                                                    if self.route[self.route.index(r)-1] != lock2.water_level:
                                                        waiting_during_converting = lock.converting_while_in_line_up_area[origin].request()
                                                        yield waiting_during_converting
                                                        yield from lock2.convert_chamber(self.env, self.route[self.route.index(r)-1])
                                                        lock.converting_while_in_line_up_area[origin].release(waiting_during_converting)

                                                    access_lock_door1 = lock2.doors_1[lock2.node_1].request(priority = -1)
                                                    yield access_lock_door1
                                                    lock2.doors_1[lock2.node_1].users[0].id = self.id

                                        access_lock_length = lock2.length.get(self.length)
                                        yield access_lock_length

                                        access_lock = lock2.resource.request()
                                        yield access_lock

                                        access_lock_pos_length = lock2.pos_length.get(self.length)
                                        self.lock_dist = lock2.pos_length.level + 0.5*self.length
                                        yield access_lock_pos_length

                                        lock2.resource.users[-1].id = self.id
                                        lock2.resource.users[-1].length = self.length
                                        lock2.resource.users[-1].lock_dist = self.lock_dist
                                        if self.route[self.route.index(r)-1] == lock2.node_1:
                                            lock2.resource.users[-1].dir = 1.0
                                        else:
                                            lock2.resource.users[-1].dir = 2.0

                                        if wait_for_lock_entry != self.env.now:
                                            waiting = self.env.now - wait_for_lock_entry
                                            self.log_entry("Waiting in line-up area start", wait_for_lock_entry, 0, orig)
                                            self.log_entry("Waiting in line-up area stop", self.env.now, waiting, orig)

                                        lock.line_up_area[origin].release(access_lineup_area)

                                        self.wgs84 = pyproj.Geod(ellps="WGS84")
                                        [doors_origin_lat, doors_origin_lon, doors_destination_lat, doors_destination_lon] = [self.env.FG.nodes[self.route[self.route.index(r)-1]]['geometry'].x, self.env.FG.nodes[self.route[self.route.index(r)-1]]['geometry'].y,
                                                                                self.env.FG.nodes[self.route[self.route.index(r)+1]]['geometry'].x, self.env.FG.nodes[self.route[self.route.index(r)+1]]['geometry'].y]
                                        fwd_azimuth,_,distance = self.wgs84.inv(doors_origin_lat, doors_origin_lon, doors_destination_lat, doors_destination_lon)
                                        [self.lock_pos_lat,self.lock_pos_lon,_] = self.wgs84.fwd(self.env.FG.nodes[self.route[self.route.index(r)-1]]['geometry'].x,
                                                                                self.env.FG.nodes[self.route[self.route.index(r)-1]]['geometry'].y,
                                                                                fwd_azimuth,self.lock_dist)

                                        departure_lineup_pos_length = lock.pos_length.put(self.length)
                                        yield departure_lineup_pos_length

                                        for r4 in reversed(self.route[:(loc-1)]):
                                            if 'Line-up area' in self.env.FG.nodes[r4].keys():
                                                locks = self.env.FG.nodes[r4]["Line-up area"]
                                                for lock4 in locks:
                                                    if lock4.name == self.lock_name:
                                                        lock4.lock_queue_length -= 1
                                break

                            elif 'Waiting area' in self.env.FG.nodes[r].keys():
                                for r2 in reversed(self.route[:(loc-1)]):
                                    if 'Lock' in self.env.FG.nodes[r2].keys():
                                        locks = self.env.FG.nodes[r2]["Lock"]
                                        for lock2 in locks:
                                            if lock2.name == self.lock_name:
                                                if self.route[self.route.index(r2)+1] == lock2.node_3 and len(lock2.doors_2[lock2.node_3].users) != 0 and lock2.doors_2[lock2.node_3].users[0].id == self.id:
                                                    lock2.doors_2[lock2.node_3].release(access_lock_door2)
                                                elif self.route[self.route.index(r2)+1] == lock2.node_1 and len(lock2.doors_1[lock2.node_1].users) != 0 and lock2.doors_1[lock2.node_1].users[0].id == self.id:
                                                    lock2.doors_1[lock2.node_1].release(access_lock_door1)

                                                lock.pass_line_up_area[origin].release(departure_lock)
                                                lock2.resource.release(access_lock)
                                                print(self.id,self.env.now,'leaving lock')
                                                departure_lock_length = lock2.length.put(self.length)
                                                departure_lock_pos_length = lock2.pos_length.put(self.length)
                                                yield departure_lock_length
                                                yield departure_lock_pos_length
                                        break

            if "Lock" in self.env.FG.nodes[origin].keys():
                locks = self.env.FG.nodes[origin]["Lock"]
                for lock in locks:
                    if lock.name == self.lock_name:
                        if self.route[self.route.index(origin)-1] == lock.node_1:
                            lock.doors_1[lock.node_1].release(access_lock_door1)
                        elif self.route[self.route.index(origin)-1] == lock.node_3:
                            lock.doors_2[lock.node_3].release(access_lock_door2)
                        print(self.id,self.env.now,'in lock')
                        orig = shapely.geometry.Point(self.lock_pos_lat,self.lock_pos_lon)
                        loc = self.route.index(origin)

                        for r2 in reversed(self.route[loc:]):
                            if "Line-up area" in self.env.FG.nodes[r2].keys():
                                locks = self.env.FG.nodes[r2]["Line-up area"]
                                for lock3 in locks:
                                    if lock3.name == self.lock_name:
                                        departure_lock = lock3.pass_line_up_area[r2].request(priority = -1)
                                        break
                                break

                        for r in reversed(self.route[:(loc-1)]):
                            if "Line-up area" in self.env.FG.nodes[r].keys():
                                locks = self.env.FG.nodes[r]["Line-up area"]
                                for lock2 in locks:
                                    if lock2.name == self.lock_name:
                                        for q2 in range(0,len(lock.resource.users)):
                                            if lock.resource.users[q2].id == self.id:
                                                break
                                        yield self.env.timeout(0.01*q2) #solves rounding errors of order 0.001s
                                        departure_lineup_length = lock2.length.put(self.length)
                                        yield departure_lineup_length
                                        start_time_in_lock = self.env.now
                                        self.log_entry("Passing lock start", self.env.now, 0, orig)

                                        for q in range(len(lock2.line_up_area[r].users)):
                                            wait_for_lined_up_vessels = lock2.enter_line_up_area[r].request()
                                            yield wait_for_lined_up_vessels
                                            lock2.enter_line_up_area[r].release(wait_for_lined_up_vessels)

                                        if lock.resource.users[0].id == self.id:
                                            yield from lock.convert_chamber(self.env, destination)
                                        else:
                                            yield self.env.timeout(lock.doors_close + lock.operation_time(self.env) + lock.doors_open)

                        passage_time = lock.doors_close + lock.operating_time + lock.doors_open
                        waiting_for_lock_departure = self.env.now

                        yield departure_lock

                        if waiting_for_lock_departure != self.env.now:
                            exit_waiting_time = self.env.now-waiting_for_lock_departure
                        else:
                            exit_waiting_time = 0

                        self.log_entry("Passing lock stop", self.env.now, self.env.now-start_time_in_lock, orig,)
                        [self.lineup_pos_lat,self.lineup_pos_lon] = [self.env.FG.nodes[self.route[self.route.index(r2)]]['geometry'].x, self.env.FG.nodes[self.route[self.route.index(r2)]]['geometry'].y]
                        yield from self.pass_edge(origin, destination)
                        self.v = speed

            else:
                yield from self.pass_edge(origin, destination)

            if node[0] + 2 == len(self.route):
                break

        # self.geometry = nx.get_node_attributes(self.env.FG, "geometry")[destination]

        logger.debug("  distance: " + "%4.2f" % self.distance + " m")
        logger.debug("  sailing:  " + "%4.2f" % self.current_speed + " m/s")
        logger.debug(
            "  duration: "
            + "%4.2f" % ((self.distance / self.current_speed) / 3600)
            + " hrs"
        )

    def pass_edge(self, origin, destination):
        edge = self.env.FG.edges[origin, destination]
        orig = nx.get_node_attributes(self.env.FG, "geometry")[origin]
        dest = nx.get_node_attributes(self.env.FG, "geometry")[destination]

        if "Lock" in self.env.FG.nodes[origin].keys():
            orig = shapely.geometry.Point(self.lock_pos_lat,self.lock_pos_lon)

        if "Lock" in self.env.FG.nodes[destination].keys():
            dest = shapely.geometry.Point(self.lock_pos_lat,self.lock_pos_lon)

        if "Line-up area" in self.env.FG.nodes[origin].keys():
            orig = shapely.geometry.Point(self.lineup_pos_lat,self.lineup_pos_lon)

        if "Line-up area" in self.env.FG.nodes[destination].keys():
            dest = shapely.geometry.Point(self.lineup_pos_lat,self.lineup_pos_lon)

        if 'geometry' in edge:
            edge_route = np.array(edge['geometry'])

            # check if edge is in the sailing direction, otherwise flip it
            distance_from_start = self.wgs84.inv(
                    orig.x,
                    orig.y,
                    edge_route[0][0],
                    edge_route[0][1],
                )[2]
            distance_from_stop = self.wgs84.inv(
                    orig.x,
                    orig.y,
                    edge_route[-1][0],
                    edge_route[-1][1],
                )[2]
            if distance_from_start>distance_from_stop:
                # when the distance from the starting point is greater than from the end point
                edge_route = np.flipud(np.array(edge['geometry']))

            for index, pt in enumerate(edge_route[:-1]):
                sub_orig = shapely.geometry.Point(edge_route[index][0], edge_route[index][1])
                sub_dest = shapely.geometry.Point(edge_route[index+1][0], edge_route[index+1][1])

                distance = self.wgs84.inv(
                    shapely.geometry.asShape(sub_orig).x,
                    shapely.geometry.asShape(sub_orig).y,
                    shapely.geometry.asShape(sub_dest).x,
                    shapely.geometry.asShape(sub_dest).y,
                )[2]
                self.distance += distance
                self.log_entry("Sailing from node {} to node {} sub edge {} start".format(origin, destination, index), self.env.now, 0, sub_orig,)
                yield self.env.timeout(distance / self.current_speed)
                self.log_entry("Sailing from node {} to node {} sub edge {} stop".format(origin, destination, index), self.env.now, 0, sub_dest,)
            self.geometry = dest
            # print('   My new origin is {}'.format(destination))
        else:
            distance = self.wgs84.inv(
                shapely.geometry.asShape(orig).x,
                shapely.geometry.asShape(orig).y,
                shapely.geometry.asShape(dest).x,
                shapely.geometry.asShape(dest).y,
            )[2]

            self.distance += distance
            arrival = self.env.now

            # Act based on resources
            if "Resources" in edge.keys():
                with self.env.FG.edges[origin, destination]["Resources"].request() as request:
                    yield request

                    if arrival != self.env.now:
                        self.log_entry("Waiting to pass edge {} - {} start".format(origin, destination), arrival, 0, orig,)
                        self.log_entry("Waiting to pass edge {} - {} stop".format(origin, destination), self.env.now, 0, orig,)

                    self.log_entry("Sailing from node {} to node {} start".format(origin, destination), self.env.now, 0, orig,)
                    yield self.env.timeout(distance / self.current_speed)
                    self.log_entry("Sailing from node {} to node {} stop".format(origin, destination), self.env.now, 0, dest,)

            else:
                self.log_entry("Sailing from node {} to node {} start".format(origin, destination), self.env.now, 0, orig,)
                yield self.env.timeout(distance / self.current_speed)
                self.log_entry("Sailing from node {} to node {} stop".format(origin, destination), self.env.now, 0, dest,)

    @property
    def current_speed(self):
        return self.v

class ContainerDependentMovable(Movable, HasContainer):
    """ContainerDependentMovable class
    Used for objects that move with a speed dependent on the container level
    compute_v: a function, given the fraction the container is filled (in [0,1]), returns the current speed"""

    def __init__(self, compute_v, *args, **kwargs):
        super().__init__(*args, **kwargs)
        """Initialization"""
        self.compute_v = compute_v
        self.wgs84 = pyproj.Geod(ellps="WGS84")

    @property
    def current_speed(self):
        return self.compute_v(self.container.level / self.container.capacity)

max_stars_repo_name: TUDelft-CITG/OpenTNSim

max_issues_repo_name: TUDelft-CITG/OpenTNSim

max_forks_repo_name: TUDelft-CITG/OpenTNSim

reason: import numpy,import networkx


text:
"""
Plot charge resolution data generated by ctapipe-chargeres-extract.
"""

from os.path import dirname, basename, expanduser, exists, splitext
from os import makedirs
from matplotlib import pyplot as plt
from math import log10
import warnings
import numpy as np
from traitlets import Dict, List, Unicode, Int, Bool
from ctapipe.core import Tool, Component
from ctapipe.analysis.camera.chargeresolution import ChargeResolutionCalculator

class ChargeResolutionPlotter(Component):
    output_path = Unicode(None, allow_none=True,
                          help='Output path to save the '
                               'plot.').tag(config=True)
    max_pe = Int(2000, help='Maximum pe to plot').tag(config=True)
    linear_x = Bool(False, help='Plot the x values on a linear axis, '
                                'instead of log').tag(config=True)
    linear_y = Bool(False, help='Plot the y values on a linear axis, '
                                'instead of log').tag(config=True)

    def __init__(self, config=None, tool=None, **kwargs):
        """
        Calculator of charge resolution.

        Parameters
        ----------
        config : traitlets.loader.Config
            Configuration specified by config file or cmdline arguments.
            Used to set traitlet values.
            Set to None if no configuration to pass.
        tool : ctapipe.core.Tool
            Tool executable that is calling this component.
            Passes the correct logger to the component.
            Set to None if no Tool to pass.
        kwargs
        """
        super().__init__(config=config, parent=tool, **kwargs)

        try:
            if self.output_path is None:
                raise ValueError
        except ValueError:
            self.log.exception('Please specify an output path')
            raise

        self.fig = plt.figure(figsize=(20, 8))
        self.ax_l = self.fig.add_subplot(121)
        self.ax_r = self.fig.add_subplot(122)

        self.fig.subplots_adjust(left=0.05, right=0.95, wspace=0.6)

        self.legend_handles = []
        self.legend_labels = []

    def plot_chargeres(self, name, x, res, error):
        valid = (x <= self.max_pe)
        x_v = x[valid]
        res_v = res[valid]
        error_v = error[valid]

        eb_l, _, _ = self.ax_l.errorbar(x_v, res_v, yerr=error_v,
                                        marker='x', linestyle="None")
        self.legend_handles.append(eb_l)
        self.legend_labels.append(splitext(name)[0])

    def plot_scaled_chargeres(self, x, res, error):
        valid = (x <= self.max_pe)
        x_v = x[valid]
        res_v = res[valid]
        error_v = error[valid]

        self.ax_r.errorbar(x_v, res_v, yerr=error_v,
                           marker='x', linestyle="None")

    def plot_limit_curves(self):
        x = np.logspace(log10(0.9), log10(self.max_pe * 1.1), 100)
        requirement = ChargeResolutionCalculator.requirement(x)
        goal = ChargeResolutionCalculator.goal(x)
        poisson = ChargeResolutionCalculator.poisson(x)

        r_p, = self.ax_l.plot(x, requirement, 'r', ls='--')
        g_p, = self.ax_l.plot(x, goal, 'g', ls='--')
        p_p, = self.ax_l.plot(x, poisson, c='0.75', ls='--')
        self.ax_r.plot(x, requirement / goal, 'r')
        self.ax_r.plot(x, np.ones_like(x), 'g')
        self.ax_r.plot(x, poisson / goal, c='0.75', ls='--')

        self.legend_handles.append(r_p)
        self.legend_labels.append("Requirement")
        self.legend_handles.append(g_p)
        self.legend_labels.append("Goal")
        self.legend_handles.append(p_p)
        self.legend_labels.append("Poisson")

    def save(self):
        if not self.linear_x:
            self.ax_l.set_xscale('log')
            self.ax_r.set_xscale('log')
        if not self.linear_y:
            self.ax_l.set_yscale('log')

        self.ax_l.set_xlabel(r'True Charge $Q_T$ (p.e.)')
        self.ax_l.set_ylabel('Charge Resolution')
        self.ax_r.set_xlabel(r'True Charge $Q_T$ (p.e.)')
        self.ax_r.set_ylabel('Charge Resolution/Goal')

        self.ax_l.legend(self.legend_handles, self.legend_labels,
                         bbox_to_anchor=(1.02, 1.), loc=2,
                         borderaxespad=0., fontsize=10)

        self.fig.suptitle(splitext(basename(self.output_path))[0])

        self.ax_l.set_xlim(0.9, self.max_pe * 1.1)
        self.ax_r.set_xlim(0.9, self.max_pe * 1.1)
        if self.max_pe > 2000:
            self.ax_r.set_xlim(0.9, 2000 * 1.1)
        # if args.maxpeplot is not None:
        #     ax_l.set_xlim(0.9, args.maxpeplot)
        #     ax_r.set_xlim(0.9, args.maxpeplot)

        warnings.filterwarnings("ignore", module="matplotlib")
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            if self.output_path is None:
                plt.show()
            else:
                self.output_path = expanduser(self.output_path)
                output_dir = dirname(self.output_path)
                if not exists(output_dir):
                    self.log.info("[output] Creating directory: "
                                  "{}".format(output_dir))
                    makedirs(output_dir)
                self.log.info("[output] {}".format(self.output_path))
                self.fig.savefig(self.output_path, bbox_inches='tight')

class ChargeResolutionViewer(Tool):
    name = "ChargeResolutionViewer"
    description = "Plot the charge resolution from " \
                  "ChargeResolutionCalculator objects restored via " \
                  "pickled dictionaries."

    input_files = List(Unicode, None,
                       help='Input hdf5 files that are produced from '
                            'ChargeResolutionCalculator.save().'
                            '').tag(config=True)

    aliases = Dict(dict(f='ChargeResolutionViewer.input_files',
                        B='ChargeResolutionCalculator.binning',
                        max_pe='ChargeResolutionPlotter.max_pe',
                        O='ChargeResolutionPlotter.output_path',
                        ))
    flags = Dict(dict(L=({'ChargeResolutionCalculator': {'log_bins': False}},
                         'Bin the x axis linearly instead of logarithmic.'),
                      linx=({'ChargeResolutionPlotter': {'linear_x': True}},
                            'Plot the x values on a linear axis, '
                            'instead of log.'),
                      liny=({'ChargeResolutionPlotter': {'linear_y': True}},
                            'Plot the x values on a linear axis, '
                            'instead of log.')
                      ))
    classes = List([ChargeResolutionCalculator,
                    ChargeResolutionPlotter
                    ])

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.calculator = None
        self.plotter = None

    def setup(self):
        self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]"
        kwargs = dict(config=self.config, tool=self)

        self.calculator = ChargeResolutionCalculator(**kwargs)
        self.plotter = ChargeResolutionPlotter(**kwargs)

    def start(self):
        self.plotter.plot_limit_curves()
        for fp in self.input_files:
            self.calculator.load(fp)
            x, res, res_error, scaled_res, scaled_res_error = \
                self.calculator.get_charge_resolution()

            name = basename(fp)
            self.plotter.plot_chargeres(name, x, res, res_error)
            self.plotter.plot_scaled_chargeres(x, scaled_res, scaled_res_error)

    def finish(self):
        self.plotter.save()

def main():
    exe = ChargeResolutionViewer()
    exe.run()

if __name__ == '__main__':
    main()

ext: py

max_stars_repo_name: mpecimotika/ctapipe

max_issues_repo_name: mpecimotika/ctapipe

max_forks_repo_name: mpecimotika/ctapipe

reason: import numpy


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

import os
import sys

import numpy as np

from simulater import Simulater
from play_back import PlayBack, PlayBacks

COMMAND = ['UP', 'DOWN', 'LEFT', 'RIGHT']

def get_max_command(target_dict):
    return max([(v,k) for k,v in target_dict.items()])[1]

def simplify(command):
    return command[0]

def print_Q(Q, x, y):
    ret = []
    for i in range(y):
        ret.append(['0' for _ in range(x)])
    for k in Q:
        ret[k[1]][k[0]] = simplify(get_max_command(Q[k]))
    for this_line in ret:
        print(''.join(this_line))

if __name__ == '__main__':
    # parameters
    file_name = 'default.txt'
    epoch_num = 1000
    max_trial = 5000
    gamma = 0.1
    alpha = 0.1
    epsilon = 0.5

    # make simulater
    sim = Simulater(file_name)

    # initialize Q value
    x, y = sim.map_size()
    Q = {}
    for i in range(x):
        for j in range(y):
            Q[(i, j)] = {_:np.random.normal() for _ in COMMAND}
            #Q[(i, j)] = {_:0.0 for _ in COMMAND}

    # main
    minimum_pbs = None
    for epoch in range(epoch_num):
        sim.reset()
        this_pbs = PlayBacks()
        for i in range(max_trial):
            # get current
            current_x, current_y = sim.get_current()

            # select_command
            tmp_Q = Q[(current_x, current_y)]
            command = get_max_command(tmp_Q) if np.random.uniform() > epsilon else np.random.choice(COMMAND)
            current_value = tmp_Q[command]

            # reward
            reward = sim(command)

            # update
            next_x, next_y = sim.get_current()
            next_max_command = get_max_command(Q[(next_x, next_y)])
            next_value = Q[(next_x, next_y)][next_max_command]
            tmp_Q[command] += alpha * (reward + gamma * next_value - current_value)

            # play back
            this_pbs.append(PlayBack((current_x, current_y),
                                     command,
                                     (next_x, next_y),
                                     reward))
            # end check
            if sim.end_episode():
                print('find goal')
                epsilon *= 0.95
                if epsilon < 0.05:
                    epsilon = 0.05
                if minimum_pbs is None:
                    minimum_pbs = this_pbs
                elif len(minimum_pbs) > len(this_pbs):
                    minimum_pbs = this_pbs
                print(epsilon)
                break
        # update with minimum_pbs
        if minimum_pbs is not None:
            for pb in minimum_pbs:
                tmp_Q = Q[pb.state]
                current_value = tmp_Q[pb.action]
                next_Q = Q[pb.next_state]
                next_max_command = get_max_command(next_Q)
                next_value = next_Q[next_max_command]
                tmp_Q[pb.action] += alpha * (pb.reward + gamma * next_value - current_value)
        sim.printing()
        print('---')
        print_Q(Q, x, y)
        print('---')


text:
# Copyright (C) 2019 Cancer Care Associates

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from pymedphys._imports import numpy as np
from pymedphys._imports import scipy

def create_bb_predictor(bb_x, bb_y, gantries, directions, default_tol=0.1):
    bb_coords_keys = ["x", "y"]
    direction_options = np.unique(directions)
    prediction_functions = {}

    for bb_coords_key, bb_coords in zip(bb_coords_keys, [bb_x, bb_y]):
        for current_direction in direction_options:
            prediction_functions[
                (bb_coords_key, current_direction)
            ] = define_inner_prediction_func(
                gantries, bb_coords, directions, current_direction
            )

    def predict_bb(gantry, direction, tol=default_tol):
        results = []
        for bb_coords_key in bb_coords_keys:
            results.append(
                prediction_functions[(bb_coords_key, direction)](gantry, tol)
            )

        return results

    return predict_bb

def define_inner_prediction_func(gantries, bb_coords, directions, current_direction):
    interps = [
        scipy.interpolate.interp1d(
            gantry, bb_coord, bounds_error=False, fill_value="extrapolate"
        )
        for gantry, bb_coord, direction in zip(gantries, bb_coords, directions)
        if direction == current_direction
    ]

    def prediction_func(gantry, tol):
        results = []

        for interp in interps:
            results.append(interp(gantry))

        min_val = np.nanmin(results, axis=0)
        max_val = np.nanmax(results, axis=0)
        # result = np.nanmean(results, axis=0)
        result = (max_val + min_val) / 2

        out_of_tol = np.logical_or(max_val - result > tol, result - min_val > tol)
        result[out_of_tol] = np.nan

        return result

    return prediction_func

max_forks_repo_name: cpbhatt/pymedphys

reason: import numpy,import scipy


text:
import kaldi_io
import numpy as np

def read_all_data(feat_scp):
    feat_fid = open(feat_scp, 'r')
    feat = feat_fid.readlines()
    feat_fid.close()
    mat_list = []

    for i in range(len(feat)):
        _, ark = feat[i].split()
        mat = kaldi_io.read_mat(ark)
        mat_list.append(mat)
    return np.concatenate(mat_list, axis=0)

def read_feats_and_targets(feat_scp, text_file):
    feat_fid = open(feat_scp, 'r')
    text_fid = open(text_file, 'r')
    feat = feat_fid.readlines()
    text = text_fid.readlines()
    feat_fid.close()
    text_fid.close()
    assert (len(feat) == len(text))
    dict_utt2feat = {}
    dict_utt2target = {}
    for i in range(len(feat)):
        utt_id1, ark = feat[i].strip('\n').split(' ')
        utt_id2, target = text[i].strip('\n').split(' ')
        assert (utt_id1 == utt_id2)
        dict_utt2feat[utt_id1] = ark
        dict_utt2target[utt_id2] = target
    return dict_utt2feat, dict_utt2target

def get_feats(target, dic_utt2feat, dict_target2utt):
    """ Read feats for a specific target
        :param target: char, '0', '1', ..., '9', o'
        :param dict_utt2feat: utterance to feat dictionary
        :param dict_target2utt: target to utterance dictionary
        :return: feature matrix for this target, num_samples * feature dim
    """
    mat_list = []
    for utt in dict_target2utt[target]:
        ark = dic_utt2feat[utt]
        mat = kaldi_io.read_mat(ark)
        mat_list.append(mat)
    return np.concatenate(mat_list, axis=0)

def cmvn(mat):
    mean = np.mean(mat, axis=0)
    var = np.var(mat, axis=0)
    mat = (mat - mean) / var
    return mat

def splice(feats, left_context, right_context):
    ''' Splice feature
    Args:
        feats: input feats
        left_context: left context for splice
        right_context: right context for splice
    Returns:
        Spliced feature
    '''
    if left_context == 0 and right_context == 0:
        return feats
    assert (len(feats.shape) == 2)
    num_rows = feats.shape[0]
    first_frame = feats[0]
    last_frame = feats[-1]
    padding_feats = feats
    if left_context > 0:
        left_padding = np.vstack([first_frame for i in range(left_context)])
        padding_feats = np.vstack((left_padding, padding_feats))
    if right_context > 0:
        right_padding = np.vstack([last_frame for i in range(right_context)])
        padding_feats = np.vstack((padding_feats, right_padding))
    outputs = []
    for i in range(num_rows):
        splice_feats = np.hstack([
            padding_feats[i]
            for i in range(i, i + 1 + left_context + right_context)
        ])
        outputs.append(splice_feats)
    return np.vstack(outputs)

def build_input(targets_mapping, utt2feat, utt2target):
    mat_list = []
    label_list = []
    for utt in utt2feat:
        assert (utt in utt2target)
        ark = utt2feat[utt]
        t = utt2target[utt]
        mat = kaldi_io.read_mat(ark)
        mat = splice(mat, 5, 5)
        mat_list.append(mat)
        label_list.extend([targets_mapping[t]] * mat.shape[0])
    return np.concatenate(mat_list, axis=0), np.array(label_list)