#!/usr/bin/env python3
# vim: set expandtab tabstop=4 shiftwidth=4:

# Copyright (c) 2018, CJ Kucera
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the development team nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL CJ KUCERA BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import os
import sys
import argparse

# Takes a source text file containing "expanded", easy-to-edit-by-hand-in-a-text-editor
# Borderlands mod definitions, and compresses them into a destination text file
# containing single "set" lines that are actually usable by Borderlands.
#
# For instance, the following could be a command in the easily-editable file:
#
#     set GD_Itempools.WeaponPools.Pool_Weapons_All_06_Legendary BalancedItems
#     (
#         (
#             ItmPoolDefinition=ItemPoolDefinition'GD_Gladiolus_Itempools.WeaponPools.Pool_Weapons_AssaultRifles_07_LegendaryPlusPearl',
#             InvBalanceDefinition=None,
#             Probability=(
#                 BaseValueConstant=1.000000,
#                 BaseValueAttribute=None,
#                 InitializationDefinition=AttributeInitializationDefinition'GD_Balance.Weighting.Weight_1_Common',
#                 BaseValueScaleConstant=2.000000
#             ),
#             bDropOnDeath=True
#         )
#     )
#
# ... running this against the source file will generate the following:
#
#    set GD_Itempools.WeaponPools.Pool_Weapons_All_06_Legendary BalancedItems ((ItmPoolDefinition=ItemPoolDefinition'GD_Gladiolus_Itempools.WeaponPools.Pool_Weapons_AssaultRifles_07_LegendaryPlusPearl',InvBalanceDefinition=None,Probability=(BaseValueConstant=1.000000,BaseValueAttribute=None,InitializationDefinition=AttributeInitializationDefinition'GD_Balance.Weighting.Weight_1_Common',BaseValueScaleConstant=2.000000),bDropOnDeath=True))
#
# Note that this does NOT process "hotfix" type patches at all; it's only good
# for "set" style commands.
#
# The "source" filename used is expected to have a suffix of "-source.txt", and
# the utility will write to the same filename minus "-source".  You can pass
# in either the destination or the source file and the utility will understand
# what to do with either.

parser = argparse.ArgumentParser(
    description='Converts human-editable Borderlands mod files into proper mod format',
    epilog='The source filename must have a suffix of "-source.txt", and the '
        'destination filename will have the same name minus "-source".  The '
        '"filename" argument can be either the source or destination filename, '
        'and the utility should figure out what to do from there.'
    )
parser.add_argument('-f', '--force',
    action='store_true',
    help='Force overwriting the destination file')
parser.add_argument('filename', nargs=1)
args = parser.parse_args()

input_file = args.filename[0]
if input_file[-11:] == '-source.txt':
    source_file = input_file
    dest_file = '{}.txt'.format(input_file[:-11])
else:
    source_file = '{}-source.txt'.format(input_file)
    dest_file = '{}.txt'.format(input_file)
print('Chosen source filename: {}'.format(source_file))
print('Chosen destination filename: {}'.format(dest_file))

# Check to make sure our source file exists
if not os.path.exists(source_file):
    print('File "{}" does not exist!'.format(source_file))
    sys.exit(1)

# Ask to overwrite if the dest file exists and we're not forcing
if os.path.exists(dest_file) and not args.force:
    user_resp = input('File "{}" exists already.  Overwrite it? [y|N] >'.format(dest_file))
    if len(user_resp) > 0 and user_resp[0].lower() == 'y':
        print('Continuing...')
    else:
        print('Exiting!')
        sys.exit(2)

# Now do the processing
print('Writing to "{}"'.format(dest_file))
with open(source_file, 'r') as df:
    with open(dest_file, 'w') as odf:
        in_set = False
        set_list = []
        for (linenum, line) in enumerate(df.readlines()):
            if in_set:
                line = line.strip()
                if line == '':
                    odf.write(''.join(set_list))
                    odf.write("\n\n")
                    in_set = False
                elif line[:4] == 'set ' or line[0] == '#':
                    raise Exception('Input file line {}: "set" statements should have an empty line after the end'.format(linenum))
                else:
                    set_list.append(line)
            elif line.lstrip()[:4] == 'set ' or line.lstrip()[:5] == '#set ':
                set_list = ['{} '.format(line.rstrip())]
                in_set = True
            else:
                odf.write(line)
        if in_set:
            odf.write(''.join(set_list))
            odf.write("\n\n")

# Report that we're done
print('Done!')


"""
Author: Le Bui Ngoc Khang
Date: 12/07/1997
Problem: Five Star Retro Video rents VHS tapes and DVDs to the same connoisseurs who like to buy LP record albums.
The store rents new videos for $3.00 a night, and oldies for $2.00 a night. Write a program that the clerks at Five
Star Retro Video can use to calculate the total charge for a customer’s video rentals. The program should prompt the
user for the number of each type of video and output the total cost.

Solution:
Enter the number of new videos: 18
Enter the number of oldies: 4
The total cost is $: 62.0

"""
# Initialize constants
NEW_RENTAL= 3.00
OLDIE_RENTAL= 2.00
# Request the inputs
newOnes=int(input("Enter the number of new videos: "))
oldOnes=int(input("Enter the number of oldies: "))
# compute the results
totalCost= newOnes * NEW_RENTAL +  oldOnes * OLDIE_RENTAL
# display the results
print("The total cost is $: "+ str(round(totalCost, 2)))


#! /usr/bin/env python
import rospy
import time
import actionlib
from my_sphero_actions.msg import record_odomGoal, record_odomFeedback, record_odomResult, record_odomAction
from nav_msgs.msg import Odometry

def feedback_callback(feedback):
    rospy.loginfo("Rec Odom Feedback feedback ==>"+str(feedback))

def count_seconds(seconds):
    for i in range(seconds):
        rospy.loginfo("Seconds Passed =>"+str(i))
        time.sleep(1)

if __name__ == "__main__":
    rospy.init_node('record_odom_action_client_node')

    client = actionlib.SimpleActionClient('/my_sphero_Ac_server', record_odomAction)
    rate = rospy.Rate(1)
    rospy.loginfo('Waiting for action Server')
    client.wait_for_server()
    rospy.loginfo('Action Server Found...')
    goal = record_odomGoal()
    client.send_goal(goal, feedback_cb=feedback_callback)
    state_result = client.get_state()

    """
    class SimpleGoalState:
        PENDING = 0
        ACTIVE = 1
        DONE = 2
        WARN = 3
        ERROR = 4

    """

    rospy.loginfo("state_result: "+str(state_result))
    i = 0
    while state_result < 2:
        rospy.loginfo("Waiting to finish: ")
        rate.sleep()
        state_result = client.get_state()
        rospy.loginfo("state_result: "+str(state_result))
        i = i+1
        if i > 10:
            client.cancel_goal()

    state_result = client.get_state()
    rospy.loginfo("[Result] State: "+str(state_result))
    if state_result == 4:
        rospy.logerr("Something went wrong in the Server Side")
    if state_result == 3:
        rospy.logwarn("There is a warning in the Server Side")

    rospy.loginfo("[Result] State: "+str(client.get_result()))

ROS For Beginners/ROS in 5 Days/src/my_sphero_actions/src/my_sphero_action_client.py


# gps.py
#
# Flight Command and Telemetry
#
# GPS Objective:
# >recieve a csv file containing gps data, from Sensor Collection Team such as:
#  latitude, longitude, altitude
#
# >parse the csv file to get data
#
# >then telemetry peeps will store this data into telemetry records to broadcast
#  this data to the ground team
#

import csv

# Need to figure out how the Sensor team is sending the csv file and how we
# are recieving it.

# TESTING: using this file to test csv reading and output

filename = 'gps_test.csv'
#filename = input("\tgimme a csv file now\n")

# This dictionary holds the latitude and longitude for each position read
positions = {}

##############################################################################
# opens the csv file
#
# Treating each row as a snapshot of the position captured. Then the data is
# stored into a dictionary where the keys are the position and the values are
# the list of data points such as latitude, longitude, etc.
#
# The data that is stored in the dictionary will be adjusted to how the Sensor
# team stores it.

with open(filename) as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    line_count = 0
    for row in csv_reader:
        if line_count == 0:
            # PRINT for testing purposes
            # note: str.join(sequence) joins the data in the sequence row
            #       and separates them using str (in our case the string  ", ")
            print(f'Column names are {", ".join(row)}')
            line_count += 1
        else:
            # dict.update(key:value) adds a new key:value pair to the dictionary
            positions.update({line_count-1:[row[0],row[1]]})

            # PRINT for testing purposes
            # note: the print(f'print me') function uses f-string which allows
            #       for formatting where using curly brackets allow variables
            #       This is similar to using str.format().
            print(f'\tPosition({line_count-1}):\tLatitude\t{row[0]}\n'
                                            f'\t\t\tLongitude\t{row[1]}')
            print('\t---------------------------------------------')

            line_count += 1
    print(f'Processed {line_count} lines.\n')
# PRINT for testing purposes
print(positions)


#! ~/IC-UERJ/environment/python3

import operator
import math
import random

import numpy

from deap import algorithms
from deap import base
from deap import creator
from deap import tools
from deap import gp

import matplotlib.pyplot as plt
import networkx as nx

pset = gp.PrimitiveSet("MAIN", 5)
pset.addPrimitive(operator.add, 2)
pset.addPrimitive(operator.mul, 2)
pset.renameArguments(ARG0='a')
pset.renameArguments(ARG1='b')
pset.renameArguments(ARG2='c')
pset.renameArguments(ARG3='d')
pset.renameArguments(ARG4='e')

creator.create("FitnessMin", base.Fitness, weights=(-1.0, -1.0))
creator.create("Individual", gp.PrimitiveTree, fitness=creator.FitnessMin)

toolbox = base.Toolbox()
toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=1, max_=10)
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.expr)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("compile", gp.compile, pset=pset)

def evalSymbReg(individual, points):

    func = toolbox.compile(expr=individual)

    smpa = random.sample([float(x) for x in range(-10,10)], k=points)
    smpb = random.sample([float(x) for x in range(-10,10)], k=points)
    smpc = random.sample([float(x) for x in range(-10,10)], k=points)
    smpd = random.sample([float(x) for x in range(-10,10)], k=points)
    smpe = random.sample([float(x) for x in range(-10,10)], k=points)

    sqerrors = ((func(a,b,c,d,e) - ((((a*b)*c)*d)*e))**2 for a,b,c,d,e in zip(smpa, smpb, smpc, smpd, smpe))
    return math.fsum(sqerrors) / points, individual.height

toolbox.register("evaluate", evalSymbReg, points=10)
toolbox.register("select", tools.selTournament, tournsize=3)
toolbox.register("mate", gp.cxOnePoint)
toolbox.register("expr_mut", gp.genFull, min_=0, max_=2)
toolbox.register("mutate", gp.mutUniform, expr=toolbox.expr_mut, pset=pset)

def main():
    random.seed()

    pop = toolbox.population(n=300)
    hof = tools.HallOfFame(1)

    stats_fit = tools.Statistics(lambda ind: ind.fitness.values)
    stats_size = tools.Statistics(len)

    mstats = tools.MultiStatistics(fitness=stats_fit, size=stats_size)
    mstats.register("avg", numpy.mean)
    mstats.register("std", numpy.std)
    mstats.register("min", numpy.min)
    mstats.register("max", numpy.max)

    pop, log = algorithms.eaSimple(pop, toolbox, 0.5, 0.1, 40, stats=mstats,
                                   halloffame=hof, verbose=True)

    #print graph
    print(str(hof[0]))
    print(hof[0].height)

    #####
    #plot graph
    expr = hof[0]
    nodes, edges, labels = gp.graph(expr)

    g = nx.Graph()
    g.add_nodes_from(nodes)
    g.add_edges_from(edges)
    pos = nx.nx_pydot.graphviz_layout(g, prog="dot")

    nx.draw_networkx_nodes(g, pos)
    nx.draw_networkx_edges(g, pos)
    nx.draw_networkx_labels(g, pos, labels)
    plt.show()
    #####

    # print log
    return pop, log, hof

if __name__ == "__main__":
    main()


import matplotlib.pyplot as plt
import numpy as np
import scipy.io as scio
from mpl_toolkits.mplot3d import Axes3D
from skimage import io
from skimage import img_as_float

import runKMeans as km
import kMeansInitCentroids as kmic
import featureNormalize as fn
import performPca as pp
import projectData as pd
import recoverData as rd
import displayData as dd

plt.ion()
# ====== 载入数据 ======
print('Visualizing example dataset for PCA.')
data = scio.loadmat('data/data1.mat')
X = data['X']

# Visualize the example dataset
plt.figure()
plt.scatter(X[:, 0], X[:, 1], facecolors='none', edgecolors='b', s=20)
plt.axis('equal')
plt.axis([0.5, 6.5, 2, 8])

input('Program paused. Press ENTER to continue')

# ====== pca ======
print ('Running PCA on example dataset.')

# 主成分分析前，先正则化 ======
X_norm, mu, sigma = fn.feature_normalize(X)

U, S = pp.perform_pca(X_norm)

km.draw_line(mu, mu + 1.5 * S[0] * U[:, 0])
km.draw_line(mu, mu + 1.5 * S[1] * U[:, 1])

print('Top eigenvector: \nU[:, 0] = {}'.format(U[:, 0]))
print('You should expect to see [-0.707107 -0.707107]')

input('Program paused. Press ENTER to continue')

# ======= 降维 =======
print('Dimension reductino on example dataset.')

# Plot the normalized dataset (returned from pca)
plt.figure()
plt.scatter(X_norm[:, 0], X_norm[:, 1], facecolors='none', edgecolors='b', s=20)
plt.axis('equal')
plt.axis([-4, 3, -4, 3])

K = 1
Z = pd.project_data(X_norm, U, K)
print('Projection of the first example: {}'.format(Z[0]))
print('(this value should be about 1.481274)')

X_rec = rd.recover_data(Z, U, K)

print('Approximation of the first example: {}'.format(X_rec[0]))
print('(this value should be about [-1.047419 -1.047419])')

# Draw lines connecting the projected points to the original points
plt.scatter(X_rec[:, 0], X_rec[:, 1], facecolors='none', edgecolors='r', s=20)
for i in range(X_norm.shape[0]):
    km.draw_line(X_norm[i], X_rec[i])

input('Program paused. Press ENTER to continue')

# ====== 载入并可视化face ======
print('Loading face dataset.')

# Load Face dataset
data = scio.loadmat('data/faces.mat')
X = data['X']

dd.display_data(X[0:100])

input('Program paused. Press ENTER to continue')

# ====== pca压缩 ======
print('Running PCA on face dataset.\n(this might take a minute or two ...)')
X_norm, mu, sigma = fn.feature_normalize(X)
U, S = pp.perform_pca(X_norm)
dd.display_data(U[:, 0:36].T)

input('Program paused. Press ENTER to continue')

print('Dimension reduction for face dataset.')

K = 100
Z = pd.project_data(X_norm, U, K)

print('The projected data Z has a shape of: {}'.format(Z.shape))

input('Program paused. Press ENTER to continue')

print('Visualizing the projected (reduced dimension) faces.')

K = 100
X_rec = rd.recover_data(Z, U, K)

# Display normalized data
dd.display_data(X_norm[0:100])
plt.title('Original faces')
plt.axis('equal')

# Display reconstructed data from only k eigenfaces
dd.display_data(X_rec[0:100])
plt.title('Recovered faces')
plt.axis('equal')

input('Program paused. Press ENTER to continue')

# 对鸟图片压缩
image = io.imread('data/bird_small.png')
image = img_as_float(image)

img_shape = image.shape

X = image.reshape((img_shape[0] * img_shape[1], 3))
K = 16
max_iters = 30
centroids, km_res = km.run_kmeans(X.copy(), K, max_iters, False)

# Sample 1000 random indices (since working with all the data is
# too expensive. If you have a fast computer, you may increase this.
selected = np.random.randint(X.shape[0], size=1000)

# Visualize the data and centroid memberships in 3D
cm = plt.cm.get_cmap('RdYlBu')
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X[selected, 0], X[selected, 1], X[selected, 2], c=km_res[selected].astype(np.float64), s=15, cmap=cm, vmin=0, vmax=K)
plt.title('Pixel dataset plotted in 3D. Color shows centroid memberships')

input('Program paused. Press ENTER to continue')

X_norm, mu, sigma = fn.feature_normalize(X)

# PCA and project the data to 2D
U, S = pp.perform_pca(X_norm)
Z = pd.project_data(X_norm, U, 2)

# Plot in 2D
plt.figure()
plt.scatter(Z[selected, 0], Z[selected, 1], c=km_res[selected].astype(np.float64), s=15, cmap=cm)
plt.title('Pixel dataset plotted in 2D, using PCA for dimensionality reduction')

input('Finished. Press ENTER to exit')

plt.ioff()


print("<---------------------------------------->")
f=True
while f:
    color= input("introduce el color que deseas: ")
    print(color)
    try:
        if int(color):
            print("numero")
        elif float(color):
            print("decimal")

    except:
        print("string")
        f=False #Para salir del while


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

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('order', '0004_auto_20150216_1452'),
    ]

    operations = [
        migrations.AddField(
            model_name='order',
            name='trade',
            field=models.CharField(max_length=50, null=True, verbose_name='\u652f\u4ed8\u5b9d\u8ba2\u5355\u53f7', blank=True),
            preserve_default=True,
        ),
    ]


lista = list()
menor = maior = 0
menor_lista = list()
maior_lista = list()
for c in (range(0, 5)):
    lista.append(int(input(f'Digite um valor para a posição {c}: ')))
    menor = min(lista)
    maior = max(lista)
for pa, c in enumerate(lista):
    if menor == c:
        menor_lista.append(pa)
    if maior == c:
        maior_lista.append(pa)
print(f'Você digitou os valores {lista}')
print(f'O maior valor digitado foi {maior} nas posições', *maior_lista, sep=', ')
print(f'O menor valor digitado foi {menor} nas posições', *menor_lista, sep=', ')


import sys
import cv2 as cv
import numpy as np
from time import sleep
from random import shuffle

if __name__=="__main__":
    p_cnt = int(sys.argv[1])

    img = cv.imread('./data/input/fruits.jpg')
    img = img[-1280:, :1280]

    new_size = 640
    img = cv.resize(img, dsize=(new_size, new_size))

    p_size = int(new_size / p_cnt)

    suf_idx = list(range(p_cnt))
    shuffle(suf_idx)

    idx = 0
    for i in range(p_cnt):
        p_img = img[:, (p_size*i):(p_size*(i+1))]
        cv.imwrite('./data/output/1d/part_' + str(suf_idx[idx]) + '.png', p_img)
        #cv.imwrite('./data/output/1d/part_' + str(i) + '.png', p_img)
        idx += 1


#Jacob Pawlak and Ryan Shah
#DerbyHacks 2017
#elevatorUp.py

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

GPIO.setup(33, GPIO.OUT)

p = GPIO.PWM(33, 50)

p.start(7.5)
p.ChangeDutyCycle(9)
time.sleep(1.26*2)
GPIO.cleanup()
"""
try:
        while True:
                p.ChangeDutyCycle(9)
                time.sleep(1.25)
                p.ChangeDutyCycle(6)
                time.sleep(1.7)

except KeyboardInterrupt:
        GPIO.cleanup()
"""


#!/usr/bin/env python3
#
# modified by Loreto:           2017-03-10_14.50.01
# #####################################################

__author__   = 'Loreto Notarantonio'
__email__    = 'nloreto@gmail.com'

__version__  = 'LnVer_2017-08-07_16.33.57'
__status__   = 'Beta'

import os
import serial       # sudo pip3.4 install pyserial
import sys
import inspect
import string
import time

def LnClass(): pass

####################
## Default values ##
####################
# Several instrument instances can share the same serialport
_SERIALPORTS = {}

BYTESIZE = 8
"""Default value for the bytesize (int)."""

PARITY   = serial.PARITY_NONE
"""Default value for the parity. See the pySerial module for documentation. Defaults to serial.PARITY_NONE"""

STOPBITS = 1
"""Default value for the number of stopbits (int)."""

read_TIMEOUT  = 0.05
"""Default value for the timeout value in seconds (float)."""

# CLOSE_PORT_AFTER_EACH_CALL = False
# CLOSE_PORT_AFTER_EACH_CALL = True
"""Default value for port closure setting."""

#####################
## Named constants ##
#####################

MODE_RTU   = 'rtu'
MODE_ASCII = 'ascii'
##############################
## Modbus instrument object ##
##############################

# Ln_SOURCE_ADDR = 0
# Ln_DEST_ADDR   = 1
# Ln_SEQNO_HIGH  = 2
# Ln_SEQNO_LOW   = 3
# Ln_COMMAND     = 4

# DATALEN             = 0     # - lunghezza dei dati escluso STX ed ETX
# SENDER_ADDR         = 0     # - Dest Address      (FF = Broadcast)
# DESTINATION_ADDR    = 1     # - source Address    (00 = Master)
# SEQNO_HIGH          = 2     # - numero del messaggio utile per associare la risposta
# SEQNO_LOW           = 3     # -
# COMMAND             = 4     # - comando da eseguire
# USER_RCODE          = 5     # - esito del comando
# USER_DATA           = 6     # - dati necessari per l'esecuzione del comando oppure i dati di risposta

# DATALEN           = 0    # - lunghezza dei dati escluso STX ed ETX
SENDER_ADDR       = 0    # - Dest Address      (FF = Broadcast)
DESTINATION_ADDR  = 1    # - source Address    (00 = Master)
SEQNO_HIGH        = 2    # - numero del messaggio utile per associare la risposta
SEQNO_LOW         = 3    # -
CMD_RCODE         = 4    # rCode di ritorno per il comando eseguito (in TX è ignorato)
COMMAND           = 5    # comando da eseguire
SUBCOMMAND        = 6    # eventuale dettaglio per il comando
COMMAND_DATA      = 7    # TX - dati necessari al comando per la sua corretta esecuzione/RX - dati di risposta

# -----------------------------------------------------------------------
# - con il gioco del complementedByte, gli unici byte che dovrebbero
# - circolare sono i seguenti al di là dello STX ed ETX
# -----------------------------------------------------------------------
LnRs485_validBytesHex = [
                '0x0F',
                '0x1E',
                '0x2D',
                '0x3C',
                '0x4B',
                '0x5A',
                '0x69',
                '0x78',
                '0x87',
                '0x96',
                '0xA5',
                '0xB4',
                '0xC3',
                '0xD2',
                '0xE1',
                '0xF0'
              ]

rs485Map = {            'DATALEN'           : 0,    # - lunghezza dei dati escluso STX ed ETX
                        'SENDER_ADDR'       : 1,    # - Dest Address      (FF = Broadcast)
                        'DESTINATION_ADDR'  : 2,    # - source Address    (00 = Master)
                        'SEQNO_HIGH'        : 3,    # - numero del messaggio utile per associare la risposta
                        'SEQNO_LOW'         : 4,    # -
                        'CMD_RCODE'         : 5,    # rCode di ritorno per il comando eseguito (in TX è ignorato)
                        'COMMAND'           : 6,    # comando da eseguire
                        'SUBCOMMAND'        : 7,    # eventuale dettaglio per il comando
                        'COMMAND_DATA'      : 8,    # TX - dati necessari al comando per la sua corretta esecuzione/RX - dati di risposta
                    };

LnRs485_writePin   = {  'COMANDO'           : 5,   # READ 1 | WRITE-2
                        'PIN_NO'            : 6,   # numero del pin su cui operare
                        'PIN_VALUE'         : 6,   # 0, 1
                    };

# ln485Map = LnClass()
# ln485Map.DATALEN = 0
# ln485Map.COMMAND_DATA = 8

class LnRs485_Instrument():
    def __init__(self, port, mode='ascii', baudrate=9600, logger=None):

        if port not in _SERIALPORTS or not _SERIALPORTS[port]:
            try:
                self.serial = _SERIALPORTS[port] = serial.Serial(
                                                    port     = port,
                                                    baudrate = baudrate,
                                                    parity   = serial.PARITY_NONE,
                                                    bytesize = serial.EIGHTBITS,
                                                    stopbits = serial.STOPBITS_ONE,
                                                    rtscts   = False,
                                                    xonxoff  = False,
                                                    dsrdtr   = False,
                                                    timeout  = read_TIMEOUT)

            except (Exception) as why:
                print ('ERROR:  ', str(why))
                sys.exit()

        else:
            self.serial = _SERIALPORTS[port]
            if self.serial.port is None:
                self.serial.open()
                # - chissà se sono importanti....
                self.serial.reset_input_buffer()        # clear input  buffer
                self.serial.reset_output_buffer()       # clear output buffer

        if logger:
            self._setLogger = logger
        else:
            self._setLogger = self._internaLogger

        self._validBytes=bytearray([int(i, 16) for i in LnRs485_validBytesHex]) # creiamo un array di integer

        self.mode = mode
        """Slave mode (str), can be MODE_RTU or MODE_ASCII.  Most often set by the constructor (see the class documentation).

        New in version 0.6.
        """

        # ----   LnRs485_payLoadMap
        # self._payLoadMap = LnClass()
        # self._payLoadMap.SENDER_ADDR       = 0
        # self._payLoadMap.DESTINATION_ADDR  = 1
        # self._payLoadMap.SEQNO_HIGH        = 2
        # self._payLoadMap.SEQNO_LOW         = 3
        # self._payLoadMap.PAYLOAD           = 4
        self._printableChars                = list(range(31,126))

        self.debug = True
        """Set this to :const:'True' to print the communication details. Defaults to :const:'False'."""

        self.sendCounter = 0
        """Set this to :const:'True' to print the communication details. Defaults to :const:'False'."""

        self.STX = int('0x02', 16) # integer
        self.ETX = int('0x03', 16) # integer
        # self.CRC = True

        self.close_port_after_each_call = False
        """If this is :const:'True', the serial port will be closed after each call. """
        if  self.close_port_after_each_call: self.serial.close()

        self.precalculate_read_size = True
        """If this is :const:'False', the serial port reads until timeout
        instead of just reading a specific number of bytes. Defaults to :const:'True'.

        New in version 0.5.
        """

    def ClosePortAfterEachCall(self, openPortAEC):
        logger = self._setLogger(package=__name__)
        self.close_port_after_each_call = openPortAEC

        if openPortAEC:
            if self.serial.isOpen():
                logger.info('closing port...')
                self.serial.close()
        else:
            if not self.serial.isOpen():
                logger.info('opening port...')
                self.serial.open()

    def _internaLogger(self, package=None):
        ##############################################################################
        # - classe che mi permette di lavorare nel caso il logger non sia richiesto
        ##############################################################################
        class nullLogger():
                def __init__(self, package=None, stackNum=1):
                    pass
                def info(self, data):
                    self._print(data)
                def debug(self, data):
                    self._print(data)
                def error(self, data):  pass
                def warning(self, data):  pass

                def _print(self, data):
                    pass
                def _print_(self, data):
                    caller = inspect.stack()[3]
                    dummy, programFile, lineNumber, funcName, lineCode, rest = caller
                    if funcName == '<module>': funcName = '__main__'
                    str = "[{FUNC:<20}:{LINENO}] - {DATA}".format(FUNC=funcName, LINENO=lineNumber, DATA=data)
                    print (str)

        return nullLogger()

    def __repr__(self):
        """String representation of the :class:'.Instrument' object."""
            # address                    = {ADDRESS},
        return """{MOD}.{CLASS}
            <class-id                  = 0x{ID:x},
            mode                       = {MODE},
            close_port_after_each_call = {CPAEC},
            precalculate_read_size     = {PRS},
            debug                      = {DEBUG},
            STX                        = 0x{STX:02x},
            ETX                        = 0x{ETX:02x},
            serial-id                  = {SERIAL},>
                """.format(
                        MOD=self.__module__,
                        CLASS=self.__class__.__name__,
                        ID=id(self),
                        MODE=self.mode,
                        CPAEC=self.close_port_after_each_call,
                        PRS=self.precalculate_read_size,
                        DEBUG=self.debug,
                        SERIAL=self.serial,
                        STX=self.STX,
                        ETX=self.ETX
            )
                        # ADDRESS=self.address,

    def _getCRC8(self, byteArray_data):
        logger = self._setLogger(package=__name__)
        crcValue = 0
        for byte in byteArray_data:
            # if isinstance(byte, str): byte = ord(byte)            # onverte nel valore ascii
            logger.debug('byte: int:{0} hex: {0:02x} - crcValue int:{1} hex: {1:02x}'.format(byte, crcValue))
            b2 = byte
            if (byte < 0):
                b2 = byte + 256
            for i in range(8):
                odd = ((b2^crcValue) & 1) == 1
                crcValue >>= 1
                b2 >>= 1
                if (odd):
                    crcValue ^= 0x8C # this means crc ^= 140

        return crcValue

    # ---------------------------------------------
    # - aaaa bbbb
    # -     byte1 = aaaa !aaaa
    # -     byte2 = bbbb !bbbb
    # -     byte = byte1_HNibble * 16 + byte2_HNibble
    # ---------------------------------------------
    def _splitComplementedByte(self, byte):
        logger = self._setLogger(package=__name__)
        logger.debug ("byte to be converted: {0} - type: {1}".format(byte, type(byte)))
        # if isinstance(byte, str): byte = ord(byte)            # onverte nel valore ascii

        # print ('....', type(byte), byte)
        # logger.debug ("converting: x{0:02X}".format(byte))

            # first nibble
        c = byte >> 4;
        byteValue = (c << 4) | (c ^ 0x0F)
        highNibble = byteValue
        logger.debug  ("    x{0:02X}".format( highNibble))

            # second nibble
        c = byte & 0x0F;
        byteValue = (c << 4) | (c ^ 0x0F)
        lowNibble = byteValue
        logger.debug  ("    x{0:02X}".format(lowNibble))

            # second two bytes
        return highNibble, lowNibble

    # ---------------------------------------------
    # -     byte1 = aaaa !aaaa
    # -     byte2 = bbbb !bbbb
    # -     byte = byte1_HNibble * 16 + byte2_HNibble
    # ---------------------------------------------
    def _combineComplementedByte(self, byte1, byte2):
        logger = self._setLogger(package=__name__)
        # if isinstance(byte1, str): byte1 = ord(byte1)            # onverte nel valore ascii
        # if isinstance(byte2, str): byte2 = ord(byte2)            # onverte nel valore ascii

        logger.debug("complementedData: x{0:02X} + x{1:02X}".format(byte1, byte2))

            # - check first byte
        byte1_HighNibble = (byte1 >> 4) & 0x0F
        byte1_LowNibble = ~byte1 & 0x0F
        if byte1_LowNibble != byte1_HighNibble:
            logger.error("byte1 nibbles corrupted: x{0:02X} + x{1:02X}".format(byte1_LowNibble, byte1_HighNibble))
            return None

            # - check second byte
        byte2_HighNibble = (byte2 >> 4) & 0x0F
        byte2_LowNibble = ~byte2 & 0x0F
        if byte2_LowNibble != byte2_HighNibble:
            logger.error("byte2 nibbles corrupted: x{0:02X} + x{1:02X}".format(byte2_LowNibble, byte2_HighNibble))
            return None

            # re-build real byte
        realByte = byte1_HighNibble*16 + byte2_HighNibble
        logger.debug("  resulting data BYTE: x{0:02X} char:{1}".format(realByte, chr(realByte)))

        return realByte

    #######################################################################
    # - Lettura dati fino a:
    # -     SOD = StartOfData  carattere che identifica l'inizio dei dati.
    # -             quelli arrivati prima saranno ignorati
    # -     EOD = None ... avanti fino al primo null char
    # -     EOD = xxx ... fino al char xxx
    # - Ritorna una bytearray di integer
    #######################################################################
    def _readSerialBuffer(self, SOD=[], EOD=[], TIMEOUT=5000, fDEBUG=False):
        logger = self._setLogger(package=__name__)

        if self.close_port_after_each_call:
            logger.debug('opening port...')
            self.serial.open()

        if isinstance(SOD, int): SOD=[SOD]
        if isinstance(EOD, int): EOD=[EOD]

        RAW = True if (not SOD and not EOD) else False

            # -------------------
            # - solo per DEBUG
            # -------------------
        sodString=''
        for val in SOD: sodString += " x{0:02x}".format(val)
        logger.debug( "SOD:     {0}".format(sodString))

        eodString=''
        for val in EOD: eodString += " x{0:02x}".format(val)
        logger.debug( "EOD:     {0}".format(eodString))

        logger.debug( "RAW:     {}".format(RAW))
        logger.debug( "TIMEOUT: {}".format(TIMEOUT))
        logger.debug( "reading buffer")

        # facciamo partire il timer
        startRun = time.time()
        elapsed = 0

        buffer = bytearray()
        while elapsed < TIMEOUT:
            # time.sleep(.01)
            elapsed = time.time()-startRun
            logger.debug( "elapsed {}/{}".format(elapsed, TIMEOUT))
                # - in attesa di un byte
            ch = self.serial.read(1)       # ch e' un type->bytes
            chInt = int.from_bytes(ch, 'little')
            if ch == b'':
                if RAW:
                    if len(buffer) > 0:
                        logger.debug( "Received byte: {0:02x} - breaking".format(chInt) )
                        break
                    else:
                        logger.debug( "Received byte: {0:02x} - skipping".format(chInt) )
                        continue
                else:
                    if len(buffer) > 0:
                        logger.debug( "Received byte: {0:02x} - breaking".format(chInt) )
                        break
                    else:
                        logger.debug( "Received byte: {0:02x} - skipping".format(chInt) )
                        continue

            logger.debug( "Received byte: {0:02x}".format(chInt) )
                # Start of Data
            if SOD and chInt in SOD:
                logger.debug( "found SOD")
                buffer = bytearray()    # reinizializza il buffer
                buffer.append(chInt)

                # se siamo in cerca di EOD
            elif EOD:
                logger.debug( "inside EOD")
                buffer.append(chInt)
                if chInt in EOD:
                    logger.debug( "found SOD")
                    break

                # - andiamo liberi senza delimiters
            else:
                logger.debug( "inside RAW")
                buffer.append(chInt)

        # print (elapsed, TIMEOUT)
        if self.close_port_after_each_call:
            logger.debug('closing port...')
            self.serial.close()

        return buffer

    #######################################################################
    # - by Loreto
    # - EOD = int('0x0A', 16) # integer
    # - EOD = None   ... legge fino al primo byte null
    #######################################################################

    def readRawData(self, SOD=[], EOD=[], hex=False, text=False, char=False, TIMEOUT=1000):
        logger = self._setLogger(package=__name__)

        bufferData = self._readSerialBuffer(SOD=[], EOD=EOD, TIMEOUT=TIMEOUT)

        if bufferData:
            # validChars = list(range(31,126))
            validChars = self._printableChars
            validChars.append(10) # aggiungiamo il newline in modo che venga displayato

            if isinstance(bufferData, bytes):
                bufferData = bufferData.decode('utf-8')

            lineToPrint = []
            for i in bufferData:
                if i in validChars:                    # Handle only printable ASCII
                    lineToPrint.append(chr(i))
                else:
                    lineToPrint.append(" ")

            if hex:
                hexData         = ' '.join('{0:02x}'.format(x) for x in bufferData)
                print ('readRawDataLib: {DESCR:^10}:  {DATA}'.format(DESCR="raw", DATA=hexData))

            if char:
                print ('readRawDataLib: {DESCR:^10}:  {DATA}'.format(DESCR="chr", DATA='  '.join(lineToPrint)))

            if text:
                print ('readRawDataLib: {DESCR:^10}:  {DATA}'.format(DESCR="text", DATA=''.join(lineToPrint)))

        return bufferData

    #######################################################################
    # - by Loreto
    # - Lettura dati bsato sul protocollo:
    # -     RS485 protocol library by Nick Gammon
    # - STX - data - CRC - ETX
    # - A parte STX e ETX tutti gli altri byte sono inviati come due nibble
    # -  byte complemented (incluso il CRC)
    # -  only values sent would be (in hex):
    # -    0F, 1E, 2D, 3C, 4B, 5A, 69, 78, 87, 96, A5, B4, C3, D2, E1, F0
    # -  Con il fatto che solo i byte di sopra possono essere inviati,
    # -  il controllo su di essi forse fa venire meno il CRC e quindi
    # -  l'ho inserito come flag
    #
    # - credo che questa funzione venga chiamata non direttamente da me
    # - in quanto ho notato che non prende ulteriori parametri.
    #######################################################################
    def readData(self, TIMEOUT=1000, fDEBUG=False):
        logger = self._setLogger(package=__name__)

        bufferData = self._readSerialBuffer(SOD=self.STX, EOD=self.ETX, TIMEOUT=TIMEOUT, fDEBUG=fDEBUG)
        msg = '{TITLE:<15}: ({LEN}) {DATA}'.format(TITLE='readDataLib: full data', LEN=len(bufferData), DATA=' '.join('{:02X}'.format(x) for x in bufferData))
        logger.debug(msg)

            # Prendiamo i dati fissi
        if not bufferData[0] == self.STX:
            msg = 'ERROR: STX missed'
            print(msg)
            logger.error(msg)
            return bytearray(), bufferData

        if not bufferData[-1] == self.ETX:
            msg = 'ERROR: ETX missed'
            print(msg)
            logger.error(msg)
            return bytearray(), bufferData

            # ---------------------------------------------
            # - ricostruzione dei bytes originari
            # - byte = byte1_HighNibble*16 + byte2_HighNibble
            # - si potrebbe usare la funzione _combineComplementedByte
            # -    che provvede anche a fare la verifica che
            # -    il secondo nibble sia il complemento del primo ma
            # -    avendo verificato che il byte si trova nei self._validBytes
            # ---------------------------------------------

            # il trick che segue ci permette di prelevare due bytes alla volta
        rcvData = bytearray()
        payLoadNibbled  = bufferData[1:-1] # skip STX and ETX - include nibbled_data+nibbled_CRC
        xy = iter(payLoadNibbled)
        for byte1, byte2 in zip(xy, xy):
                # re-build real byte
            if byte1 in self._validBytes and byte2 in self._validBytes:
                byte1_HighNibble = (byte1 >> 4) & 0x0F
                byte2_HighNibble = (byte2 >> 4) & 0x0F
                realByte = byte1_HighNibble*16 + byte2_HighNibble

            else:
                msg = 'ERROR: some byte corrupted byte1:{0:02x} byte2:{1:02x}'.format(byte1, byte2)
                print(msg)
                logger.error(msg)
                return bytearray(), bufferData

            rcvData.append(realByte)

            # -----------------------------------------------------------------------
            # - Una volta ricostruidi i bytes origilali,
            # - calcoliamo il CRC sui dati (ovviamento escluso il byte di CRC stesso)
            # -----------------------------------------------------------------------
        CRC_calculated  = self._getCRC8(rcvData[:-1])
            # ---------------------------------
            # - check CRC (drop STX and ETX)
            # ---------------------------------
        CRC_received    = rcvData[-1]
        rcvData         = rcvData[:-1]

        logger.debug("    CRC received  : x{0:02X}".format(CRC_received))
        logger.debug("    CRC calculated: x{0:02X}".format(CRC_calculated))
        xMitCode = CRC_received - CRC_calculated

        if xMitCode:
            logger.error('Il valore di CRC non coincide')
            print ('ERROR: Il valore di CRC non coincide')
            print ()
            print ("    CRC received  : x{0:02X}".format(CRC_received))
            print ("    CRC calculated: x{0:02X}".format(CRC_calculated))
            print ()
            return bytearray(), bufferData

        if fDEBUG and len(rcvData) > 0:
                # sommario
            print ()
            print ('[Pi-RX] - ', end="")
            print (' [{0:02X}/{0:03}]'.format(rcvData[SENDER_ADDR]), end="")
            print (' --> [{0:02X}/{0:03}]'.format(rcvData[DESTINATION_ADDR]), end="")
            print (' - SeqNo: {0:05}'.format(rcvData[SEQNO_HIGH]*256+rcvData[SEQNO_LOW]), end="")
            print (' - [rcvdCode: {0:03}]'.format(xMitCode))
            print ()

                # hezadecimal
            print ('    full data - len: [{0:03}] - '.format(len(rcvData)), end="")
            for byte in rcvData: print ('{0:02X} '.format(byte), end="")
            print ()

                # hezadecimal solo la parte comando
            userData = rcvData[COMMAND_DATA:]
            print ('    user data - len: [{0:03}] - '.format(len(userData)), end="")
            print ('   '*COMMAND_DATA, end="")
            for byte in userData: print ('{0:02X} '.format(byte), end="")

                # ascii solo la parte comando
            print ('')
            print ('    user data - len: [{0:03}] - '.format(len(userData)), end="")
            print ('   '*COMMAND_DATA, end="")
            print ('[', end="")
            for byte in userData:
                if byte in self._printableChars:   # Handle only printable ASCII
                    print(chr(byte), end="")
                else:
                    print(' ', end="")
            print (']')
            print ('')
            print ('    CRC Rec/Cal 0x : {0:02X} {1:02X}'.format(CRC_received, CRC_calculated))
            print ('    SEQNO       0x : {0:02X} {1:02X}'.format(rcvData[SEQNO_HIGH], rcvData[SEQNO_LOW]))
            print ('    CMD_RCode   0x : {0:02X}'.format(rcvData[CMD_RCODE]))
            print ('    CMD/subCMD  0x : {0:02X} {1:02X}'.format(rcvData[COMMAND], rcvData[SUBCOMMAND]))

        return rcvData, bufferData

    def _getSendCounter(self):
        self.sendCounter += 1
        yy = self.sendCounter.to_bytes(2, byteorder='big')
        return yy

    #######################################################################
    # - sendDataSDD - con parametri di input diversi
    # -    richiama comunque sendData
    #######################################################################
    def sendDataSDD(self, sourceAddress, destAddress, dataStr, fDEBUG=False):
        ''' formato esplicito dei parametri '''
        dataToSend = bytearray()
        dataToSend.append(sourceAddress)
        dataToSend.append(destAddress)

        yy = self._getSendCounter()
        dataToSend.append(yy[0])  # high byte
        dataToSend.append(yy[1])  # Low byte

        for x in dataStr:
            dataToSend.append(ord(x))

        dataSent = self.sendData(dataToSend, fDEBUG=fDEBUG)
        return dataSent

    #######################################################################
    # - sendDataCMD - con parametri di input diversi
    # -    richiama comunque sendData
    # -    ordine:
    # -      SENDER_ADDR       = 0    # - Dest Address      (FF = Broadcast)
    # -      DESTINATION_ADDR  = 1    # - source Address    (00 = Master)
    # -      SEQNO_HIGH        = 2    # - numero del messaggio utile per associare la risposta
    # -      SEQNO_LOW         = 3    # -
    # -      CMD_RCODE         = 4    # rCode di ritorno per il comando eseguito (in TX è ignorato)
    # -      COMMAND           = 5    # comando da eseguire
    # -      SUBCOMMAND        = 6    # eventuale dettaglio per il comando
    # -      COMMAND_DATA      = 7    # TX - dati necessari al comando per la sua corretta esecuzione/RX - dati di risposta
    #######################################################################
    def sendDataCMD(self, CMD, fDEBUG=False):
        ''' formato CLASS dei parametri '''
        dataToSend = bytearray()
        dataToSend.append(CMD.sourceAddr)
        dataToSend.append(CMD.destAddr)

        yy = self._getSendCounter()
        dataToSend.append(yy[0])  # high byte
        dataToSend.append(yy[1])  # Low byte

        dataToSend.append(CMD.xmitRcode)  # 0 per una TX
        dataToSend.append(CMD.command)
        dataToSend.append(CMD.subCommand)

        for x in CMD.dataStr:
            dataToSend.append(ord(x))

        dataSent = self.sendData(dataToSend, fDEBUG=fDEBUG)
        return dataSent

    #######################################################################
    # - by Loreto
    # - Scrittura dati basato sul protocollo:
    # -     RS485 protocol library by Nick Gammon
    # - STX - data - CRC - ETX
    # - A parte STX e ETX tutti gli altri byte sono inviati come due nibble
    # -  byte complemented (incluso il CRC)
    # -  only values sent would be (in hex):
    # -    0F, 1E, 2D, 3C, 4B, 5A, 69, 78, 87, 96, A5, B4, C3, D2, E1, F0
    #######################################################################
    def sendData(self, txData, fDEBUG=False):
        ''' formato in bytearray dei parametri '''
        logger = self._setLogger(package=__name__)
        if fDEBUG:
            # print()
            # seqNO = data[SEQNO_LOW]+data[SEQNO_HIGH]*256
            # print ('sendDataLib: dataLen=', len(data))
            # print ('    source:{sADDR:03}  dest:{dADDR:03} CMD:{CMD:03} seqNo:{SEQ:05}'.format(sADDR=data[SENDER_ADDR], dADDR=data[DESTINATION_ADDR], SEQ=seqNO, CMD=data[COMMAND]))
            # print ('    {DESCR:<10}: {DATA}'.format(DESCR="payload", DATA=' '.join('{0:02x}'.format(x) for x in data)))

            '''

            print ('sendDataLib:')
            print ('    seqNo    : {0:05}'.format(payLoad[SEQNO_HIGH]*256+payLoad[SEQNO_LOW]))
            print ('    xMitCode : {0:03} (0 for TX)'.format(0))
            print ()

            print ('    full data - len: [{0:03}] - '.format(len(payLoad)), end="")
            for byte in payLoad: print ('{0:02X} '.format(byte), end="")
            print ()

            userData = payLoad[USER_DATA:]
            print ('    user data - len: [{0:03}] - '.format(len(userData)), end="")
            print ('   '*USER_DATA, end="")
            for byte in userData: print ('{0:02X} '.format(byte), end="")

            print ('')
            print ('    user data - len: [{0:03}] - '.format(len(userData)), end="")
            print ('   '*USER_DATA, end="")
            print ('[', end="")
            for byte in userData:
                if byte in self._printableChars:   # Handle only printable ASCII
                    print(chr(byte), end="")
                else:
                    print(' ', end="")
            print (']')
            print ('')
            print ('    SourceAddr 0x : {0:02X}'.format(payLoad[SENDER_ADDR]))
            print ('    DestAddr   0x : {0:02X}'.format(payLoad[DESTINATION_ADDR]))
            print ('    SEQNO      0x : {0:02X} {1:02X}'.format(payLoad[SEQNO_HIGH], payLoad[SEQNO_LOW]))
            print ('    Command    0x : {0:02X}'.format(payLoad[COMMAND]))
            print ('    userRCode  0x : {0:02X}'.format(payLoad[USER_RCODE]))

            '''

            # - preparaiamo il bytearray con i dati da inviare
        dataToSend=bytearray()

            # - STX nell'array
        dataToSend.append(self.STX)

            # - Data nell'array
        for thisByte in txData:
            byte1, byte2 = self._splitComplementedByte(thisByte)
            dataToSend.append(byte1)
            dataToSend.append(byte2)

            # - CRC nell'array
        if self.CRC:
            CRC_value    = self._getCRC8(txData)
            byte1, byte2 = self._splitComplementedByte(CRC_value)
            dataToSend.append(byte1)
            dataToSend.append(byte2)

            # - ETX
        dataToSend.append(self.ETX)

        if self.close_port_after_each_call:
            self.serial.open()

            # INVIO dati
        self.serial.write(dataToSend)

        if self.close_port_after_each_call:
            self.serial.close()

        if fDEBUG:
            print ('[Pi-TX] - ', end="")
            print (' [{0:02X}/{0:03}]'.format(txData[SENDER_ADDR]), end="")
            print (' --> [{0:02X}/{0:03}]'.format(txData[DESTINATION_ADDR]), end="")
            print (' - SeqNo: {0:05}'.format(txData[SEQNO_HIGH]*256+txData[SEQNO_LOW]), end="")
            print ()
            print ()

            print ('    full data - len: [{0:03}] - '.format(len(txData)), end="")
            for byte in txData: print ('{0:02X} '.format(byte), end="")
            print ()

            userData = txData[COMMAND_DATA:]
            print ('    user data - len: [{0:03}] - '.format(len(userData)), end="")
            print ('   '*COMMAND_DATA, end="")
            for byte in userData: print ('{0:02X} '.format(byte), end="")

            print ('')
            print ('    user data - len: [{0:03}] - '.format(len(userData)), end="")
            print ('   '*COMMAND_DATA, end="")
            print ('[', end="")
            for byte in userData:
                if byte in self._printableChars:   # Handle only printable ASCII
                    print(chr(byte), end="")
                else:
                    print(' ', end="")
            print (']')
            print ('')
            print ('    xMitted CRC 0x : {0:02X}'.format(CRC_value))
            print ('    SEQNO       0x : {0:02X} {1:02X}'.format(txData[SEQNO_HIGH], txData[SEQNO_LOW]))
            print ('    CMD_RCode   0x : {0:02X}'.format(txData[CMD_RCODE]))
            print ('    CMD/subCMD  0x : {0:02X} {1:02X}'.format(txData[COMMAND], txData[SUBCOMMAND]))

            print ('    {DESCR:<10}: {DATA}'.format(DESCR="raw data", DATA=' '.join('{0:02x}'.format(x) for x in dataToSend)))

        return dataToSend

class LnClass(): pass
################################################################################
# - M A I N
# - Prevede:
# -  2 - Controllo parametri di input
# -  5 - Chiamata al programma principale del progetto
################################################################################
if __name__ == '__main__':
    import time
    Sintax = """
        Immettere:
            action.usbPortNO.EoD [EOD=endOfData, default=10='\n']

        es.:
            monitor.0   : per monitorare la porta /dev/ttyUSB0
            send.0      : per inviare messaggi sulla porta /dev/ttyUSB0
    """

    if len(sys.argv) > 1:
        token = sys.argv[1].split('.')

        if len(token) == 2:
            action, portNO = sys.argv[1].split('.')
            EOD = b'\x03'

        elif len(token) == 3:
            action, portNO, EOD = sys.argv[1].split('.')
            iEOD = int(EOD)
            EOD = bytes([iEOD])

        else:
            print (Sintax)
            sys.exit()
    else:
        print (Sintax)
        sys.exit()

    LnRs485                = LnRs485_Instrument   # short pointer alla classe
    rs485                  = LnClass()
    rs485.MASTER_ADDRESS   = 0
    rs485.bSTX             = b'\x02'
    rs485.bETX             = b'\x03'
    rs485.usbDevPath       = '/dev/ttyUSB{0}'.format(portNO)
    # rs485.baudRate         = 9600
    rs485.mode             = 'ascii'

    print('     .....action:', action)
    print('     .....portNO:', portNO)
    print('     .....EOD:   ', EOD)

        # ===================================================
        # = RS-485 port monitor
        # ===================================================
    if action == 'monitor':
        print('Monitoring port: {0}'.format(rs485.usbDevPath))
            # ------------------------------
            # - Inizializzazione
            # ------------------------------
        try:
            address = 5
            print('setting port {0} to address {1}'.format(rs485.usbDevPath, address))
            monPort = LnRs485(rs485.usbDevPath, address, rs485.mode, logger=None)  # port name, slave address (in decimal)
            monPort.CRC = True

            print ('... press ctrl-c to stop the process.')
            while True:
                payLoad, rawData = monPort.readData()
                print ('rawData (Hex):  {0}'.format(' '.join('{0:02x}'.format(x) for x in rawData)))
                if payLoad:
                    print ('payLoad (Hex):      {0}'.format(' '.join('{0:02x}'.format(x) for x in payLoad)))
                    print ('payLoad (chr):      {0}'.format(' '.join('{0:>2}'.format(chr(x)) for x in payLoad)))
                else:
                    print ('payLoad ERROR....')
                print()

        except (KeyboardInterrupt) as key:
            print ("Keybord interrupt has been pressed")
            sys.exit()

    elif action == 'send':
        print('Sending data to port: {0}'.format(rs485.usbDevPath))
            # ------------------------------
            # - Inizializzazione
            # ------------------------------
        try:
            address = 5
            print('setting port {0} to address {1}'.format(rs485.usbDevPath, address))
            wrPort = LnRs485(rs485.usbDevPath, address, rs485.mode, logger=None)  # port name, slave address (in decimal)
            # - setting di alcuni parametri delle funzioni
            # - me li ritrovo come self.PARAM
            wrport.CRC       = False
            print ('... press ctrl-c to stop the process.')
            index = 0
            basedata = 'Loreto.'
            while True:
                index += 1
                dataToSend  = '[{0}.{1:04}]'.format(basedata, index)
                line        = '[{0}:{1:04}] - {2}'.format(rs485.usbDevPath, index, dataToSend)
                print (line)
                dataSent = wrPort.sendData(dataToSend, CRC=True)
                print ('sent (Hex): {0}'.format(' '.join('{0:02x}'.format(x) for x in dataSent)))
                print()
                time.sleep(5)

        except (KeyboardInterrupt) as key:
            print ("Keybord interrupt has been pressed")
            sys.exit()

    else:
        print(gv.INPUT_PARAM.actionCommand, 'not available')

''' OLD functions
    #######################################################################
    # - Lettura dati da StartOfData fino a EndOfData
    # - Ritorna una bytearray di integer
    #######################################################################
    def _read_SOD_EOD_Buffer(self, SOD=None, EOD=None, TIMEOUT=1000):
        logger = self._setLogger(package=__name__)

        if self.close_port_after_each_call:
            logger.debug('opening port...')
            self.serial.open()

        if not SOD: SOD = self.STX
        if not EOD: EOD = self.ETX
        buffer = bytearray()

        logger.debug( "reading buffer")

            # facciamo partire il timer
        startRun = time.time()
        elapsed = 0

        while TIMEOUT:
            TIMEOUT -= (time.time()-startRun)
            ch = self.serial.read(1)       # ch e' un bytes
            if ch==b'': continue
            chInt = int.from_bytes(ch, 'little')
            buffer.append(chInt)
            break

        logger.debug( "Received: SOD {0:02x}, waiting for EOD {1:02x}".format(SOD, EOD))

        while TIMEOUT:
            TIMEOUT -= (time.time()-startRun)
            ch = self.serial.read(1)       # ch e' un bytes
            if ch == b'': continue
            chInt = int.from_bytes(ch, 'little')
            buffer.append(chInt)
            logger.debug( "Received: byte hex: {0:02x}... waiting for {1:02x}".format(chInt, EOD) )
            if chInt==EOD: break

        if self.close_port_after_each_call:
            logger.debug('closing port...')
            self.serial.close()

        return buffer

    #######################################################################
    # - Lettura dati da StartOfData fino a EndOfData
    # - Ritorna una bytearray di integer
    #######################################################################
    def _readBuffer_OK_TO_BE_DELETED(self):
        logger = self._setLogger(package=__name__)

        if self.close_port_after_each_call:
            logger.debug('opening port...')
            self.serial.open()

        buffer = bytearray()

        logger.debug( "reading buffer")
        chInt=-1
        while chInt != self.STX:
            ch = self.serial.read(1)       # ch e' un bytes
            if ch == b'': continue
            chInt = int.from_bytes(ch, 'little')

        buffer.append(chInt)
        logger.debug( "Received: STX")
        chInt=-1
        while chInt != self.ETX:
            ch = self.serial.read(1)       # ch e' un bytes
            if ch == b'': continue
            chInt = int.from_bytes(ch, 'little')
            buffer.append(chInt)
            logger.debug( "Received: byte hex: {0:02x}... waiting for {1:02x}".format(chInt, self.ETX) )

        if self.close_port_after_each_call:
            logger.debug('closing port...')
            self.serial.close()

        return buffer

    #######################################################################
    # - Lettura dati fino a:
    # -     EOD = None ... fino al primo NULL byte
    # -     EOD = xxx ... fino al char xxx
    # - Ritorna una bytearray di integer
    #######################################################################
    def _readRawBuffer_OK_TO_BE_DELETED(self, EOD=None):
        logger = self._setLogger(package=__name__)

        if self.close_port_after_each_call:
            logger.debug('opening port...')
            self.serial.open()

        # print ('..............', EOD)
        buffer = bytearray()

        if EOD:
            chInt=-1
            while chInt != EOD:
                ch = self.serial.read(1)       # ch e' un bytes
                if ch == b'': continue
                chInt = int.from_bytes(ch, 'little')
                buffer.append(chInt)
                logger.debug( "Received byte: {0:02x}... waiting for {1:02x}".format(chInt, EOD) )

        else:
            while True:
                ch = self.serial.read(1)       # ch e' un bytes
                if ch == b'': break
                chInt = int.from_bytes(ch, 'little')
                buffer.append(chInt)
                logger.debug( "Received byte: {0:02x}... waiting for NULL".format(chInt) )

        if self.close_port_after_each_call:
            logger.debug('closing port...')
            self.serial.close()

        return buffer

'''


class Inc:
    def __init__(self, a):
        self.idx = 0
        self.cont = a

    def __call__(self):
        temp = self.cont[self.idx]
        self.idx += 1
        return temp

a = [1, 2, 3, 4, 5]
it = iter(a)
for i in iter(lambda: next(it), 5):
    print(i)


from flask import Flask, request
import numpy as np
from statsd.defaults.env import statsd

#STATSD_HOST=localhost
#STATSD_PORT=8125
#STATSD_PREFIX=None
#STATSD_MAXUDPSIZE=512

app = Flask(__name__)

@app.route("/task", methods=["GET"])
@statsd.timer('task')
def task():
	try:
		m = int(request.args.get('m', default=3))
		n = int(request.args.get('n', default=3))
		A = np.random.rand(m, n)
		b = np.random.rand(m, 1)
		x = np.linalg.lstsq(A, b)

		statsd.incr('succeeded')
		return str(x), 200
	except Exception as e:
		statsd.incr('failed')
		return str(e), 500


#!/usr/bin/env python
# -*- coding=utf-8 -*-
#
# ======================================================================================================================
#
# project: xprism
# name: /xprism/lib/api_functions/ext/ssh.py
# web: http://github.com/xprism/
# license: BSD-3-Clause
#
# ======================================================================================================================

# Imports --->
from lib.api_functions.ext import iptables
from lib.misc import fnc

# Functions --->
def init(args):
    flags = ['set_port', 'root_access']

    if not args or args[0] not in flags:
        fnc.output('xprism --addon -ssh %s' % fnc.flag_s(flags), 'Usage', 1)

    if args[0] == 'set_port':
        set_port(args[1:2])

    if args[0] == 'root_access':
        root_access(args[1:2])

def set_port(args):
    if fnc.arg_range(args, 1):
        fnc.output('xprism --addon -ssh set_port [disable, port_number]', 'Usage', 1)

    # Variables --->
    conf_path = '/etc/ssh/sshd_config'
    port_o = fnc.conf_get(r'([\s#]+)?Port\s+[0-9]+', conf_path)
    port_n = args[0].lower()

    # Disable access through SSH service --->
    if port_n == 'disable':
        # Stop/disable service --->
        fnc.service_cmd(['-disable', 'sshd'])
        svc = fnc.service_cmd(['-stop', 'sshd'])
        msg = 'SSH is disabled.' if svc['status'] != 'Error' else svc['service']
        status = 'Success' if svc['status'] != 'Error' else 'Error'
        fnc.output(msg, status, 0 if status == 'Success' else 1)

        # Reload iptables --->
        if fnc.service_cmd(['-status', 'iptables'])['status'] == 'active':
            iptables.init(['reload'])

        fnc.output(None, auto_exit=1)

    # Set or change the SSH port number --->
    if fnc.is_number(port_n) and len(port_n) > 1:
        if port_o:
            port_o = port_o.split()[1]
            status = 'Warning'
            msg = 'SSH port already set to that.'

            if port_n != port_o:
                status = 'Success'
                msg = 'SSH port updated.'

                # Edit port in sshd_config --->
                fnc.conf_edit(r'([\s#]+)?(Port\s+)[0-9]+', r'\g<2>{0}'.format(port_n), conf_path)

                # Reload iptables --->
                if fnc.service_cmd(['-status', 'iptables'])['status'] == 'active':
                    iptables.init(['reload'])

            # Start/enable service --->
            fnc.service_cmd(['-enable', 'sshd'])
            svc = fnc.service_cmd(['-restart', 'sshd'])
            msg = msg if svc['status'] != 'Error' else svc['service']
            status = status if svc['status'] != 'Error' else 'Error'
            fnc.output(msg, status, 1)

        else:
            fnc.output('Unable to find port variable in sshd_config.', 'Error', 1)

    else:
        fnc.output('Invalid port number.', 'Error', 1)

def root_access(args):
    if fnc.arg_range(args, 1):
        fnc.output('xprism --addon -ssh root_access [disable, enable]', 'Usage', 1)

    # Variables --->
    conf_path = '/etc/ssh/sshd_config'
    port_o = fnc.conf_get(r'([\s#]+)?PermitRootLogin\s+[a-zA-Z\-]+', conf_path)
    access = args[0].lower()
    msg = 'Something went wrong!'

    # Edit PermitRootLogin in sshd_config --->
    if port_o:
        if access == 'disable':
            fnc.conf_edit(r'([\s#]+)?(PermitRootLogin\s+)[a-zA-Z\-]+', r'\g<2>prohibit-password', conf_path)
            msg = 'SSH access disabled for Root.'

        if access == 'enable':
            fnc.conf_edit(r'([\s#]+)?(PermitRootLogin\s+)[a-zA-Z\-]+', r'\g<2>yes', conf_path)
            msg = 'SSH access enabled for Root.'

        svc = fnc.service_cmd(['-restart', 'sshd'])
        msg = msg if svc['status'] != 'Error' else svc['service']
        status = 'Success' if svc['status'] != 'Error' else 'Error'
        fnc.output(msg, status, 1)

    else:
        fnc.output('Unable to find PermitRootLogin variable in sshd_config.', 'Error', 1)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Jan  9 18:22:03 2019

@author: shanedenecke
"""

import os
from Bio import SeqIO
from Bio.SeqIO.FastaIO import FastaWriter
import sys

os.path.dirname(os.path.abspath(__file__))
#os.chdir('/home/shanedenecke/Dropbox/wp5_midgut_uptake/ABC_phylo/ABC_id/Nv/trinity/alignments')

#sys.argv=['','./Dm_Nv_combined_ABC_NBD_filtered.fa','./Manual_domain_missing.txt']

##define argument variables
if len(sys.argv)>2:
    fa=list(SeqIO.parse(str(sys.argv[1]), 'fasta'))
    rem=[line.rstrip('\n') for line in open(sys.argv[2])]
#elif len(sys.argv)==2:
    #fa=list(SeqIO.parse(str(sys.stdin, 'fasta'))
    #rem=[line.rstrip('\n') for line in open(sys.argv[1])]

clean=[]
for record in fa:
   if record.id not in rem:
       clean.append(record)

## Write temporary file
handle = open('temp.fa', "w")
writer = FastaWriter(handle, wrap=0)
writer.write_file(clean)
handle.close()

## Read in temporary file and print properly formatted fasta
x = open("temp.fa", "r")
y=x.readlines()
z=''.join(y)
if z[-1]=='\n':
    z=z[:-1]
print (z)
os.remove("temp.fa")


## -*- coding:utf-8 -*-
## INVERSION.PY -- Takes raw data from Airmodus A09 PSM .dat files and runs
##                 simple stepwise inversion on it based on Lehtipalo et al, 2014.
##                 Plots size distributions and contour plots as well as saves
##                 raw size data to comma-delimited .txt formats
##
## Cateogries:
##      Aerosol nucleation
## Author:
##      Lee Tiszenkel, UAH

import numpy as np
import datetime as dt
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy.signal import argrelextrema
from statistics import mean
import matplotlib.dates as mdates
import matplotlib.ticker as ticker

dataDate="20210319"
dataDay=dataDate[-4:]
filename = "PSM-Example-{}.dat".format(dataDate)
calibFilename = "Calibration.txt"

calibPlot = False
plotting = True

pi = 3.1415927

#Fits/smoothing functions
def moving_average(x, w):
    return np.convolve(x, np.ones(w), "same") / w
def power_law(x, a, b):
    return a*np.power(x, b)
def exponential(x, a, b, c, d):
    return (a*np.exp(b*x))+(c*np.exp(d*x))
def visc(t):
    return (174+0.433*(t-273))*1e-7
def rlambda(t, press):
    dm = 3.7e-10
    avog = 6.022e23
    return 8.3143*t/((2**(1/2))*avog*press*pi*dm*dm)
def cunn(dp, t, press):
    return 1.0+rlambda(t,press)/dp*(2.514+0.8*np.exp(-0.55*dp/rlambda(t,press)))
def reynolds(flow, diameter, t, press):
    density = 1.29*(273/t)*(press/101325)
    pipearea = pi/4*diameter**2
    velocity = flow/pipearea
    return density*velocity*pipearea/visc(t)
def diffusion(dpp, temp, press):
    K = 1.38e-23
    return (K*temp*cunn(dpp,temp,press))/(3*pi*visc(temp)*dpp)
def ltubefl(dpp, plength, pflow, temp, press):
    rmuu = pi*diffusion(dpp, temp, press)*(plength/pflow)
    i = 0
    res = []
    while i < len(dpp):
        if rmuu[i] < 0.02:
            res.append(1-2.56*rmuu[i]**(2/3)+1.2*rmuu[i]+0.177*rmuu[i]**(4/3))
        else:
            res.append(0.819*np.exp(-3.657*rmuu[i])+0.097*np.exp(-22.3*rmuu[i])+0.032*np.exp(-57*rmuu[i]))
        i += 1
    return res

#Retrieving data
print("Retrieving data...")
time = np.genfromtxt(filename, delimiter=",", usecols=0, dtype="str")
timeDT = []
for x in time:
    timeDT.append(dt.datetime.strptime(x, "%d.%m.%Y %H:%M:%S"))
conc = np.genfromtxt(filename, delimiter=",", usecols=1)
satflow = np.genfromtxt(filename, delimiter=",", usecols=2)

timeUS = []
for x in timeDT:
    timeUS.append(dt.datetime.strftime(x, "%m/%d/%Y %H:%M:%S"))
concSmooth = moving_average(conc,2)

flowmax = round(100*max(satflow))/100
flowmin = round(100*min(satflow))/100

#Size bin cutoffs
dia = [3.1,2.8,2.5,2.0,1.7,1.5,1.35,1.25]
diaCut = []
i = 0
while i < len(dia)-1:
    diaCut.append((dia[i]+dia[i+1])/2)
    i += 1
print("Done.")

#Retrieving calibration data
print("Retrieving calibration data from " + calibFilename)
calibSat = np.genfromtxt(calibFilename, delimiter=",", usecols=0)
calibDia = np.genfromtxt(calibFilename, delimiter=",", usecols=1)
calibDet = np.genfromtxt(calibFilename, delimiter=",", usecols=2)

#Plotting calibration data, curve/parameter fitting
print("Parameterizing calibration...")
pars1, cov1 = curve_fit(f=exponential, xdata=calibDia, ydata=calibSat, p0=[0, 0, 0, 0], bounds=(-np.inf, np.inf))
pars2, cov2 = curve_fit(f=exponential, xdata=calibDia, ydata=calibDet, p0=[0, 0, 0, 0], bounds=(-np.inf, np.inf))
pars3, cov3 = curve_fit(f=exponential, xdata=calibSat, ydata=calibDia, p0=[0, 0, 0, 0], bounds=(-np.inf, np.inf))

#stdevs = np.sqrt(np.diag(cov1))
#stdevs = np.sqrt(np.diag(cov2))

y1 = []
y2 = []
y3 = []
for x in diaCut:
    y1.append(exponential(x, *pars1))
    y2.append(exponential(x, *pars2))
for x in satflow:
    y3.append(exponential(x, *pars3))

apu = np.array(range(0, len(diaCut)+1, 1))
a = (flowmax/flowmin)**(1/(len(diaCut)))
P0 = flowmax/a**len(diaCut)
satflowAM = (P0*(a**apu))
print("Done.")
print("Determining number of scans...")
##Enumerating scans
satflowSmooth = moving_average(satflow, 2)
k11 = argrelextrema(satflowSmooth, np.less, order=3)
k1 = np.append(k11, len(satflowSmooth))
nscan = []
k2 = np.amin(k1)
i=0
j=1

for g in k1:
    while i < int(g):
        nscan.append(j)
        i+=1
    j += 1
numScans = str(max(nscan))
print(numScans + " scans found.")
print("Averaging bins for each scan...")
##Averaging bins for each scan
lr = len(satflowAM)
timenew_avg = []
meanflow = []
conc1b = []
diameter = []
i = 2
ii = 1
iii = 1

npNscan = np.array(nscan)
while iii < lr:
    meanflow.append((satflowAM[iii-1]+satflowAM[iii])/2)
    diameter.append((dia[iii-1]+dia[iii])/2)
    iii += 1

while i < np.max(npNscan):
    tempConc = []
    k = np.where(npNscan == i)
    timenew_avg.append(timeUS[int(np.mean(k[0]))])
    concMx = []
    satMx = []
    for b in k[0]:
        concMx.append(conc[b])
        satMx.append(satflow[b])
    npconcMx = np.array(concMx)
    npsatMx = np.array(satMx)
    for c in meanflow:
        if c == min(meanflow):
            k1 = np.where(npsatMx < c)
            k2 = np.where(npsatMx > satflowAM[0])
        elif c == max(meanflow):
            k1 = np.where(npsatMx > meanflow[-1])
            k2 = np.where(npsatMx < satflowAM[-1])
        else:
            k1 = np.where(npsatMx > meanflow[(meanflow.index(c))-1])
            k2 = np.where(npsatMx < c)
        k3 = np.intersect1d(k1, k2)
        try:
            avgConc = mean(concMx[x] for x in k3)
            tempConc.append(avgConc)
        except:
            tempConc.append(0)
    conc1b.append([i, tempConc])
    i += 1
print("Done.")
print("Calculating detection efficiency...")
DETEFF = []
for d in diameter:
    DETEFF.append(exponential(d, *pars2))
print("Done.")
M = []

for g in conc1b:
    cMax = np.nanmax(g[1])
    cf = np.polyfit(meanflow,g[1]/cMax,1)
    M.append([i, cf[1]])

dconc = []
for g in conc1b:
    tempdConc = []
    i = 0
    while i<len(g[1])-1:
        tempdConc.append((g[1][i+1]-g[1][i])/DETEFF[i])
        i += 1
    dconc.append([g[0], tempdConc])

##Loss correction

#Length of tube (cm)
inletl = 19.05
#Radius of tube (cm)
inletr = 0.635
#Inlet flow rate (LPM)
inletfr = 2.5
#temperature
temp = 298
#pressure
press = 101325

print("Calculating diffusional losses...")
inletl = inletl * 1e-2
inletr = inletr * 1e-2

d = np.array(diaCut) * 1e-9
Q = inletfr*0.001/60

rooi = 1.205
roop = 1000
vis = visc(temp)
A = pi*(inletr**2)
U = Q/A
Re = reynolds(Q,inletr*2,temp,press)

D = diffusion(d, temp, press)

Vd = 0
Pt = 1
Pl = ltubefl(d, inletl, Q, temp, press)
npPl = np.array(Pl)
print("Done.")
print("Correcting size distribution...")
concCorr = []
for g in conc1b:
    conx = np.array(g[1])
    conxCorr = conx/npPl
    concCorr.append(conxCorr)

dconc = []
dconcNans = []
for g in concCorr:
    tempdConc = []
    tempdConcNans = []
    i = 0
    while i<len(g)-1:
        value = (g[i+1]-g[i])/DETEFF[i]
        if value < 0:
            tempdConc.append(0)
            tempdConcNans.append(float('nan'))
        else:
            tempdConc.append(value)
            tempdConcNans.append(value)
        #tempdConc.append((g[i+1]-g[i])/DETEFF[i])
        i += 1
    dconc.append(tempdConc)
    dconcNans.append(tempdConcNans)
print("Done.")
print("Calcuating dN/dLogDp...")
#Calculating dLogDp
i=0
dlogdp = []
while i < len(diaCut)-1:
    dlogdp.append(np.log10(diaCut[i]*1e-9)-np.log10(diaCut[i+1]*1e-9))
    i += 1

#conc4 is dN/dlogDp
NPdlogdp = np.array(dlogdp)
conc4 = []
conc4Nans = []

for g in dconc:
    conc4.append(g/NPdlogdp)
for g in dconcNans:
    conc4Nans.append(g/NPdlogdp)

concTime = zip(timenew_avg, concCorr)
dconcTime = zip(timenew_avg, conc4)

dtTimenew = []
for x in timenew_avg:
    dtTimenew.append(dt.datetime.strptime(x, "%m/%d/%Y %H:%M:%S"))
figbins = []
i=0
while i < len(diaCut)-1:
    figbins.append((diaCut[i]+diaCut[i+1])/2)
    i += 1
print("Done.")
print("Creating output files...")
i=0
with open('{}-PSMconcDN.txt'.format(dataDay), 'w') as fp:
    fp.write("{}\n".format(",".join([str(y) for y in diaCut])))
    while i<len(timenew_avg):
        fp.write("{},{}\n".format(timenew_avg[i], ",".join([str(y) for y in conc4[i]])))
        i += 1

i=0
with open('{}-PSMconc.txt'.format(dataDay), 'w') as fp:
    while i<len(timenew_avg):
        fp.write("{},{}\n".format(timenew_avg[i], ",".join([str(y) for y in concCorr[i]])))
        i += 1
print("Done.")
if plotting == True:
    print("Plotting...")
    if calibPlot == True:
        fig = plt.figure(figsize=(10,10))
        ax = fig.add_subplot(3,1,1)
        ax2 = fig.add_subplot(3,1,2)
        ax3 = fig.add_subplot(3,1,3)
        ax.scatter(calibDia, calibSat)
        ax2.scatter(calibDia, calibDet)
        smoothX = np.linspace(min(calibDia),max(calibDia), 100)
        ax.plot(smoothX, exponential(smoothX, *pars1), linewidth=2, linestyle='--', color='black')
        ax2.plot(smoothX, exponential(smoothX, *pars2), linewidth=2, linestyle='--', color='black')
        ax3.scatter(diaCut, Pl)

    fig2 = plt.figure(figsize=(15,5))
    ax4 = fig2.add_subplot(1,1,1)
    fig3 = plt.figure(figsize=(15,5))
    ax5 = fig3.add_subplot(1,1,1)
    fig4 = plt.figure(figsize=(15,5))
    ax6 = fig4.add_subplot(1,1,1)

    bananaPlot = ax4.contourf(dtTimenew,figbins,np.array(conc4).T+0.1, np.arange(0.1, 300000, 100), cmap='jet', extend='max')
    myFmt = mdates.DateFormatter("%m/%d/%Y") #Format date
    myFmt2 = mdates.DateFormatter("%H:%M:%S") #Format time
    ax4.xaxis.set_major_formatter(myFmt2)
    ax4.xaxis.set_major_locator(mdates.SecondLocator(interval=int(((max(dtTimenew)-min(dtTimenew)).total_seconds())/5))) #6 marks on x axis
    ax4.xaxis.set_minor_formatter(myFmt)
    ax4.xaxis.set_minor_locator(mdates.DayLocator(interval=1))
    ax4.xaxis.set_tick_params(which='minor', pad=15) #Keeps major/minor axis from overlapping
    ax4.set_yscale('log')
    ax4.yaxis.set_major_locator(ticker.MultipleLocator(0.1))

    #Size distribution in bins
    ax5.plot(dtTimenew, [y[0] for y in concCorr], label=">2.95 nm")
    ax5.plot(dtTimenew, [y[1] for y in concCorr], label=">2.65 nm")
    ax5.plot(dtTimenew, [y[2] for y in concCorr], label=">2.25 nm")
    ax5.plot(dtTimenew, [y[3] for y in concCorr], label=">1.85 nm")
    ax5.plot(dtTimenew, [y[4] for y in concCorr], label=">1.6 nm")
    ax5.plot(dtTimenew, [y[5] for y in concCorr], label=">1.5 nm")
    ax5.plot(dtTimenew, [y[6] for y in concCorr], label=">1.3 nm")
    ax5.xaxis.set_major_formatter(myFmt2)
    ax5.xaxis.set_major_locator(mdates.SecondLocator(interval=int(((max(dtTimenew)-min(dtTimenew)).total_seconds())/5))) #6 marks on x axis
    ax5.xaxis.set_minor_formatter(myFmt)
    ax5.xaxis.set_minor_locator(mdates.DayLocator(interval=1))
    ax5.xaxis.set_tick_params(which='minor', pad=15) #Keeps major/minor axis from overlapping
    ax5.set_yscale('log')
    ax5.legend()

    ax6.plot(dtTimenew, [y[0] for y in conc4Nans], label="2.65-2.95 nm")
    ax6.plot(dtTimenew, [y[1] for y in conc4Nans], label="2.25-2.65 nm")
    ax6.plot(dtTimenew, [y[2] for y in conc4Nans], label="1.85-2.25 nm")
    ax6.plot(dtTimenew, [y[3] for y in conc4Nans], label="1.6-1.85 nm")
    ax6.plot(dtTimenew, [y[4] for y in conc4Nans], label="1.5-1.6 nm")
    ax6.plot(dtTimenew, [y[5] for y in conc4Nans], label="1.3-1.5 nm")
    #ax6.plot(dtTimenew, [y[6] for y in concCorr], label=">1.3")
    ax6.xaxis.set_major_formatter(myFmt2)
    ax6.xaxis.set_major_locator(mdates.SecondLocator(interval=int(((max(dtTimenew)-min(dtTimenew)).total_seconds())/5))) #6 marks on x axis
    ax6.xaxis.set_minor_formatter(myFmt)
    ax6.xaxis.set_minor_locator(mdates.DayLocator(interval=1))
    ax6.xaxis.set_tick_params(which='minor', pad=15) #Keeps major/minor axis from overlapping
    ax6.set_yscale('log')
    ax6.legend()

    #Colorbar Setup - putting neater ticks on, label
    cb = fig2.colorbar(bananaPlot, ax = ax4)
    cb.set_label('dN/dlogDp')

    #Axis labels
    ax4.set_xlabel('Time (UTC)')
    ax4.set_ylabel('Dp (nm)')
    fig2.savefig("{}-bananaplot.png".format(dataDate))
    fig3.savefig("{}-conc.png".format(dataDate))
    fig4.savefig("{}-dN.png".format(dataDate))
    plt.show()


import json
import csv
import numpy as np
import pandas as pd
import re

from collections import Counter
from fuzzywuzzy import fuzz
import lightgbm as lgb
from sklearn.metrics import f1_score
from sklearn.feature_extraction.text import CountVectorizer

"""
This assignment can be done in groups of 3 students. Everyone must submit individually.

Write down the UNIs of your group (if applicable)

Name : Roland Zhou
Uni  : rz2388

Member 2: Mohammad Radiyat, mr3719

Member 3: Kathy Lin, kl2615
"""
def get_matches(locu_train_path, foursquare_train_path, matches_train_path, locu_test_path, foursquare_test_path):
    """
        In this function, You need to design your own algorithm or model to find the matches and generate
        a matches_test.csv in the current folder.

        you are given locu_train, foursquare_train json file path and matches_train.csv path to train
        your model or algorithm.

        Then you should test your model or algorithm with locu_test and foursquare_test json file.
        Make sure that you write the test matches to a file in the same directory called matches_test.csv.

    """
    # Load the training data as pandas dataframes
    matches_train = pd.read_csv(matches_train_path)
    foursq_train = pd.read_json(foursquare_train_path)
    locu_train = pd.read_json(locu_train_path)

    # Join the foursq and locu data using a cartesian product
    train_df = crossjoin(foursq_train,
        locu_train,
        suffixes=['_foursq', '_locu'])

    # Merge the match labels and training data
    matches_train.columns = ['id_locu', 'id_foursq']
    matches_train['matched'] = 1
    train_df = train_df.merge(matches_train,
        how='left',
        left_on=['id_locu', 'id_foursq'],
        right_on=['id_locu', 'id_foursq'])
    train_df['matched'].fillna(0, inplace=True)

    foursq_test = pd.read_json(foursquare_test_path)
    locu_test = pd.read_json(locu_test_path)

    # Join the foursq and locu data using a cartesian product
    test_df = crossjoin(foursq_test,
        locu_test,
        suffixes=['_foursq', '_locu'])

    # Gathering common brand names based on counts
    all_names = foursq_train['name'] \
                .append(locu_train['name']) \
                .append(foursq_test['name']) \
                .append(locu_test['name'])
    all_names.apply(lambda n: norm_name(n, default='None'))
    name_counts = Counter(all_names)
    brand_names = [name for name in name_counts if name_counts[name] > 2]

    def name_match(df):
        return name_match_no_brands(df, brand_names)

    '''
    features_train = featurize(train_df,
                               lat_long_continuous,
                               address_match,
                               name_match,
                               name_fuzzy,
                               addr_fuzzy,
                               phone_num_match)

    features_test = featurize(test_df,
                              lat_long_continuous,
                              address_match,
                              name_match,
                              name_fuzzy,
                              addr_fuzzy,
                              phone_num_match)
    '''

    df_train, _ = filter_matches(train_df,
        lambda df: simple_addr_match(df) & name_match(df))
    df_test, filtered_matches = filter_matches(test_df,
        lambda df: simple_addr_match(df) & name_match(df))

    df_train = filter_neg(df_train,
        lambda df: ~postal_match(df) & ~region_match(df))
    df_test = filter_neg(df_test,
        lambda df: ~postal_match(df) & ~region_match(df))

    feats_train = featurize(df_train,
                            lat_long_continuous,
                            name_fuzzy,
                            addr_fuzzy,
                            phone_num_match)

    feats_test = featurize(df_test,
                           lat_long_continuous,
                           name_fuzzy,
                           addr_fuzzy,
                           phone_num_match)

    '''
    Load and train a gradient boosted tree using LightGBM's
    default configuration and Dataset wrapper API.
    '''
    feats_train_lgb = lgb.Dataset(feats_train, label=df_train['matched'])
    params = {}
    clf = lgb.train(params, feats_train_lgb, 100)

    fake_preds = [True] * _.shape[0]
    print('F1 score: {}'.format(
        f1_score(np.concatenate([clf.predict(feats_train) > .35, fake_preds]),
                 np.concatenate([df_train['matched'].values > 0, fake_preds]))
    ))

    # Binarize continuous prediction scores from 0 to 1
    preds_test = clf.predict(feats_test) > .35
    print("Shapes:")
    print(feats_test.shape)
    print(preds_test.shape)
    print(df_test.shape)

    # Select rows which are matches via boolean indexing and write to csv
    matches_test = df_test[preds_test][['id_locu', 'id_foursq']]
    matches_test = pd.concat([filtered_matches[['id_locu', 'id_foursq']], matches_test])
    matches_test.columns = ['locu_id', 'foursquare_id']
    matches_test.to_csv('matches_test.csv', index=False)

def crossjoin(df1, df2, **kwargs):
    # Cross join the two org's data to form a dataframe of all possible pairs
    df1['_tmp'] = 1
    df2['_tmp'] = 1
    joined = pd.merge(df1, df2, on=['_tmp'], **kwargs).drop('_tmp', axis=1)
    return joined

'''
Text processing
'''
stop_words = ['restaurant', 'inc', 'cafe', 'bakery', 'and', 'the', 'of']

def remove_words(s, words):
    return ' '.join([token for token in s.split() if s not in words])

def remove_punc(s):
    return re.sub('[.,&#\'()]', '', s)

def norm_name(name, default=''):
    # Normalize a location's name to get matches
    if not name:
        return default

    name = str(name).lower()
    name = remove_punc(name)
    name = remove_words(name, stop_words)
    return name

def unigrams(name):
    return norm_name(name).split()

'''
Discrete Features
'''

def lat_long_match(df):
    # Latitude and longitudes differ in decimal places for foursquare and locu
    # Errors in coordinates and misisng values also reduce recall
    def norm_coord(coord):
        return round(coord, 4)
    return (df['latitude_foursq'].apply(norm_coord) == df['latitude_locu'].apply(norm_coord)) \
         & (df['longitude_foursq'].apply(norm_coord) == df['longitude_locu'].apply(norm_coord))

def phone_num_match(df):
    def norm_foursq_phone(p, default='None'):
        if not p:
            return default
        p = str(p).replace('(', '')
        p = p.replace(')', '')
        p = p.replace(' ', '')
        p = p.replace('-', '')
        return p

    norm_phone = df['phone_foursq'].apply(lambda p: norm_foursq_phone(p, default='None_foursq'))
    return norm_phone == df['phone_locu'].apply(lambda p: norm_foursq_phone(p, default='None_locu'))

def simple_addr_match(df):
    '''Simple address exact matching for filtering purposes'''
    return ~(df['street_address_locu'] == '') \
        & ~(df['street_address_foursq'] == '') \
        & (df['street_address_locu'] == df['street_address_foursq'])

def address_match(df):
    def norm(a, default='None'):
        if not a:
            return default
        a = str(a).lower()
        a = a.replace('east', 'e')
        a = a.replace('west', 'w')
        a = a.replace('south', 's')
        a = a.replace('north', 'n')
        a = a.replace('square', 'sq')
        a = a.replace('th ', ' ')
        a = a.replace('st ', ' ')
        a = a.replace('st. ', ' ')
        a = a.replace('.', '')
        a = a.replace(',', '')
        return a

    return df['street_address_foursq'].apply(lambda a: norm(a, default='None_foursq')) \
        == df['street_address_locu'].apply(lambda a: norm(a, default='None_locu'))

def name_match_no_brands(df, brand_names):
    normed1 = df['name_foursq'].apply(lambda a: norm_name(a, default='None_foursq'))
    normed2 = df['name_locu'].apply(lambda a: norm_name(a, default='None_locu'))
    return ((normed1 == normed2)
        & pd.Series([name not in brand_names for name in df['name_foursq']])
        & pd.Series([name not in brand_names for name in df['name_locu']]))

'''
Continuous Features (mostly based on fuzzy matching)
'''
def name_fuzzy(df):
    fuzzy_ratio = df.apply(lambda row: fuzz.ratio(norm_name(row['name_foursq'], default='None_foursq'),
                                                  norm_name(row['name_locu'], default='None_locu')), axis=1)
    return fuzzy_ratio

def addr_fuzzy(df):
    fuzzy_ratio = df.apply(lambda row: fuzz.ratio(row['street_address_foursq'] or 'None_foursq',
                                                  row['street_address_locu'] or 'None_locu'), axis=1)
    return fuzzy_ratio

def lat_long_continuous(df):
    # Latitude and longitudes differ in decimal places for foursquare and locu
    # Errors in coordinates and misisng values also reduce recall
    def norm_coord(coord):
        return round(coord, 4) if not np.isnan(coord) else -1

    def euclid_dist(row):
        return np.sqrt((norm_coord(row['latitude_foursq'])
                        - norm_coord(row['latitude_locu']))**2
                       + (norm_coord(row['longitude_foursq'])
                        - norm_coord(row['longitude_locu']))**2)

    return df.apply(euclid_dist, axis=1)

'''
Filtering on pairs to avoid training model on all n^2 pairs
'''
def filter_matches(df, *high_prec_feats):
    '''
    Filter out pairs with high precision features.
    Since each location can only be matched once, for each match
    we can reduce all other negative pairs containing that location.
    '''
    # Accumulate the union of positive predictions according to our feats
    # These can be filtered out by virtue of our feats being high precision
    pos = pd.Series([False] * df.shape[0])
    for feat in high_prec_feats:
        pos |= feat(df)

    # Select the positively predicted pairs
    matches = df[pos]

    # Remove all locu and foursquare ids that have already been matched
    # Do this using np.array operations and boolean indexing (which may not be the most efficient)
    keep = pd.Series([True] * (df.shape[0] - matches.shape[0]))
    for id in matches['id_locu']:
        keep = keep & (df['id_locu'] != id)

    for id in matches['id_foursq']:
        keep = keep & (df['id_foursq'] != id)

    # Return the positive predictions separately
    return df[~pos & keep], matches

def filter_neg(df, *high_rec_feats):
    '''
    Filter out pairs that do not match against very rec features.
    This means we can exclude them from consideration because they are
    unlikely to match.
    '''
    excl = pd.Series([False] * df.shape[0])
    for feat in high_rec_feats:
        excl |= feat(df)

    return df[~excl]

'''Evaluating precision and recall of potentially simple filtering heuristics'''
def postal_match(df):
    return df['postal_code_locu'] == df['postal_code_foursq']

def region_match(df):
    return df['locality_locu'] == df['locality_foursq']

def addr_match(df):
    return ~(df['street_address_locu'] == '') \
        & ~(df['street_address_foursq'] == '') \
        & (df['street_address_locu'] == df['street_address_foursq'])

'''Creating the feature matrix'''

def featurize(df, *features):
    feat_df = pd.DataFrame({f.__name__: f(df) for f in features})
    return feat_df

if __name__ == '__main__':
    get_matches('train/locu_train.json',
                'train/foursquare_train.json',
                'train/matches_train.csv',
                'online_competition/locu_test.json',
                'online_competition/foursquare_test.json')


# Bales, Greyson
# 9/5/19
# highscore list

#creating a highscore list
#names for highscores

name1   = "Rachel"
name2   = "Greyson"
name3   = "Rachle"
name4   = "Grayson"
name5   = "Raychl"
name6   = "Gracin"
name7   = "Raechle"
name8   = "Graeson"
name9   = "Rachil"
name10  = "Grecin"

#highscores

score1 = 10
score2 = 9
score3 = 8
score4 = 7
score5 = 6
score6 = 5
score7 = 4
score8 = 3
score9 = 2
score10 = 1

#printing highscores

print("   HIGHSCORE   ")
print("---------------")
print(name1 , str(score1))
print(name2 , str(score2))
print(name3 , str(score3))
print(name4 , str(score4))
print(name5 , str(score5))
print(name6 , str(score6))
print(name7 , str(score7))
print(name8 , str(score8))
print(name9 , str(score9))
print(name10 , str(score10))