C:在二进制数据流中查找和分析集群

时间:2016-03-16 14:27:28

标签: c cluster-analysis binaryfiles multiplexing

文件结构和系统描述

我想要分析的流(一个大的二进制文件)组成如下:

  • 40字节标题
  • 10字节信号流:

    • 前8个字节表示信号注册的时间
    • 最后2个字节描述信号注册的通道

信号由每隔SIGNAL_INTERVAL发送一次脉冲的信号源发出,探测器可能检测到也可能没有检测到信号。如果检测器计数,它会将结果发送到计数器的通道,该通道打印如上所示的计数。该计数器共有8个通道。

复用

为了增加检测器的数量,使用多路复用方法。两个检测器将它们的计数发送到相同的通道(例如,检测器1和9耦合在计数器的通道1上)。其中一个信号(例如9)延迟DELAY,因此延迟计数相对于非延迟计数发生偏移。

解复用

想法是将延迟数据与非延迟数据相除,然后减去延迟(将通道值加8,使通道1上的延迟计数显示为通道9上的计数),然后重新加入这两个阵列。

如果SIGNAL_INTERVAL是常数,这相对容易:我定义了一个“掩码”[0, DELAY, SIGNAL_INTERVAL],并且在获取参考时间戳值时,查看掩码中每个计数的位置。

尝试不同的面具并计算哪一个计数最多,可以识别非延迟计数的延迟计数。完成最后一部分是因为我们允许时间计数出错,因此流不会完美地聚集。此外,如果第一个计数是延迟计数,非延迟计数或偶数计数,则无法知道先验。

这是逐个通道完成的,因为通道可能具有彼此不同的响应时间。

使用这种方法,代码非常简单:

uint64_t maskCheck(struct count *data, int ch_num, int elements){

    const int MAX_NUM = 27; // Maximum number of masks checked

    int ref = 0; // The reference variable used as starting point at every cycle
    uint64_t sing_count[2][MAX_NUM]; // The array containing the singles counts
    uint64_t max_count; // Variable used to find the maximum in the array
    int t = 0; // Time index for the following loop
    uint64_t result = 0; // The final result, i.e. the index with the most singles counts

// Initializing max_count (it has MAX_NUM as length, so it must be initialized after being declared)
    for(int i = 0; i < MAX_NUM; i++)sing_count[0][i] = 0;
    for(int i = 0; i < MAX_NUM; i++)sing_count[1][i] = 0;

    while(getChannel(data[t])!=ch_num){
        t++;
        if(t == elements - 1){
            printf("%s\n", "Nothing found");
            return 0;
        }
    }
    if(getChannel(data[t]) == ch_num) ref = getTimestamp(data[t]);
    uint64_t ref_indexed = ref;

    for(int index = 0; index < MAX_NUM; index++){


        sing_count[1][index] = ref + nsToBins(index) - nsToBins(MAX_NUM/2);
        ref_indexed = sing_count[1][index];

        for(t = 0; t < elements; t++){
        // Skips the counts not occurring at ch_num
            if(getChannel(data[t]) != ch_num) {
                continue;
            }


        if(longAbs(getTimestamp(data[t]), ref_indexed) % nsToBins(SIGNAL_INTERVAL) <= nsToBins(MASK) + nsToBins(COUNT_ERROR) &&
           longAbs(getTimestamp(data[t]), ref_indexed) % nsToBins(SIGNAL_INTERVAL) >= nsToBins(MASK) - nsToBins(COUNT_ERROR)){
            sing_count[0][index]++;

        }
        else if(longAbs(getTimestamp(data[t]), ref_indexed) % nsToBins(SIGNAL_INTERVAL) <= nsToBins(COUNT_ERROR) ||
            longAbs(getTimestamp(data[t]), ref_indexed) % nsToBins(SIGNAL_INTERVAL) >= nsToBins(SIGNAL_INTERVAL) - nsToBins(COUNT_ERROR)){
            sing_count[0][index]++; 
        }
        }
    }

// This last part maximizes the array.
    max_count = sing_count[0][0];
    result = sing_count[1][0];

    for(int i = 1; i < MAX_NUM; i++){
        if(sing_count[0][i] > max_count)
        {
            max_count = sing_count[0][i];
            result = sing_count[1][i];
        }
    }

其中struct count被定义为函数getTimestamp()getChannel()读取的10字节数组,而nsToBins()只是转换时间单位。

拥有“最佳掩码”,我可以通过它分割数组,然后执行所有其他所需的操作。

问题

现在,问题来了。 SIGNAL_INTERVAL不是常数,并且它甚至没有确定(为了给你一个想法,频率在75.6 Mhz76.3 MHz之间振荡)。 上述方法现在证明是非常不成功的:

  • SIGNAL_INTERVAL的错误大约为0.3 ns
  • 测量超过30秒
  • 请记住,SIGNAL_INTERVAL的数量级为10 ns,仅一秒后误差就会太大
  • 这会导致时间戳错误划分,影响所有后续操作。

我想到的是分析数据中的聚类(SIGNAL_INTERVAL不是常数,但振荡远小于DELAY,因此原则上可以观察到一些聚类)并找到另一种划分两个数组的方法。

但到目前为止我一无所有。任何帮助将不胜感激。

0 个答案:

没有答案