import re
import os
import json
from datetime import date, datetime
from collections.abc import Iterable
import pandas as pd
from pandas.api.types import is_numeric_dtype, is_categorical_dtype, is_string_dtype, is_object_dtype, infer_dtype
import plotly

from .currencies import get_valid_currencies

def __generic_error_message(text:str):
    """
    This function can be used if a custom error message function is not provided.
    It simply returns the text it was passed.
    """
    return text

def check_int(value_to_check, name:str, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is an integer. If not, this will raise
    an error.
    Params:
        value_to_check: The value in question.
        name: The variable name for the error message.
        get_error_message_function: The function to call to get the error message template.
    Raises:
        TypeError - If the check fails.
    """
    if not isinstance(value_to_check, int):
        message = get_error_message_function(f"{name} must be an integer.")
        raise TypeError(message)

def check_positive_numeric(value_to_check, name:str, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is a positive number (int or float). If not, this will raise
    an error.
    Params:
        value_to_check: The value in question.
        name: The variable name for the error message.
        get_error_message_function: The function to call to get the error message template.
    Raises:
        TypeError - If the check fails.
    """
    if (isinstance(value_to_check, int) or isinstance(value_to_check, float)) and value_to_check > 0:
        pass
    else:
        message = get_error_message_function(f"{name} must be a positive number.")
        raise ValueError(message)

def check_int(value_to_check, name:str, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is an integer. If not, this will raise
    an error.
    Params:
        value_to_check: The value in question.
        name: The variable name for the error message.
        get_error_message_function: The function to call to get the error message template.
    Raises:
        TypeError - If the check fails.
    """
    if not isinstance(value_to_check, int):
        message = get_error_message_function(f"{name} must be an integer.")
        raise TypeError(message)

def check_bool(value_to_check, name:str, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is a boolean. If not, this will raise
    an error.
    Params:
        value_to_check: The value in question.
        name: The variable name for the error message.
        get_error_message_function: The function to call to get the error message template.
    Raises:
        TypeError - If the check fails.
    """
    if not isinstance(value_to_check, bool):
        message = get_error_message_function(f"{name} must be a boolean value (must be logical).")
        raise TypeError(message)

def check_scalar(value_to_check, name:str, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is a scalar value, meaning, that it is NOT
    a iterable. Note that for these purposes strings are considered scalars,
    even though they are technically iterable.
    Params:
        value_to_check: The value in question.
        name: The variable name for the error message.
        get_error_message_function: The function to call to get the error message template.
    Raises:
        TypeError - If the check fails.
    """
    if not isinstance(value_to_check, str) and isinstance(value_to_check, Iterable):
        message = get_error_message_function(f"{name} must be a scalar (not a list or other iterable type).")
        raise TypeError(message)

def check_enum(value_to_check, possible_values, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is in a list of possible values.
    Params:
        value_to_check: The value in question
        possible_values: An iterable list of values
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if not value_to_check in possible_values:
        message = get_error_message_function(f"{value_to_check} must be one of {possible_values}")
        raise ValueError(message)

def check_is_list(value_to_check, get_error_message_function):
    """
    Verify that the provided value is a list.
    Params:
        value_to_check: The value in question
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if not isinstance(value_to_check, list):
        message = get_error_message_function(f"Expected value '{value_to_check}' to be a list")
        raise ValueError(message)

def check_has_variable(df: pd.DataFrame, varname: str, get_error_message_function):
    """
    Verify that the dataframe contains the column.
    Params:
        df: Pandas DataFrame
        varname: The variable name to check
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if varname not in df.columns:
        raise ValueError(get_error_message_function(f"Could not find variable {varname} is in the list of columns"))

def check_numeric(df: pd.DataFrame, varname: str, get_error_message_function):
    """
    Verify that in the dataframe, the column 'varname' is numeric.
    Params:
        df: Pandas DataFrame
        varname: The variable name to check
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if not is_numeric_dtype(df[varname]):
        raise ValueError(get_error_message_function(f"The variable '{varname}' must be numeric."))

def check_string_datatype(df: pd.DataFrame, varname: str, get_error_message_function=__generic_error_message):
    """
    Verify that in the dataframe, the column 'varname' is a string datatype.
    Params:
        df: Pandas DataFrame
        varname: The variable name to check
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if not is_string_column(df[varname]):
        raise ValueError(get_error_message_function(f"The variable '{varname}' is not a string."))

def check_atomic_vector(df: pd.DataFrame, varname: str, get_error_message_function=__generic_error_message):
    """
    Verify that in the dataframe, the column 'varname' is an atomic vector, or
    in other words, not a nested type.
    Params:
        df: Pandas DataFrame
        varname: The variable name to check
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if infer_dtype(df[varname]) == "mixed":
        raise ValueError(get_error_message_function(f"The variable '{varname}' is must be an atomic vector (not a nested type)."))

def check_valid_currency(value_to_check: str, get_error_message_function):
    """
    Verify that the provided currency is a valid one (e.g., USD, EUR).
    Params:
        value_to_check: the value in question.
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    check_enum(value_to_check, get_valid_currencies(), get_error_message_function)

def check_range(df: pd.DataFrame, varname: str, min: float, max: float, get_error_message_function):
    """
    Verify that all values in 'varname' column in the dataframe are within this range.
    Params:
        df: Pandas DataFrame
        varname: The column
        min: float - The minimum value of the range (inclusive)
        max: float - The maximum value of the range (inclusive)
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if not df[varname].between(min, max, "both").all():
        raise ValueError(get_error_message_function(f"The variable '{varname}' must be in the range {min} to {max}."))

def check_latitude_variable(df: pd.DataFrame, varname: str, get_error_message_function):
    """
    Verify that the latitude variable is numeric and in the proper range.
    Params:
        df: Pandas DataFrame
        varname: The latitude column
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    check_numeric(df, varname, get_error_message_function)
    check_range(df, varname, -90, 90, get_error_message_function)

def check_longitude_variable(df: pd.DataFrame, varname: str, get_error_message_function):
    """
    Verify that the longitude variable is numeric and in the proper range.
    Params:
        df: Pandas DataFrame
        varname: The longitude column
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    check_numeric(df, varname, get_error_message_function)
    check_range(df, varname, 0, 180, get_error_message_function)

# From: https://stackoverflow.com/a/22238613
def custom_json_serializer(obj):
    """JSON serializer for objects not serializable by default json code"""

    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    raise TypeError("Type {type(obj)} is not serializable")

def check_exhaustive_levels(df: pd.DataFrame, levels: list, varname: str, get_error_message_function):
    """
    Verifies that the values in the `varname` column contains only those values specified
    in `levels`. If any extras are found, an error is raised.
    Params:
        df: Pandas DataFrame
        levels: list - The possible values
        varname: The column to check
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    actual_values = set(df[varname].unique())
    expected_values = set(levels)

    diff = actual_values - expected_values

    if len(diff) > 0:
        raise ValueError(get_error_message_function(f"{varname} contains values not specified in levels:{levels}"))

def check_graph_var(df: pd.DataFrame, varname: str, id_varname: str, get_error_message_function):
    """
    """
    # TODO: After we have determined how to handle the graph data in Pandas,
    # implement this method to verify it.

    raise NotImplementedError()

valid_image_extensions = {"apng", "avif", "gif", "jpg", "jpeg", "jfif", "pjpeg",
  "pjp", "png", "svg", "webp"}

def _extension_matches(text:str, ext_to_match:str, match_case:bool = False):
    """
    Returns true if the extension of `text` matches the provided
    `ext_to_match`.

    Params:
        text: str - The filepath
        ext_to_match: str - The extension not including the . (pass "jpg" not ".jpg")

    Designed to be used as a "lambda" function in an apply method.
    """
    (_, ext) = os.path.splitext(text)

    # Get rid of the leading . in .jpg
    ext = ext.removeprefix(".")

    is_match = False

    if match_case:
        is_match = (ext == ext_to_match)
    else:
        is_match = (ext.lower() == ext_to_match.lower())

    return is_match

def find_figure_columns(df:pd.DataFrame):
    """
    Finds a list of columns in the dataframe that are completely filled with
    `Figure` objects.
    """

    # SB: This function (and its unit tests)  place a dependency on plotly,
    # because they check for plotly figure object. If this is not desired,
    # another approach could be used such as checking for a "facel_panel"
    # column name or something similar.

    figure_cols = []
    obj_cols = [col for col in df.columns if is_object_dtype(df[col])]

    for col in obj_cols:
        if isinstance(df[col][0], plotly.graph_objs.Figure):
            # The first row is a Figure, check all now
            if df[col].apply(lambda x: isinstance(x, plotly.graph_objs.Figure)).all():
                figure_cols.append(col)

    return figure_cols

def find_image_columns(df:pd.DataFrame):
    """
    Finds a list of columns in the dataframe that are completely filled with
    image references.
    """
    image_cols = []
    str_cols = [col for col in df.columns if is_string_column(df[col])]

    for col in str_cols:
        if is_image_column(df, col):
            image_cols.append(col)

    return image_cols

def is_image_column(df:pd.DataFrame, col:str) -> bool:
    """
    Returns True if the provided column is an image column, meaning
    that every value has the same, valid image extension.
    """
    is_image = False

    # Get the extension of the first item
    (_, ext) = os.path.splitext(df[col][0])

    # Get rid of the leading . in .jpg
    ext = ext.removeprefix(".")

    if ext in valid_image_extensions:
        # The first row had a valid image extension, now check if
        # they all have this same extension
        if df[col].apply(lambda x: _extension_matches(x, ext)).all():
            # All rows in this column have this extension
            is_image = True

    return is_image

def check_image_extension(list_to_check:list, get_error_message_function=__generic_error_message):
    """
    Verify that each element in the list has a valid image extension.
    Params:
        list_to_check: The list of strings.
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    for item in list_to_check:
        filename, ext = os.path.splitext(item)

        # Get rid of the leading . in .jpg
        ext = ext.removeprefix(".")

        if ext not in valid_image_extensions:
            # Found invalid file extension
            message = get_error_message_function(f"Extension {ext} is not valid. All file extensions must be one of: {valid_image_extensions}")
            raise ValueError(message)

def is_all_remote(col:pd.Series):
    """
    Determines if every value in the provided `col` column is
    remote, meaning that they all begin with `http:`.
    """
    return col.apply(lambda x: x.startswith("http")).all()

def sanitize(text:str, to_lower=True) -> str:
    if to_lower:
        text = text.lower()

    text = text.replace(" ", "_")
    text = re.sub(r"[^\w]", "", text)

    return text

def get_jsonp_wrap_text_dict(jsonp: bool, function_name: str) -> dict():
    """
    Gets the starting and ending text to use for the config file.
    If it is jsonp, it will have a function name and ()'s. If it is
    not (ie, regular json), it will have empty strings.
    """
    text_dict = {}
    if jsonp:
        text_dict["start"] = f"{function_name}("
        text_dict["end"] = ")"
    else:
        text_dict["start"] = ""
        text_dict["end"] = ""

    return text_dict

def write_json_file(file_path: str, jsonp: bool, function_name: str, content: str):
    wrap_text_dict = get_jsonp_wrap_text_dict(jsonp, function_name)
    wrapped_content = wrap_text_dict["start"] + content + wrap_text_dict["end"]

    with open(file_path, "w") as output_file:
        output_file.write(wrapped_content)

def write_window_js_file(file_path: str, window_var_name: str, content: str):
    wrapped_content = f"window.{window_var_name} = {content}"

    with open(file_path, "w") as output_file:
        output_file.write(wrapped_content)

def get_file_path(directory: str, filename_no_ext: str, jsonp: bool):
    file_ext = "jsonp" if jsonp else "json"
    filename = f"{filename_no_ext}.{file_ext}"

    file_path = os.path.join(directory, filename)

    return file_path

def read_jsonp(file: str) -> dict():
    """
    Reads the json content of the .json or .jsonp file. If the file is
    a .jsonp file, the function name and ()'s will be ignored.
    Params:
        file: str - The full path to the file.
    Returns:
        dict - The content of the .json or .jsonp file.
    """
    content = ""
    with open(file) as file_handle:
        content = file_handle.read()

    json_content = ""

    if file.endswith(".json"):
        json_content = content
    elif file.endswith(".jsonp"):
        open_paren_index = content.index("(")
        close_paren_index = content.rindex(")")
        json_content = content[open_paren_index + 1 : close_paren_index]
    else:
        raise ValueError(f"Unrecognized file extension for file {file}. Expected .json or .jsonp")

    result = json.loads(json_content)
    return result

def is_dataframe_grouped(df: pd.DataFrame) -> bool:
    index_names = df.index.names

    is_empty_index = len(index_names) == 1 and index_names[0] is None
    return not is_empty_index

def get_dataframe_grouped_columns(df: pd.DataFrame) -> list:
    return df.index.names

def get_string_columns(df: pd.DataFrame) -> list:
    char_cols = [c for c in df.columns if is_string_column(df[c])]
    return char_cols

def get_string_or_factor_columns(df: pd.DataFrame) -> list:
    char_cols = [c for c in df.columns if is_string_column(df[c]) or df[c].dtype == "category"]
    return char_cols

def get_numeric_columns(df: pd.DataFrame) -> list:
    return list(df.select_dtypes('number'))

def get_uniquely_identifying_cols(df: pd.DataFrame) -> list:
    unique_key_cols = []

    # Try all columns, beginning with characters
    char_cols = get_string_columns(df)
    numeric_cols = get_numeric_columns(df)
    all_cols = char_cols + numeric_cols

    key_cols = []

    for col in all_cols:
        key_cols.append(col)

        if df.set_index(key_cols).index.is_unique:
            # This set of key_cols uniquely identifies the rows
            unique_key_cols = key_cols
            break

    return unique_key_cols

def is_string_column(column: pd.Series):
    """
    Checks to see if the provided column (Pandas Series) is a string datatype,
    including checking that it is not a Figure object.
    """
    is_string = False

    if is_string_dtype(column) and not is_categorical_dtype(column):
        # This is a "string dtype" but that could include other types of
        # objects such as a plotly `Figure`, so verify that the first value
        # is actually a string.
        if type(column[0]) == str:
            is_string = True

    return is_string


from PIL import Image
import requests
from io import BytesIO
import json

pages = json.load(open('bots/botpages.json', 'r'))

new_json = []

pageid = 1
for page in pages:
	dpurl = page["dp_link"]
	new_page_data = {}
	new_page_data["title"] = page["title"]
	new_page_data["fb_link"] = page["fb_link"]
	new_page_data["tags"] = page["tags"]
	new_page_data["dp_link"] = page["dp_link"]
	new_page_data["dp_id"] = "../pagedps/{}.png".format(pageid)
	if "github" in page:
		new_page_data["github"] = page["github"]
	new_json.append(new_page_data)

	response = requests.get(dpurl)
	try:
		img = Image.open(BytesIO(response.content))
	except:
		print("Link is dead; check the following page:")
		print(page["title"])
	img.thumbnail((80, 80))
	img.save("pagedps/{}.png".format(pageid), "PNG")

	print(str(pageid) + " done")
	pageid += 1

with open('bots/botpages.json', 'w') as outfile:
    json.dump(new_json, outfile)


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('owner_crm', '0007_campaign'),
    ]

    operations = [
        migrations.AlterField(
            model_name='campaign',
            name='preferred_medium',
            field=models.IntegerField(default=1, choices=[(0, 'SMS'), (1, 'Email'), (2, 'SMS & Email')]),
        ),
    ]


#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
This module provides a class for a CAN wrapper for the ADC channels of the MOPS Chip.
It also provides a function for using this server as a command line tool.
Note
----
:Author: Ahmed Qamesh
:Contact: ahmed.qamesh@cern.ch
:Organization: Bergische Universität Wuppertal
"""
# Standard library modules
#from __future__ import annotations
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from configparser import ConfigParser
from typing import *
import time
import datetime
#import asyncio
#from asyncio.tasks import sleep
import sys
import os
from threading import Thread, Event, Lock
import subprocess
import threading
import numpy as np
try:
    from logger_main   import Logger
    from analysis_utils import AnalysisUtils
    from analysis import Analysis
except (ImportError, ModuleNotFoundError):
    from .logger_main   import Logger
    from .analysis_utils import AnalysisUtils
    from .analysis import Analysis
import struct
# Third party modules
from collections import deque, Counter
from tqdm import tqdm
import ctypes as ct
import logging
import queue
from bs4 import BeautifulSoup #virtual env
from typing import List, Any
from random import randint
import uhal

import random
#from csv import writer
logger = Logger().setup_main_logger(name = " Lib Check ",console_loglevel=logging.INFO, logger_file = False)

rootdir = os.path.dirname(os.path.abspath(__file__))
config_dir = "config_files/"
lib_dir = rootdir[:-8]

class UHALWrapper(object):#READSocketcan):#Instead of object

    def __init__(self,
                 file_loglevel=logging.INFO,
                 logdir=None,load_config = False,
                 logfile = None,
                 console_loglevel=logging.INFO,
                 mainWindow= False):

        super(UHALWrapper, self).__init__()  # super keyword to call its methods from a subclass:
        #Initialize a watchdog (to be done)
        #Begin a thread settings (to be done)
        self.sem_read_block = threading.Semaphore(value=0)
        self.sem_recv_block = threading.Semaphore(value=0)
        self.sem_config_block = threading.Semaphore()

        """:obj:`~logging.Logger`: Main logger for this class"""
        if logdir is None:
            #'Directory where log files should be stored'
            logdir = os.path.join(lib_dir, 'log')
        self.logger = Logger().setup_main_logger(name = "UHAL Wrapper",console_loglevel=console_loglevel, logger_file = False)

        if load_config:
           # Read CAN settings from a file
            self.__uri, self.__addressFilePath =   self.load_settings_file()

        # Initialize library and set connection parameters
        self.__canMsgQueue = deque([], 100)  # queue with a size of 100 to queue all the messages in the bus
        self.__uhalMsgQueue = deque([], 100)
        self.__cnt = Counter()
        self.error_counter = 0
        self.__pill2kill = Event()
        self.__lock = Lock()
        self.__hw = None
        self.logger.success('....Done Initialization!')
        self.__address_byte = [0x80, 0x88, 0x90, 0x98, 0x80]
        if logfile is not None:
            ts = os.path.join(logdir, time.strftime('%Y-%m-%d_%H-%M-%S_UHAL_Wrapper.'))
            self.logger.info(f'Existing logging Handler: {ts}'+'log')
            self.logger_file = Logger().setup_file_logger(name = "UHALWrapper",console_loglevel=console_loglevel, logger_file = ts)#for later usage
            self.logger_file.success('....Done Initialization!')

    def set_hw_connection(self):
        self.logger.info(f'Starting a Thread for MOPSHUB')
        self.__uhalMsgThread = Thread(target=self.read_uhal_mopshub_message, args=(["reg0","reg1","reg2"], 0.001,  None))#self.between_thread_callback)
        self.__uhalMsgThread.start()

    def between_thread_callback(self):
        loop = asyncio.new_event_loop()
        loop.run_until_complete(self.call_back_read_uhal_mopshub_message())

    def call_back_read_uhal_mopshub_message(self):
        self.read_uhal_mopshub_message(reg = ["reg0","reg1","reg2"], timeout=0.001, out_msg = None)

    def config_uhal_hardware(self, uri = None, addressFilePath = None):
        if uri is None:
            uri = self.__uri
        if addressFilePath is None:
            addressFilePath = self.__addressFilePath
        hw = uhal.getDevice("mopshub", uri, "file://" + addressFilePath)
        self.set_uhal_hardware(hw)
        self.set_hw_connection()
        return hw

    def get_ual_node(self, hw =None, registerName = None):
        node = hw.getNode(registerName)
        return node

    def load_settings_file(self, file="main_settings.yml"):
        """Load all the information related to the hardware
        Parameters
        ----------
        file : :obj:`str` represents the yaml file name
        """

        filename = lib_dir + config_dir + file
        filename = os.path.join(lib_dir, config_dir + file)
        test_date = time.ctime(os.path.getmtime(filename))
        # Load settings from bus settings file
        self.logger.notice("Loading bus settings from the file %s produced on %s" % (filename, test_date))
        try:
            _channelSettings = AnalysisUtils().open_yaml_file(file=config_dir + "main_settings.yml", directory=lib_dir)
            _uri = _channelSettings['ethernet']["uri"]
            _addressFilePath = _channelSettings['ethernet']["addressFilePath"]
            return _uri,_addressFilePath
        except:
          self.logger.error("uri %s settings Not found" % (_uri))
          return None,None

    def read_uhal_message(self, hw = None, node =None, registerName=None, timeout=None, out_msg = True, w_r= "Read"):
        """Read incoming UHAL messages without storing any Queue
        node: obj: uhal._core type
        registerName: str:
        """
        reg_value = node.read()
        # Send IPbus transactions
        hw.dispatch()
        if out_msg:  self.logger.info(f'{w_r} {hex(reg_value.value())} : {registerName}')
        return reg_value

    def write_uhal_mopshub_message(self, hw =None, data=None,reg =None, timeout=None, out_msg= True):
        """Combining writing functions for different |CAN| interfaces
        Parameters
        ----------
        data : :obj:`list` of :obj:`int` or :obj:`bytes`
            Data bytes

        timeout : :obj:`int`, optional
            |SDO| write timeout in milliseconds. When :data:`None` or not
            given an infinit timeout is used.
        """
        nodes = []
        reqmsg = 0
        for r in reg:
            nodes = np.append(nodes,self.get_ual_node(hw =hw, registerName = r))
        [self.write_uhal_message(hw =hw,node =nodes[data.index(d)], data=d, registerName=r, timeout=timeout, out_msg=out_msg) for r,d in zip(reg,data)]
        reqmsg = 1
        return reqmsg

    def write_uhal_message(self,hw =None, node =None, data=None, registerName=None, timeout=None, out_msg = True ):
        reqmsg = 0
        node.write(data)
        reqmsg= 1
        reg_ret_value = self.read_uhal_message(hw = hw, node =node, registerName=registerName, timeout=timeout, out_msg = out_msg, w_r= "Writing")
        status = (hex(data) ==hex(reg_ret_value.value()))
        if out_msg and not status:  self.logger.warning(f'Writing mismatch in {registerName} [W: {hex(data)} |R:{hex(reg_ret_value.value())}]')
        # Send IPbus transactions
        hw.dispatch()
        #time.sleep(timeout)
        return reqmsg

    def build_response_sdo_msg(self, reg =[], out_msg = True):
        # Data_rec_reg is 76 bits = sdo[12bits]+payload[32bits]+bus_id[5bits]++3bits0+8bits0+16bits0
        reg_values = []
        data_ret = [0 for b in np.arange(9)]
        new_Bytes = [0 for b in np.arange(9)]
        responsereg = Analysis().binToHexa(bin(int(reg[0],16))[2:].zfill(32)
                                           +bin(int(reg[1],16))[2:].zfill(32)
                                           +bin(int(reg[2],16))[2:].zfill(32))
        for r in reg:
            try:
                reg_values = np.append(reg_values,hex(r))
            except:
                reg_values = np.append(reg_values,r)
        msg_bin_0 = bin(int(reg_values[0],16))[2:].zfill(32)
        msg_bin_1 = bin(int(reg_values[1],16))[2:].zfill(32)
        msg_bin_2 = bin(int(reg_values[2],16))[2:].zfill(32)
        data_ret  = [hex(Analysis().binToHexa(msg_bin_0[0:12]))#cobid
                   ,hex(Analysis().binToHexa(msg_bin_0[12:20]))
                   ,hex(Analysis().binToHexa(msg_bin_0[20:28]))
                   ,hex(Analysis().binToHexa(msg_bin_0[28:32]+msg_bin_1[0:4]))
                   ,hex(Analysis().binToHexa(msg_bin_1[4:12]))
                   ,hex(Analysis().binToHexa(msg_bin_1[12:20]) )
                   ,hex(Analysis().binToHexa(msg_bin_1[20:28]) )
                   ,hex(Analysis().binToHexa(msg_bin_1[28:32]+msg_bin_2[0:4]))
                   ,hex(Analysis().binToHexa(msg_bin_2[4:12]) )]
        new_Bytes= [data_ret[0],data_ret[1],data_ret[3],data_ret[2],data_ret[4],data_ret[8],data_ret[7],data_ret[6],data_ret[5]]

        for i in range(len(data_ret)):
            if new_Bytes[i] =='': new_Bytes[i]=0
        else:   pass
        return new_Bytes, responsereg

    def dumpMessage(self, cobid, msg, t):
        """Dumps a uhal message to the screen and log file
        Parameters
        ----------
        cobid : :obj:`int`
            |CAN| identifier
        msg : :obj:`bytes`
            |CAN| data - max length 8
        t : obj'int'
        """
        msgstr = '{:3X} {:d}   '.format(cobid, 8)
        for i in range(len(msg)):
            msgstr += '{:02x}  '.format(msg[i])
        msgstr += '    ' * (8 - len(msg))
        st = datetime.datetime.fromtimestamp(t).strftime('%H:%M:%S')
        msgstr += str(st)
        self.logger.info(msgstr)

    def enable_read_signal (self,timeout =None, out_msg = None):
         #wait for interrupt signal from FIFO
        hw = self.get_uhal_hardware()
        count, count_limit = 0, 2
        #irq_tra_sig = 0x0
        while (count !=count_limit):
            irq_tra_sig =   self.read_uhal_message(hw = hw,
                                                    node =self.get_ual_node(hw =hw, registerName = "reg3"),
                                                    registerName="reg3", timeout=timeout, out_msg = None)
            count= count+1
            if out_msg: self.logger.info(f'Read irq_tra_sig =  {irq_tra_sig} Count ({count})')
            time.sleep(timeout)
            if irq_tra_sig >=0x1:break
        #Read data  from FIFO
        if irq_tra_sig>0x0:
            found_msg =True
            if out_msg: self.logger.info(f'Found Message in the buffer (irq_tra_sig = {irq_tra_sig})')
            # Start read elink
            self.write_uhal_message(hw = hw,
                                         node =self.get_ual_node(hw =hw, registerName = "reg10"),
                                         registerName="reg10",
                                         data = 0x1,
                                         timeout=timeout, out_msg = False)
        else:
            found_msg = False
            self.logger.warning(f'Nothing Found in the buffer (irq_tra_sig = {irq_tra_sig})')
        return found_msg

    def read_uhal_mopshub_message(self, reg =None, timeout=None,  out_msg = True):
        hw = self.get_uhal_hardware()
        nodes = []
        reg_values = []
        respmsg = 0
        msg_found =  self.enable_read_signal(timeout= timeout, out_msg = out_msg)
        if msg_found:
            for r in reg:
                nodes = np.append(nodes,self.get_ual_node(hw =hw, registerName = r))
                reg_value = nodes[reg.index(r)].read()
                # Send IPbus transactions
                hw.dispatch()
                #time.sleep(timeout)#The code has really developed afer commenting this line
                if out_msg: self.logger.info(f'Read {r} Value = {hex(reg_value.value())}')
                reg_values = np.append(reg_values,hex(reg_value.value()))
            respmsg = 1
            t = time.time()
            data, responsereg =  self.build_response_sdo_msg(reg = reg_values, out_msg=out_msg)
            cobid = int(data[0],16)
            data_ret = [0 for b in np.arange(len(data)-1)]
            for i in np.arange(len(data_ret)): data_ret[i] = int(data[i+1],16)
            if out_msg: self.dumpMessage(cobid, data_ret, t)
            self.__uhalMsgQueue.appendleft((cobid, data_ret, t))
            return cobid, bytearray(data_ret), respmsg, hex(responsereg), t
        else:
            respmsg = 0
            self.__cnt["messageFailed_response"] =self.__cnt["messageFailed_response"]+ 1
            return None, None, respmsg, None, None

    def  return_valid_message(self, nodeId, index, subindex, cobid_ret, data_ret, SDO_TX, SDO_RX,timeout):
        messageValid = False
        status = 0
        respmsg, responsereg = 0, None
        messageValid_queue = False
        t0 = time.perf_counter()
        while time.perf_counter() - t0 < 1 and messageValid_queue == False:
                # check the message validity [nodid, msg size,...]
                for i, (cobid_ret, data_ret, t) in zip(range(len(self.__uhalMsgQueue)), self.__uhalMsgQueue):
                    messageValid_queue = (cobid_ret == SDO_RX + nodeId
                                    and data_ret[0] in [0x80, 0x43, 0x47, 0x4b, 0x4f, 0x42]
                                    and int.from_bytes([data_ret[1], data_ret[2]], 'little') == index
                                    and data_ret[3] == subindex)

                    if (messageValid_queue):
                        del self.__uhalMsgQueue[i]
                        break
                if (messageValid_queue ==False):
                    _, _, respmsg, responsereg, _ = self.read_uhal_mopshub_message(reg = ["reg0","reg1","reg2"], timeout=timeout, out_msg = None)
                self.__uhalMsgThread.join()
        # The following are the only expected response
        #
        # messageValid = (cobid_ret == SDO_RX + nodeId
        #                 and data_ret[0] in [0x80, 0x43, 0x47, 0x4b, 0x4f, 0x42]
        #                 and int.from_bytes([data_ret[1], data_ret[2]], 'little') == index
        #                 and data_ret[3] == subindex)
        if messageValid_queue:
            status = 1
            nDatabytes = 4 - ((data_ret[0] >> 2) & 0b11) if data_ret[0] != 0x42 else 4
            data = []
            for i in range(nDatabytes-1):
                data.append(data_ret[4 + i])
            return int.from_bytes(data, 'little'), messageValid_queue, status, respmsg, responsereg
        else:
            status = 0
            self.logger.info(f'SDO read response timeout (node {nodeId}, index'
                 f' {index:04X}:{subindex:02X})')
            self.__cnt["messageInvalid_queue"]=self.__cnt["messageInvalid_queue"]+1
            return None, messageValid_queue, status, respmsg, responsereg

    def read_adc(self,hw, bus_id,timeout):
        self.logger.debug(f'CIC Channel {bus_id} - ADC readout')

        adc_result = [[int(), int()] for _ in range(4)]
        adc_info = []
        self.logger.debug("Read ADC channels:")
        counter = 0
        for address in self.__address_byte:
            #adc_out = self.spi.xfer2([address, 0x00, 0x00, 0x00, 0x00])
            _, _, _, adc_out =  self.read_monitoring_uhal(hw =hw,
                                                              cobid = 0x20,
                                                              spi_reg =address,
                                                              spi_id=bus_id,
                                                              timeout=timeout,
                                                              out_msg =False)
            time.sleep(0.7)
            last_bits = bin(adc_out[4])[6:][:2]
            adc_info.append(adc_out)
            if adc_out[4] == 255:
                adc_result[int(last_bits, 2)][0] = self.__address_byte.index(address)
                adc_result[int(last_bits, 2)][1] = -1
            # search in the last four bits channel indicator bits
            elif last_bits in {'00', '01', '10'}:#indicates which physical inputs to be converted
                if bin(adc_out[4])[9:] == '1':
                    self.logger.warning(
                        f"OF-Error during ADC Readout of phy. channel {int(last_bits, 2)}")
                    self.cnt[f"OF-ERROR Channel {int(last_bits, 2)}"] += 1
                    self.logger.warning(adc_out[4])
                if bin(adc_out[4])[8:][:1] == '1':
                    self.logger.warning(
                        f"OD-Error during ADC Readout of phy. channel {int(last_bits, 2)}")
                    self.cnt[f"OD-ERROR Channel {int(last_bits, 2)}"] += 1
                    self.logger.warning(adc_out[4])
                try:#ch1 is Ucurr(in volt) has a apecial conversion
                    if last_bits == '01':
                        value = round(((adc_out[2] * 256 + adc_out[3]) * 0.03814697), 3)
                    else:
                        value = round(((adc_out[2] * 256 + adc_out[3]) * 0.03814697 / 1000), 3)
                    adc_result[int(last_bits, 2)][0] = int(last_bits, 2)
                    adc_result[int(last_bits, 2)][1] = value  # 2,5V Ref
                except ZeroDivisionError:
                    adc_result[int(last_bits, 2)][0] = int(last_bits, 2)
                    adc_result[int(last_bits, 2)][1] = -1
            elif last_bits == '11':
                if bin(adc_out[4])[9:] == '1':
                    self.logger.warning(
                        f"OF-Error during ADC Readout of phy. channel {int(last_bits, 2)}")
                    self.cnt[f"OF-ERROR Channel {int(last_bits, 2)}"] += 1
                    self.logger.warning(adc_out[4])
                if bin(adc_out[4])[8:][:1] == '1':
                    self.logger.warning(
                        f"OD-Error during ADC Readout of phy. channel {int(last_bits, 2)}")
                    self.cnt[f"OF-ERROR Channel {int(last_bits, 2)}"] += 1
                    self.logger.warning(adc_out[4])
                try:
                    v_ntc = round(((adc_out[2] * 256 + adc_out[3]) * 0.03814697 / 1000), 3)
                    r_ntc = v_ntc * (20 / 2.5)
                    value = round((298.15 / (1 - (298.15 / 3435) * np.log(10 / r_ntc))) - 273.15, 3)
                    adc_result[int(last_bits, 2)][0] = int(last_bits, 2)
                    adc_result[int(last_bits, 2)][1] = value
                except ZeroDivisionError:
                    adc_result[int(last_bits, 2)][0] = int(last_bits, 2)
                    adc_result[int(last_bits, 2)][1] = -1
            else:
                adc_result[self.__address_byte.index(address)][0] = self.__address_byte.index(address)
                adc_result[self.__address_byte.index(address)][1] = -1
                counter += 1
                self.cnt["error_cnt"] += 1
                if counter % 5 == 0:
                    self.cnt["bad_readout"] += 1
                    self.logger.warning(f"Bad readout - {adc_result} - {self.cnt}")

        if self.cnt["bad_readout"] % 3 == 1:
            self.cnt["reset_cnt"] += 1
            #self.cs5523_startup(spi_cs, bus_id, mp_id)
            self.logger.warning(f"Restart ADC on Bus {bus_id}")

        # print(f"ADC readout finished: Bus_id: {bus_id} - {adc_result}")
        self.logger.debug(f"ADC readout finished: Bus_id: {bus_id} - {adc_result}")
        return

    def read_monitoring_uhal(self,hw =None, spi_reg =None, spi_id=None,cobid = 0X20, timeout=1,out_msg=None):
        status =0;
        respmsg, responsereg  = 0, None
        #build Payload in a CAN SDO format
        mon_reg6_hex = Analysis().binToHexa(bin(cobid)[2:].zfill(8)+
                                            bin(spi_id)[2:].zfill(8)+
                                            bin(spi_reg)[2:].zfill(8)+
                                            bin(0)[2:].zfill(8))
        reqmsg =  self.write_uhal_mopshub_message(hw =hw,
                                              data=[mon_reg6_hex,0x0,0x0,0xa],
                                              reg = ["reg6","reg7","reg8","reg9"],
                                              timeout=timeout,
                                              out_msg = out_msg)
        #read the response from the socket
        _frame  =  self.read_uhal_mopshub_message(reg = ["reg0","reg1","reg2"],
                                                        timeout=timeout,
                                                        out_msg = out_msg)
        hw.dispatch()
        _, msg_ret,respmsg_ret, responsereg_ret, t = _frame
        if (not all(m is None for m in _frame[0:2])):
            responsereg_ret = bin(int(responsereg_ret,16))[2:].zfill(96)
            cobid_ret    = hex(Analysis().binToHexa(responsereg_ret[0:8]))
            spi_id_ret   = hex(Analysis().binToHexa(responsereg_ret[8:16]))
            spi_reg_ret  = hex(Analysis().binToHexa(responsereg_ret[16:24]))

            adc_out =   [hex(Analysis().binToHexa(responsereg_ret[24:32])),
                         hex(Analysis().binToHexa(responsereg_ret[32:40])),
                         hex(Analysis().binToHexa(responsereg_ret[40:48])),
                         hex(Analysis().binToHexa(responsereg_ret[48:56])),
                         hex(Analysis().binToHexa(responsereg_ret[56:64]))]
            xadc_code =  Analysis().binToHexa(responsereg_ret[64:76])
            temp_xadc = xadc_code*503.975/4096-273.15
            if out_msg: self.logger.info(f'cobid_ret:{cobid_ret}|| spi_id_ret: {spi_id_ret}||spi_reg_ret:{spi_reg_ret}||adc_out:{adc_out})')
            if out_msg: self.logger.info(f'FPGA temp_xadc:{round(temp_xadc,2)} C')
            adc_out =[int(adc_out[i],16) for i in range(len(adc_out))]
            last_bits = bin(adc_out[4])[2:][4:]
            print(hex(spi_reg),last_bits[1:3], adc_out, bin(adc_out[4])[2:])
            return cobid_ret, spi_id_ret, spi_reg_ret, adc_out
        else:
            status = 0
        #     if responsereg is not None: return None, reqmsg, hex(responsereg),respmsg, responsereg, status
            return None, None, None, None
        #

    def read_sdo_uhal(self,hw= None, bus= None, nodeId=None, index=None, subindex=None, timeout=1, SDO_TX=0x600, SDO_RX=0x580,out_msg=None):
        """Read an object via |SDO|

        Currently expedited and segmented transfer is supported by this method.
        The function will writing the dictionary request from the master to the node then read the response from the node to the master
        The user has to decide how to decode the data.

        Parameters
        ----------
        nodeId : :obj:`int`
            The id from the node to read from
        index : :obj:`int`
            The Object Dictionary index to read from
        subindex : :obj:`int`
            |OD| Subindex. Defaults to zero for single value entries.
        timeout : :obj:`int`, optional
            |SDO| timeout in milliseconds

        Returns
        -------
        :obj:`list` of :obj:`int`
            The data if was successfully read
        :data:`None`
            In case of errors
        """
        status =0;
        respmsg, responsereg  = 0, None
        if nodeId is None or index is None or subindex is None:
            self.logger.warning('SDO read protocol cancelled before it could begin.')
            self.__cnt["SDO read total"] = self.__cnt["SDO read total"]+1
            return None, None, None,respmsg, responsereg , status
        hw =  self.get_uhal_hardware()
        #build Payload in a CAN SDO format
        reg6_hex, reg7_hex, reg8_hex, requestreg = self.build_request_sdo_msg(cobid = SDO_TX+nodeId, bus = bus,  index=index, subindex=subindex)

        #write the Request to the Socket
        try:
            reqmsg =  self.write_uhal_mopshub_message(hw =hw,
                                                  data=[reg6_hex,reg7_hex,reg8_hex,0xa],
                                                  reg = ["reg6","reg7","reg8","reg9"],
                                                  timeout=timeout,
                                                  out_msg = out_msg)
        except:
            reqmsg = 0
        #read the response from the socket
        _frame  =  self.read_uhal_mopshub_message(reg = ["reg0","reg1","reg2"],
                                                       timeout=timeout,
                                                       out_msg = out_msg)
        hw.dispatch()
        cobid_ret, msg_ret,respmsg_ret, responsereg_ret, t = _frame
        if (not all(m is None for m in _frame[0:2])):
           data_ret, messageValid, status,respmsg, responsereg  =  self.return_valid_message(nodeId=nodeId,
                                                                                index=index,
                                                                                subindex=subindex,
                                                                                cobid_ret=cobid_ret,
                                                                                data_ret=msg_ret,
                                                                                SDO_TX=SDO_TX, SDO_RX=SDO_RX,
                                                                                timeout=timeout)
           if responsereg is None:
               responsereg = responsereg_ret
               respmsg = respmsg_ret
           # Check command byte
           if msg_ret[0] == (0x80):
                status =0
                abort_code = int.from_bytes(msg_ret[4:], 'little')
                self.logger.error(f'Received SDO abort message while reading '
                                  f'object {index:04X}:{subindex:02X} of node '
                                  f'{nodeId} with abort code {abort_code:08X}')
                if requestreg is not None: return None, reqmsg, hex(requestreg),respmsg, responsereg, status
                else : return None, reqmsg, requestreg,respmsg, responsereg, status
           else:
                return data_ret , reqmsg, hex(requestreg), respmsg, responsereg  , status

        else:
            status = 0
            if responsereg is not None: return None, reqmsg, hex(responsereg),respmsg, responsereg, status
            else : return None, reqmsg, hex(requestreg),respmsg, responsereg, status

    def build_request_sdo_msg(self,bus = None, cobid = None, index=None, subindex=None,msg_0 =0x40):
        max_data_bytes = 8
        msg = [0 for i in range(max_data_bytes)]
        msg[0] = msg_0
        msg[1], msg[2] = index.to_bytes(2, 'little')
        msg[3] = subindex
        msg_bin_0 = bin(msg[0])[2:].zfill(8)
        msg_bin_1 = bin(msg[1])[2:].zfill(8)
        msg_bin_2 = bin(msg[2])[2:].zfill(8)
        msg_bin_3 = bin(msg[3])[2:].zfill(8)
        reg6_hex = Analysis().binToHexa(bin(cobid)[2:].zfill(12)#12bits
                                        +msg_bin_0#8bits
                                        +msg_bin_2#8bits
                                        +msg_bin_1[0:4]#4bits
                                        )

        reg7_hex = Analysis().binToHexa(msg_bin_1[4:8]#4bits
                                        +msg_bin_3#8bits
                                        +bin(bus)[2:].zfill(8)#8bits
                                        +bin(0)[2:].zfill(8)#8bits
                                        +bin(0)[2:].zfill(4))#4bits

        reg8_hex = Analysis().binToHexa(bin(0)[2:].zfill(32))

        requestreg = Analysis().binToHexa(bin(cobid)[2:].zfill(12)#12bits
                                        +msg_bin_0#8bits
                                        +msg_bin_2#8bits
                                        +msg_bin_1#bin(0)[2:].zfill(4)#4bits
                                        #+bin(0)[2:].zfill(4)#4bits
                                        +msg_bin_3#8bits
                                        +bin(bus)[2:].zfill(8)#8bits
                                        +bin(0)[2:].zfill(8)#it was msg_bin_1 8bits
                                        +bin(0)[2:].zfill(4)
                                        +bin(0)[2:].zfill(32))
        return reg6_hex, reg7_hex, reg8_hex, requestreg

    def create_mopshub_adc_data_file(self,outputname, outputdir):
        # Write header to the data
        fieldnames = ['time',"test_tx",'bus_id',"nodeId","adc_ch","index","sub_index","adc_data", "adc_data_converted","reqmsg","requestreg","respmsg","responsereg", "status"]
        csv_writer = AnalysisUtils().build_data_base(fieldnames=fieldnames,outputname = outputname, directory = outputdir)
        return csv_writer

    def read_mopshub_adc_channels(self, hw, bus_range, file, directory,outputname, outputdir , nodeId, n_readings,timeout,csv_writer):
        """Start actual CANopen communication
        This function contains an endless loop in which it is looped over all
        ADC channels. Each value is read using
        :meth:`read_sdo_can_thread` and written to its corresponding
        """
        self.logger.info(f'Reading ADC channels of Mops with ID {nodeId}')
        dev = AnalysisUtils().open_yaml_file(file=file, directory=directory)
        # yaml file is needed to get the object dictionary items
        _adc_channels_reg = dev["adc_channels_reg"]["adc_channels"]
        _adc_index = list(dev["adc_channels_reg"]["adc_index"])[0]
        _channelItems = [int(channel) for channel in list(_adc_channels_reg)]
        # Write header to the data
        #fieldnames = ['time',"test_tx",'bus_id',"nodeId","adc_ch","index","sub_index","adc_data", "adc_data_converted","reqmsg","requestreg","respmsg","responsereg", "status"]
        #csv_writer = AnalysisUtils().build_data_base(fieldnames=fieldnames,outputname = outputname, directory = outputdir)
        monitoringTime = time.time()
        for point in np.arange(0, n_readings):
            for bus in bus_range:
                for node in nodeId:
                    # Read ADC channels
                    for c in tqdm(np.arange(len(_channelItems)),colour="green"):
                        channel =  _channelItems[c]
                        subindex = channel - 2
                        data_point, reqmsg, requestreg, respmsg,responsereg , status =  self.read_sdo_uhal(hw =hw,
                                                                                bus = bus,
                                                                                nodeId= node,
                                                                                index = int(_adc_index, 16),
                                                                                subindex = subindex,
                                                                                timeout = timeout,
                                                                                out_msg = False)

                        #time.sleep(0.01) #It makes no difference
                        ts = time.time()
                        elapsedtime = ts - monitoringTime
                        if data_point is not None:
                            adc_converted = Analysis().adc_conversion(_adc_channels_reg[str(channel)], data_point)
                            adc_converted = round(adc_converted, 3)
                            self.logger.info(f'[{point}] Got data for channel {channel} [{hex(subindex)}]: = {adc_converted}')
                        else:
                            adc_converted = None
                        csv_writer.writerow((str(elapsedtime),
                                             str(1),
                                             str(bus),
                                             str(node),
                                             str(channel),
                                             str(_adc_index),
                                             str(subindex),
                                             str(data_point),
                                             str(adc_converted),
                                             str(reqmsg),
                                             str(requestreg),
                                             str(respmsg),
                                             str(responsereg),
                                             status))

        self.logger.info(f'No. of invalid responses = {self.__cnt["messageInvalid_queue"]}|| No. of failed responses = {self.__cnt["messageFailed_response"]-1}')
        #self.logger.notice("ADC data are saved to %s/%s" % (outputdir,outputname))

    # Setter and getter functions
    def set_uhal_hardware(self, x):
        self.__hw = x

    def set_nodeList(self, x):
        self.__nodeList = x

    def set_channelPorts(self, x):
        self.__can_channels = x

    def set_channel(self, x):
        self.__channel = x

    def set_ipAddress(self, x):
        self.__ipAddress = x

    def set_bitrate(self, bitrate):
        if self.__interface == 'Kvaser':
            self.__bitrate = bitrate
        else:
            self.__bitrate = bitrate

    def set_sample_point(self, x):
        self.__sample_point = float(x)

    def get_DllVersion(self):
        ret = analib.wrapper.dllInfo()
        return ret

    def get_nodeList(self):
        return self.__nodeList

    def get_channelPorts(self):
        return self.__can_channels

    def get_bitrate(self):
        return self.__bitrate

    def get_sample_point(self):
        return self.__sample_point

    def get_ipAddress(self):
        """:obj:`str` : Network address of the AnaGate partner. Only used for
        AnaGate CAN interfaces."""
        if self.__interface == 'Kvaser':
            raise AttributeError('You are using a Kvaser CAN interface!')
        return self.__ipAddress

    def get_uhal_hardware(self):
        """:obj:`str` : Vendor of the CAN interface. Possible values are
        ``'Kvaser'`` and ``'AnaGate'``."""
        return self.__hw

    def get_channel(self):
        """:obj:`int` : Number of the crurrently used |CAN| channel."""
        return self.__channel

    def get_channelState(self, channel):
        return channel.state

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception_value, traceback):
        if exception_type is KeyboardInterrupt:
            self.logger.warning('Received Ctrl+C event (KeyboardInterrupt).')
        else:
            self.logger.exception(exception_value)
        self.stop()
        logging.shutdown()
        return True

    @property
    def lock(self):
        """:class:`~threading.Lock` : Lock object for accessing the incoming
        message queue :attr:`canMsgQueue`"""
        return self.__lock

    @property
    def canMsgQueue(self):
        """:class:`collections.deque` : Queue object holding incoming |CAN|
        messages. This class supports thread-safe adding and removing of
        elements but not thread-safe iterating. Therefore the designated
        :class:`~threading.Lock` object :attr:`lock` should be acquired before
        accessing it.

        The queue is initialized with a maxmimum length of ``1000`` elements
        to avoid memory problems although it is not expected to grow at all.

        This special class is used instead of the :class:`queue.Queue` class
        because it is iterable and fast."""
        return self.__canMsgQueue

    @property
    def kvaserLock(self):
        """:class:`~threading.Lock` : Lock object which should be acquired for
        performing read or write operations on the Kvaser |CAN| channel. It
        turned out that bad things can happen if that is not done."""
        return self.__kvaserLock

    @property
    def cnt(self):
        """:class:`~collections.Counter` : Counter holding information about
        quality of transmitting and receiving. Its contens are logged when the
        program ends."""
        return self.__cnt

    @property
    def pill2kill(self):
        """:class:`threading.Event` : Stop event for the message collecting
        method :meth:`read_can_message_thread`"""
        return self.__pill2kill

    # @property
    def channel(self):
        """Currently used |CAN| channel. The actual class depends on the used
        |CAN| interface."""
        return self.ch0

    @property
    def bitRate(self):
        """:obj:`int` : Currently used bit rate. When you try to change it
        :func:`stop` will be called before."""
        if self.__interface == 'Kvaser':
            return self.__bitrate
        else:
            return self.ch0.baudrate

    @bitRate.setter
    def bitRate(self, bitrate):
        if self.__interface == 'Kvaser':
            self.stop()
            self.__bitrate = bitrate
            self.start()
        else:
            self.ch0.baudrate = bitrate

def main():
    """Wrapper function for using the server as a command line tool

    The command line tool accepts arguments for configuring the server which
    are transferred to the :class:`CanWrapper` class.
    """

    # Parse arguments
    parser = ArgumentParser(description='CANMOPS Interpreter for MOPS chip',
                            epilog='For more information contact '
                            'ahmed.qamesh@cern.ch',
                            formatter_class=ArgumentDefaultsHelpFormatter)

    parser.set_defaults(interface='socketcan')
    # CAN interface
    CGroup = parser.add_argument_group('CAN interface')
    iGroup = CGroup.add_mutually_exclusive_group()
    iGroup.add_argument('-K', '--kvaser', action='store_const', const='Kvaser',
                        dest='interface',
                        help='Use Kvaser CAN interface (default). When no '
                        'Kvaser interface is found or connected a virtual '
                        'channel is used.')
    iGroup.add_argument('-A', '--anagate', action='store_const',
                        const='AnaGate', dest='interface',
                        help='Use AnaGate Ethernet CAN interface')

    iGroup.add_argument('-S', '--socketcan', action='store_const',
                        const='socketcan', dest='interface',
                        help='Use socketcan  interface')

    # CAN settings group
    cGroup = parser.add_argument_group('CAN settings')
    cGroup.add_argument('-c', '--channel', metavar='CHANNEL',
                        help='Number of CAN channel to use',
                        default=0)

    cGroup.add_argument('-i', '--ipaddress', metavar='IPADDRESS',
                        default='192.168.1.254', dest='ipAddress',
                        help='IP address of the AnaGate Ethernet CAN '
                        'interface')
    cGroup.add_argument('-b', '--bitrate', metavar='BITRATE',
                        default=125000,
                        help='CAN bitrate as integer in bit/s')

    cGroup.add_argument('-sp', '--samplePoint', metavar='SAMPLEPOINT',
                        default=0.5,
                        help='CAN sample point in decimal')

    cGroup.add_argument('-sjw', '--sjw', metavar='SJW',
                        default=4,
                        help='Synchronization Jump Width')

    cGroup.add_argument('-tseg1', '--tseg1', metavar='tseg1',
                        default=0,
                        help='Time Segment1')

    cGroup.add_argument('-tseg2', '--tseg2', metavar='tseg2',
                        default=0,
                        help='Time Segment2')

    cGroup.add_argument('-nodeid', '--nodeid', metavar='nodeid',
                        default=0,
                        help='Node Id of the MOPS chip under test')

    # Logging configuration
    lGroup = parser.add_argument_group('Logging settings')
    lGroup.add_argument('-cl', '--console_loglevel',
                        choices={'NOTSET', 'SPAM', 'DEBUG', 'VERBOSE', 'INFO',
                                 'NOTICE', 'SUCCESS', 'WARNING', 'ERROR',
                                 'CRITICAL'},
                        default='INFO',
                        help='Level of console logging')

    args = parser.parse_args()

    # Start the server
    wrapper = CanWrapper(**vars(args))

class ConsumerThread(Thread):
    def run(self):
        global queue
        while True:
            lock.acquire()
            if not queue:
                print ("Nothing in queue, but consumer will try to consume")
            num = queue.pop(0)
            print ("Consumed", num)
            lock.release()
            time.sleep(random.random())

if __name__ == "__main__":
    main()

    ProducerThread().start()
    ConsumerThread().start()


"""Audio signal feature extraction utilitary functions."""
import librosa
import numpy as np

def extract_features(signal, freq=16000, n_mfcc=5, size=512, step=16):
    """Extract MFCC features from an audio signal.

    Args:
        signal (np.ndarray): audio signal
        freq (int, optional): MFCC features sampling rate. Defaults to 16000.
        n_mfcc (int, optional): number of MFCC features to extract. Defaults to 5.
        size (int, optional): MFCC features size. Defaults to 512.
        step (int, optional): MFCC features step. Defaults to 16.

    Returns:
        features (np.ndarray): MFCC features as an array
    """
    # Mel Frequency Cepstral Coefficents
    mfcc = librosa.feature.mfcc(
        y=signal,
        sr=freq,
        n_mfcc=n_mfcc,
        n_fft=size,
        hop_length=step,
    )
    mfcc_delta = librosa.feature.delta(mfcc)
    mfcc_delta2 = librosa.feature.delta(mfcc, order=2)

    # Root Mean Square Energy
    mel_spectogram = librosa.feature.melspectrogram(
        y=signal, sr=freq, n_fft=size, hop_length=step
    )
    rmse = librosa.feature.rms(S=mel_spectogram, frame_length=size, hop_length=step)

    mfcc = np.asarray(mfcc)
    mfcc_delta = np.asarray(mfcc_delta)
    mfcc_delta2 = np.asarray(mfcc_delta2)
    rmse = np.asarray(rmse)

    features = np.concatenate((mfcc, mfcc_delta, mfcc_delta2, rmse), axis=0)
    return features


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

# **************************
# src/main.py
# **************************

import datetime

from calculation import (
    calculate_line_daily_mileage,
    calculate_train_lenght,
    calculate_transportation_values
)
from changing import (
    update_wagons_attrs,
)
from classes import (
    Normatives,
    Registry
)
from confirmation import (
    confirm_possible_trains
)
from conversion import (
    convert_confirmed_trains,
    convert_preplanned_services,
    convert_wagons_attrs
)
from creation import (
    create_debug_file_output,
    create_trains,
    create_wagons
)
from normatives import (
    mileage_frequency_standards,
    service_duration_standards
)
from parsing import (
    convert_start_date,
    pars_wagons_data
)
from planning import (
    service_planning
)
from selection import (
    select_current_idle_end,
    select_extra_wagon_data_path,
    select_hitched_wagons,
    select_idle_wagons,
    select_line_motion_time,
    select_main_wagon_data_path,
    select_output_data_path,
    select_planning_end_date,
    select_possible_trains,
    select_preplanned_services,
    select_text_result_data_path,
    select_transportation_values,
    select_unhitched_wagons
)
from utility import (
    daterange,
    print_result_services_to_file
)
from verification import (
    verify_planning_results,
)

raw_start_date, raw_main_wagons_attrs = pars_wagons_data(
    select_main_wagon_data_path())

Registry.planning_start_date = convert_start_date(raw_start_date)

Registry.planning_end_date = select_planning_end_date()

Registry.mileage_standards = mileage_frequency_standards()
Registry.duration_standards = service_duration_standards()
wagons_attrs = convert_wagons_attrs(raw_main_wagons_attrs)

Registry.wagons = create_wagons(wagons_attrs,
                                start_date=Registry.planning_start_date,
                                end_date=Registry.planning_end_date)

update_wagons_attrs(pars_wagons_data(select_extra_wagon_data_path()))

hitched_wagons = select_hitched_wagons()
Registry.train_lenght = calculate_train_lenght(hitched_wagons)
Registry.unhitched_wagons = select_unhitched_wagons()
possible_trains = select_possible_trains()
confirmed_trains = confirm_possible_trains(possible_trains)
Registry.trains = create_trains(
    Registry.train_lenght, hitched_wagons, verbose=False)
if not confirmed_trains is None:
    Registry.trains.update(create_trains(
        Registry.train_lenght, convert_confirmed_trains(confirmed_trains)))

Registry.transportation_values = calculate_transportation_values(
    start_date=Registry.planning_start_date,
    end_date=Registry.planning_end_date,
    basic_values=select_transportation_values(),
    line_motion_time=select_line_motion_time())

calculate_line_daily_mileage()

for wagon_number, wagon_object in Registry.wagons.items():
    serv_date = Registry.wagons[wagon_number].usage_start_date
    wagon_object.change_idle_reason(serv_date,
                                    wagon_object.define_service_type(
                                        serv_date),
                                    verbose=False)

for train_object in Registry.trains.values():
    if not train_object.verify_wagons_idle_reasons(Registry.planning_start_date,
                                                   verbose=False):
        train_object.unify_train_service_type(Registry.planning_start_date,
                                              verbose=False)

# Проставляем на начало расчета отстой сцепу №904 (56009-56010) по ремонту редукторов
# ТОЛЬКО ДЛЯ РАСЧЕТА ОТ 31.03.2022!!!
for wagon_object in Registry.trains[904].wagons.values():
    wagon_object.change_idle_reason(Registry.planning_start_date,
                                    "o",
                                    verbose=False)

Registry.result_services = select_current_idle_end(
    select_idle_wagons(Registry.planning_start_date))

# Вносим в расчет информацию о выходе из ТОиР вагонов,
# находящихся в ТОиР на дату начала расчета
for service_type, periods in Registry.result_services.items():
    for (start_date, end_date), rolling_stock_data in periods.items():
        first_date = start_date + datetime.timedelta(days=1)
        for rolling_stock_type, objects in rolling_stock_data.items():
            for rolling_stock_object in objects:
                if rolling_stock_type == "trains":
                    for wagon_object in rolling_stock_object.wagons.values():
                        for date in daterange(first_date, end_date):
                            wagon_object.change_idle_reason(date,
                                                            service_type,
                                                            verbose=False)
                if rolling_stock_type == "single_wagons":
                    for date in daterange(first_date, end_date):
                        rolling_stock_object.change_idle_reason(date,
                                                                service_type,
                                                                verbose=False)

converted_preplanned_services = convert_preplanned_services(
    select_preplanned_services())
# print(converted_preplanned_services)  # debug
# Вносим в расчет информацию о предзапланированных ТОиР
for wagon_number, services in converted_preplanned_services.items():
    Registry.wagons[wagon_number].preplanned_services = services

service_types = (  # "sr",
    "tr3",
    "tr2",
    "tr1",
    # "to2",
    # "to1"
)

service_planning(service_types)
verify_planning_results(service_types)

create_debug_file_output(select_output_data_path())
print_result_services_to_file(select_text_result_data_path())

print("END")

# Откорректировать метод verify_wagons_idle_reasons для Train


import os
import csv
import re
from django.core.management import BaseCommand
from ifbcat_api.models import Credit
from ifbcat_api.models import Service
from ifbcat_api.models import ElixirCommunities
from ifbcat_api.models import Publication
from ifbcat.settings import BASE_DIR

class Command(BaseCommand):
    def import_service_from_csv_file(self):
        data_folder = os.path.join(BASE_DIR, './import_data')
        Service.objects.all().delete()
        Credit.objects.all().delete()
        ElixirCommunities.objects.all().delete()
        Publication.objects.all().delete()
        print(data_folder, 'data_folder')
        for data_file in os.listdir(data_folder):
            # name of the correct csv file
            if data_file == "services.csv":
                with open(os.path.join(data_folder, data_file), encoding='utf-8') as data_file:
                    data = csv.reader(data_file)
                    # skip first line as there is always a header
                    next(data)
                    # do the work
                    for data_object in data:
                        if data_object == []:
                            continue  # Check for empty lines
                        credit_list = []
                        service_name = data_object[0]
                        credit_name = data_object[1]

                        credit_laboratory = data_object[2]
                        credit_institute = data_object[3]
                        credit_adress = data_object[4]
                        credit_email = data_object[5]
                        try:

                            credit1, created = Credit.objects.get_or_create(
                                name=credit_name,
                                laboratory=credit_laboratory,
                                institute=credit_institute,
                                adress=credit_adress,
                                email=credit_email,
                            )

                            credit1.save()
                            credit_list.append(credit1)
                            display_format = "\nCredit, {}, has been saved."
                            print(display_format.format(credit1))
                        except Exception as ex:
                            print(str(ex))
                            msg = "\n\nSomething went wrong saving this credit: {}\n{}".format(credit1, str(ex))
                            print(msg)

                        credit_name2 = data_object[6]
                        credit_laboratory2 = data_object[7]
                        credit_institute2 = data_object[8]
                        credit_adress2 = data_object[9]
                        credit_email2 = data_object[10]
                        if data_object[6] != " ":

                            try:
                                credit2, created = Credit.objects.get_or_create(
                                    name=credit_name2,
                                    laboratory=credit_laboratory2,
                                    institute=credit_institute2,
                                    adress=credit_adress2,
                                    email=credit_email2,
                                )

                                credit2.save()
                                credit_list.append(credit2)
                                display_format = "\nCredit, {}, has been saved."
                                print(display_format.format(credit2))
                            except Exception as ex:
                                print(str(ex))
                                msg = "\n\nSomething went wrong saving this credit: {}\n{}".format(credit2, str(ex))
                                print(msg)

                        service_scope = data_object[11]

                        category = data_object[12]
                        category2 = category.split("\n")
                        service_is_tool = False
                        service_is_data = False
                        service_is_training = False
                        service_is_compute = False
                        service_is_interoperability = False
                        for category3 in category2:
                            if category3 == "Tool":
                                service_is_tool = True
                            elif category3 == "Data":
                                service_is_data = True
                            elif category3 == "Training":
                                service_is_training = True
                            elif category3 == "Compute":
                                service_is_compute = True
                            elif category3 == "Interoperability":
                                service_is_interoperability = True
                        service_description = data_object[13]
                        service_communities = data_object[14]
                        elixir_communities_name_bis = data_object[15]
                        elixir_communities_name = elixir_communities_name_bis.split("\n")
                        elixir_communities_list = []
                        elixir_community = ""
                        for community in elixir_communities_name:
                            if len(community) > 4:

                                try:

                                    elixir_community, created = ElixirCommunities.objects.get_or_create(
                                        name=community,
                                    )
                                    elixir_community.save()
                                    elixir_communities_list.append(elixir_community)
                                    display_format = "\nElixirCommunities, {}, has been saved."
                                    print(display_format.format(elixir_community))
                                except Exception as ex:
                                    print(str(ex))
                                    msg = "\n\nSomething went wrong saving this Elixir_communities: {}\n{}".format(
                                        elixir_community, str(ex)
                                    )
                                    print(msg)

                        service_year_created = data_object[16]
                        service_maturity = data_object[17].upper()
                        service_access = data_object[18]
                        service_quality = data_object[19]
                        service_usage = data_object[20]
                        service_publication_citations_nb = data_object[21]
                        service_publication_coauthor_nb = data_object[22]
                        publications_doi = []
                        doi = data_object[23]
                        doi_split = doi.split("\n")
                        for line in doi_split:
                            match = re.findall(r'(10.[0-9]{4,9}[A-Za-z0-9:;\)\(_/.-]+)', line)
                            if str(match) != '[]':
                                try:

                                    publication, created = Publication.objects.get_or_create(
                                        doi=str(match).strip('[]').strip('\'\''),
                                    )

                                    publication.save()
                                    publications_doi.append(publication)
                                except Exception as ex:
                                    print(str(ex))
                                    msg = "\n\nSomething went wrong saving this publication: {}\n{}".format(
                                        publication, str(ex)
                                    )
                                    print(msg)
                            else:
                                continue

                        service_sab_user_comittee = data_object[25]
                        service_term_of_use = data_object[26]
                        service_ethics_policy = data_object[27]
                        service_funding = data_object[28]
                        motivation = data_object[29]
                        motivation_split = motivation.split("\n")
                        for motivations in motivation_split:
                            if motivations == "be registered in the IFB catalogue of tools":
                                service_motivation_catalog = True
                            if motivations == "be registered as an ELIXIR service (in its SDP)":
                                service_motivation_sdp = True
                        service_motivation_support_ifb_it = False
                        service_motivation_support_ifb_curation = False
                        service_motivation_support_ifb_core_resource = False
                        support = data_object[30]
                        support_split = support.split("\n")
                        for supports in support_split:
                            if supports == "IT support (computation/storage)":
                                service_motivation_support_ifb_it = True
                            elif supports == "curation (tools and network of experts)":
                                service_motivation_support_ifb_curation = True
                            elif supports == "support for the application to become an ELIXIR core resource":
                                service_motivation_support_ifb_core_resource = True

                        service = ""
                        try:

                            service, created = Service.objects.get_or_create(
                                name=service_name,
                                scope=service_scope,
                                is_tool=service_is_tool,
                                is_data=service_is_data,
                                is_training=service_is_training,
                                is_compute=service_is_compute,
                                is_interoperability=service_is_interoperability,
                                description=service_description,
                                communities=service_communities,
                                year_created=service_year_created,
                                maturity=service_maturity,
                                access=service_access,
                                quality=service_quality,
                                usage=service_usage,
                                publication_citations_nb=service_publication_citations_nb.replace(",", ""),
                                publication_coauthor_nb=service_publication_coauthor_nb.replace(",", ""),
                                sab_user_comittee=service_sab_user_comittee,
                                term_of_use=service_term_of_use,
                                ethics_policy=service_ethics_policy,
                                funding=service_funding,
                                motivation_catalog=service_motivation_catalog,
                                motivation_sdp=service_motivation_sdp,
                                motivation_support_ifb_it=service_motivation_support_ifb_it,
                                motivation_support_ifb_curation=service_motivation_support_ifb_curation,
                                motivation_support_ifb_core_resource=service_motivation_support_ifb_core_resource,
                            )

                            if created:
                                service.save()

                                display_format = "\nService, {}, has been saved."
                                print(display_format.format(service))
                                for credit_service in credit_list:
                                    service.credit.add(credit_service)
                                    print(credit_service)
                                for service_elixir_community in elixir_communities_list:
                                    service.elixir_communities.add(service_elixir_community)
                                for service_pub in publications_doi:
                                    service.key_pub.add(service_pub)

                                service.save()

                        except Exception as ex:
                            print(str(ex))
                            msg = "\n\nSomething went wrong saving this service: {}\n{}".format(service, str(ex))
                            print(msg)

    def handle(self, *args, **options):
        """
        Call the function to import data
        """
        self.import_service_from_csv_file()


from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor, endpoints
from twisted.web.static import File

root = Resource()
root.putChild(b"game", File("./www.godfield.net/game"))
root.putChild(b"scripts", File("./www.godfield.net/scripts"))
root.putChild(b"stylesheets", File("./www.godfield.net/stylesheets"))
root.putChild(b"en.html", File("./www.godfield.net/en.html"))
root.putChild(b"favicon.ico", File("./www.godfield.net/favicon.ico"))
root.putChild(b"index.html", File("./www.godfield.net/index.html"))
root.putChild(b"crossdomain.xml", File("./static.godfield.net/crossdomain.xml"))
root.putChild(b"images", File("./static.godfield.net/images"))
root.putChild(b"sounds", File("./static.godfield.net/sounds"))

factory = Site(root)
endpoint = endpoints.TCP4ServerEndpoint(reactor, 80)
endpoint.listen(factory)
print("Server listening for new connections")
reactor.run()


import sys
import heapq
from collections import namedtuple

stdin = sys.stdin

Query = namedtuple('Query', 'id period')

if __name__ == '__main__':
    queries = []
    for row in stdin:
        row = row.strip()
        if '#' in row:
            n = int(stdin.readline().strip())
            break
        q = Query(*list(map(int, row.split()[1:])))
        queries.append(q)

    heap_smallest_to_largest = []
    heap_largest_to_smallest = []

    queries.sort(key=lambda x: x.period)
    n_queries = 0
    for i in range(1, n+1):
        for q in queries:
            if len(heap_smallest_to_largest) >= n:
                largest = abs(heap_largest_to_smallest[0][0])
                if q.period * i > largest:
                    break
            heapq.heappush(heap_largest_to_smallest, (-q.period * i, q.id))
            heapq.heappush(heap_smallest_to_largest, (q.period * i, q.id))

    while n_queries < n:
        print(heapq.heappop(heap_smallest_to_largest)[1])
        n_queries += 1