# -*- coding: utf-8 -*-
import numpy as np

import plotly.graph_objs as go
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State

import dash_daq as daq

from dash_daq_drivers import keithley_instruments

# Define the app
app = dash.Dash(
    __name__, meta_tags=[{"name": "viewport", "content": "width=device-width"}]
)
server = app.server
app.config.suppress_callback_exceptions = False

# Instance of a Keithley2400 connected with Prologix GPIB to USB controller
iv_generator = keithley_instruments.KT2400(mock_mode=False)

# font and background colors associated with each themes
bkg_color = {"dark": "#2a3f5f", "light": "#F3F6FA"}
grid_color = {"dark": "white", "light": "#C8D4E3"}
text_color = {"dark": "white", "light": "#506784"}

def is_instrument_port(port_name):
    """test if a string can be a com of gpib port"""
    answer = False
    if isinstance(port_name, str):
        ports = ["COM", "com", "GPIB0::", "gpib0::"]
        for port in ports:
            if port in port_name:
                answer = not (port == port_name)
    return answer

class UsefulVariables:
    """Class to store information useful to callbacks"""

    def __init__(self):
        self.n_clicks = 0
        self.n_clicks_clear_graph = 0
        self.n_refresh = 0
        self.source = "V"
        self.is_source_being_changed = False
        self.mode = "single"
        self.sourced_values = []
        self.measured_values = []

    def change_n_clicks(self, nclicks):
        self.n_clicks = nclicks

    def change_n_clicks_clear_graph(self, nclicks):
        self.n_clicks_clear_graph = nclicks

    def reset_n_clicks(self):
        self.n_clicks = 0
        self.n_clicks_clear_graph = 0

    def change_n_refresh(self, nrefresh):
        self.n_refresh = nrefresh

    def reset_interval(self):
        self.n_refresh = 0

    def clear_graph(self):
        self.sourced_values = []
        self.measured_values = []

    def sorted_values(self):
        """ Sort the data so the are ascending according to the source """
        data_array = np.vstack([local_vars.sourced_values, local_vars.measured_values])
        data_array = data_array[:, data_array[0, :].argsort()]

        return data_array

local_vars = UsefulVariables()

def get_source_labels(source="V"):
    """labels for source/measure elements"""
    if source == "V":
        # we source voltage and measure current
        source_label = "Voltage"
        measure_label = "Current"
    elif source == "I":
        # we source current and measure voltage
        source_label = "Current"
        measure_label = "Voltage"

    return source_label, measure_label

def get_source_units(source="V"):
    """units for source/measure elements"""
    if source == "V":
        # we source voltage and measure current
        source_unit = "V"
        measure_unit = "A"
    elif source == "I":
        # we source current and measure voltage
        source_unit = "μA"
        measure_unit = "V"

    return source_unit, measure_unit

def get_source_max(source="V"):
    """units for source/measure elements"""
    if source == "V":
        # we source voltage and measure current
        return 20
    elif source == "I":
        # we source current and measure voltage
        return 100

h_style = {
    "display": "flex",
    "flex-direction": "row",
    "alignItems": "center",
    "justifyContent": "space-between",
    "margin": "5px",
}

# Create controls using a function
def generate_main_layout(
    theme="light", src_type="V", mode_val="single", fig=None, sourcemeter=iv_generator
):
    """generate the layout of the app"""

    source_label, measure_label = get_source_labels(src_type)
    source_unit, measure_unit = get_source_units(src_type)
    source_max = get_source_max(src_type)

    if mode_val == "single":
        single_style = {
            "display": "flex",
            "flex-direction": "column",
            "alignItems": "center",
        }
        sweep_style = {"display": "none"}

        label_btn = "Single measure"
    else:
        single_style = {"display": "none"}
        sweep_style = {
            "display": "flex",
            "flex-direction": "column",
            "alignItems": "center",
        }

        label_btn = "Start sweep"

    # As the trigger-measure btn will have its n_clicks reset by the reloading
    # of the layout we need to reset this one as well
    local_vars.reset_n_clicks()

    # Doesn't clear the data of the graph
    if fig is None:
        data = []
    else:
        data = fig["data"]

    html_layout = [
        html.Div(
            className="row",
            children=[
                # graph to trace out the result(s) of the measurement(s)
                html.Div(
                    id="IV_graph_div",
                    className="eight columns",
                    style={"margin": "20px"},
                    children=[
                        dcc.Graph(
                            id="IV_graph",
                            figure={
                                "data": data,
                                "layout": dict(
                                    paper_bgcolor=bkg_color[theme],
                                    plot_bgcolor=bkg_color[theme],
                                    font=dict(color=text_color[theme], size=15),
                                    xaxis={
                                        "color": grid_color[theme],
                                        "gridcolor": grid_color[theme],
                                    },
                                    yaxis={
                                        "color": grid_color[theme],
                                        "gridcolor": grid_color[theme],
                                    },
                                ),
                            },
                        )
                    ],
                ),
                # controls for the connexion to the instrument
                html.Div(
                    id="instr_controls",
                    className="two columns",
                    children=[
                        html.H4(sourcemeter.instr_user_name),
                        # A button to turn the instrument on or off
                        html.Div(
                            children=[
                                html.Div(
                                    id="power_button_div",
                                    children=daq.PowerButton(
                                        id="power_button", on="false"
                                    ),
                                ),
                                html.Br(),
                                html.Div(
                                    children=daq.Indicator(
                                        id="mock_indicator",
                                        value=sourcemeter.mock_mode,
                                        label="is mock?",
                                    ),
                                    style={"margin": "20px"},
                                    title="If the indicator is on, it means "
                                    "the instrument is in mock mode",
                                ),
                            ],
                            style=h_style,
                        ),
                        # An input to choose the COM/GPIB port
                        dcc.Input(
                            id="instr_port_input",
                            placeholder="Enter port name...",
                            type="text",
                            value="",
                        ),
                        html.Br(),
                        # A button which will initiate the connexion
                        daq.StopButton(
                            id="instr_port_button", buttonText="Connect", disabled=True
                        ),
                        html.Br(),
                        html.Div(
                            id="instr_status_div",
                            children="",
                            style={"margin": "10 px"},
                        ),
                    ],
                    style={
                        "margin": "50px",
                        "display": "flex",
                        "flex-direction": "column",
                        "alignItems": "center",
                        "justifyContent": "space-between",
                        "border": "2px solid #C8D4E3",
                        "background": "#f2f5fa",
                    },
                ),
            ],
        ),
        html.Div(
            id="measure_controls_div",
            className="row",
            children=[
                # controls and options for the IV tracer
                html.Div(
                    className="two columns",
                    id="IV-options_div",
                    children=[
                        html.H4(
                            "Sourcing",
                            title="Choose whether you want to source voltage "
                            "and measure current or source current and "
                            "measure voltage",
                        ),
                        dcc.RadioItems(
                            id="source-choice",
                            options=[
                                {"label": "Voltage", "value": "V"},
                                {"label": "Current", "value": "I"},
                            ],
                            value=src_type,
                        ),
                        html.Br(),
                        html.H4(
                            "Measure mode",
                            title="Choose if you want to do single measurement"
                            " or to start a sweep",
                        ),
                        dcc.RadioItems(
                            id="mode-choice",
                            options=[
                                {"label": "Single measure", "value": "single"},
                                {"label": "Sweep", "value": "sweep"},
                            ],
                            value=mode_val,
                        ),
                        html.Br(),
                        html.Div(
                            daq.StopButton(
                                id="clear-graph_btn", buttonText="Clear graph", size=150
                            ),
                            style={
                                "alignItems": "center",
                                "display": "flex",
                                "flex-direction": "row",
                            },
                        ),
                        html.Br(),
                        daq.Indicator(
                            id="clear-graph_ind", value=False, style={"display": "none"}
                        ),
                    ],
                ),
                # Sourcing controls
                html.Div(
                    id="source-div",
                    className="three columns",
                    children=[
                        # To perform single measures adjusting the source with
                        # a knob
                        html.Div(
                            id="single_div",
                            children=[
                                daq.Knob(
                                    id="source-knob",
                                    value=0.00,
                                    min=0,
                                    max=source_max,
                                    label="%s (%s)" % (source_label, source_unit),
                                ),
                                daq.LEDDisplay(
                                    id="source-knob-display",
                                    label="Knob readout",
                                    value=0.00,
                                ),
                            ],
                            style=single_style,
                        ),
                        # To perfom automatic sweeps of the source
                        html.Div(
                            id="sweep_div",
                            children=[
                                html.Div(
                                    id="sweep-title",
                                    children=html.H4("%s sweep:" % source_label),
                                ),
                                html.Div(
                                    [
                                        "Start",
                                        html.Br(),
                                        daq.PrecisionInput(
                                            id="sweep-start",
                                            precision=4,
                                            min=0,
                                            max=source_max,
                                            label=" %s" % source_unit,
                                            labelPosition="right",
                                            value=1,
                                            style={"margin": "5px"},
                                        ),
                                    ],
                                    title="The lowest value of the sweep",
                                    style=h_style,
                                ),
                                html.Div(
                                    [
                                        "Stop",
                                        daq.PrecisionInput(
                                            id="sweep-stop",
                                            precision=4,
                                            min=0,
                                            max=source_max,
                                            label=" %s" % source_unit,
                                            labelPosition="right",
                                            value=9,
                                            style={"margin": "5px"},
                                        ),
                                    ],
                                    title="The highest value of the sweep",
                                    style=h_style,
                                ),
                                html.Div(
                                    [
                                        "Step",
                                        daq.PrecisionInput(
                                            id="sweep-step",
                                            precision=4,
                                            min=0,
                                            max=source_max,
                                            label=" %s" % source_unit,
                                            labelPosition="right",
                                            value=source_max / 20.0,
                                            style={"margin": "5px"},
                                        ),
                                    ],
                                    title="The increment of the sweep",
                                    style=h_style,
                                ),
                                html.Div(
                                    [
                                        "Time of a step",
                                        daq.NumericInput(
                                            id="sweep-dt",
                                            value=0.5,
                                            min=0.1,
                                            style={"margin": "5px"},
                                        ),
                                        "s",
                                    ],
                                    title="The time spent on each increment",
                                    style=h_style,
                                ),
                                html.Div(
                                    [
                                        daq.Indicator(
                                            id="sweep-status",
                                            label="Sweep active",
                                            value=False,
                                        )
                                    ],
                                    title="Indicates if the sweep is running",
                                    style=h_style,
                                ),
                            ],
                            style=sweep_style,
                        ),
                    ],
                ),
                # measure button and indicator
                html.Div(
                    id="trigger_div",
                    className="two columns",
                    children=[
                        daq.StopButton(
                            id="trigger-measure_btn", buttonText=label_btn, size=150
                        ),
                        daq.Indicator(
                            id="measure-triggered", value=False, label="Measure active"
                        ),
                    ],
                ),
                # Display the sourced and measured values
                html.Div(
                    id="measure_div",
                    className="five columns",
                    children=[
                        daq.LEDDisplay(
                            id="source-display",
                            label="Applied %s (%s)" % (source_label, source_unit),
                            value="0.0000",
                        ),
                        daq.LEDDisplay(
                            id="measure-display",
                            label="Measured %s (%s)" % (measure_label, measure_unit),
                            value="0.0000",
                        ),
                    ],
                ),
            ],
            style={
                # "width": "100%",
                "flexDirection": "column",
                "alignItems": "center",
                "justifyContent": "space-between",
            },
        ),
        html.Div(
            children=[
                html.Div(
                    children=dcc.Markdown(
                        """
**What is this app about?**

This is an app to show the graphic elements of Dash DAQ used to create an
interface for an IV curve tracer using a Keithley 2400 SourceMeter. This mock
demo does not actually connect to a physical instrument the values displayed
are generated from an IV curve model for demonstration purposes.

**How to use the app**

First choose if you want to source (apply) current or voltage, using the radio
item located on the right of the graph area. Then choose if you want to operate
in a single measurement mode or in a sweep mode.

***Single measurement mode***

Adjust the value of the source with the knob at the bottom of the graph area
and click on the `SINGLE MEASURE` button, the measured value will be displayed.
Repetition of this procedure for different source values will reveal the full
IV curve.

***Sweep mode***

Set the sweep parameters `start`, `stop` and `step` as well as the time
spent on each step, then click on the button `START SWEEP`, the result of the
sweep will be displayed on the graph.

The data is never erased unless the button `CLEAR GRAPH is pressed` or if the
source type is changed.

You can purchase the Dash DAQ components at [
dashdaq.io](https://www.dashdaq.io/)
                    """
                    ),
                    style={
                        "margin": "20px",
                        "padding": "50px",
                        "alignItems": "left",
                        "border": "1px solid #DFE8F3",
                        "color": text_color[theme],
                        "background": bkg_color[theme],
                    },
                )
            ]
        ),
    ]

    if theme == "dark":
        return daq.DarkThemeProvider(children=html_layout)
    elif theme == "light":
        return html_layout

root_layout = html.Div(
    id="main_page",
    children=[
        dcc.Location(id="url", refresh=False),
        dcc.Interval(id="refresher", interval=1000000),
        html.Div(
            id="header",
            className="banner",
            children=[
                html.H2("Dash DAQ: IV curve tracer", style={"margin-left": "25px"}),
                daq.ToggleSwitch(
                    id="toggleTheme",
                    label="Dark/Light layout",
                    size=30,
                    style={"display": "none"},
                ),
                html.Img(
                    src=app.get_asset_url("dash-logo.png"),
                    className="logo",
                    style={"margin-right": "25px"},
                ),
            ],
            style={
                "width": "100%",
                "display": "flex",
                "flexDirection": "row",
                "alignItems": "center",
                "justifyContent": "space-between",
                "background": "#A2B1C6",
                "color": "#506784",
            },
        ),
        html.Div(
            id="page-content",
            children=generate_main_layout(),
            # className='ten columns',
            style={"width": "100%"},
        ),
    ],
    style={"background-color": "rgb(243, 246, 250)"},
)

# Create app layout
app.layout = root_layout

# ======= Dark/light themes callbacks =======
@app.callback(
    Output("page-content", "children"),
    [Input("toggleTheme", "value")],
    [
        State("source-choice", "value"),
        State("mode-choice", "value"),
        State("IV_graph", "figure"),
    ],
)
def page_layout(value, src_type, mode_val, fig):
    """update the theme of the daq components"""

    if value:
        return generate_main_layout("dark", src_type, mode_val, fig)
    else:
        return generate_main_layout("light", src_type, mode_val, fig)

@app.callback(
    Output("page-content", "style"),
    [Input("toggleTheme", "value")],
    [State("page-content", "style")],
)
def page_style(value, style_dict):
    """update the theme of the app"""
    if value:
        theme = "dark"
    else:
        theme = "light"

    style_dict["color"] = text_color[theme]
    style_dict["background"] = bkg_color[theme]
    return style_dict

# ======= Power on/off toggle callbacks =======
@app.callback(
    Output("instr_port_button", "disabled"),
    [Input("power_button", "on"), Input("instr_port_input", "value")],
    [State("instr_port_input", "value"), State("instr_port_input", "placeholder")],
)
def instrument_port_btn_update(pwr_status, _, text, placeholder):
    """enable or disable the connect button
    depending on the port name
    """
    answer = True

    if text != placeholder:
        if is_instrument_port(text):
            answer = not pwr_status
    return answer

@app.callback(
    Output("instr_status_div", "children"),
    [Input("instr_port_button", "n_clicks")],
    [State("instr_port_input", "value")],
)
def instrument_port_btn_click(_, text):
    """reconnect the instrument to the new com port"""
    iv_generator.connect(text)
    print(iv_generator.ask("*IDN?"))
    return str(iv_generator.ask("*IDN?"))

def automatic_grey_out_callback(div_id, app):
    """generate a callback for the gauges which number can vary from instrument
        to instrument.
    """

    @app.callback(
        Output(div_id, "style"), [Input("power_button", "on")], [State(div_id, "style")]
    )
    def grey_out(pwr_status, style_dict):
        if style_dict is None:
            answer = {}
        else:
            answer = style_dict
        if pwr_status:
            answer["opacity"] = 1
        else:
            answer["opacity"] = 0.3
        return answer

    grey_out.__name__ = "grey_out_%s" % div_id

    return grey_out

for div_id in [
    "IV_graph_div",
    "IV-options_div",
    "measure_controls_div",
    "measure_div",
    "trigger_div",
]:
    automatic_grey_out_callback(div_id, app)

def automatic_enable_callback(div_id, app):
    """generate a callback for the gauges which number can vary from instrument
        to instrument.
    """

    @app.callback(Output(div_id, "disabled"), [Input("power_button", "on")])
    def enable(pwr_status):
        return not pwr_status

    enable.__name__ = "enable_%s" % div_id

    return enable

for div_id in ["clear-graph_btn", "trigger-measure_btn", "source-knob"]:
    automatic_enable_callback(div_id, app)

# ======= Callbacks for changing labels =======
@app.callback(
    Output("source-knob", "label"),
    [Input("source-choice", "value"), Input("mode-choice", "value")],
)
def source_knob_label(src_type, _):
    """update label upon modification of Radio Items"""
    source_label, measure_label = get_source_labels(src_type)
    return source_label

@app.callback(
    Output("source-knob-display", "label"),
    [Input("source-choice", "value"), Input("mode-choice", "value")],
)
def source_knob_display_label(scr_type, _):
    """update label upon modification of Radio Items"""
    source_label, measure_label = get_source_labels(scr_type)
    source_unit, measure_unit = get_source_units(scr_type)
    return "Value : %s (%s)" % (source_label, source_unit)

@app.callback(
    Output("sweep-start", "label"),
    [Input("source-choice", "value"), Input("mode-choice", "value")],
)
def sweep_start_label(src_type, _):
    """update label upon modification of Radio Items"""
    source_unit, measure_unit = get_source_units(src_type)
    return "(%s)" % source_unit

@app.callback(
    Output("sweep-stop", "label"),
    [Input("source-choice", "value"), Input("mode-choice", "value")],
)
def sweep_stop_label(src_type, _):
    """update label upon modification of Radio Items"""
    source_unit, measure_unit = get_source_units(src_type)
    return "(%s)" % source_unit

@app.callback(
    Output("sweep-step", "label"),
    [Input("source-choice", "value"), Input("mode-choice", "value")],
)
def sweep_step_label(src_type, _):
    """update label upon modification of Radio Items"""
    source_unit, measure_unit = get_source_units(src_type)
    return "(%s)" % source_unit

@app.callback(
    Output("sweep-title", "children"),
    [Input("source-choice", "value"), Input("mode-choice", "value")],
)
def sweep_title_label(src_type, _):
    """update label upon modification of Radio Items"""
    source_label, measure_label = get_source_labels(src_type)
    return html.H4("%s sweep:" % source_label)

@app.callback(
    Output("source-display", "label"),
    [Input("source-choice", "value"), Input("mode-choice", "value")],
)
def source_display_label(src_type, _):
    """update label upon modification of Radio Items"""
    source_label, measure_label = get_source_labels(src_type)
    source_unit, measure_unit = get_source_units(src_type)
    return "Applied %s (%s)" % (source_label, source_unit)

@app.callback(
    Output("measure-display", "label"),
    [Input("source-choice", "value"), Input("mode-choice", "value")],
)
def measure_display_label(src_type, _):
    """update label upon modification of Radio Items"""
    source_label, measure_label = get_source_labels(src_type)
    source_unit, measure_unit = get_source_units(src_type)
    return "Measured %s (%s)" % (measure_label, measure_unit)

# ======= Callbacks to change elements in the layout =======
@app.callback(Output("single_div", "style"), [Input("mode-choice", "value")])
def single_div_toggle_style(mode_val):
    """toggle the layout for single measure"""
    if mode_val == "single":
        return {"display": "flex", "flex-direction": "column", "alignItems": "center"}
    else:
        return {"display": "none"}

@app.callback(Output("sweep_div", "style"), [Input("mode-choice", "value")])
def sweep_div_toggle_style(mode_val):
    """toggle the layout for sweep"""
    if mode_val == "single":
        return {"display": "none"}
    else:
        return {"display": "flex", "flex-direction": "column", "alignItems": "center"}

@app.callback(Output("source-knob", "max"), [Input("source-choice", "value")])
def source_knob_max(src_type):
    """update max value upon changing source type"""
    return get_source_max(src_type)

@app.callback(Output("sweep-start", "max"), [Input("source-choice", "value")])
def sweep_start_max(src_type):
    """update max value upon changing source type"""
    return get_source_max(src_type)

@app.callback(Output("sweep-stop", "max"), [Input("source-choice", "value")])
def sweep_stop_max(src_type):
    """update max value upon changing source type"""
    return get_source_max(src_type)

@app.callback(Output("sweep-step", "max"), [Input("source-choice", "value")])
def sweep_step_max(src_type):
    """update max value upon changing source type"""
    return get_source_max(src_type)

@app.callback(
    Output("trigger-measure_btn", "buttonText"),
    [Input("measure-triggered", "value"), Input("mode-choice", "value")],
    [State("trigger-measure_btn", "buttonText")],
)
def toggle_trigger_measure_button_label(measure_triggered, mode_val, btn_text):
    """change the label of the trigger button"""

    if mode_val == "single":
        return "Single measure"
    else:
        if measure_triggered:
            if btn_text == "Start sweep":
                return "Stop sweep"
            else:
                return "Start sweep"
        else:
            return "Start sweep"

# ======= Applied/measured values display =======
@app.callback(
    Output("source-knob", "value"),
    [Input("source-choice", "value")],
    [State("source-knob", "value")],
)
def source_change(src_type, src_val):
    """modification upon source-change
    change the source type in local_vars
    reset the knob to zero
    reset the measured values on the graph
    """
    if src_type == local_vars.source:
        local_vars.is_source_being_changed = False
        return src_val
    else:
        local_vars.is_source_being_changed = True
        local_vars.source = src_type
        return 0.00

# ======= Interval callbacks =======
@app.callback(
    Output("refresher", "interval"),
    [Input("sweep-status", "value")],
    [State("mode-choice", "value"), State("sweep-dt", "value")],
)
def interval_toggle(swp_on, mode_val, dt):
    """change the interval to high frequency for sweep"""
    if dt <= 0:
        # Precaution against the user
        dt = 0.5
    if mode_val == "single":
        return 1000000
    else:
        if swp_on:
            return dt * 1000
        else:
            return 1000000

@app.callback(
    Output("refresher", "n_intervals"),
    [Input("trigger-measure_btn", "n_clicks"), Input("mode-choice", "value")],
    [State("sweep-status", "value"), State("refresher", "n_intervals")],
)
def reset_interval(_, mode_val, swp_on, n_interval):
    """reset the n_interval of the dcc.Interval once a sweep is done"""
    if mode_val == "single":
        local_vars.reset_interval()
        return 0
    else:
        if swp_on:
            return n_interval
        else:
            local_vars.reset_interval()
            return 0

@app.callback(
    Output("sweep-status", "value"),
    [Input("trigger-measure_btn", "n_clicks"), Input("source-display", "value")],
    [
        State("trigger-measure_btn", "buttonText"),
        State("measure-triggered", "value"),
        State("sweep-status", "value"),
        State("sweep-stop", "value"),
        State("sweep-step", "value"),
        State("mode-choice", "value"),
    ],
)
def sweep_activation_toggle(
    n_clicks, sourced_val, trig_button_text, _, swp_on, swp_stop, swp_step, mode_val
):
    """decide whether to turn on or off the sweep
    when single mode is selected, it is off by default
    when sweep mode is selected, it enables the sweep if is wasn't on
    otherwise it stops the sweep once the sourced value gets higher or equal
    than the sweep limit minus the sweep step
    """
    if mode_val == "single":
        return False
    else:
        if swp_on:
            # The condition of continuation is to source lower than the sweep
            # limit minus one sweep step
            answer = float(sourced_val) <= float(swp_stop) - float(swp_step)
            print("sweep on")
            print(answer)

            if trig_button_text == "Start sweep":
                # the button was clicked on and is back to Start sweep
                return False
            else:
                # the button wasn't clicked on
                return answer
        else:
            if trig_button_text == "Start sweep":
                # The 'trigger-measure_btn' wasn't pressed yet
                print("sweep not on, not considering")
                return False
            else:
                # Initiate a sweep
                print("sweep not on, initiating")
                return True

# ======= Measurements callbacks =======
@app.callback(Output("source-knob-display", "value"), [Input("source-knob", "value")])
def set_source_knob_display(knob_val):
    """"set the value of the knob on a LED display"""
    return knob_val

@app.callback(
    Output("measure-triggered", "value"),
    [Input("trigger-measure_btn", "n_clicks"), Input("mode-choice", "value")],
    [State("sweep-status", "value")],
)
def update_trigger_measure(nclick, mode_val, _):
    """ Controls if a measure can be made or not
    The indicator 'measure-triggered' can be set to True only by a click
    on the 'trigger-measure_btn' button or by the 'refresher' interval
    """

    if nclick is None:
        nclick = 0

    if int(nclick) != local_vars.n_clicks:
        # It was triggered by a click on the trigger-measure_btn button
        local_vars.change_n_clicks(int(nclick))
        return True
    else:
        if mode_val == "single":
            # It was triggered by a change of the mode
            return False

@app.callback(
    Output("source-display", "value"),
    [Input("refresher", "n_intervals"), Input("measure-triggered", "value")],
    [
        State("source-knob", "value"),
        State("source-display", "value"),
        State("sweep-start", "value"),
        State("sweep-stop", "value"),
        State("sweep-step", "value"),
        State("mode-choice", "value"),
        State("sweep-status", "value"),
    ],
)
def set_source_display(
    n_interval,
    meas_triggered,
    knob_val,
    old_source_display_val,
    swp_start,
    swp_stop,
    swp_step,
    mode_val,
    swp_on,
):
    """"set the source value to the instrument"""
    if mode_val == "single":
        return knob_val
    else:
        if meas_triggered:
            if swp_on:
                answer = float(swp_start) + (int(n_interval) - 1) * float(swp_step)
                if answer > float(swp_stop):
                    return old_source_display_val
                else:
                    return answer
            else:
                return old_source_display_val
        else:
            return old_source_display_val

@app.callback(
    Output("measure-display", "value"),
    [Input("source-display", "value")],
    [
        State("measure-triggered", "value"),
        State("measure-display", "value"),
        State("source-choice", "value"),
        State("mode-choice", "value"),
        State("sweep-status", "value"),
    ],
)
def update_measure_display(
    src_val, meas_triggered, meas_old_val, src_type, mode_val, swp_on
):
    """"read the measured value from the instrument
    check if a measure should be made
    initiate a measure of the KT2400
    read the measure value and return it
    by default it simply return the value previously available
    """
    source_value = float(src_val)
    measured_value = meas_old_val

    if mode_val == "single":
        if meas_triggered:
            # Save the sourced value
            local_vars.sourced_values.append(source_value)
            # Initiate a measurement
            measured_value = iv_generator.source_and_measure(src_type, src_val)
            # Save the measured value
            local_vars.measured_values.append(measured_value)
    else:
        if meas_triggered and swp_on:
            # Save the sourced value
            local_vars.sourced_values.append(source_value)
            # Initiate a measurement
            measured_value = iv_generator.source_and_measure(src_type, src_val)
            # Save the measured value
            local_vars.measured_values.append(measured_value)

    return measured_value

# ======= Graph related callbacks =======
@app.callback(
    Output("clear-graph_ind", "value"),
    [
        Input("source-knob", "value"),
        Input("clear-graph_btn", "n_clicks"),
        Input("measure-triggered", "value"),
    ],
)
def clear_graph_click(src_val, nclick, meas_triggered):
    """clear the data on the graph
    Uses the callback of the knob value triggered by source-choice change
    or the click on the clear-graph_btn
    everytime a measure is initiated, this value is reset to False, this
    is why we need the input of measure_triggered
    """
    if nclick is None:
        nclick = 0

    if local_vars.is_source_being_changed:
        # The callback was triggered by a source change
        local_vars.is_source_being_changed = False
        local_vars.clear_graph()
        return True
    else:
        if int(nclick) != local_vars.n_clicks_clear_graph:
            # It was triggered by a click on the clear-graph_btn button
            local_vars.change_n_clicks_clear_graph(int(nclick))
            # Reset the data
            local_vars.clear_graph()
            return True
        else:
            return False

@app.callback(
    Output("IV_graph", "figure"),
    [Input("measure-display", "value"), Input("clear-graph_ind", "value")],
    [
        State("toggleTheme", "value"),
        State("measure-triggered", "value"),
        State("IV_graph", "figure"),
        State("source-choice", "value"),
        State("mode-choice", "value"),
        State("sweep-status", "value"),
    ],
)
def update_graph(
    measured_val,
    clear_graph,  # Had to do this because of the lack of multiple Outputs
    theme,
    meas_triggered,
    graph_data,
    src_type,
    mode_val,
    swp_on,
):
    """"update the IV graph"""
    if theme:
        theme = "dark"
    else:
        theme = "light"

    # Labels for sourced and measured quantities
    source_label, measure_label = get_source_labels(src_type)
    source_unit, measure_unit = get_source_units(src_type)

    if mode_val == "single":
        if meas_triggered:
            # The change to the graph was triggered by a measure

            # Sort the stored data so the are ascending in x
            data_array = local_vars.sorted_values()

            xdata = data_array[0, :]
            ydata = data_array[1, :]

            data_for_graph = [
                go.Scatter(
                    x=xdata,
                    y=ydata,
                    mode="lines+markers",
                    name="IV curve",
                    line={"color": "#EF553B", "width": 2},
                )
            ]

            return {
                "data": data_for_graph,
                "layout": dict(
                    xaxis={
                        "title": "Applied %s (%s)" % (source_label, source_unit),
                        "color": text_color[theme],
                        "gridcolor": grid_color[theme],
                    },
                    yaxis={
                        "title": "Measured %s (%s)" % (measure_label, measure_unit),
                        "gridcolor": grid_color[theme],
                    },
                    font=dict(color=text_color[theme], size=15),
                    margin={"l": 100, "b": 100, "t": 50, "r": 20, "pad": 0},
                    plot_bgcolor=bkg_color[theme],
                    paper_bgcolor=bkg_color[theme],
                ),
            }
        else:
            if clear_graph:
                graph_data["data"] = local_vars.sorted_values()
            return graph_data
    else:
        if swp_on:
            # The change to the graph was triggered by a measure

            # Sort the stored data so the are ascending in x
            data_array = local_vars.sorted_values()

            xdata = data_array[0, :]
            ydata = data_array[1, :]

            data_for_graph = [
                go.Scatter(
                    x=xdata,
                    y=ydata,
                    mode="lines+markers",
                    name="IV curve",
                    line={"color": "#EF553B", "width": 2},
                )
            ]

            return {
                "data": data_for_graph,
                "layout": dict(
                    xaxis={
                        "title": "Applied %s (%s)" % (source_label, source_unit),
                        "color": text_color[theme],
                        "gridcolor": grid_color[theme],
                    },
                    yaxis={
                        "title": "Measured %s (%s)" % (measure_label, measure_unit),
                        "gridcolor": grid_color[theme],
                    },
                    font=dict(color=text_color[theme], size=15),
                    margin={"l": 100, "b": 100, "t": 50, "r": 20, "pad": 0},
                    plot_bgcolor=bkg_color[theme],
                    paper_bgcolor=bkg_color[theme],
                ),
            }
        else:
            if clear_graph:
                graph_data["data"] = local_vars.sorted_values()
            return graph_data

if __name__ == "__main__":
    app.run_server(debug=False)


import os
import re
import glob
import uuid
import sys
import time

try:
    import pip
except ImportError:
    pip = None

from . import fs_tracker
from .util import shquote

class Experiment(object):
    """Experiment information."""

    def __init__(self, key, filename, args, pythonenv,
                 project=None,
                 artifacts=None,
                 status='waiting',
                 resources_needed=None,
                 time_added=None,
                 time_started=None,
                 time_last_checkpoint=None,
                 time_finished=None,
                 info={},
                 git=None,
                 metric=None,
                 pythonver=None,
                 max_duration=None):

        self.key = key
        self.args = []
        self.filename = filename

        if filename and '::' in filename:
            self.filename = '-m'
            module_name = filename.replace('::', '.')
            if module_name.startswith('.'):
                module_name = module_name[1:]

            self.args.append(module_name)

        if args:
            self.args += args

        self.args = [shquote(a) for a in self.args]

        self.pythonenv = pythonenv
        self.project = project
        self.pythonver = pythonver if pythonver else sys.version_info[0]

        workspace_path = os.path.abspath('.')
        try:
            model_dir = fs_tracker.get_model_directory(key)
        except BaseException:
            model_dir = None

        self.artifacts = {
            'workspace': {
                'local': workspace_path,
                'mutable': False,
                'unpack': True
            },
            'modeldir': {
                'local': model_dir,
                'mutable': True,
                'unpack': True
            },
            'output': {
                'local': fs_tracker.get_artifact_cache('output', key),
                'mutable': True,
                'unpack': True
            },
            'tb': {
                'local': fs_tracker.get_tensorboard_dir(key),
                'mutable': True,
                'unpack': True
            },
            '_metrics': {
                'local': fs_tracker.get_artifact_cache('_metrics', key),
                'mutable': True,
                'unpack': True
            }
        }
        if artifacts is not None:
            self.artifacts.update(artifacts)

        self.resources_needed = resources_needed
        self.status = status
        self.time_added = time_added
        self.time_started = time_started
        self.time_last_checkpoint = time_last_checkpoint
        self.time_finished = time_finished
        self.info = info
        self.git = git
        self.metric = metric
        self.max_duration = max_duration

    def get_model(self, db):
        modeldir = db.get_artifact(self.artifacts['modeldir'])
        hdf5_files = [
            (p, os.path.getmtime(p))
            for p in
            glob.glob(modeldir + '/*.hdf*') +
            glob.glob(modeldir + '/*.h5')]
        if any(hdf5_files):
            # experiment type - keras
            import keras
            last_checkpoint = max(hdf5_files, key=lambda t: t[1])[0]
            return keras.models.load_model(last_checkpoint)

        if self.info.get('type') == 'tensorflow':
            raise NotImplementedError

        raise ValueError("Experiment type is unknown!")

def create_experiment(
        filename,
        args,
        experiment_name=None,
        project=None,
        artifacts={},
        resources_needed=None,
        metric=None,
        max_duration=None):
    key = experiment_name if experiment_name else \
        str(int(time.time())) + "_" + str(uuid.uuid4())

    packages = []
    for pkg in pip.operations.freeze.freeze():

        if pkg.startswith('-e git+'):
            # git package
            packages.append(pkg)
        elif '==' in pkg:
            # pypi package
            pkey = re.search(r'^.*?(?=\=\=)', pkg).group(0)
            pversion = re.search(r'(?<=\=\=).*\Z', pkg).group(0)

            if resources_needed is not None and \
                    int(resources_needed.get('gpus')) > 0:
                if (pkey == 'tensorflow' or key == 'tf-nightly'):
                    pkey = pkey + '-gpu'

            # TODO add installation logic for torch
            packages.append(pkey + '==' + pversion)

    return Experiment(
        key=key,
        filename=filename,
        args=args,
        pythonenv=[p for p in packages],
        project=project,
        artifacts=artifacts,
        resources_needed=resources_needed,
        metric=metric,
        max_duration=max_duration)

def experiment_from_dict(data, info={}):
    try:
        return Experiment(
            key=data['key'],
            filename=data['filename'],
            args=data.get('args'),
            pythonenv=data['pythonenv'],
            project=data.get('project'),
            status=data['status'],
            artifacts=data.get('artifacts'),
            resources_needed=data.get('resources_needed'),
            time_added=data['time_added'],
            time_started=data.get('time_started'),
            time_last_checkpoint=data.get('time_last_checkpoint'),
            time_finished=data.get('time_finished'),
            info=info if any(info) else data.get('info'),
            git=data.get('git'),
            metric=data.get('metric'),
            pythonver=data.get('pythonver'),
            max_duration=data.get('max_duration')
        )
    except KeyError as e:
        self.logger.error(data)
        raise e


import os
import errno
import logging
import numbers
import warnings
from inspect import cleandoc
from collections import OrderedDict

import numpy as np
import h5py
from atom.api import Str, Enum, Value, Bool, Dict, Int, Typed, List, set_default

from exopy.tasks.api import SimpleTask, RootTask, validators
from exopy.tasks.tasks.logic.loop_task import LoopTask
from exopy.utils.atom_util import ordered_dict_from_pref, ordered_dict_to_pref
from exopy.utils.traceback import format_exc

logger = logging.getLogger(__name__)

class SmartSaveTask(SimpleTask):
    """Save the specified data in a HDF5 file.

    Try to detect if it is placed inside of nested loops and reshape
    the data accordingly.

    """
    #: Folder in which to save the data.
    folder = Str('{default_path}').tag(pref=True, fmt=True)

    #: Name of the file in which to write the data.
    filename = Str().tag(pref=True, fmt=True)

    #: Currently opened file object. (File mode)
    file_object = Value()

    #: Header to write at the top of the file.
    header = Str().tag(pref=True, fmt=True)

    #: Values to save as an ordered dictionary.
    saved_values = Typed(OrderedDict, ()).tag(pref=(ordered_dict_to_pref,
                                                    ordered_dict_from_pref))

    #: Parameters to save
    saved_parameters = Typed(OrderedDict, ()).tag(pref=(ordered_dict_to_pref,
                                                        ordered_dict_from_pref))

    #: Data type (float16, float32, etc.)
    datatype = Enum('float16', 'float32', 'float64').tag(pref=True)

    #: Flag indicating whether or not initialisation has been performed.
    initialized = Bool(False)

    database_entries = set_default({'file': None})

    wait = set_default({'activated': True})  # Wait on all pools by default.

    def perform(self):
        """ Collect all data and write them to file.

        """
        # Initialisation.
        if not self.initialized:
            for name, path in self._loop_paths.items():
                self._dims.append(self.database.get_value(path, f"{name}_point_number"))
            self._dims.reverse()

            self._formatted_labels = []

            full_folder_path = self.format_string(self.folder)
            filename = self.format_string(self.filename)
            full_path = os.path.join(full_folder_path, filename)
            try:
                self.file_object = h5py.File(full_path, 'w', libver='latest')
            except IOError:
                log = logging.getLogger()
                msg = "In {}, failed to open the specified file."
                log.exception(msg.format(self.name))
                self.root.should_stop.set()

            self.root.resources['files'][full_path] = self.file_object

            f = self.file_object

            parameters_group = f.create_group("parameters")
            for l, v in self.saved_parameters.items():
                label = self.format_string(l)
                value = self.format_and_eval_string(v)
                parameters_group.create_dataset(label, data=value)

            data_group = f.create_group("data")
            for l, v in self.saved_values.items():
                label = self.format_string(l)
                self._formatted_labels.append(label)
                value = self.format_and_eval_string(v)
                if isinstance(value, np.ndarray):
                    names = value.dtype.names
                    if names:
                        for m in names:
                            data_shape = tuple(self._dims) + value[m].shape
                            data_group.create_dataset(label + '_' + m,
                                             data_shape,
                                             self.datatype)
                    else:
                        data_shape = tuple(self._dims) + value.shape
                        data_group.create_dataset(label,
                                         data_shape,
                                         self.datatype)
                else:
                    data_shape = tuple(self._dims)
                    data_group.create_dataset(label, data_shape,
                                     self.datatype)
            f.attrs['header'] = self.format_string(self.header)
            f.attrs['count_calls'] = 0
            f.swmr_mode = True

            self.initialized = True

        f = self.file_object
        count_calls = f.attrs['count_calls']

        labels = self._formatted_labels
        for i, v in enumerate(self.saved_values.values()):
            value = self.format_and_eval_string(v)
            index = np.unravel_index(count_calls, self._dims)
            if isinstance(value, np.ndarray) and value.dtype.names:
                for m in value.dtype.names:
                    f['data'][labels[i] + '_' + m][index] = value[m]
            else:
                expected_size = f['data'][labels[i]][index].size
                if isinstance(value, np.ndarray) and value.size != expected_size:
                    logger.warning("Incorrect data size. Attempting to resize the data")
                    value = np.copy(value)
                    value.resize(f['data'][labels[i]][index].shape)
                f['data'][labels[i]][index] = value

        f.attrs['count_calls'] = count_calls + 1
        f.flush()

    def check(self, *args, **kwargs):
        """Check that all the parameters are correct.

        """
        self.detect_loops(update_names=False)

        err_path = self.get_error_path()
        test, traceback = super(SmartSaveTask, self).check(*args, **kwargs)
        try:
            full_folder_path = self.format_string(self.folder)
            filename = self.format_string(self.filename)
        except Exception:
            return test, traceback

        full_path = os.path.join(full_folder_path, filename)

        overwrite = False
        if os.path.isfile(full_path):
            overwrite = True
            traceback[err_path + '-file'] = \
                cleandoc('''File already exists, running the measure will
                override it.''')

        try:
            f = open(full_path, 'ab')
            f.close()
            if not overwrite:
                os.remove(full_path)
        except Exception as e:
            mess = 'Failed to open the specified file : {}'.format(e)
            traceback[err_path] = mess.format(e)
            return False, traceback

        labels = set()
        for i, (l, v) in enumerate(self.saved_values.items()):
            try:
                labels.add(self.format_string(l))
            except Exception:
                traceback[err_path + '-label_' + str(i)] = \
                    'Failed to evaluate label {}:\n{}'.format(l, format_exc())
                test = False
            try:
                self.format_and_eval_string(v)
            except Exception:
                traceback[err_path + '-entry_' + str(i)] = \
                    'Failed to evaluate entry {}:\n{}'.format(v, format_exc())
                test = False

        if len(labels) != len(self.saved_values):
            traceback[err_path] = "All labels must be different."
            return False, traceback

        labels = set()
        for i, (l, v) in enumerate(self.saved_parameters.items()):
            try:
                labels.add(self.format_string(l))
            except Exception:
                traceback[err_path + '-label_' + str(i)] = \
                    'Failed to evaluate label {}:\n{}'.format(l, format_exc())
                test = False
            try:
                self.format_and_eval_string(v)
            except Exception:
                traceback[err_path + '-entry_' + str(i)] = \
                    'Failed to evaluate entry {}:\n{}'.format(v, format_exc())
                test = False

        if not test:
            return test, traceback

        if len(labels) != len(self.saved_parameters):
            traceback[err_path] = "All labels must be different."
            return False, traceback

        return test, traceback

    def detect_loops(self, update_names=True):
        n = self.parent
        tmp_names = []
        tmp_paths = OrderedDict()
        while not isinstance(n, RootTask):
            if isinstance(n, LoopTask):
                if n.name not in self.saved_parameters:
                    tmp_names.append((n.name, f"{{{n.name}_loop_values}}"))
                else:
                    tmp_names.append((n.name, self.saved_parameters[n.name]))
                tmp_paths[n.name] = n.path
            n = n.parent
        # Only refresh the names if the number of nested loops has changed
        if update_names and len(tmp_names) != len(self.saved_parameters):
            self.saved_parameters = OrderedDict(tmp_names)
        self._loop_paths = OrderedDict(tmp_paths)

    #: List of the formatted names of the entries.
    _formatted_labels = List()

    #: List of the paths of the loops
    _loop_paths = Typed(OrderedDict, ())

    #: Data dimensions:
    _dims = List()


from .base import FunctionalTest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

class NewVisitorTest(FunctionalTest):

    def test_can_start_a_list_for_one_user(self):
        # User searches out new to-do app via its homepage
        self.browser.get(self.live_server_url)

        # User notices page title and header mention to-do lists
        self.browser.quit()
        self.browser = webdriver.Firefox()
        self.browser.get(self.live_server_url)
        self.assertIn('To-Do', self.browser.title)
        header_text = self.browser.find_element_by_tag_name('h1').text
        self.assertIn('To-Do', header_text)

        # User is invited to enter a to-do list item immediately
        inputbox = self.get_item_input_box()
        self.assertEqual(
            inputbox.get_attribute('placeholder'),
            'Enter a to-do item'
        )

        # User types "Buy guitar strings" into a text box
        # When user hits enter, page updates, now page lists
        # "1: Buy guitar strings" as an item in a to-do list
        self.add_list_item('Buy guitar strings')

        # There is still a text box inviting her to add another item.
        # User enters "Re-string guitar"
        self.add_list_item('Re-string guitar')

        # The page updates again - both items are now on the list
        self.wait_for_row_in_list_table('1: Buy guitar strings')
        self.wait_for_row_in_list_table('2: Re-string guitar')

        # Site has generated unique URL for user -- there is text explaining this
        # self.fail('Finish the test!')

        # User visits that URL - their to-do list is still there

        # Satisfied, they go on about their day

    def test_multiple_users_can_start_lists_at_different_urls(self):
        # Edith starts a new to-do list
        self.browser.get(self.live_server_url)
        inputbox = self.get_item_input_box()
        self.add_list_item('Buy guitar strings')

        # Edith noticed that their list has a unique URL
        edith_list_url = self.browser.current_url
        self.assertRegex(edith_list_url, '/lists/.+')

        ## We use a new browser session to make sure that no info
        ## of Edith's is coming through from cookies, etc.
        self.browser.quit()
        self.browser = webdriver.Firefox()

        # Francis visits the home page. Cannot see Edith's list
        self.browser.get(self.live_server_url)
        page_text = self.browser.find_element_by_tag_name('body').text
        self.assertNotIn('Buy guitar strings', page_text)
        self.assertNotIn('Re-string guitar', page_text)

        # Francis starts a new list by entering a new item.
        inputbox = self.get_item_input_box()
        self.add_list_item('Buy milk')

        # Francis gets own unique URL
        francis_list_url = self.browser.current_url
        self.assertRegex(francis_list_url, '/lists/.+')
        self.assertNotEqual(francis_list_url, edith_list_url)

        # Again, no sign of Edith's list
        page_text = self.browser.find_element_by_tag_name('body').text
        self.assertNotIn('Buy guitar strings', page_text)
        self.assertIn('Buy milk', page_text)

        # Both satisfied - days carry on.


import numpy as np
import matplotlib.pyplot as plt

inp_signal = input('Enter binary bit: ')

time = np.array(list())
amplitude = np.array(list())
step = 0
Low_amplitude = 1
High_amplitude = 3

def getSignal(A,time):
    frequency = 2
    phase = 0
    return A*np.sin(2*np.pi*frequency*time+phase)

for i in inp_signal:
    temp_time = np.arange(step,step+2,0.001)
    time = np.append(time,temp_time)
    if i == '0':
        amplitude = np.append(amplitude,getSignal(Low_amplitude,temp_time))
    else:
        amplitude = np.append(amplitude,getSignal(High_amplitude,temp_time))
    step = step + 2

plt.title('ASK Representation of : '+inp_signal)

plt.plot(time,amplitude,color='red')
plt.grid(True)
plt.show()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

#
# SPDX-License-Identifier: GPL-3.0
#
# GNU Radio Python Flow Graph
# Title: AM Modulation (SSB)
# GNU Radio version: 3.10.3.0

from packaging.version import Version as StrictVersion

if __name__ == '__main__':
    import ctypes
    import sys
    if sys.platform.startswith('linux'):
        try:
            x11 = ctypes.cdll.LoadLibrary('libX11.so')
            x11.XInitThreads()
        except:
            print("Warning: failed to XInitThreads()")

from PyQt5 import Qt
from gnuradio import qtgui
from gnuradio.filter import firdes
import sip
from gnuradio import analog
from gnuradio import audio
from gnuradio import blocks
from gnuradio import filter
from gnuradio import gr
from gnuradio.fft import window
import sys
import signal
from argparse import ArgumentParser
from gnuradio.eng_arg import eng_float, intx
from gnuradio import eng_notation
from gnuradio import zeromq
from gnuradio.qtgui import Range, RangeWidget
from PyQt5 import QtCore

from gnuradio import qtgui

class ssb_transmitter(gr.top_block, Qt.QWidget):

    def __init__(self):
        gr.top_block.__init__(self, "AM Modulation (SSB)", catch_exceptions=True)
        Qt.QWidget.__init__(self)
        self.setWindowTitle("AM Modulation (SSB)")
        qtgui.util.check_set_qss()
        try:
            self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
        except:
            pass
        self.top_scroll_layout = Qt.QVBoxLayout()
        self.setLayout(self.top_scroll_layout)
        self.top_scroll = Qt.QScrollArea()
        self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
        self.top_scroll_layout.addWidget(self.top_scroll)
        self.top_scroll.setWidgetResizable(True)
        self.top_widget = Qt.QWidget()
        self.top_scroll.setWidget(self.top_widget)
        self.top_layout = Qt.QVBoxLayout(self.top_widget)
        self.top_grid_layout = Qt.QGridLayout()
        self.top_layout.addLayout(self.top_grid_layout)

        self.settings = Qt.QSettings("GNU Radio", "ssb_transmitter")

        try:
            if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
                self.restoreGeometry(self.settings.value("geometry").toByteArray())
            else:
                self.restoreGeometry(self.settings.value("geometry"))
        except:
            pass

        ##################################################
        # Variables
        ##################################################
        self.volume = volume = 10
        self.samp_rate = samp_rate = 192000
        self.interp = interp = 4
        self.carrier_freq = carrier_freq = 16000
        self.audio_rate = audio_rate = 48000

        ##################################################
        # Blocks
        ##################################################
        self._volume_range = Range(0, 20, 0.1, 10, 200)
        self._volume_win = RangeWidget(self._volume_range, self.set_volume, "Audio Gain", "counter_slider", float, QtCore.Qt.Horizontal)
        self.top_layout.addWidget(self._volume_win)
        self.zeromq_push_sink_0 = zeromq.push_sink(gr.sizeof_gr_complex, 1, 'tcp://127.0.0.1:50301', 100, False, (-1))
        self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c(
            2048, #size
            window.WIN_BLACKMAN_hARRIS, #wintype
            0, #fc
            samp_rate, #bw
            "", #name
            1,
            None # parent
        )
        self.qtgui_freq_sink_x_0.set_update_time(0.10)
        self.qtgui_freq_sink_x_0.set_y_axis((-140), 10)
        self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB')
        self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "")
        self.qtgui_freq_sink_x_0.enable_autoscale(False)
        self.qtgui_freq_sink_x_0.enable_grid(False)
        self.qtgui_freq_sink_x_0.set_fft_average(1.0)
        self.qtgui_freq_sink_x_0.enable_axis_labels(True)
        self.qtgui_freq_sink_x_0.enable_control_panel(False)
        self.qtgui_freq_sink_x_0.set_fft_window_normalized(False)

        labels = ['', '', '', '', '',
            '', '', '', '', '']
        widths = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]
        colors = ["blue", "red", "green", "black", "cyan",
            "magenta", "yellow", "dark red", "dark green", "dark blue"]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
            1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i))
            else:
                self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
            self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
            self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])

        self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.qwidget(), Qt.QWidget)
        self.top_layout.addWidget(self._qtgui_freq_sink_x_0_win)
        self.blocks_repeat_0 = blocks.repeat(gr.sizeof_float*1, interp)
        self.blocks_multiply_xx_0 = blocks.multiply_vcc(1)
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_ff(volume)
        self.blocks_float_to_complex_0 = blocks.float_to_complex(1)
        self.band_pass_filter_0 = filter.fir_filter_ccf(
            1,
            firdes.band_pass(
                1,
                samp_rate,
                16300,
                19000,
                200,
                window.WIN_HAMMING,
                6.76))
        self.audio_source_0 = audio.source(48000, '', True)
        self.analog_sig_source_x_0 = analog.sig_source_c(samp_rate, analog.GR_SIN_WAVE, carrier_freq, 1, 0, 0)
        self.analog_const_source_x_0 = analog.sig_source_f(0, analog.GR_CONST_WAVE, 0, 0, 0)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_const_source_x_0, 0), (self.blocks_float_to_complex_0, 0))
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_multiply_xx_0, 0))
        self.connect((self.audio_source_0, 0), (self.blocks_multiply_const_vxx_0, 0))
        self.connect((self.band_pass_filter_0, 0), (self.qtgui_freq_sink_x_0, 0))
        self.connect((self.band_pass_filter_0, 0), (self.zeromq_push_sink_0, 0))
        self.connect((self.blocks_float_to_complex_0, 0), (self.blocks_multiply_xx_0, 1))
        self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_repeat_0, 0))
        self.connect((self.blocks_multiply_xx_0, 0), (self.band_pass_filter_0, 0))
        self.connect((self.blocks_repeat_0, 0), (self.blocks_float_to_complex_0, 1))

    def closeEvent(self, event):
        self.settings = Qt.QSettings("GNU Radio", "ssb_transmitter")
        self.settings.setValue("geometry", self.saveGeometry())
        self.stop()
        self.wait()

        event.accept()

    def get_volume(self):
        return self.volume

    def set_volume(self, volume):
        self.volume = volume
        self.blocks_multiply_const_vxx_0.set_k(self.volume)

    def get_samp_rate(self):
        return self.samp_rate

    def set_samp_rate(self, samp_rate):
        self.samp_rate = samp_rate
        self.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
        self.band_pass_filter_0.set_taps(firdes.band_pass(1, self.samp_rate, 16300, 19000, 200, window.WIN_HAMMING, 6.76))
        self.qtgui_freq_sink_x_0.set_frequency_range(0, self.samp_rate)

    def get_interp(self):
        return self.interp

    def set_interp(self, interp):
        self.interp = interp
        self.blocks_repeat_0.set_interpolation(self.interp)

    def get_carrier_freq(self):
        return self.carrier_freq

    def set_carrier_freq(self, carrier_freq):
        self.carrier_freq = carrier_freq
        self.analog_sig_source_x_0.set_frequency(self.carrier_freq)

    def get_audio_rate(self):
        return self.audio_rate

    def set_audio_rate(self, audio_rate):
        self.audio_rate = audio_rate

def main(top_block_cls=ssb_transmitter, options=None):

    if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
        style = gr.prefs().get_string('qtgui', 'style', 'raster')
        Qt.QApplication.setGraphicsSystem(style)
    qapp = Qt.QApplication(sys.argv)

    tb = top_block_cls()

    tb.start()

    tb.show()

    def sig_handler(sig=None, frame=None):
        tb.stop()
        tb.wait()

        Qt.QApplication.quit()

    signal.signal(signal.SIGINT, sig_handler)
    signal.signal(signal.SIGTERM, sig_handler)

    timer = Qt.QTimer()
    timer.start(500)
    timer.timeout.connect(lambda: None)

    qapp.exec_()

if __name__ == '__main__':
    main()


import argparse
import os
import pandas as pd

def splitBedpe(bedpe,tmp1="tmp1.bed",tmp2="tmp2.bed",header=False,verbose=False):
	""" Function that splits up bedpe files into 2 temp files """
	if header:
		inputBedpe = pd.read_csv(bedpe,sep="\t")
	else:
		inputBedpe = pd.read_csv(bedpe,sep="\t",header=None)
	num_cols = len(inputBedpe.columns)
	id_col = num_cols
	inputBedpe[id_col] = inputBedpe.index
	inputBedpe.iloc[:,[0,1,2,id_col]].to_csv("tmp1.bed", sep="\t", header = False, index = False)
	inputBedpe.iloc[:,[3,4,5,id_col]].to_csv("tmp2.bed", sep="\t", header = False, index = False)
	if num_cols > 6:
		extra_data = inputBedpe.iloc[:,list(range(6,num_cols))].copy()
		return extra_data
	else:
		return None

def doliftOver(liftOver,chain,infile,verbose=False):
	""" Function that implements liftOver """
	cmd = " ".join([liftOver,infile,chain,infile + ".success",infile + ".failure"])
	if verbose:
		print(cmd)
	os.system(cmd)

def mergeliftOver(f1,f2,extra_data,outputfile,verbose=False):
	""" Function that merges liftOver """
	sideA = pd.read_csv(f1, header = None, sep="\t", index_col = 3)
	sideB = pd.read_csv(f2, header = None, sep="\t", index_col = 3)
	merged = sideA.merge(sideB,left_index=True,right_index=True,validate ="one_to_one")
	if extra_data is not None:
		merged = sideA.merge(extra_data,left_index=True,right_index=True,validate ="one_to_one")
	merged.to_csv(outputfile, sep="\t", header = False, index = False)

if __name__ == "__main__":

	parser = argparse.ArgumentParser(description='wrapper for liftOver to accomodate bedpe files')

	parser.add_argument("-i",'--input', dest='infile', action='store', required=True,
                    help='input file name')
	parser.add_argument("-o",'--output', dest='outfile', action='store', required=True,
						help='ouput file name')
	parser.add_argument("-v",'--verbose', dest='verbose', action='store_true', default=False, required=False,
						help='Verbose')
	parser.add_argument("-t",'--header', dest='header', action='store_true', default=False, required=False,
						help='If file has a 1-line header')
	parser.add_argument("-l",'--lift', dest='liftOver', action='store', required=True,
                    help='path to liftOver')
	parser.add_argument("-c",'--chain', dest='chain', action='store', required=True,
						help='path to chain file')

	# parse arguments
	args = parser.parse_args()

	# read in args
	LO       = args.liftOver
	chain    = args.chain
	bedpeIN  = args.infile
	bedpeOUT = args.outfile
	tmp1     = "tmp1.bed"
	tmp2     = "tmp2.bed"
	header	 = args.header
	verbose	 = args.verbose

	# break up the files
	extra_data = splitBedpe(bedpeIN,tmp1,tmp2,header,verbose)

	# perform liftOver
	doliftOver(LO,chain,tmp1,verbose)
	doliftOver(LO,chain,tmp2,verbose)

	# merge liftOvered files
	mergeliftOver(tmp1+".success",tmp2+".success",extra_data,bedpeOUT,verbose)

	# remove tmp files
	os.remove(tmp1)
	os.remove(tmp2)
	os.remove(tmp1+".success")
	os.remove(tmp1+".failure")
	os.remove(tmp2+".success")
	os.remove(tmp2+".failure")


'''
Coder: Jacky Shew
Description: Returns maximum congestion level of a graph from some vertex u,v.
			 Congestion is defined as number of edge-disjoint paths meaning
			 no usage of edges as other paths, however nodes may be reused.
Input: First Line: Total number of nodes. Following Lines: Adjacency list of the nodes.
	   Repeat until 0.
Input example:
8
4 5 7
5 6
6 7
7
0 7
0 1
1 2 7
0 2 3 4 6
4
1 2
0 2
3 0 1
2
0
'''

import time
import operator
import networkx as nx
from networkx.algorithms.flow import edmonds_karp

def instantiate_graph(nodes):
	degree_pair_list = []
	G = nx.DiGraph()
	#G.add_nodes_from(list(range(nodes))) #can also add_nodes_from(another_graph) #augment
	for i in range(nodes):
		nodes_edge = input().split() #Returns list of nodes to connect to by node[n]
		for j in range(len(nodes_edge)): #Loops for length of elements in 'nodes to connect to'
			current_edge = int(nodes_edge[j])
			if current_edge > i: #Optimise by keeping already connected edges
				G.add_edge(i,current_edge, capacity=1)
				G.add_edge(current_edge, i, capacity=1)
				degree_pair_list += [(i,G.degree(i))]
	#print(degree_pair_list)
	#print(G.edges)
	#print(G.nodes)
	start_time = time.time()
	while_counter = 0
	counter = 0
	congestion = 0
	visited_list = {}
	x = sorted(degree_pair_list, key=lambda x:x[1])
	while while_counter != nodes:
		i = x.pop()
		highest_degree_i = i[0]
		#print(highest_degree_i)
		if highest_degree_i > congestion:
			if highest_degree_i not in visited_list:
				visited_list[highest_degree_i] = []
			for j in range(nodes): #highest_degree_i node source, j node sink
				if j not in visited_list:
						visited_list[j] = []
				if highest_degree_i!=j and G.degree(highest_degree_i)//2 > congestion and G.degree(j)//2 > congestion and j not in visited_list[highest_degree_i]:
					#print("congestion:", congestion, 'G.degree(j):', G.degree(j))
					flow_value = nx.maximum_flow_value(G,highest_degree_i,j)
					congestion = max(congestion, flow_value)
					visited_list[j].append(highest_degree_i)
					counter += 1
					#print(highest_degree_i, j, "congestion:", congestion)
		while_counter += 1
	print(congestion)
	#print("Counter:", counter)
	#print("--- %s seconds ---" % (time.time() - start_time))

nodes = int(input()) #Start
while nodes != 0: #Optimise for duplicated graphs
	if nodes != 1:
		instantiate_graph(nodes)
	else:
		input()
		print(1)
	nodes = int(input())

'''import networkx as nx
from networkx.algorithms.flow import edmonds_karp
from networkx.algorithms import approximation as approx

G = nx.DiGraph()
G.add_edge('x','a', capacity=3.0)
G.add_edge('x','b', capacity=1.0)
G.add_edge('a','c', capacity=3.0)
G.add_edge('b','c', capacity=5.0)
G.add_edge('b','d', capacity=4.0)
G.add_edge('d','e', capacity=2.0)
G.add_edge('c','y', capacity=2.0)
G.add_edge('e','y', capacity=3.0)
R = edmonds_karp(G, 'x', 'y')
flow_value = nx.maximum_flow_value(G, 'x', 'y')
print(flow_value)
flow_value == R.graph['flow_value']
'''


# -*- coding: utf-8 -*-
"""Working with Path-like objects."""
from pathlib import Path

def full_path_glob(path):
    """Recursive glob, including directories with regex."""
    resolved = Path(path.absolute().parts[0])
    glob_parts = []
    to_path = True
    for part in path.parts[1:]:
        if to_path and ("*" in part):
            to_path = False
        if to_path:
            resolved /= part
        else:
            glob_parts.append(part)
    gen = resolved.rglob(path.anchor.join(glob_parts))
    return gen

def lsdir(path):
    """List all files and directories in the given path, sorted."""
    return sorted(path.iterdir())

class DisplayablePath:
    """
    Tree-like representation of a path.

    Usage:
    ------
    >>> paths = DisplayablePath.make_tree(Path("foo"))
    >>> for path in paths:
            print(path.displayable())

    """

    display_filename_prefix_middle = "├──"
    display_filename_prefix_last = "└──"
    display_parent_prefix_middle = "    "
    display_parent_prefix_last = "│   "

    def __init__(self, path, parent_path, is_last):
        """Initialise DisplayablePath."""
        self.path = Path(str(path))
        self.parent = parent_path
        self.is_last = is_last
        if self.parent:
            self.depth = self.parent.depth + 1
        else:
            self.depth = 0

    @classmethod
    def make_tree(cls, root, parent=None, is_last=False, criteria=None):
        """Make a path tree from the given top-level path."""
        root = Path(str(root))
        criteria = criteria or cls._default_criteria

        displayable_root = cls(root, parent, is_last)
        yield displayable_root

        children = sorted(
            (path for path in root.iterdir() if criteria(path)),
            key=lambda s: str(s).lower(),
        )
        count = 1
        for path in children:
            is_last = count == len(children)
            if path.is_dir():
                yield from cls.make_tree(
                    path, parent=displayable_root, is_last=is_last, criteria=criteria
                )
            else:
                yield cls(path, displayable_root, is_last)
            count += 1

    @classmethod
    def _default_criteria(cls, path):
        return True

    @property
    def displayname(self):  # noqa
        if self.path.is_dir():
            return self.path.name + "/"
        return self.path.name

    def displayable(self):  # noqa
        if self.parent is None:
            return self.displayname

        _filename_prefix = (
            self.display_filename_prefix_last
            if self.is_last
            else self.display_filename_prefix_middle
        )

        parts = ["{!s} {!s}".format(_filename_prefix, self.displayname)]

        parent = self.parent
        while parent and parent.parent is not None:
            parts.append(
                self.display_parent_prefix_middle
                if parent.is_last
                else self.display_parent_prefix_last
            )
            parent = parent.parent

        return "".join(reversed(parts))


# -*- coding: utf-8 -*-
import threading
import multiprocessing as mp
import sys, pyaudio, os
import speech_recognition as sr
from playsound import playsound
from gtts import gTTS
from datetime import datetime
from respostas_datetime import data, horas
from agenda import agenda

reload(sys)
sys.setdefaultencoding('utf-8')

# TODO: adicionar a thread do calendário para ocorrer de maneira paralela às threads
agora = datetime.now()
frase = []
mara = False
lembrete = False

def processa_funcao(audio):
    global mara
    global agora
    global lembrete
    # mostrando a string de audio que foi criada quando você falou
    tts = gTTS(audio,lang='pt-br')

    print("MARA chegou no processo: ", mara)
    #Da play ao audio
    if("bom dia" in audio.lower()):
        playsound('audios/bom_dia.mp3')
    if("que horas são" in audio.lower()):
        horas(agora)
        playsound('audios/horario.mp3')
    if("que dia é hoje" in audio.lower()):
        data(agora)
        playsound('audios/data_hoje.mp3')
    if ("conte uma piada" in audio.lower()):
        playsound ('audios/piada.mp3')
    if (audio == "ativar contato de emergência"):
        playsound ('audios/emergencia.mp3')
        #enviar_sms()
    if ("quem é você" in audio.lower()):
        playsound ('audios/mara.mp3')
    if ("como você está" in audio.lower()):
        playsound ('audios/estou_bem.mp3')
    if ("criar um lembrete" in audio.lower()):
        lembrete = True
        print("NOVO VALOR DE LEMBRETE:", lembrete)

    mara = False
    print("MARA terminou de processar: ", mara)
    main_task()

def frases(lock):
    global frase
    global mara
    lock.acquire()
    print("MARA(frases): ", mara)
    while(True):
        print("Estou te ouvindo")
        microfone = sr.Recognizer()
        with sr.Microphone() as source:
            #Chama um algoritmo de reducao de ruidos no som
            microfone.adjust_for_ambient_noise(source)
            #Armazena o que foi dito numa variavel
            audio = microfone.listen(source)
        try:
            #Passa a variavel para o algoritmo reconhecedor de padroes
            frase = microfone.recognize_google(audio,language='pt-BR')
            print(frase)
            if "Mara" in frase:
                mara = True
                print("MARA foi encontrada: ", mara)
                break
            if(mara is True):
                print("MARA sendo processada: ", mara)
                processa_funcao(frase)
                break
        except sr.UnknownValueError:
            if(mara is True):
                playsound ('audios/nao_entendi.mp3')
                mara = False
                print("MARA sendo processada(com error): ", mara)

            else:
                print("...")

    lock.release()

def lembrete_func(lock):
    global lembrete
    lock.acquire()
    print("Executando função para criar um lembrete")
    # chama a função agenda para salvar o novo áudio falando os lembretes do dia
    agenda()
    # Executa o áudio com o nome X, criado em agenda
    lembrete = False
    lock.release()

def main_task():
    global mara
    global lembrete
    lock = threading.Lock()

    escutando = threading.Thread(target=frases, args=(lock,)) # procurar "Mara"
    funcao = threading.Thread(target=frases, args=(lock,)) # ouvir a função
    lembrando = threading.Thread(target=lembrete_func, args=(lock,)) # função de agenda ativada

    print("______Lembrete",lembrete)
    if(lembrete is True):
        playsound('audios/lembrete_passo1.mp3')
        lembrando.start()
        lembrando.join()

    if(mara is False):
        print("modo escuta")
        escutando.start()
        escutando.join()
    if(mara is True):
        print("iniciando a funcao")
        playsound('audios/chamou.mp3')
        funcao.start()
        funcao.join()

if __name__ == "__main__":
    main_task()


import numpy as np
import os
import cv2
import predict

recs = []

th = 45
minSize = 15

def setT(t):
    th = t

class Rect:
    def __init__(self, x, y, w, h):
        self.x1, self.y1, self.w, self.h = x, y, w, h
        self.x2 = self.x1 + self.w
        self.y2 = self.y1 + self.h

    def area(self):
        return self.w*self.h

def calDist(rect1, rect2):

    cx1 = rect1.x1 + rect1.w // 2
    cy1 = rect1.y1 + rect1.h // 2
    cx2 = rect2.x1 + rect2.w// 2
    cy2 = rect2.y1 + rect2.h // 2

    dist = ((cx1 - cx2)** 2 + (cy1 - cy2)** 2)** 0.5

    return dist

def recs_or(rect1, rect2):  # 并集
    x1 = min(rect1.x1, rect2.x1)
    x2 = max(rect1.x2, rect2.x2)
    y1 = min(rect1.y1, rect2.y1)
    y2 = max(rect1.y2, rect2.y2)
    return Rect(x1, y1, x2 - x1, y2 - y1)

def recs_and(rect1, rect2): # 交集
    x1 = max(rect1.x1, rect2.x1)
    y1 = max(rect1.y1, rect2.y1)
    x2 = min(rect1.x2, rect2.x2)
    y2 = min(rect1.y2, rect2.y2)

    if x1 > x2 or y1 > y2:
        return 0
    else:
        return Rect(x1, y1, x2 - x1, y2 - y1)

def isInside(rect1, rect2):
    # 若两矩形相交的比例超过任意一个矩形的50%，则认为inside
    res = recs_and(rect1, rect2)
    if res == 0:
        return False
    else:
        if res.area() > 0.5 * rect1.area() or res.area() > 0.5 * rect2.area():
            return True
    return False

def update(rect):
    if len(recs) == 0:
        recs.append(rect)
        return

    for i in range(len(recs)):
        if calDist(recs[i], rect) < th:
            newRect = recs_or(recs[i], rect)
            del recs[i]
            recs.append(newRect)
            return

    recs.append(rect)
    return

def merge():
    for i in range(len(recs)):
        for j in range(i + 1, len(recs), 1):
            if isInside(recs[i], recs[j]):
                recs[i] = recs_or(recs[i], recs[j])
                del recs[j]
                return False
    return True

def getSobel(ROI):
    if len(ROI.shape) == 3:
        ROI = cv2.cvtColor(ROI, cv2.COLOR_BGR2GRAY)
    xgrad = cv2.Sobel(ROI, cv2.CV_8UC1, 1, 0, 3)
    ygrad = cv2.Sobel(ROI, cv2.CV_8UC1, 0, 1, 3)
    res = cv2.addWeighted(xgrad, 0.5, ygrad, 0.5, 0)
    return res

def getLapliacian(ROI):
    if len(ROI.shape) == 3:
        ROI = cv2.cvtColor(ROI, cv2.COLOR_BGR2GRAY)
    res = cv2.Laplacian(ROI, cv2.CV_8UC1, ksize = 3)
    return res

def calG_C(ROI, sobel, feature):
    if len(ROI.shape) == 3:
        ROI = cv2.cvtColor(ROI, cv2.COLOR_BGR2GRAY)
    sobel[feature==0] = 0

    totalG = 0
    totalN = 0
    totalColor = 0
    colorN = 0

    for i in range(ROI.shape[1]):
        for j in range(ROI.shape[0]):
            if sobel[j][i] != 0:
                totalG += sobel[j][i]
            if ROI[j][i] != 255:
                totalColor += ROI[j][i]
                colorN += 1

    if colorN == 0:
        return 0
    aveColor = totalColor / colorN
    return totalG / aveColor

def locate(img, ori, border, faceBorder, harris, t, sobel):

    final_recs = []

    recs.clear()
    setT(t)

    ori = cv2.cvtColor(ori, cv2.COLOR_GRAY2BGR)

    clone = ori.copy()

    border = border.reshape((border.shape[0], -1))
    faceBorder = faceBorder.reshape((faceBorder.shape[0], -1))

    img[border == 0] = 0
    img[faceBorder == 0] = 0

    img = cv2.addWeighted(img, 1, harris, 1, 0)

    feature = img.copy()

    contours, hierarchy = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

    ori2 = ori.copy()
    cv2.drawContours(ori2, contours, -1, (0, 0, 255), 3)

    for ct in contours:
        x, y, w, h = cv2.boundingRect(ct)
        update(Rect(x, y, w, h))

    c = merge()

    while c == False:
        c = merge()

    count = 0
    font = cv2.FONT_HERSHEY_SIMPLEX
    for i in range(len(recs)):
        if recs[i].area() > minSize:

            block_feature = img[recs[i].y1:recs[i].y2+1, recs[i].x1:recs[i].x2+1]
            block_sobel = sobel[recs[i].y1:recs[i].y2+1, recs[i].x1:recs[i].x2+1]

            block = clone[recs[i].y1:recs[i].y2+1, recs[i].x1:recs[i].x2+1]

            aveT = calG_C(block, block_sobel, block_feature)

            #if aveT > 10:
            count += 1
            cv2.rectangle(ori, (recs[i].x1, recs[i].y1), (recs[i].x2, recs[i].y2), (0, 255, 0), 1)
            cv2.putText(ori, str(count), (recs[i].x1, recs[i].y1), font, 0.8, (0, 0, 255), 1)
            final_recs.append(recs[i])

    return ori, ori2, final_recs, feature


#!/usr/bin/env python2
from __future__ import print_function

import argparse
import gfal2

from random import sample
from os.path import basename, dirname, realpath
from time import time

class Dump:
    def __init__(self, path):
        self.path = path
        self.nlines = None

    def _count_lines(self):
        with open(self.path) as fd:
            for idx, line in enumerate(fd):
                pass
        self.nlines = idx

    @property
    def ready(self):
        return self.nlines is not None

    def prepare(self):
        self._count_lines()

    def random_lines(self, line_count):
        if not self.ready:
            self.prepare()

        if line_count > self.nlines:
            raise ValueError("Requested more {0} lines, while there is only {1} in {2}".format(line_count, self.nlines, self.path))

        selected = sample(range(self.nlines), line_count)

        res = []
        with open(self.path) as fd:
            for idx, line in enumerate(fd):
                if idx in selected:
                   res.append(line)
        return res

def run_stats(dump, count, output_dir='.', check_type='stat'):
    do_stat = lambda ctx, url: ctx.stat(url)
    do_cksum = lambda ctx, url: ctx.getxattr(url, 'xroot.cksum')

    if check_type == 'stat':
        check_func = do_stat
    elif check_type == 'csum':
        check_func = do_cksum
    elif check_type == 'both':
        check_func = lambda ctx,url: (do_stat(ctx, url), do_cksum(ctx, url))
    else:
        raise ValueError("Wrong check type: shoud be either 'stat', 'csum' or 'both'.")

    output_urls = "{0}/urls_{1}.csv".format(realpath(output_dir), basename(dump.path))
    output_chunks = "{0}/chunks_{1}.csv".format(realpath(output_dir), basename(dump.path))
    URLs = dump.random_lines(count)
    ctx = gfal2.creat_context()
    url_times = []
    chunk_res = 0
    print("Starting stats for {0} at {1}".format(dump.path, time()))
    chunk_start = time()
    for idx, url in enumerate(URLs):
        url = url.strip()
        url_start = time()
        try:
            test_res = check_func(ctx, url)
        except gfal2.GError as e:
            print("Exception while stat {0}: {1}".format(url, e))
            res = 1
        else:
            res = 0
        finally:
            url_end = time()
            url_times.append( (url_start, url_end-url_start, res) )
            chunk_res = max(chunk_res, res)
        if (idx+1) % 50 == 0:
            print("{0} urls processed".format(idx+1))
    chunk_time = url_end - chunk_start
    print("Chunk processed in {0}".format(chunk_time))

    for fname, res in ( (output_urls, url_times), (output_chunks, [(chunk_start, chunk_time, chunk_res)]) ):
        with open(fname, 'a') as fd:
            for tup in res:
                print("{0},{1},{2}".format(tup[0],tup[1],tup[2]), file=fd)

def run_dirac_checks(dump, prefix, count, se, output_dir='.'):
    output_file = "{0}/chunks_{1}.csv".format(realpath(output_dir), basename(dump.path))
    URLs = [u.replace(prefix, '', 1) for u in  dump.random_lines(count)]
    replicas = {}
    for url in URLs:
        replicas[url] = [se]

    from LHCbDIRAC.DataManagementSystem.Client.DataIntegrityClient import DataIntegrityClient
    client = DataIntegrityClient()

    print("Starting stats for {0} at {1}".format(dump.path, time()))
    chunk_start = time()
    res = client.checkPhysicalFiles(replicas=replicas, catalogMetadata={})
    exec_time = time() - chunk_start

    print("Execution took {0}".format(exec_time))

    with open(output_file, 'a') as fd:
        print( "{0},{1},{2}".format(chunk_start, exec_time, 0 if res['OK'] else 1) , file=fd)

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("-c", "--count", help="Number of files to stat. Must not be less then number of lines in a dump", type=int)
    parser.add_argument("-d", "--dumps", help="Comma-separated list of files with URLs for stats. No commas in filenames, please")
    parser.add_argument("-o", "--output_dir", help="Dir where results should be stored")
    parser.add_argument("-t", "--check_type", help="Check type. Either 'stat' (e.g. do only stats), 'cksum' (only cksums) or 'both' (both of the above). Default is 'stat'.", default='stat')
    parser.add_argument("-D", "--DIRAC", help="Run DIRAC-specific checks", action='store_true')
    parser.add_argument("-S", "--SE", help="Dirac SE. Required only for DIRAC-specific tests", default=None)
    parser.add_argument("-p", "--prefix", help="Prefix to remove from PFN to get LFN. Required only for DIRAC-Specific tests", default=None)
    args = parser.parse_args()
    if args.DIRAC and (args.SE is None or args.prefix is None):
        raise ValueError("For DIRAC-specific tests SE and prefix must be given.")
    elif not args.DIRAC and (args.SE is not None or args.prefix is not None):
        raise ValueError("For non DIRAC-specific tests SE and prefix must not be given.")
    return args

if __name__ == '__main__':
    args = parse_args()
    Dumps = []
    for fname in args.dumps.split(','):
        Dumps.append(Dump(fname))

    for dump in Dumps:
        if args.DIRAC:
            run_dirac_checks(dump, args.prefix, args.count, args.SE)
        else:
            run_stats(dump, args.count, output_dir=args.output_dir, check_type=args.check_type)


#!/usr/bin/env python3
'''Equivariant pentago networks

Let G = Z_4 be the group of global rotations.  (For now we are ignoring rotations,
as they're harder to deal with.)  Ignoring batch dimension, our interior activations
will have shape [4,width], corresponding to one width-dimension vector per quadrant.
If b is a board, h(b) is some internal layer of the network, and f(b) is the final
logits (shape [3]), we will enforce

1. g h(b) = h(gb)  # equivariance
2. f(b) = f(gb)    # invariance

where g ∈ G acts on internal activations of shape [4,width] by cyclic rotation.
'''

from functools import partial
import haiku as hk
import jax
import jax.numpy as jnp
import numpy as np

class Embed(hk.Module):
  """Embed [batch,4,9]-shaped boards equivariantly into [batch,4,width] activations

  We embed each quadrant by summing together embeddings at each position, using
  an embedding tensor of shape [9,3,width].  This tensor is rotated when applying
  it to the non-lower-left quadrants (or rather, those quadrants and rotated) so
  that equivariance holds after embedding.

  We also embed the total stone count, in particular to tell the network whose turn it is.

  Args:
    boards: A [batch,4,9]-shaped integer tensor with values in 0,1,2 (empty, black, white)
    width: Inner embedding dimension

  Returns:
    [batch,4,width]-shaped tensor
  """
  def __init__(self, width):
    super().__init__()
    self._width = width

  def __call__(self, boards):
    batch = boards.shape[0]
    width = self._width
    assert boards.shape == (batch, 4, 9)
    q0, q1, q2, q3 = boards.swapaxes(0,1)
    q1 = q1.reshape(batch, 3, 3).swapaxes(1,2)[:,::-1,:].reshape(batch, 9)
    q2 = q2.reshape(batch, 3, 3)[:,::-1,:].swapaxes(1,2).reshape(batch, 9)
    q3 = q3[:, ::-1]
    rotated = jnp.stack([q0, q2, q3, q1], axis=1)  # Put quads in counterclockwise order
    count = (rotated.reshape(batch, 4*9) != 0).astype(np.int32).sum(axis=-1)
    init = hk.initializers.RandomNormal(1 / np.sqrt(9+1))
    w_quads = hk.get_parameter('w_quads', shape=(9*3, width), init=init)
    w_count = hk.get_parameter('w_count', shape=(19, width), init=init)
    x = jax.nn.one_hot(rotated, 3).reshape(batch, 4, 9*3) @ w_quads
    x += (jax.nn.one_hot(count, 19) @ w_count)[:,None,:]
    assert x.shape == (batch, 4, width)
    return x

def fourier(s, *, axis, scale=0.5):
  """Size 4 Fourier transform"""
  assert s.dtype == np.float32
  s0, s1, s2, s3 = scale * jnp.moveaxis(s, axis, 0)
  s02 = s0 + s2
  s13 = s1 + s3
  t0 = s02 + s13
  t1 = jax.lax.complex(s0 - s2, s3 - s1)
  t2 = s02 - s13
  return t0, t1, t2

def unfourier(t, *, axis, scale=0.5):
  """Size 4 inverse Fourier transform"""
  t0, t1, t2 = t
  t0 = scale * t0
  t2 = scale * t2
  t1 = 2 * scale * t1
  s02 = t0 + t2
  s13 = t0 - t2
  s0 = s02 + t1.real
  s2 = s02 - t1.real
  s1 = s13 - t1.imag
  s3 = s13 + t1.imag
  return jnp.stack([s0, s1, s2, s3], axis=axis)

def convolve(x, y, *, axis, mul=jnp.matmul):
  """Convolve tensors of shape [a,4,b], [b,4,c] → shape [a,4,c]"""
  x = fourier(x, axis=axis, scale=1)
  y = fourier(y, axis=axis, scale=1)
  z = jax.tree_multimap(mul, x, y)
  return unfourier(z, axis=axis, scale=0.25)

def sws_standardize(w, *, gain, eps=1e-4, scale=1):
  """Scaled weight standardize a matrix, with optional scalar gain

  See Brock et al., https://arxiv.org/abs/2101.08692 for details.
  Code modified from https://github.com/deepmind/deepmind-research/blob/master/nfnets/base.py#L121.
  """
  n_in, n_out = w.shape
  w = w - jnp.mean(w, axis=0, keepdims=True)
  sum_sqr = jnp.square(w).sum(axis=0, keepdims=True)
  scale *= jax.lax.rsqrt(jnp.maximum(sum_sqr, eps))  # 1 / sqrt(n_in * var)
  if gain:
    scale *= hk.get_parameter('gain', shape=(n_out,), dtype=w.dtype, init=jnp.ones)
  return scale * w

class SwsLinear(hk.Module):
  """SWS linear layer"""
  def __init__(self, size, *, gain=True):
    super().__init__()
    self._size = size
    self._gain = gain

  def __call__(self, x):
    n_in = x.shape[-1]
    n_out = self._size
    w = hk.get_parameter('w', shape=(n_in, n_out), dtype=x.dtype,
                         init=hk.initializers.VarianceScaling(1, 'fan_in', 'normal'))
    bias = hk.get_parameter('bias', shape=(n_out,), dtype=x.dtype, init=jnp.zeros)
    w = sws_standardize(w, gain=self._gain)
    return x @ w + bias

class SwsConv(hk.Module):
  """SWS convolutional layer"""
  def __init__(self, size, *, gain=True, scale=1):
    super().__init__()
    self._size = size
    self._gain = gain
    self._scale = scale

  def __call__(self, x):
    batch, _, n_in = x.shape
    n_out = self._size
    assert x.shape == (batch, 4, n_in)
    w = hk.get_parameter('w', shape=(4*n_in, n_out), dtype=x.dtype,
                         init=hk.initializers.VarianceScaling(1, 'fan_in', 'normal'))
    bias = hk.get_parameter('bias', shape=(n_out,), dtype=x.dtype, init=jnp.zeros)
    w = sws_standardize(w, gain=self._gain, scale=self._scale)
    w = w.reshape(n_in, 4, n_out)
    y = convolve(x, w, axis=1) + bias
    assert y.shape == (batch, 4, n_out)
    return y

class EquivariantLinear:
  """An equivariant linear layer"""
  def __init__(self, size):
    self._size = size

  def __call__(self, x):
    batch, _, width = x.shape
    assert x.shape == (batch, 4, width)
    # Make a [batch,4,4*width]-shape tensor by rolling x 4 ways
    rolls = jnp.stack([jnp.roll(x, -k, axis=1) for k in range(4)], axis=1)
    rolls = rolls.reshape(batch, 4, 4*width)
    x = hk.Linear(self._size)(rolls)
    assert x.shape == (batch, 4, self._size)
    return x

class EquivariantBlock(hk.Module):
  """An equivariant resnet block: x → x + linear(gelu(ev_linear(norm(x))))"""

  def __init__(self, *, mid):
    super().__init__()
    self._mid = mid

  def __call__(self, x):
    mid = self._mid
    batch, _, width = x.shape
    assert x.shape == (batch, 4, width)
    y = hk.LayerNorm(axis=-1, create_scale=True, create_offset=True)(x)
    y = EquivariantLinear(self._mid)(y)
    y = jax.nn.gelu(y)
    y = hk.Linear(width)(y)
    return x + y

class NFBlock(hk.Module):
  """Normalizer-free resnet block

  See Brock et al., https://arxiv.org/abs/2101.08692 for details.
  """
  def __init__(self, mid):
    super().__init__()
    self._mid = mid

  def __call__(self, x, *, in_scale, out_scale):
    batch, _, width = x.shape
    assert x.shape == (batch, 4, width)
    gamma = np.sqrt(2 / (1 - 1/np.pi))
    y = SwsConv(self._mid, scale=gamma / in_scale)(x)
    y = jax.nn.relu(y)
    y = SwsConv(width, scale=out_scale)(y)
    return x + y

class InvariantLogits:
  def __call__(self, x, *, classes=3):
    """Invariant final logit layer

    Returns [batch,3]-shaped outcome logits on the value of the positions, with indices
    0,1,2 corresponding to outcomes -1,0,1 representing value for the player to move.
    """
    batch, _, width = x.shape
    assert x.shape == (batch, 4, width)
    x = hk.LayerNorm(axis=-1, create_scale=False, create_offset=False)(x)
    x = jnp.mean(x, axis=1)
    logits = hk.Linear(classes)(x)
    return logits

def invariant_net(boards, *, layers, width, mid):
  """A simple equivariant pentago reset"""
  x = Embed(width)(boards)
  for layer in range(layers):
    x = EquivariantBlock(mid=mid)(x)
  logits = InvariantLogits()(x)
  metrics = {}
  return logits, metrics

def nf_net_scale(layer, *, layer_scale):
  return jnp.sqrt(1 + layer*jnp.square(layer_scale))

def nf_net(boards, *, layers, width, mid, layer_scale, classes=3):
  """A normalizer-free equivariant pentago resnet"""
  scale = partial(nf_net_scale, layer_scale=layer_scale)
  means, stds = [], []
  def stat(x):
    means.append(jnp.mean(x))
    stds.append(jnp.std(x))
  x = Embed(width)(boards)
  stat(x)
  for layer in range(layers):
    x = NFBlock(mid)(x, in_scale=scale(layer), out_scale=layer_scale)
    stat(x)
  x = 0.25 / scale(layers) * x.sum(axis=1)
  logits = hk.Linear(classes)(x)
  metrics = dict(means=jnp.asarray(means),
                 stds=jnp.asarray(stds))
  return logits, metrics