Python发射窗口长度分析器 背景:

Python发射窗口长度分析器 背景:,python,parsing,Python,Parsing,我正在写论文“覆盖网络中萤火虫激发的心跳同步”。正如其标题所示,本文打算同步萤火虫等设备,使它们在发光时同步 为此,我实现了本文中介绍的自适应Ermentrout模型,并进行了一些测试,以分析模型的行为。我现在有这样的情节 ,显示节点的同步 我现在想做的是计算发射窗口长度作为时间的函数。发射被定义为可能发生在不同节点上的闪光事件的集合(了解图中的列)。换句话说,我想得到发射的第一次闪光的时间,以及发射的最后一次闪光的时间。 这就是我遇到麻烦的地方,我没有设法解决它 有一个参数$\Delta$,它

我正在写论文“覆盖网络中萤火虫激发的心跳同步”。正如其标题所示,本文打算同步萤火虫等设备,使它们在发光时同步

为此,我实现了本文中介绍的自适应Ermentrout模型,并进行了一些测试,以分析模型的行为。我现在有这样的情节 ,显示节点的同步

我现在想做的是计算发射窗口长度作为时间的函数。发射被定义为可能发生在不同节点上的闪光事件的集合(了解图中的列)。换句话说,我想得到发射的第一次闪光的时间,以及发射的最后一次闪光的时间。 这就是我遇到麻烦的地方,我没有设法解决它

有一个参数$\Delta$,它是周期长度,该参数随时间而变化

我开始用Python编写解析器,这就是我现在所拥有的:

import getopt
import sys
import re


def get_time(line):
    time = re.match('(\d+):(\d+):(\d+)\.(\d+) \(\d+\)  \w+', line)
    return int(time.group(1)) * 3600 + int(time.group(2)) * 60 + int(time.group(3)) + int(time.group(4)) / 10 ** (len(time.group(4)))


def init_parser():
    input_file = ''
    output_file = ''

    try:
        opts, args = getopt.getopt(sys.argv[1:], 'hi:o:', ['ifile=', 'ofile='])
    except getopt.GetoptError:
        print('python3 Parser-emission-window.py -i <input file> -o <output file>')
        sys.exit(2)

    for opt, arg in opts:
        if opt == '-h':
            print('python3 Parser-emission-window.py -i <input file> -o <output file>')
            sys.exit()
        elif opt in ('-i', '--ifile'):
            input_file = arg
        elif opt in ('-o', '--ofile'):
            output_file = arg

    return input_file, output_file


def parser():
    input_file, output_file = init_parser()
    reference_time, initial_time, current_time, delta = 0, 0, 0, 2
    is_reference_time, is_initial_time = False, False
    input_file = open(input_file, 'r')
    output_file = open(output_file, 'w')

    for line in input_file:
        current_line = re.match('(\d+):(\d+):(\d+)\.(\d)\d* \(\d+\)  Node (\d+) emitted a flash.', line)

        if current_line and not is_initial_time:
            initial_time = get_time(line)
            is_initial_time = True

        if current_line and not is_reference_time:
            reference_time = get_time(line)
            is_reference_time = True

        if current_line and get_time(line) - reference_time < delta:
            current_time = get_time(line)
        elif current_line and get_time(line) - reference_time >= delta:
            output_file.write(str(current_time - initial_time) + "\t" + str(current_time - reference_time) + "\n")
            reference_time = get_time(line)

    input_file.close()
    output_file.close()


def main():
    parser()


if __name__ == '__main__':
    main()
导入getopt
导入系统
进口稀土
def get_时间(行):
时间=重新匹配(“(\d+):(\d+):(\d+)\(\d+)\(\d+)\w+”,行)
return int(time.group(1))*3600+int(time.group(2))*60+int(time.group(3))+int(time.group(4))/10**(len(time.group(4)))
def init_解析器():
输入文件=“”
输出文件=“”
尝试:
opts,args=getopt.getopt(sys.argv[1:],'hi:o:',['ifile=','ofile=')
除getopt.GetoptError外:
打印('python3 Parser-emission-window.py-i-o')
系统出口(2)
对于opt,opt中的参数:
如果opt='-h':
打印('python3 Parser-emission-window.py-i-o')
sys.exit()
elif选择加入('-i','-ifile'):
输入文件=arg
elif选择加入('-o','-ofile'):
输出文件=arg
返回输入文件、输出文件
def解析器():
输入文件,输出文件=init\u解析器()
参考时间,初始时间,当前时间,增量=0,0,0,2
is_reference_time,is_initial_time=False,False
输入文件=打开(输入文件'r')
输出文件=打开(输出文件“w”)
对于输入_文件中的行:
当前\u line=re.match(“(\d+):(\d+):(\d+)\(\d)\d*\(\d+\)节点(\d+)发出闪光。”,第行)
如果“当前”和“非”为“初始”时间:
初始时间=获取时间(行)
_initial_time=真吗
如果当前_线和非_参考_时间:
参考时间=获取时间(行)
_reference_time=真吗
如果当前_行和获取_时间(行)-参考_时间<增量:
当前时间=获取时间(行)
elif当前行和获取时间(行)-参考时间>=增量:
输出文件.write(str(当前时间-初始时间)+“\t”+str(当前时间-参考时间)+“\n”)
参考时间=获取时间(行)
输入_文件。关闭()
输出_文件。关闭()
def main():
解析器()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()
但正如你所看到的 ,这与另一个图并不完全对应

如果这有什么帮助的话,我在MacOSX10.10.5上工作

另外,如果你需要相应的日志,我会将其发布在通讯中(不能放置超过2个链接)


欢迎任何帮助/提示

好的,所以我想出了办法。 我将在下面发布代码,如果有人需要它,它(我希望)已经有足够的注释了。(请注意,我没有花时间对其进行优化,而且我不是Python专家,所以我所做的一些事情可能不正确/实现得不好)

导入getopt
进口稀土
导入系统
类分析器(对象):
def_uuuinit_uuu(自,输入文件):
self.input\u file=输入文件
def get_节点数(自身):
"""
:return:根据文件名的节点数
"""
返回int(re.match('Logs/Firefly-\w\w-(\d+).+',self.input\u file.group(1))
@静力学方法
def get_时间(行):
"""
函数获取时间
:param line:包含格式为HH:MM:SS.NNNN的时间戳的日志行
:return:以秒为单位的时间
"""
时间=重新匹配(“(\d+):(\d+):(\d+)\(\d+)\(\d+)\w+”,行)
return int(time.group(1))*3600+int(time.group(2))*60+int(time.group(3))+int(time.group(4))/10**(
len(时间组(4)))
def get_初始_时间_和_id(自身):
"""
函数get_initial_time:读取输入_文件,直到找到第一个闪存
:rtype:object
:return:第一次闪烁的时间(秒)
"""
打开(self.input_文件,'r')作为f:
对于f中的行:
当前\u line=re.match(“(\d+):(\d+):(\d+)\。\d+\(\d+\)节点(\d+)发出闪光。”,第行)
如果当前_行:
返回self.get_time(line),int(当前_line.group(4))
#需要定义东西来创建所有的表和东西
def get_时间戳(自身):
"""
get_timestamps:读取输入_文件(日志),每次节点发出闪存时,读取闪存的时间
发出的数据存储在列表的第i个数组中(其中i是节点的id)。
:return:包含节点发光时间的列表。
"""
init_time,u=self.get_initial_time_和_id()
列出范围内i的_时间=[[](self.get_节点数())]
打开(self.input_文件,'r')作为ifile:
对于ifile中的行:
当前\u line=re.match(“(\d+):(\d+):(\d+)\(\d)\d*\(\d+\)节点(\d+)发出闪光。”,第行)
如果当前_行:
列出\u时间[int(当前\u行.group(5))-1]。追加(self.get\u时间(行)-init\u时间)
返回时间
def get_路径():
"""
通过获取输入文件(作为参数传递)生成输出文件
:return:周期长度的输入文件、输出文件
import getopt
import re
import sys


class Parser(object):
    def __init__(self, input_file):
        self.input_file = input_file

    def get_number_of_nodes(self):
        """
        :return: the number of nodes according to the name of the file
        """
        return int(re.match('Logs/Firefly-\w\w-(\d+).+', self.input_file).group(1))

    @staticmethod
    def get_time(line):
        """
        Function get_time
        :param line: line of the log containing a timestamp of the form HH:MM:SS.NNNN
        :return: Time in seconds
        """
        time = re.match('(\d+):(\d+):(\d+)\.(\d+) \(\d+\)  \w+', line)
        return int(time.group(1)) * 3600 + int(time.group(2)) * 60 + int(time.group(3)) + int(time.group(4)) / 10 ** (
            len(time.group(4)))

    def get_initial_time_and_id(self):
        """
        Function get_initial_time: reads input_file until it finds the first flash
        :rtype: object
        :return: time (in seconds) of the first flash
        """
        with open(self.input_file, 'r') as f:
            for line in f:
                current_line = re.match('(\d+):(\d+):(\d+)\.\d+ \(\d+\)  Node (\d+) emitted a flash.', line)
                if current_line:
                    return self.get_time(line), int(current_line.group(4))

    # Need to define the thing to create all the tables and stuff
    def get_timestamps(self):
        """
        get_timestamps: reads the input_file (log) and every time a node emits a flash, the time at which the flash was
                        emitted is stored in the i-th array of lists_time (where i is the id of the node).
        :return: the lists containing the time at which nodes emitted light.
        """
        init_time, _ = self.get_initial_time_and_id()
        lists_time = [[] for i in range(self.get_number_of_nodes())]
        with open(self.input_file, 'r') as ifile:
            for line in ifile:
                current_line = re.match('(\d+):(\d+):(\d+)\.(\d)\d* \(\d+\)  Node (\d+) emitted a flash.', line)
                if current_line:
                    lists_time[int(current_line.group(5)) - 1].append(self.get_time(line) - init_time)
        return lists_time


def get_paths():
    """
    Generate the output files by getting the input file (passed as an argument)
    :return: input file, output file for cycle lengths, output file for emission window length
    """
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'hi:', ['ifile='])
    except getopt.GetoptError:
        print('python3 Parser-synchronization.py -i <input file>')
        sys.exit(2)

    for opt, arg in opts:
        if opt == '-h':
            print('python3 Parser-synchronization.py -i <input file>')
            print('Ex: \"python3 Parser-synchronization.py -i foo\" will get the file Logs/foo.txt')
            sys.exit()
        elif opt in ('-i', '--ifile'):
            input_file = 'Logs/' + str(arg) + '.txt'
            output_file_cl = 'Parsed-logs/' + str(arg) + '-cl-parsed.txt'
            output_file_ewl = 'Parsed-logs/' + str(arg) + '-ewl-parsed.txt'

    return input_file, output_file_cl, output_file_ewl


def cycle_lengths(lists, ofile):
    """
    This function calculates the cycle lengths for each nodes.
    :param lists: list containing the times at which every node flashed
    :param ofile: output file to write the cycle lengths to.
    """
    with open(ofile, 'w') as output_file:
        for elem in lists:
            for i in range(1, len(elem)):
                output_file.write(str(elem[i]) + '\t' + str(elem[i] - elem[i - 1]) + '\n')


def get_closests(lists, time):
    # This is not the best thing to do, but radius = Delta/2
    # I did not want to create another parameter, especially that I only used Delta = 5 in my test.
    """
    This is the second step of the algorithm described in emission_window_length.
    It reads every time list (for each node) until it finds a timestamp within 2.5sec
    :param lists: list containing the times at which every node flashed
    :param time: time of the reference node to look for
    :return: list of all the time within 2.5 sec of the ref time (at most one per node)
    """
    radius = 2.5
    closests = []
    for l in lists:
        i = 0
        while i < len(l)-1 and abs(l[i] - time) > radius:
            i += 1
        # Now we found an element in the ball of center time and radius 2.5.
        # We need to check which of this element or the successor is closest to time.
        if abs(l[i] - time) <= radius:
            if i < len(l) - 2 and abs(l[i] - time) > abs(l[i + 1] - time):
                closests.append(l[i + 1])
            else:
                closests.append(l[i])
    return closests


def emission_window_length(lists, ofile, ref_id):
    """
    Explanation of how the function works:
      1. We get the id of the node that emitted the first flash. This will be our ref_id (passed in parameter)
      2. Every time this node emit a flash, we look for all the nodes that emitted a flash less than 2.5 seconds
         before or after the node. We consider that it is in the same emission.

      node id      node 3 = ref node, At first node 2 is not in the emission window.
         ^      -----------
         |   3  |    o     |        o              o
         |      |<-- 5 --->|
         |   2  |          |       o               o
         |      |<2.5>     |
         |   1  |     o    |         o             o
         |      -----------
         --------------------------------------------------------> time

      3. Once we have this list, we look for the min and max, and max-min is our emission window length for the
         current emission.
      4. Do this for every time ref_id flashed.
    WARNING: As the nodes do not start at the same time, we do NOT consider the flashes after ref_id node stops.
    :param lists: list containing the times at which every node flashed
    :param ofile: output file
    :param ref_id: reference id of the node that first flashed
    """
    with open(ofile, 'w') as output_file:
        for time in lists[ref_id]:
            lists_closests = get_closests(lists, time)
            # to get min and max of list, we use the built in functions in python
            min_time = min(lists_closests)
            max_time = max(lists_closests)
            length = max_time - min_time
            output_file.write('{0}\t{1}\n'.format(str(time), str(length)))


def main():
    ifile, ofile_cl, ofile_ewl = get_paths()

    parser = Parser(ifile)

    _, init_id = parser.get_initial_time_and_id()

    lists_time = parser.get_timestamps()

    cycle_lengths(lists_time, ofile_cl)

    emission_window_length(lists_time, ofile_ewl, init_id)


if __name__ == '__main__':
    main()