#!/usr/bin/env python3

import socketserver
import selectors
import time
from .lib import Datagetter
import json

# import struct

class LiveServer(object):
    sel = selectors.DefaultSelector()  # global selector
    default_port = 58741
    srv = None
    clients = []
    t0 = None

    def __init__(self, server_address=("0.0.0.0", default_port)):
        self.srv = socketserver.TCPServer(server_address, socketserver.StreamRequestHandler, bind_and_activate=False)
        self.srv.timeout = None  # never time out
        self.srv.allow_reuse_address = True
        self.t0 = time.time()

    def connect(self):
        print(f"Listening for clients on {self.srv.server_address}")
        self.srv.server_bind()
        self.srv.server_activate()
        self.sel.register(self.srv.socket, selectors.EVENT_READ, self.accept)

    def accept(self, sock):
        conn, addr = sock.accept()  # accept a connection
        print(f"Accepted new connection: {conn} from ip {addr}")
        # conn.setblocking(False)
        self.sel.register(conn, selectors.EVENT_READ, self.get_data)
        return (conn,)

    def get_data(self, conn):
        try:
            data = conn.recv(1024)
        except Exception as e:
            data = None
        if data:
            pass
        else:  # must be a disconnect
            print("closing", conn)
            self.sel.unregister(conn)
            conn.close()
        return (conn, data)

    def run(self, timeout=float("inf"), dtype="thermal", zone=8):
        with Datagetter(dtype=dtype, zone=zone) as dg:
            self.sel.register(dg.socket, selectors.EVENT_READ, self.get_data)
            while (time.time() - self.t0) < timeout:
                events = self.sel.select(timeout=0.5)  # timeout is how often to check for timed exit
                for key, mask in events:
                    callback = key.data
                    callback_return = callback(key.fileobj)
                    if len(callback_return) == 1:
                        # new client
                        conn = callback_return
                        if len(self.clients) == 0:
                            dg.trigger_new()  # special data request on 0 -> 1 client transition
                        self.clients.append(conn[0])
                    else:  # len will be 2 if not new client
                        # data from connected client
                        conn, data = callback_return
                        if conn in self.clients:
                            if (not data) or (conn._closed):  # client diconnect
                                print(f"Cleaning up client #{self.clients.index(conn)}, {conn}")
                                del self.clients[self.clients.index(conn)]
                            else:
                                try:
                                    cmd = json.loads(data.decode())
                                    if "dtype" in cmd:
                                        dg.dtype = cmd["dtype"]
                                    if "zone" in cmd:
                                        dg.zone = cmd["zone"]
                                    if "delay" in cmd:
                                        dg.delay = cmd["delay"]
                                    if "thermaltype" in cmd:
                                        conn.send(f"{dg.thermaltype}\n".encode())
                                except Exception as e:
                                    # unexpected client data?
                                    print(f"New data from client #{self.clients.index(conn)}, {conn}: {data}")
                        else:  # data from getter
                            # print(f"Got new value = {struct.unpack('f', data)[0]}")
                            if len(self.clients) > 0:
                                dg.trigger_new()  # clients exist, so we'll ask for new data
                                for c in self.clients:
                                    try:
                                        c.send(data)  # relay the data to all clients
                                    except Exception as e:
                                        pass  # best effort

    def serve(self):
        self.connect()
        self.run()

def main():
    ls = LiveServer()
    ls.serve()

if __name__ == "__main__":
    main()


from flask import Blueprint, jsonify
from flask_login import login_required
from app.models import User, Notebook, Note, Tag

user_routes = Blueprint('users', __name__)

@user_routes.route('/')
@login_required
def users():
    """
    Query for all users and returns them in a list of user dictionaries
    """
    users = User.query.all()
    return {'users': [user.to_dict() for user in users]}

@user_routes.route('/<int:id>')
@login_required
def user(id):
    """
    Query for a user by id and returns that user in a dictionary
    """
    user = User.query.get(id)
    return user.to_dict()

@user_routes.route('/<int:id>/notebooks')
@login_required
def get_notebooks_by_user_id(id):
    notebooks = Notebook.query.filter(Notebook.user_id == id).all()

    # notebook_list = list()

    # for notebook in notebooks:
    #     notebook_dict = notebook.to_dict()
    #     notebook_dict['notes'] = [note.to_dict() for note in notebook.notes]
    #     notebook_list.append(notebook_dict)

    # return { 'notebooks': notebook_list }

    return { 'notebooks' : [notebook.to_dict() for notebook in notebooks] }

@user_routes.route('/<int:id>/notes')
@login_required
def get_notes_by_user_id(id):
    notes = Note.query.filter(Note.user_id == id).all()
    return { 'userNotes' : [note.to_dict() for note in notes] }

@user_routes.route('/<int:id>/tags')
@login_required
def get_tags_by_user_id(id):
    tags = Tag.query.filter(Tag.user_id == id).all()
    return { 'tags' : [tag.to_dict() for tag in tags] }


import functools

file = [
    [list(map(int, [z for z in y.split("-")])) for y in x.split(",")] for x in open("input.txt").read().split("\n")
]

def contains_check(acc, e):
    if e[0][0] <= e[1][0] and e[0][1] >= e[1][1]:
        return acc + 1
    if e[1][0] <= e[0][0] and e[1][1] >= e[0][1]:
        return acc + 1
    return acc

print(functools.reduce(contains_check, file, 0))


import pika

#用户名和密码
credentials = pika.PlainCredentials('kudoxi','kudoxi')
#连接机器
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '192.168.254.138',credentials=credentials
))

#建立rabbitmq协议通道
channel = connection.channel()

#声明队列，告诉要发到哪个队列里
channel.queue_declare(queue='hello')

#发消息
#exchange 交换机
#routing_key
channel.basic_publish(
                    exchange='',
                    routing_key='hello',
                    body='hello world')

#关掉队列
connection.close()

#启动
#sudo rabbitmq-server -detached
#创建用户
#rabbitmqctl add_user kudoxi kudoxi
#创建管理员
#rabbitmqctl set_user_tags kudoxi administrator
#授权
#rabbitmqctl set_permissions -p / kudoxi ".*" ".*" ".*"
#重启服务
#/etc/init.d/rabbitmq-server restart
#获取消息 sender里面发了，可以用该命令获取
#rabbitmqctl list_queues


# All the software here is distributed under the terms of the GNU General Public License Version 3, June 2007.
# Trajalign is a free software and comes with ABSOLUTELY NO WARRANTY.
#
# You are welcome to redistribute the software. However, we appreciate is use of such software would result in citations of
# Picco, A., Kaksonen, M., _Precise tracking of the dynamics of multiple proteins in endocytic events_,  Methods in Cell Biology, Vol. 139, pages 51-68 (2017)
# http://www.sciencedirect.com/science/article/pii/S0091679X16301546
#
# Author: Andrea Picco (https://github.com/apicco)
# Year: 2017

import os
from trajalign.traj import Traj
import copy as cp
import numpy as np
import warnings as wr

from sklearn import linear_model

def header( version = 1.99 , year = 2018 , printit = True ) :

    if printit :

        print('|-----------------------------------------------------|')
        print('| Trajalign version ' + str( version ) +' Copyright ' + str( year ) + ' Andrea Picco. |')
        print('|   Url: www.apicco.github.io/trajectory_alignment/   |')
        print('|-----------------------------------------------------|')

    elif not printit :

        return version

    else :

        raise AttributeError('Please, if you want to print the header (printit = True) or if you want to return the verion number only (printit = False).')

def load_directory(path , pattern = '.txt' , sep = None , comment_char = '#' , dt = None , t_unit = '' , coord_unit = '' , intensity_normalisation = 'None' , **attrs ):

    """
    load_directory(path , pattern = '.txt' , sep = None , comment_char = '#' , dt = None , t_unit = '' , coord_unit = '' , intensity_normalisation = 'None' , **attrs ):
    loads all the trajectories listed in 'path', which have the same 'pattern'.
    columns are separated by 'sep' (default is None: a indefinite number of
    white spaces). Comments in the trajectory start with 'comment_char'.

    intensity_normalisation can be: 'None' (no normalisation, default), 'Integral' (normalise over the integral of the fluorescence intensity),
    or 'Absolute' (normalise the fluorescence intensity values between 0 and 1)"

    **attrs is used to assign columns to the trajectory attributes and to
    add annotations.
    If the time interval is added (and 't' is not called in the **attrs)
    then the time column 't' is added, and the 't_unit' can be set.
    If 'coord' is called then the unit must be added.
    """

    if ('coord' in attrs.keys()) & (len(coord_unit) == 0):
        raise AttributeError('Please, specify the coordinate unit \'coord_unit\'')
    if ('t' in attrs.keys()) & (len(t_unit) == 0):
        raise AttributeError('Please, specify the time unit \'t_unit\'')
    if (dt != None) & (len(t_unit) == 0):
        raise AttributeError('Please, specify the time unit \'t_unit\'')
    if (dt != None) & ('t' in attrs.keys()):
        raise AttributeError('Time is already loaded by the trajectories, you cannot also compute it from frames. Please, either remove the dt option or do not load the \'t\' column from the trajectories')

    trajectories = [] #the list of trajectories
    if ( pattern[ len( pattern ) - 1 ] == '$' ) :
        files = [ f for f in sorted( os.listdir(path) ) if f.endswith( pattern[ : - 1 ] ) ] #list all the files in path that have pattern
    else :
        files = [ f for f in sorted( os.listdir(path) ) if pattern in f] #list all the files in path that have pattern

    for file in files:
        trajectory = Traj(experiment = path, path = os.getcwd()+'/'+path, file = file)
        trajectory.load(path+'/'+file,sep = sep, comment_char = comment_char, **attrs)
        if (dt != None):
            trajectory.time(dt,t_unit)
        if ('coord' in attrs.keys()):

            trajectory.annotations('coord_unit',coord_unit)

        if intensity_normalisation == 'Integral' :

            trajectory.scale_f()

        elif intensity_normalisation == 'Absolute' :

            trajectory.norm_f()

        elif intensity_normalisation != 'None' :

            raise AttributeError( "load_directory: Please, choose a value for the variable intensity_normalisation between 'None' (no normalisation, default), 'Integral' (normalise over the integral of the fluorescence intensity), or 'Absolute' (normalise the fluorescence intensity values between 0 and 1)" )

        trajectory.annotations( 'intensity_normalisation' , intensity_normalisation )
        trajectory.fill()
        trajectories.append(trajectory)

    print( "\n >> load_directory: The 'intensity_normalisation' applied to the trajectories is '" + intensity_normalisation + "' <<\n" )

    return trajectories

def MSD(input_t1 , input_t2):

    """
    MSD(t1,t2): finds the rototranslation the  minimises the mean square displacement between the trajectories t1 and t2 and returns the rototranslation of t2.
    Adapted from Horn, 1987, to the 2D case with means weighted on the product of the fluorescence intensities.
    """

    msdt1 = cp.deepcopy(input_t1)
    msdt2 = cp.deepcopy(input_t2)

    if (len(msdt1.f()) == 0) | (len(msdt2.f()) == 0):
        raise AttributeError('MSD(msdt1,msdt2) requires that trajectories msdt1 and msdt2 have values for the fluorescence intensity')

    #the following code follow Horn's (1987) nomenclature. msdt1 is what is
    #called in the paper as 'right coordinates'.
    #msdt2 is what is called as 'left coordinates'

    with wr.catch_warnings():
        # if both f() are 0 or if their product is 0,  a warning about invalid true divide is output. Here we suppress such warnings.
        wr.simplefilter("ignore", category=RuntimeWarning)
        w = msdt1.f() * msdt2.f() / np.nansum( msdt1.f() * msdt2.f() )
    #computed the center of mass, weigthed on the fluorescence intensity product
    rc = np.array([ np.nansum( w * msdt1.coord()[0] ), np.nansum( w * msdt1.coord()[1] )])
    lc = np.array([ np.nansum( w * msdt2.coord()[0] ), np.nansum( w * msdt2.coord()[1] )])

    #translate the trajecotries to their weigthed center of mass
    msdt1.translate( -1 * rc )
    msdt2.translate( -1 * lc )

    Sxx = np.nansum( w * msdt2.coord()[0] * msdt1.coord()[0] )
    Sxy = np.nansum( w * msdt2.coord()[0] * msdt1.coord()[1] )
    Syx = np.nansum( w * msdt2.coord()[1] * msdt1.coord()[0] )
    Syy = np.nansum( w * msdt2.coord()[1] * msdt1.coord()[1] )

    A = ( Syx - Sxy )
    B = ( Sxx + Syy )

    if ( ( A == 0 ) & ( B == 0 ) ):
        theta = np.nan
    else :
        theta = np.arctan2( - A , B )
#        M = - A / B
#
#        theta1 = np.arctan( M )
#        theta2 = theta1 + np.pi
#
#        if B * np.cos(theta1) >= A * np.sin(theta1) :
#            theta = theta1
#        else:
#            theta = theta2

    msdt2.rotate( theta )

    #the 'score' is the mean square displacement weighted on the cross correlation of the fluorescence intensities
    score = np.nansum( w * ( msdt1.coord()[0] - msdt2.coord()[0] )**2 + w * ( msdt1.coord()[1] - msdt2.coord()[1] )**2 )

    #when the min_w is small and the software is sampling the start or end of trajectories,
    #which often have a large number of nan, then theta can become nan as M is the
    #fraction of 0.0/0.0. If that happens then the score is set to infinite.
    if theta != theta:
        score = np.inf

    return({
        'angle' : theta,
        'rc' : rc,
        'lc' : lc,
        'score' : score
        })

def nanMAD( x , axis = None , k = 1.4826):
    MAD = np.nanmedian( np.absolute( x - np.nanmedian( x , axis ) ) , axis )
    return( k * MAD )

def compute_average_start_and_end( trajectories_time_span , aligned_trajectories , max_frame ) :

    l = len( trajectories_time_span[ 'old_start' ] )
    # Define the START and the END of the average trajectory:
    #compute the start and the end of the average trajectory using the
    #start and end of the aligned trajectories whose frame numbers are
    # greater than 0 (i.e. that appeared after the movie recording was
    #started)
    traj_starts_to_average = [trajectories_time_span[ 'new_start' ][ j ] for j in range(l)\
            if trajectories_time_span[ 'old_start' ][ j ] > 0]
    if len( traj_starts_to_average ) > 0 :
        mean_starts = np.mean( traj_starts_to_average )
        n_starts =  len( traj_starts_to_average )
        std_starts = np.std( traj_starts_to_average )

    else  :
        #it can be that all trajectories start with 0 (old_start), which means they
        #started before the movie begun. If so the mean start is set as the latest
        #time between the two trajectories.
        mean_starts = max(trajectories_time_span[ 'new_start' ])
        n_starts = np.nan
        std_starts = np.nan
        print( 'Warning: all trajectory starts were trunkated' )

    #same as for nan mean_starts. However, for the selected mean_ends is the smallest
    traj_ends_to_average = [trajectories_time_span[ 'new_end' ][ j ] for j in range(l)\
            if trajectories_time_span[ 'old_end' ][ j ] < ( max_frame - 3 ) * float(aligned_trajectories[ 0 ].annotations()[ 'delta_t' ])]
    if len( traj_ends_to_average ) > 0 :
        mean_ends = np.mean( traj_ends_to_average )
        n_ends = len( traj_ends_to_average )
        std_ends = np.std( traj_ends_to_average )
    else  :
        mean_ends = min(trajectories_time_span[ 'new_end' ])
        n_ends = np.nan
        std_ends = np.nan
        print( 'Warning: all trajectory ends were trunkated' )

    return( mean_starts , std_starts , n_starts , mean_ends , std_ends , n_ends )

#-------------------------------------END-OF-DEFINITIONS-in-compute_average_start_and_end-----------------------------------
def trajectory_average( aligned_trajectories_to_average , r , median , fimax ) :

    #define the trajectory where the average will be stored
    t = Traj()

    #inherit the annotations from the reference trajectory
    for a in aligned_trajectories_to_average[ r ].annotations().keys():

        if a == 'file':
            t.annotations( 'reference_file' , aligned_trajectories_to_average[ r ].annotations()[ a ])
        else :
            t.annotations( a , aligned_trajectories_to_average[ r ].annotations()[ a ])

    if fimax :
        t.annotations( 'fimax' , 'TRUE' )

    #group all the attributes of the aligned trajectories...
    attributes = [ a for a in aligned_trajectories_to_average[ r ].attributes() if a not in ('t','frames')]
    #create an empy dictionary where all the attributes that will be then averaged are stored
    attributes_to_be_averaged = {}
    for a in attributes:
        attributes_to_be_averaged[a] = []

    #merge all the trajectory attributes into the dictionary attributes_to_be_averaged.
    for j in range( len( aligned_trajectories_to_average ) ):

        for a in attributes:

            attributes_to_be_averaged[a].append(getattr(aligned_trajectories_to_average[ j ],'_'+a))

    #all the aligned trajectories are set to start at the same  mean_start and finish at mean_end computed from
    #trajectories_time_span in compute_average().Hence, the time interval is the same
    t.input_values( 't' , aligned_trajectories_to_average[ r ].t())

    #average the attributes of the trajectories and assign
    #them to the average trajectory [ r ]
    with wr.catch_warnings():

        # if a line is made only of nan that are averaged, then a waring is outputed. Here we suppress such warnings.
        wr.simplefilter("ignore", category=RuntimeWarning)

        for a in attributes:

            if a[ len( a ) - 4 : len( a ) ] == '_err' :

                raise AttributeError('The trajectories to be averaged have already an non empty error element, suggeting that they are already the result of an average. These error currently are not propagated. Check that your trajectories are correct')

            #if _a_err is in the trajectories slots, it means that the attribute a is not
            #an error attribute (i.e. an attribute ending by _err; in fact if a would end by '_err'
            #then _a_err would have twice the appendix _err (i.e. _err_err) and would have
            #no equivalent in the trajectory __slots__. If _a_err is then in the trajectory
            #slots, then both the mean and the sem can be computed. There is no sem without mean.

            if '_' + a + '_err' in t.__slots__:

                if median :

                    t.input_values( a ,
                            np.nanmedian( attributes_to_be_averaged[ a ], axis = 0 )
                        )

                else :

                    t.input_values( a ,
                            np.nanmean( attributes_to_be_averaged[ a ], axis = 0 )
                        )

                #if there is no n defined yet, it computes it
                if not t.n().any() :
                    #compute the number of not-nan data points by dividing
                    #the nansum by the nanmean. The operation is performed
                    #on the last attribute in the loop that can either have
                    #two dimensions (as 'coord') or one. In case of two dims
                    #only one is used to compute '_n'.

                    x = np.nanmean( attributes_to_be_averaged[ a ] , axis = 0 )
                    y = np.nansum( attributes_to_be_averaged[a] , axis = 0 )

                    if len(x) == 2:
                        t.input_values( 'n' , y[0]/x[0] )
                    else:
                        with wr.catch_warnings():
                            # if both y[i] and x[i] are 0, then a waring is outputed. Here we suppress such warnings.
                            wr.simplefilter("ignore", category=RuntimeWarning)
                            t.input_values( 'n' , y/x )

                #compute the errors as standard errors of the mean/median
                try :
                    if median :

                        t.input_values( a + '_err' ,
                            nanMAD( attributes_to_be_averaged[ a ], axis = 0 ) / np.sqrt( t.n() )
                            )

                    else :

                        t.input_values( a + '_err' ,
                            np.nanstd( attributes_to_be_averaged[ a ], axis = 0 ) / np.sqrt( t.n() )
                            )

                except :

                    raise AttributeError( 'The attribute ' + a + ' cannot have its error assigned' )

            else :

                raise AttributeError( 'The attribute ' + a + ' is not recongnised as an attribute' )

    return( t )
#-------------------------------------END-OF-DEFINITION-of-trajectory_average-----------------------------------

def average_trajectories( trajectory_list , output_file = 'average' , median = False , unify_start_end = True , max_frame=[] , fimax = False , fimax_filter = [ -3/35 , 12/35 , 17/35 , 12/35 , -3/35 ] ):

    """
    average_trajectories( trajectory_list , max_frame = 500 , output_file = 'average' , median = False ): align all the
    trajectories in the list together, and average them. 'max_frame' is the max number of frames the movies from which
    the trajctories have been extracted has. It is used to check whether some trajectories are trunkated at the end.
    'output_file' is the name of the output. average_trajectories outputs a txt file with the average trajectroy and
    a directory with all the raw trajectories that have been used to compute the average aligned together in space and time.
    median is an option to compute the median instead of the average of the aligned trajectories. It is useful in case
    of noisy datasets.
    """

    if len(trajectory_list) == 0 :

        raise IndexError('There are not tajectories in the list; check that the trajectories were loaded correctly')

    if not max_frame :

        raise TypeError('You need to specify the max_frame, which is the frame number in your movies')

    def R(alpha):
        """
        R(alpha): returns the rotation matrix:

            /    cos(alpha)    -sin(alpha)        \
        R =    |                                |
            \    sin(alpha)    cos(alpha)        /
        """
        return(np.matrix([[np.cos(alpha),-np.sin(alpha)], [np.sin(alpha),np.cos(alpha)]]))

    def float_range(x,y,step):
        while x < y:
            yield x
            x += step
    def compute_score(average_t,t_list):

        s = []

        for t in t_list:

            w = average_t.f() * t.f() / np.nansum( average_t.f() * t.f() )
            s.append(np.nansum(w * np.nansum((average_t.coord() - t.coord())**2)))

        return(s)

    def triplicate_trajectory( t ):
        #triplicate t adding itself at its beginning and at its end

        output = cp.deepcopy( t )

        #anticipate the start of trajectory by the trajectory duration and a time interval (you need one time interval
        #between the beginning of the real trajectory and the last point of the "anticipated" bit.
        #as len(t) is the number of frames + 1, then len(t) *dt is the duration of the trajectory + one dt interval, which is needed to
        #separate the duplicate trajectory form the original trajectory
        output.start( t.start() - ( len( t ) * float(t.annotations()['delta_t']) ) )
        #delay the end of trajectory in the same way
        output.end( t.end() + ( len( t ) * float(t.annotations()['delta_t']) ) )

        #coord
        output.coord()[:,0:len(t)] = t.coord()
        output.coord()[:,( len(output) - len(t) ):len(output)] = t.coord()
        #f
        output.f()[0:len(t)] = t.f()
        output.f()[( len(output) - len(t) ):len(output)] = t.f()

        return(output)
    def meanangle(angle_estimates):

        #angles can be identical +- n * pi. Hence, averaging
        #absolute values for the mean angle is wrong. Example:
        # np.mean( ( 0, 2 * np.pi ) )
        #is not 0 but np.pi. However, cos and sin are invariant
        #and the mean angle can be computed back from the
        #mean cos and mean sin.
        #angle_estimates is an array (matrix) where the i-th
        #element has estimates of the angles that rotate the
        #i-th trajectory.

        mean_cos = np.mean(np.cos(angle_estimates),axis=1)
        mean_sin = np.mean(np.sin(angle_estimates),axis=1)

        mean_angle = np.arctan2( mean_sin , mean_cos )

        return( mean_angle )

    def refine_alignment( t1 , t2 , lag , alignments , WeightTrajOverlap = False ):

        t1_frames = t1.frames()
        t2_frames = t2.frames() + lag

        sel_t1 = [ i for i in range( len(t1_frames) ) if t1_frames[i] in t2_frames ]
        sel_t2 = [ i for i in range( len(t2_frames) ) if t2_frames[i] in t1_frames ]

        if ( len(sel_t1) > 0 ) & ( len(sel_t2) > 0 ) :

            alignments.append(
                    MSD( t1.extract( sel_t1 ) , t2.extract( sel_t2 ) )
                    )
            alignments[ len( alignments ) - 1][ 'lag' ] = lag

            if WeightTrajOverlap :
                #the scores are weighted with the number of datapoints of the two trajectoreis that
                #trajectories (for example, trajectories that overlap with two data points only).

                alignments[ len( alignments ) - 1 ][ 'score' ] =\
                        alignments[ len( alignments ) - 1 ][ 'score' ] / np.sqrt( len( sel_t1 ) )
        return()

    def lie_down( t ):
        translation_vector = ( - np.nanmedian( t.coord()[0] ) ,- np.nanmedian( t.coord()[1] ) )
        t.translate( translation_vector )

        I_xx = np.nansum( t.f() * t.coord()[1] ** 2 )
        I_yy = np.nansum( t.f() * t.coord()[0] ** 2 )
        I_xy = np.nansum( t.f() * t.coord()[0] * t.coord()[1] )

        theta = np.arctan2( 2 * I_xy , I_xx - I_yy ) / 2

        I_x = I_xx + I_xy * np.tan( theta )
        I_y = I_yy - I_xy * np.tan( theta )

        if I_x > I_y : theta = theta - np.pi/2
        t.rotate( theta )

        with wr.catch_warnings():
            # if a coord has nan then a waring is outputed when nan > 0 or nan < 0 is asked. Here we suppress such warnings.
            wr.simplefilter("ignore", category=RuntimeWarning)
            A = np.nanmedian( t.coord()[0][ t.coord()[0] > 0 ] ** 2 )
            B = np.nanmedian( t.coord()[0][ t.coord()[0] < 0 ] ** 2 )

            if B > A :
                t.rotate( np.pi )
                theta = theta + np.pi #to ouptput the angle

        model = linear_model.LinearRegression()
        model_RANSACR = linear_model.RANSACRegressor( model , random_state = 42 )

        l = len( t )

        j = 0
        for i in range( l ) :

            if ( not np.isnan( t.coord()[ 0 ][ i ] ) ) & ( not np.isnan( t.coord()[ 1 ][ i ] ) ) :
                if j == 0 :
                    X = np.array( [[ t.coord()[ 0 ][ i ] ]] )
                    y = np.array( [ t.coord()[ 1 ][ i ] ] )
                else :
                    X = np.insert( X , 0 , t.coord()[ 0 ][ i ] , axis = 0 )
                    y = np.insert( y , 0 , t.coord()[ 1 ][ i ] , axis = 0 )
                j += 1

        with wr.catch_warnings():
            # also a bug warning occurs from linear models, RANSACR.
            wr.simplefilter("ignore", category=RuntimeWarning)
            model_RANSACR.fit( X , y )

        t.rotate( - np.arctan( model_RANSACR.estimator_.coef_[0] ) )

        return( { 'translation' :  translation_vector , 'angle' : theta - np.arctan( model_RANSACR.estimator_.coef_[0] ) } )

    #-------------------------------------END-OF-DEFINITIONS-in-average_trajectories-----------------------------------

    def compute_transformations( t1 , t1_index , trajectory_list , fimax , fimax_filter ) :

            selected_alignments = []

            if ( fimax ) :

                t1 = t1.fimax( fimax_filter )

            for traj2 in [ traj2 for traj2 in trajectory_list ]:

                if trajectory_list.index(traj2) >= t1_index :

                    #list of trajectories called in the second loop; as the transformation matrices are
                    #symmetric, transformations are computed only in the upper diagonal.
                    selected_alignments.append(
                        {
                            'angle' : 0,
                            'rc' : np.array([0,0]),
                            'lc' : np.array([0,0]),
                            'lag' : 0,
                            'lag_unit' : 'frames',
                            'score' : np.NaN
                            })

                else :

                    t2 = cp.deepcopy( traj2 )
                    #t2.norm_f()

                    print( 'ref. traj.:\t' + t1.annotations()['file'] )
                    print( 'aligned traj.:\t' + t2.annotations()['file'] )

                    alignments = []

                    if ( fimax ) :

                        t2 = t2.fimax( fimax_filter )

                    #triplicate the longest trajectory by adding itself at its beginning and at its end
                    if ( len(t1)  >= len(t2) ) :
                        x = triplicate_trajectory(t1)
                        y = t2
                    else :
                        x = triplicate_trajectory(t2)
                        y = t1

                    convolution_steps = len(x) - len(y)
                    for i in range( 0 , convolution_steps ) :
                        #by triplicating the longest trajectory we can test all possible alignments in
                        #space and time starting with the entire trajectories x and y.
                        lag = int( x.frames( 0 ) - y.frames( 0 ) + i )
                        x_frames = x.frames()
                        y_frames = y.frames() + lag

                        #select the frames that are overlapping
                        sel_frames = [ i for i in range( len( x_frames) ) if x_frames[ i ] in y_frames ]

                        #which trajectory was triplicated decides the sign of the lag
                        if ( len(t1)  >= len(t2) ) :

                            alignments.append(
                                    MSD( x.extract( sel_frames ) , y )
                                    )
                            alignments[ len(alignments)-1 ][ 'lag' ] = lag

                        else :

                            alignments.append(
                                    MSD( y , x.extract( sel_frames ) )
                                    )
                            alignments[ len(alignments)-1 ][ 'lag' ] = - lag

                    s = [ a['score'] for a in alignments ]
                    lags = [ a['lag'] for a in alignments ]
                    sel_alignments = [ i for i in range(len(s)) if s[i] == min(s) ]

                    #check which of the selected alignments best fit the trajectory t1
                    #and not just its triplicate. Importantly, also recompute the alignment
                    #without repetitions of the trajectory, which alter the alignment output
                    refined_alignments_1 = []
                    t1_frames = t1.frames()
                    for sa in sel_alignments:

                        refine_alignment( t1 , t2 , lags[ sa ] , refined_alignments_1 , WeightTrajOverlap = True )

                    refined_s_1 = [  a['score'] for a in refined_alignments_1 ]

                    refined_alignments_2 =[]
                    lag = refined_alignments_1[ refined_s_1.index( min( refined_s_1 ) ) ][ 'lag' ]

                    #define a span, which is not too small, nor too big compared to the trajectory length
                    refine_span = int( min( len( t1 ) , len( t2 ) ) / 10 )
                    for refined_lag in range( lag - refine_span , lag + refine_span + 1 ):

                        refine_alignment( t1 , t2 , refined_lag , refined_alignments_2 , WeightTrajOverlap = False )

                    refined_s_2 = [  a['score'] for a in refined_alignments_2 ]

                    selected_alignments.append( refined_alignments_2[ refined_s_2.index( min( refined_s_2 ) ) ] )

            if ( fimax ) :

                print('\nfimax = True; Transformations were computed using only the trajectory information up to the max in fluorescence intensity.')

            print('________________')

            return( selected_alignments )

    #-------------------------------------END-OF-DEFINITIONS-in-compute_transformations-----------------------------------

    def compute_average( trajectory_list , tranformations , median , fimax , max_frame , unify_start_end ) :

        aligned_trajectories = [] #contains all the alignments in respect to each trajectory
        average_trajectory = [] #contains all averages in respect to each trajectory
        alignment_precision = [] #contains the alignment precision, measured as a score of the alignment

        #As each trajectory is aligned to a reference trajectory or
        #acts as a reference the rc and lc vectors are obtained
        #from rcs and its transpose (i.e. the aligning trajectory
        #becomes the aligned trajectory).
        rcs = transformations['rcs'] + np.transpose(transformations['lcs'],axes=(1,0,2))

        l = len(transformations['angles'])
        #reference trajectories are indexed with r
        for r in range( l ) :

            #define a dictionary used to store the starts and ends of the aligned
            #trajectories to compute the start of the average trajectory
            trajectories_time_span = \
                    { 'old_start' : [], 'new_start' : [], 'old_end' : [], 'new_end' : []}

            #compute the transformation of the trajectories
            #in respect to the r-th trajectory
            #--angles--
            angles_in_respect_of_r = transformations['angles'][ r , ] - transformations['angles']
            m_angles = meanangle(angles_in_respect_of_r)
            #--lags--
            #lags_in_respect_of_r = transformations['lags'] - transformations['lags'][ r ,]
            lags_in_respect_of_r = transformations['lags'][ r ,] - transformations['lags']
            m_lags = [ int(round(l)) for l in np.mean(lags_in_respect_of_r,axis=1)]
            #--translations--
            r_cm = np.mean([rcs[ r , j ] for j in range(l) if j != r ] , axis = 0 )

            #make a copy of the trajectory_list, whose trajectories need to be aligned
            aligned_trajectories.append( cp.deepcopy( trajectory_list ) )

            ##################################################
            #align the trajectoris together in space and time
            ##################################################
            for j in range(l):

                trajectories_time_span[ 'old_start' ].append(aligned_trajectories[ r ][ j ].start())
                trajectories_time_span[ 'old_end' ].append(aligned_trajectories[ r ][ j ].end())

                #compute the center of mass of the full trajectory

                l_cm = np.mean([rcs[ j , r ] for r in range(l) if r != j ] , axis=0 )

                # the following is equivalent to
                #
                # R( m_angles ) @ aligned_trajectories + T
                #
                # where R would be the rotation matrix computed from m_angles
                # and T is the translation computed as
                #
                # r_cm - R( m_angles ) @ l_cm
                #
                # see Horn 1987 for details.
                aligned_trajectories[ r ][ j ].translate( - l_cm )
                aligned_trajectories[ r ][ j ].rotate( m_angles[ j ] )

                aligned_trajectories[ r ][ j ].translate( r_cm )
                aligned_trajectories[ r ][ j ].lag( m_lags[ j ] )

                aligned_trajectories[ r ][ j ].annotations()[ 'l_cm' ] = tuple( l_cm )
                aligned_trajectories[ r ][ j ].annotations()[ 'r_cm' ] = tuple( r_cm )
                aligned_trajectories[ r ][ j ].annotations()[ 'm_angle' ] = m_angles[ j ]
                aligned_trajectories[ r ][ j ].annotations()[ 'm_lag' ] = m_lags[ j ]

                trajectories_time_span[ 'new_start' ].append(aligned_trajectories[ r ][ j ].start())
                trajectories_time_span[ 'new_end' ].append(aligned_trajectories[ r ][ j ].end())

            mean_start , std_start , n_start , mean_end , std_end , n_end = compute_average_start_and_end( trajectories_time_span , aligned_trajectories[ r ] , max_frame )

            if unify_start_end :

                #uniform start and end of aligned trajectories to mean_start and mean_end
                for j in range(l):

                    #if the unify_start_end is choosen, the average trajectory is started (and ended) from the average
                    #start (and end) of the trajectory minus (and plus) the 95% CI. This addition (or subtraction) as
                    #been choosen to counter the intrinsic underestimate of the trajectories lifetimes.
                    aligned_trajectories[ r ][ j ].start( mean_start - 1.96 * std_start / np.sqrt( n_start ) )
                    aligned_trajectories[ r ][ j ].end( mean_end + 1.96 * std_end / np.sqrt( n_end ) )

            else :

                for j in range(l):

                    aligned_trajectories[ r ][ j ].start( min( trajectories_time_span[ 'new_start' ] ) )
                    aligned_trajectories[ r ][ j ].end( max( trajectories_time_span[ 'new_end' ] ) )

            ########################################################################
            #compute the average of the trajectories aligned to the r-th trajectory
            #define the average trajectory and its time attribute
            ########################################################################

            ta = trajectory_average( aligned_trajectories[ r ] , r , median , fimax )

            #record the standard deviation of the average start and end, so that the user
            #knows how the start and end timepoints of the raw trajectories are distributed,
            #once alingned.

            ta.annotations( 'mean_starts' , str( mean_start ) )
            ta.annotations( 'std_starts' , str( std_start ) )
            ta.annotations( 'n_starts' , str( n_start ) )
            ta.annotations( 'mean_ends' , str( mean_end ) )
            ta.annotations( 'std_ends' , str( std_end ) )
            ta.annotations( 'n_ends' , str( n_end ) )

            if not unify_start_end :

                ta.annotations( 'unified_start' , mean_start - 1.96 * std_start / np.sqrt( n_start ) )
                ta.annotations( 'unified_end' , mean_end + 1.96 * std_end / np.sqrt( n_end ) )

            average_trajectory.append( ta )

            #store the transformations of the trajectories in respect of the trajectory r.
            if r == 0:
                all_m_angles = np.array([ m_angles ])
                all_m_lags = np.array([ m_lags ])
            else :
                all_m_angles = np.vstack([ all_m_angles , m_angles ])
                all_m_lags = np.vstack([ all_m_lags , m_lags ])

            mean_precision =  np.sqrt(
                    np.nanmean(
                        average_trajectory[ r ].coord_err()[ 0 ] ** 2 + average_trajectory[ r ].coord_err()[ 1 ] ** 2
                        )
                    )
            alignment_precision.append(mean_precision)

        print('ALIGNMENT PRECISIONS.\nMIN is the alignment\nselected for the average\n----------------------')
        for a in alignment_precision :

            if a == min( alignment_precision ) :

                print( 'MIN>>\t' + str( a ) )

            elif a == max( alignment_precision ) :

                print( 'MAX>>\t' + str( a ) )

            else :

                print( '\t' + str( a ) )

        print('----------------------')
        print( 'MEAN:\t' + str( np.mean( alignment_precision ) ) )

        return( aligned_trajectories , average_trajectory , alignment_precision )

    #-------------------------------------END-OF-DEFINITIONS-in-compute_average-----------------------------------

    header()

    #define the list where transformations are stored
    transformations = {
            'angles' : np.array( [] ),
            'rcs' : np.array( [ np.array( [] ) , np.array( [] ) ] ),#note that the matric rcs is the transpose of the lcs
            'lcs' : np.array( [ np.array( [] ) , np.array( [] ) ] ),
            'lags' : np.array( [] ),
            'lag_units' : np.array( [] )
            }

    for traj1 in trajectory_list:

        #t1 is the reference trajectory to which all the other trajectories are alinged
        #The loop goes on all trajectories as all of them are eligible to be used as reference

        #the index need to be computed now, becuase if fi_max is true, then t1 will be replaced
        #by the part of t1 trajectory that stops at the peak of fluorescence intensity. This
        #new trajectory cannot be found animore in trajectory_list. Hence, we must compute the
        #index before.

        t1 = cp.deepcopy( traj1 )
        t1_index = trajectory_list.index(traj1)
        #t1.norm_f()

        selected_alignments = compute_transformations( t1 , t1_index , trajectory_list , fimax , fimax_filter )

        #Create a matrix with all the transformations: angle, lag and center of masses.
        #As a convention the element i,j in the matrix contains the elements for the
        #rototranslation and temporal shift to align the trajectori i to j, j being the
        #reference.
        if t1_index == 0:

            transformations['angles'] = np.array(
                    [a['angle'] for a in selected_alignments]
                    )
            transformations['rcs'] = np.array([
                    np.array([a['rc'] for a in selected_alignments])
                    ])
            transformations['lcs'] = np.array([
                    np.array([a['lc'] for a in selected_alignments])
                    ])
            transformations['lags'] = np.array(
                    [a['lag'] for a in selected_alignments]
                    )
        else:

            transformations['angles'] = np.vstack([
                transformations['angles'],
                np.array([
                    np.array([a['angle'] for a in selected_alignments])
                    ])
                ])
            transformations['rcs'] = np.vstack([
                transformations['rcs'],
                    [[a['rc'] for a in selected_alignments]]
                ])
            transformations['lcs'] = np.vstack([
                transformations['lcs'],
                    [[a['lc'] for a in selected_alignments]]
                ])
            transformations['lags'] = np.vstack([
                transformations['lags'],
                np.array(
                    [a['lag'] for a in selected_alignments]
                    )
                ])

    transformations['angles'] = transformations['angles'] - np.transpose(transformations['angles'])
    transformations['lags'] = transformations['lags'] - np.transpose(transformations['lags'])

    l = len(transformations['angles'])
    for i in range( l ):
        transformations['lcs'][ i , i ] = [ 0 , 0 ]

    #compute the average transformation using each trajectory as possible reference
    aligned_trajectories , average_trajectory , alignment_precision = compute_average( trajectory_list , transformations , median , fimax , max_frame , unify_start_end )

    best_average = alignment_precision.index( np.nanmin( alignment_precision ) )
    worst_average = alignment_precision.index( np.nanmax( alignment_precision ) )

    if not unify_start_end :

        # compute the lie_down only on the part of the trajectory that represents
        # most of the average trajectories. That would be the part of average trajectory
        # chosen if unify_start_end = True, i.e. the part of trajectory comprised between
        # the annotations unified_start and unified_end
        average_trajectory_tmp = cp.deepcopy( average_trajectory[ best_average ] )
        average_trajectory_tmp.start( float( average_trajectory_tmp.annotations()[ 'unified_start' ] ) )
        average_trajectory_tmp.end( float( average_trajectory_tmp.annotations()[ 'unified_end' ] ) )
        lie_down_transform = lie_down( average_trajectory_tmp )

        # lie_down modified average_trajectory_tmp with the transformations in dict lie_down_transform
        # we apply these transformations to average_trajectory[ best_average ]
        average_trajectory[ best_average ].translate( lie_down_transform[ 'translation' ] )
        average_trajectory[ best_average ].rotate( lie_down_transform[ 'angle' ] )

    else :

        lie_down_transform = lie_down( average_trajectory[ best_average ] )

    average_trajectory[ best_average ].annotations()[ 'trajalign_version' ] = header( printit = False )
    average_trajectory[ best_average ].save( output_file )

    #save the trajectories use to compute the average, lied down as the average trajectory
    for i in range(l):
        aligned_trajectories[ best_average ][ i ].translate( lie_down_transform[ 'translation' ] )
        aligned_trajectories[ best_average ][ i ].rotate( lie_down_transform[ 'angle' ] )
        aligned_trajectories[ best_average ][ i ].annotations()[ 'trajalign_version' ] = header( printit = False )
        aligned_trajectories[ best_average ][ i ].annotations()[ 'lie_down_angle' ] = lie_down_transform[ 'angle' ]
        aligned_trajectories[ best_average ][ i ].annotations()[ 'lie_down_translation' ] = tuple( lie_down_transform[ 'translation' ] )

        filename = "./" + output_file + "/" + aligned_trajectories[ best_average ][ i ].annotations()[ 'file' ]
        if i == 0 :
            directory = os.path.dirname( filename )
            if not os.path.exists( directory ) :
                os.makedirs( directory )
        aligned_trajectories[ best_average ][ i ].save( filename )

    with open( "./" + output_file + "/alignment_precision.txt" , 'w' ) as f :

        for ap in alignment_precision :
            f.write( repr( ap ) + '\n' )

    f.close()

    return( average_trajectory[ best_average ] , average_trajectory[ worst_average ] , aligned_trajectories[ best_average ] )

def unified_start( t , add_CI = True , correct_lag = True ) :

    try :

        if add_CI :
            ustart =  float( t.annotations()[ 'mean_starts' ] ) - 1.96 * float( t.annotations()[ 'std_starts' ] ) / np.sqrt( float( t.annotations()[ 'n_starts' ] ) )
        else :
            ustart = float( t.annotations()[ 'mean_starts' ] )

        if ( 'alignment_lag' in t.annotations().keys() ) & correct_lag :
            return ustart + float( t.annotations()[ 'alignment_lag' ].split()[ 0 ] )
        else :
            return ustart

    except :

        print( 'Error: one or more of the annotations mean_starts, std_starts, and n_starts is/are missiong' )

def unified_end( t , add_CI = True , correct_lag = True ) :

    try :

        if add_CI :
            uend = float( t.annotations()[ 'mean_ends' ] ) + 1.96 * float( t.annotations()[ 'std_ends' ] ) / np.sqrt( float( t.annotations()[ 'n_ends' ] ) )
        else :
            uend = float( t.annotations()[ 'mean_ends' ] )

        if ( 'alignment_lag' in t.annotations().keys() ) & correct_lag :
            return uend + float( t.annotations()[ 'alignment_lag' ].split()[ 0 ] )
        else :
            return uend

    except :

        print( 'Error: one or more of the annotations mean_ends, std_ends, and n_ends is/are missiong' )


import numpy as np

from tenpy.algorithms import dmrg
from tenpy.networks.mps import MPS
from tenpy.networks import site

from tenpy.models.model import CouplingMPOModel
from tenpy.networks.site import FermionSite
from tenpy.models import lattice

class BipartiteSquare(lattice.Lattice):
    def __init__(self, Lx, Ly, siteA, **kwargs):
        basis = np.array(([2, 0.], [0, 2]))

        pos = np.array(([0, 0], [1, 0], [0, 1], [1, 1]))

        kwargs.setdefault('order', 'default')
        kwargs.setdefault('bc', 'periodic')
        kwargs.setdefault('bc_MPS', 'infinite')
        kwargs.setdefault('basis', basis)
        kwargs.setdefault('positions', pos)

        super().__init__([Lx, Ly], [siteA, siteA, siteA, siteA], **kwargs)

        self.NN = [(0, 1, np.array([0, 0])), (1, 3, np.array([0, 0])), (3, 2, np.array([0, 0])),
                   (2, 0, np.array([0, 0])), (2, 0, np.array([0, 1])), (1, 3, np.array([0, -1])),
                   (0, 1, np.array([-1, 0])), (3, 2, np.array([1, 0]))]
        self.nNNdashed = [(0, 3, np.array([0, 0])), (2, 1, np.array([0, 0])),
                          (3, 0, np.array([1, 1])), (1, 2, np.array([1, -1]))]
        self.nNNdotted = [(1, 2, np.array([1, 0])), (3, 0, np.array([1, 0])),
                          (2, 1, np.array([0, 1])), (3, 0, np.array([0, 1]))]

class FermionicPiFluxModel(CouplingMPOModel):
    def init_sites(self, model_params):
        conserve = model_params.get('conserve', 'N')
        site = FermionSite(conserve=conserve)
        return site

    def init_lattice(self, model_params):
        Lx = model_params.get('Lx', 1)
        Ly = model_params.get('Ly', 3)
        fs = self.init_sites(model_params)
        lat = BipartiteSquare(Lx, Ly, fs)
        return lat

    def init_terms(self, model_params):
        t = np.asarray(model_params.get('t', -1.))
        V = np.asarray(model_params.get('V', 0.))
        mu = np.asarray(model_params.get('mu', 0.))
        phi_ext = 2 * np.pi * model_params.get('phi_ext', 0.)

        t1 = t * np.exp(1j * np.pi / 4)
        t2 = t / np.sqrt(2)

        self.add_onsite(mu, 0, 'N', category='mu N')
        self.add_onsite(-mu, 1, 'N', category='mu N')

        for u1, u2, dx in self.lat.NN:
            t1_phi = self.coupling_strength_add_ext_flux(t1, dx, [0, phi_ext])
            self.add_coupling(t1_phi, u1, 'Cd', u2, 'C', dx, 'JW', True,
                              category='t1 Cd_i C_j', add_hc=True)  # yapf: disable
            self.add_coupling(V, u1, 'N', u2, 'N', dx, category='V N_i N_j')

        for u1, u2, dx in self.lat.nNNdashed:
            t2_phi = self.coupling_strength_add_ext_flux(t2, dx, [0, phi_ext])
            self.add_coupling(t2_phi, u1, 'Cd', u2, 'C', dx, 'JW', True,
                              category='t2 Cd_i C_j', add_hc=True)  # yapf: disable

        for u1, u2, dx in self.lat.nNNdotted:
            t2_phi = self.coupling_strength_add_ext_flux(t2, dx, [0, phi_ext])
            self.add_coupling(-t2_phi, u1, 'Cd', u2, 'C', dx, 'JW', True,
                              category='-t2 Cd_i C_j', add_hc=True)  # yapf: disable

def plot_lattice():

    import matplotlib.pyplot as plt
    ax = plt.gca()
    fs = site.FermionSite()
    lat = BipartiteSquare(3, 3, fs, basis=[[2, 0], [0, 2]])
    lat.plot_sites(ax)
    lat.plot_coupling(ax, lat.NN, linestyle='-', color='green')
    lat.plot_coupling(ax, lat.nNNdashed, linestyle='--', color='black')
    lat.plot_coupling(ax, lat.nNNdotted, linestyle='--', color='red')
    ax.set_aspect('equal')
    plt.show()

def run(phi_ext=np.linspace(0, 1.0, 7)):

    data = dict(phi_ext=phi_ext, QL=[], ent_spectrum=[])

    model_params = dict(conserve='N', t=-1, V=0, mu=0, Lx=1, Ly=3, verbose=1)

    dmrg_params = {
        'mixer': True,  # setting this to True helps to escape local minima
        'mixer_params': {
            'amplitude': 1.e-5,
            'decay': 1.2,
            'disable_after': 30
        },
        'trunc_params': {
            'svd_min': 1.e-10,
        },
        'lanczos_params': {
            'N_min': 5,
            'N_max': 20
        },
        'chi_list': {
            0: 9,
            10: 49,
            20: 100
        },
        'max_E_err': 1.e-10,
        'max_S_err': 1.e-6,
        'max_sweeps': 150,
        'verbose': 1.,
    }

    prod_state = ['empty', 'full'] * (model_params['Lx'] * model_params['Ly'] * 2)

    eng = None

    for phi in phi_ext:

        print("=" * 100)
        print("phi_ext = ", phi)

        model_params['phi_ext'] = phi

        if eng is None:  # first time in the loop
            M = FermionicPiFluxModel(model_params)
            psi = MPS.from_product_state(M.lat.mps_sites(), prod_state, bc=M.lat.bc_MPS)
            eng = dmrg.TwoSiteDMRGEngine(psi, M, dmrg_params)
        else:
            del eng.options['chi_list']
            M = FermionicPiFluxModel(model_params)
            eng.init_env(model=M)

        E, psi = eng.run()

        data['QL'].append(psi.average_charge(bond=0)[0])
        data['ent_spectrum'].append(psi.entanglement_spectrum(by_charge=True)[0])

    return data

def plot_results(data):

    import matplotlib.pyplot as plt

    plt.figure()
    ax = plt.gca()
    ax.plot(data['phi_ext'], data['QL'], marker='o')
    ax.set_xlabel(r"$\Phi_y / 2 \pi$")
    ax.set_ylabel(r"$ \langle Q^L(\Phi_y) \rangle$")
    plt.savefig("chiral_pi_flux_charge_pump.pdf")

    plt.figure()
    ax = plt.gca()
    colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k']
    color_by_charge = {}
    for phi_ext, spectrum in zip(data['phi_ext'], data['ent_spectrum']):
        for q, s in spectrum:
            q = q[0]
            label = ""
            if q not in color_by_charge:
                label = "{q:d}".format(q=q)
                color_by_charge[q] = colors[len(color_by_charge) % len(colors)]
            color = color_by_charge[q]
            ax.plot(phi_ext * np.ones(s.shape),
                    s,
                    linestyle='',
                    marker='_',
                    color=color,
                    label=label)
    ax.set_xlabel(r"$\Phi_y / 2 \pi$")
    ax.set_ylabel(r"$ \epsilon_\alpha $")
    ax.set_ylim(0., 8.)
    ax.legend(loc='upper right')
    plt.savefig("chiral_pi_flux_ent_spec_flow.pdf")

if __name__ == "__main__":

    # plot_lattice()
    data = run()
    plot_results(data)


from django.shortcuts import render, redirect
from .models import Files
from ProjectApp.models import Projects
from django.contrib.auth.models import User
from UserApp.models import Profile
import random

# def show_project_list(request):
#     proj_obj = []
#     User_Profile = Profile.objects.get(user=request.user)
#     # filter는 쿼리셋 메소드를 가져오니까 get으로 값을 불러오세요!!!!!!
#     User_Projects = User_Profile.projects.split(',')

#     for i in User_Projects:
#         proj_obj += Projects.objects.filter(name=i)
#     return render(request, 'ProjectApp/project_list.html', {'proj_obj' : proj_obj})

def show_file_list(request,project_id):
    project = Projects.objects.get(id = project_id)
    pro_name = project.name
    # detail pro name 뽑아오는 과정
    proj_obj = []
    proj_user = []
    empty = ''
    # for문 위한 초기 선언
    for x in Profile.objects.all():
        a = x.projects.split(',')
        proj_obj = a
        if pro_name in proj_obj:
            proj_user.append(x.user)
    # for문 지나서 project 가진 user 정보들이 list로 뽑힙니다
    file_obj = Files.objects.filter(ownerPCode=project_id)
    if len(file_obj) == 0:
        empty = '추적한 파일이 없습니다'
    return render(request, 'FileApp/file_list.html', {'file_obj':file_obj,'proj_user':proj_user,'empty':empty})

# def form_create_new_file(request):
#     return render(request, 'FileApp/form_create_new_file.html')

# def show_upload(request):
#     return render(request, 'FileApp/upload.html')

# def create_new_file(request):
#     file_obj = Files()
#     file_obj.fileName = "따뜻한라떼"
#     file_obj.Code = random.randint(0,0xffffff)
#     file_obj.whoIsOwner = User.objects.get(username = 'sea')
#     file_obj.ownerPCode = Projects.objects.get(name = 'proscons')
#     file_obj.save()
#     return redirect('project_detail')


from random import randint
import pygame as pg
from pygame.sprite import Sprite, Group
from laser import Lasers
from timer import Timer

class Alien(Sprite):

    #alien_images = pg.image.load('images/alien3.png')
    #alien_explosion_images = [pg.image.load(f'images/explode{n}.png') for n in range(7)]

    def __init__(self, settings, screen, rowNum):

        if rowNum%3 == 0:
            self.alien_explosion_images = [pg.image.load(f'images/PExplode{n}.png') for n in range(8)]
            self.alien_images = [pg.image.load(f'images/PurpleAlien{n}.png') for n in range(2)]
            self.points = 10
        elif rowNum % 3 == 1:
            self.alien_explosion_images = [pg.image.load(f'images/BExplode{n}.png') for n in range(8)]
            self.alien_images = [pg.image.load(f'images/BlueAlien{n}.png') for n in range(2)]
            self.points = 20
        else:
            self.alien_explosion_images = [pg.image.load(f'images/GExplode{n}.png') for n in range(8)]
            self.alien_images = [pg.image.load(f'images/GreenAlien{n}.png') for n in range(2)]
            self.points = 40
        super().__init__()
        self.screen = screen
        self.settings = settings
        self.image = pg.image.load('images/alien0.bmp')
        self.rect = self.image.get_rect()
        self.rect.y = self.rect.height
        self.x = float(self.rect.x)

        self.dying = self.dead = False
        self.timer_normal = Timer(image_list=self.alien_images)
        self.timer_explosion = Timer(image_list=self.alien_explosion_images, is_loop=False)
        self.timer = self.timer_normal

    def check_edges(self):
        screen_rect = self.screen.get_rect()
        return self.rect.right >= screen_rect.right or self.rect.left <= 0
    def check_bottom_or_ship(self, ship):
        screen_rect = self.screen.get_rect()
        return self.rect.bottom >= screen_rect.bottom or self.rect.colliderect(ship.rect)
    def hit(self):
        self.dying = True
        self.timer = self.timer_explosion
    def update(self):
        if self.timer == self.timer_explosion and self.timer.is_expired():
            self.kill()
        settings = self.settings
        self.x += (settings.alien_speed_factor * settings.fleet_direction)
        self.rect.x = self.x
        self.draw()
    def draw(self):
        image = self.timer.image()
        rect = image.get_rect()
        rect.left, rect.top = self.rect.left, self.rect.top
        self.screen.blit(image, rect)
        # self.screen.blit(self.image, self.rect)

class UFO(Sprite):

    #alien_images = pg.image.load('images/alien3.png')
    #alien_explosion_images = [pg.image.load(f'images/explode{n}.png') for n in range(7)]

    def __init__(self, settings, screen):
        self.alien_explosion_images = []
        self.alien_images = [pg.image.load(f'images/UFO{n}.png') for n in range(2)]
        self.points = randint(50,250)
        super().__init__()
        self.screen = screen
        self.settings = settings
        self.image = pg.image.load('images/UFO0.png')
        self.rect = self.image.get_rect()
        self.rect.y = self.rect.height
        self.x = float(self.rect.x)

        text_color = (255, 0, 0)
        font = pg.font.SysFont(None, 50)

        score_image = None

        score_str = str(self.points)
        score_image = font.render(score_str, True, text_color)

        for i in range(10):
            self.alien_explosion_images.append(score_image)

        self.dying = self.dead = False
        self.timer_normal = Timer(image_list=self.alien_images)
        self.timer_explosion = Timer(image_list=self.alien_explosion_images, is_loop=False)
        self.timer = self.timer_normal

    def check_edges(self):
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right + 50:
            self.hit()
        return self.rect.right >= screen_rect.right+300
    def check_bottom_or_ship(self, ship):
        screen_rect = self.screen.get_rect()
        return self.rect.bottom >= screen_rect.bottom or self.rect.colliderect(ship.rect)
    def hit(self):
        self.dying = True
        self.timer = self.timer_explosion
    def update(self):
        if self.timer == self.timer_explosion and self.timer.is_expired():
            self.kill()
        settings = self.settings
        self.x += (settings.alien_speed_factor)
        self.rect.x = self.x
        self.draw()
    def draw(self):
        image = self.timer.image()
        rect = image.get_rect()
        rect.left, rect.top = self.rect.left, self.rect.top
        self.screen.blit(image, rect)

class Aliens:
    def __init__(self, game, screen, settings, lasers: Lasers, ship, bunkers):
        self.model_alien = Alien(settings=settings, screen=screen, rowNum=0)
        self.game = game
        self.sb = game.scoreboard
        self.aliens = Group()
        self.lasers = lasers.lasers    # a laser Group
        self.screen = screen
        self.settings = settings
        self.ship = ship
        self.bunkers = bunkers
        self.create_fleet()
        self.alienLasers = Lasers(settings = self.settings)
    def get_number_aliens_x(self, alien_width):
        available_space_x = self.settings.screen_width - 2 * alien_width
        number_aliens_x = int(available_space_x / (2 * alien_width))
        return number_aliens_x
    def get_number_rows(self, ship_height, alien_height):
        available_space_y = (self.settings.screen_height - (3 * alien_height) - ship_height)
        number_rows = int(available_space_y / (2 * alien_height))
        return number_rows
    def reset(self):
        self.aliens.empty()
        self.create_fleet()
    def create_alien(self, alien_number, row_number):
        alien = Alien(settings=self.settings, screen=self.screen, rowNum=row_number)
        alien_width = alien.rect.width

        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)

    def add_UFO(self):
        ufo = UFO(settings=self.settings, screen=self.screen)
        #ufo_width = ufo.rect.width

        ufo.rect.x = -200
        ufo.rect.y = 10

        #self.UFO = ufo
        self.aliens.add(ufo)

    def create_fleet(self):
        number_aliens_x = self.get_number_aliens_x(self.model_alien.rect.width)
        number_rows = self.get_number_rows(self.ship.rect.height, self.model_alien.rect.height)
        for row_number in range(number_rows):
            for alien_number in range(number_aliens_x):
                   self.create_alien(alien_number, row_number)
        #self.add_UFO()
    def check_fleet_edges(self):
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self.change_fleet_direction()
                break
    def check_fleet_bottom(self):
        for alien in self.aliens.sprites():
            if alien.check_bottom_or_ship(self.ship):
                self.ship.die()
                break
        #if self.UFO.check_bottom_or_ship(self.ship):
            #self.ship.die()
    def check_fleet_empty(self):
        if len(self.aliens.sprites()) == 0:
            print('Aliens all gone!')
            self.game.reset()
    def change_fleet_direction(self):
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1
    def check_collisions(self):
        collisions = pg.sprite.groupcollide(self.aliens, self.lasers, False, True)
        if collisions:
            for alien in collisions:
                alien.hit()
                self.sb.increment_score(alien.points)
        #self.sb.increment_score()
        #ufo_collision = pg.sprite.groupcollide(self.UFO, self.lasers, False, True)
        #asdf = self.UFO.rect.colliderect(self.lasers
        collisions = pg.sprite.groupcollide(self.alienLasers.lasers, self.bunkers.bunkers, True, False)
        if not self.alienLasers.isEmpty():

            for laser in self.alienLasers.lasers:
                #print("IN ALIEN LASER CHECK")
                if laser.rect.colliderect(self.ship):
                    self.alienLasers.lasers.empty()
                    print("SHIP HIT")
                    self.ship.die()
    def update(self):
        if randint(0,10001) % 2000 == 0: # my very bootleg timer
            self.add_UFO()
        self.check_fleet_edges()
        self.check_fleet_bottom()
        self.check_collisions()
        self.check_fleet_empty()
        self.alienLasers.update()
        for alien in self.aliens.sprites():
            if alien.dead:      # set True once the explosion animation has completed
                alien.remove()
            alien.update()
            if randint(0,10001) % 7500 == 0: # my very bootleg timer
                self.alienLasers.AlienShoot(settings=self.settings, screen=self.screen, ship=alien)
        #self.UFO.update() #CUT

    def draw(self):
        for alien in self.aliens.sprites():
            alien.draw()
        #self.UFO.draw() #CUT

    def clearFleet(self):
        for a in self.aliens:
            a.remove()


#!/usr/bin/env python3
# encoding: utf-8

# The list of lexical features:
'''
Avg KEELY log freq
A1 lemma INCSC
A2 lemma incsc
B1 lemma incsc
B2 lemma incsc
C1 lemma incsc
C2 lemma incsc
difficult word incsc
difficult noun & verb incsc
oov incsc
no lemma incsc
                No lemma incsc, the lemmas of the input sentence are checked against the SALDO lexicon,
                not via the <saldo> element, but rather based on the output of the lemmatizer integrated
                in the Sparv annotation pipeline used for preprocessing, you can find more details at these links:
                https://spraakbanken.gu.se/eng/research/infrastructure/sparv/annotations
                https://ws.spraakbanken.gu.se/ws/sparv/v2/
'''
import math
import pickle
from util import read_json
from util import mean, median, incsc, mean_median
from collections import Counter
from statistics import stdev
#########################################################################
############specific lexical feature computation#########################
#########################################################################

def lemma_incsc(sentence, cefr, kelly_dict, raw=True): # typ is which cefr level the sentence is involved, d is dict
    '''cefr is 1,2,3,4,5,6 which represents A1, A2, B1, B2, C1, C2
    this function will be applied to extra the values of the following features
    A1 lemma INCSC
    A2 lemma INCSC
    B1 lemma INCSC
    B2 lemma INCSC
    C1 lemma INCSC
    C2 lemma INCSC
    #Missing lemma form INCSC
    #Out-of Kelly-list INCSC'''

    t = len(sentence.tokens)
    sent_cefr = []
    for token in sentence.tokens:
        if token.lemma+'|'+token.upos in kelly_dict:
            sent_cefr.append(kelly_dict[token.lemma+'|'+token.upos])
        else:
            sent_cefr.append(None)
    countDict = {t:counts for t,counts in Counter(sent_cefr).most_common()}
    if raw:
        return countDict.setdefault(cefr, 0), t
    return float(countDict.setdefault(cefr,0))/t

def difficult_word(sentence, kelly_dict,noun_verb=False, raw=True):
    #difficult words refer to words above and inclunding B1 level

    t,p = len(sentence.tokens), 0
    for token in sentence.tokens:
        if token.lemma+'|'+token.upos in kelly_dict:
            if kelly_dict[token.lemma+'|'+token.upos] in "3456":
                if noun_verb:
                    if token.upos in ["NOUN","VERB"]: #Only noun and verb valid, not propn and aux
                        p += 1
                        continue
                else:
                    p += 1
    if raw:
        return p, t
    return float(p*1000)/t

def out_of_kelly(sentence, kelly_dict, raw=True):
    if not sentence:
        return 0.0
    t,p = len(sentence.tokens), 0
    for token in sentence.tokens:
        if token.lemma+"|"+token.upos not in kelly_dict:
            p += 1
    if raw:
        return p, t
    return float(p*1000)/t

def kelly_log_frequency(sentence, wpm_dict, raw=True):
    '''WPM is used to compute the avg kelly log freq
    the computation of log-freq for the tokens out of the kelly list is ignored
    the natural logarthigm is used
    '''
    if not sentence:
        return 0.0
    wpms = [wpm_dict[token.lemma+'|'+token.upos] for token in sentence.tokens if token.lemma+'|'+token.upos in wpm_dict]
    if raw:
        return wpms
    return mean([math.log(wpm) for wpm in wpms])

#########################################################################
############lexical feature computation##################################
#sentence_level##############text_level##################################
#########################################################################

def get_lexical(t):
    #L2 features(given Kelly-list based on CEFR vocabulary:
    #https://spraakbanken.gu.se/resource/kelly
    #features are [A1,A2,B1,B2,C1,C2] lemma incsc
    #difficult word incsc
    #difficult noun or verb incsc
    #out of kelly-list incsc
    #missing lemma form incsc
    #avg kelly log-frequency

    '''
    A1 lemma INCSC
    A2 lemma incsc
    B1 lemma incsc
    B2 lemma incsc
    C1 lemma incsc
    C2 lemma incsc
    difficult word incsc
    difficult noun & verb incsc
    oov incsc
    Avg KELLY log freq
    '''

    kelly_dict = read_json('sv_kelly_cefr')
    wpm_dict = read_json('sv_kelly_wpm')

    feature_sentence_level = [[] for _ in range(len(t.sentences))]
    feature_text_count = [[0,0] for _ in range(9)]
    feature_text_count.append([])
    #feature_text_wpms = []
    n_lexical = 10
    feature_text_level = [None for _ in range(n_lexical*3)]

    for index, s in enumerate(t.sentences):

        for feature_n, (p,t) in enumerate([
            lemma_incsc(s, '1', kelly_dict),
            lemma_incsc(s, '2', kelly_dict),
            lemma_incsc(s, '3', kelly_dict),
            lemma_incsc(s, '4', kelly_dict),
            lemma_incsc(s, '5', kelly_dict),
            lemma_incsc(s, '6', kelly_dict),

            difficult_word(s, kelly_dict),
            difficult_word(s, kelly_dict, noun_verb=True),
            out_of_kelly(s, kelly_dict)
        ]):
            feature_sentence_level[index].append(incsc(p,t))
            feature_text_count[feature_n][0] += p
            feature_text_count[feature_n][1] += t

        feature_sentence_level[index].append(kelly_log_frequency(s, wpm_dict,raw=False))
        feature_text_count[-1].extend(kelly_log_frequency(s, wpm_dict,raw=True))

    for feature_n, (p,t) in enumerate(feature_text_count[:-1]):
        feature_list = [feat[feature_n] for feat in feature_sentence_level]
        feature_text_level[feature_n] = incsc(p,t)
        feature_text_level[feature_n + n_lexical] = mean_median(feature_list)
        feature_text_level[feature_n + 2 * n_lexical] = stdev(feature_list)
    #insert wpms
    feature_list = [feat[n_lexical-1] for feat in feature_sentence_level]
    feature_text_level[n_lexical-1] = mean([math.log(wpm) for wpm in feature_text_count[-1]])
    feature_text_level[2*n_lexical-1] = mean_median(feature_list)
    feature_text_level[3*n_lexical-1] = stdev(feature_list)

    return feature_sentence_level, feature_text_level


import input
import statistics as stats

# get the mean
m = stats.mean(input.list)
m = round(m)
print(str(m))

# calculate the total amount of fuel
fuel = 0
for n in input.list:
    steps = abs(n - m)
    i = 1
    cost = 0

    while i <= steps:
        cost += i
        i += 1

    fuel += cost

# print the amount of fuel
print(str(fuel))


# This is if you wanted both the ticker and the sector.
# The sector could be helpful for analysis between sector related stocks.
# These help get list from wiki.
import bs4 as bs        # Beautiful soup for web scraping.
import pickle           # Searilizes any python object. Aka pickling/saves data in an efficient manner.
import requests
# These help with getting data from yahoo.
import datetime as dt
import os               # Create new directories.
import pandas as pd
import pandas_datareader.data as web

# Getting all the ticker symbols for S&P 500 companies from Wikipedia.
# This will save the S&P 500 list so we dont have to go to Wikipedia everytime we run this program.
# It will create a pickle file called sp500tickers.pickle which has all of the
# S&P 500 companies' ticker symbols.
# I would probably try and run this once every year as the company line up
# changes from year to year.
def save_sp500_tickers_sectors():
    # Get S&P 500 list source code from Wikipedia.
    response = requests.get('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies')
    # Beautiful soup object. response.text = text of source code.
    soup = bs.BeautifulSoup(response.text, "lxml")
    # Table data or find a specific table we need by class because there are other tables on the page.
    table = soup.find('table', {'class':'wikitable sortable'})
    # **************************************************************************
    # **************************************************************************
    # **************************************************************************
    # Difference between sp500_datacollection_2.py and sp500_datacollection.py
    # Empty ticker and sector dictionary.
    tickers_sector = {}
    for row in table.findAll('tr')[1:]:     # We dont need the first row because it is column titles.
        key = row.findAll('td')[1].text     # The symbols are in the 2nd row. (first_row = 0, second_row = 1, ..., etc.)
        value = row.findAll('td')[3].text   # Sector as value.
        tickers_sector[key] = value         # Adding the key and value to dictionary.
    # **************************************************************************
    # **************************************************************************
    # **************************************************************************

    # Saving the data gathered for future use as sp500tickers.pickle.
    with open("sp500tickers_sectors.pickle", "wb") as f:    # Opening pickle so we can write in it.
        pickle.dump(tickers_sector, f)                     # Adding the tickers list to f aka pickle file.

    return tickers_sector

# save_sp500_tickers_sectors()                  # This will create the pickle file.

#Check to see if it created.
# pickle_in = open("sp500tickers_sectors.pickle", "rb")
# example_dct = pickle.load(pickle_in)
# print(example_dct['AAPL'])

# Now that we have all the companies we need to find data of we can collect the data we need.
def get_data_from_yahoo(reload_sp500=False):    # Since we are not calling previous function.
    if not reload_sp500:
        tickers_sectors = save_sp500_tickers_sectors()          # We will call it here if we need to.
    else:
        with open("sp500tickers_sectors.pickle", "rb") as f:    # We are reading the file since it already has symbols in it.
            tickers_sectors = pickle.load(f)

    # Take all the stock data and store them into their own directories in a csv file.
    # We want to do this because it takes way too long to do it everytime because of the size of the data.
    if not os.path.exists('stock_dfs'):  # Checking to see if stock_dfs directory exists.
        os.makedirs('stock_dfs')        # If it doesnt exist, then make it.

    # We are setting the data length.
    start = dt.datetime(2009, 1, 1)
    end = dt.datetime.today()

    for ticker in tickers_sectors:  # Traversing all the keys which are the tickers.
        print(ticker)           # This is just to make sure it is working. You can comment this out.
        if not os.path.exists('stock_dfs/{}.csv'.format(ticker)):
            # Had to replace just ticker with ticker.replace('.','-') because of tickers with '.' in them.
            df = web.DataReader(ticker.replace('.','-'), 'yahoo', start, end)
            df.reset_index(inplace=True)
            df.set_index("Date", inplace=True)
            df = df.drop("Symbol", axis=1)
            df.to_csv('stock_dfs/{}.csv'.format(ticker))
        else:
            print('Already have {}!'.format(ticker))

get_data_from_yahoo()