首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >流式细胞术FCS文件数据段,线性数据似乎倾斜

流式细胞术FCS文件数据段,线性数据似乎倾斜
EN

Stack Overflow用户
提问于 2014-02-06 20:35:50
回答 2查看 631关注 0票数 3

最后一次更新(我保证)

问题的核心是遍历数据,就像Jonathan暗示的那样。二进制数据被“排列”在一个矩阵中。例如,如果我有3个事件和4个位宽8的参数,则二进制数据

代码语言:javascript
复制
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

看起来就像

代码语言:javascript
复制
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00

我有两个循环I& j,我需要用它来计算偏移量。

我一开始

代码语言:javascript
复制
(i * PAR * 2) + (j * PnB/8)

其中PAR是参数的数量,PnB是位宽度,i从0到总事件,j是从0到PAR。这是不正确的,也不知道我是怎么得到这个公式的。

==

我正在开发一个内部流程分析软件,并且遇到了一些问题。我用来测试软件的FCS示例数据文件是用FACSCaliber在MacOS 9 CellQuest上生成的。当我提取FSC和SSC的数据点时,我不会得到与其他流软件(即FlowJo)相同的结果。我理解在MacOS 9 CellQuest上生成的数据是按大端顺序存储的,并且相信我正在正确地转换数据:

代码语言:javascript
复制
for (int i = 0; i < params[j-1].PnB/8; ++i)
{
    lebyte[i] = (bytes[(params[j-1].PnB/8)-1-i] & 0xff) << i*8u;
    cx |= lebyte[i];
}

代码可能并不优雅,但它似乎是按照我的意愿对已知的数据样本进行处理的。

PnB是位宽PnR是信道值范围。

使用实际流数据时得到的结果看起来是正确的,因为值在PnR指定的范围内,也就是说,如果PnR = 1024,则存储在16位空间中的数据介于0-1023之间。

然而,当我绘制数据时,我得到一个倾斜的点图,其中散射向FSC轴弯曲。

以下是FCS 3.1标准(流式细胞术数据文件标准,国际细胞计量学促进会;第13页)的摘录:

$BYTEORD/n1,n2,n3,n4/ $BYTEORD/4,3,2,1/需要 此关键字指定数据的endianness,即用于在数据集中存储数字数据值的字节顺序。关键字的这个值对应于从数值上最小的{1}到数值上最重要的{4}的顺序,其中四个二进制数据字节被写入数据采集计算机中组成32位字。数字用逗号分隔(ASCII 44)。只允许两个不同的值:

  • $BYTEORD/1,2,3,4/ (小字节,即最不重要的先写字节,例如基于x86的个人计算机)
  • $BYTEORD/4,3,2,1/ (大端字节,即最不重要的字节,例如,在切换到基于英特尔的体系结构之前,PowerPC包括较老的Apple计算机)这些值中的一个值应用于指定即使数据值的大小超过32位($DATATYPE/D/)

如果我不能很好地解释问题,并愿意在必要时进一步澄清任何问题,我将事先表示歉意。任何帮助都将不胜感激。

更新附加图像来说明这一点。图1

更新2

我做了一个简化版本的endian转换器并对其进行了测试。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

int main() {
    int PnB = 16; // bitwidth of data stored for a specific channel value
    // for example the data value for sample A is stored in 16 bits.
    char bytes[PnB/8];
    unsigned int lebyte[PnB/8];
    unsigned int cx = 0;

    unsigned int b0, b1;

    /*  |  [0] |  [1] |
    *  | 0xff | 0x03 |
    */
    bytes[1] = 0x03;
    bytes[0] = 0xff;

    // in big endian print out

    b0 = (bytes[0] & 0xff) << 8u;
    b1 = bytes[1] & 0xff;

    cx = b0 | b1;

    printf("%d\n", cx);

    cx = 0;

    // convert to little endian

    for (int i = 0; i < PnB/8; ++i)
    {
        lebyte[i] = (bytes[i] & 0xff) << i*8u;
        cx |= lebyte[i];
    }

    printf("%d\n", cx);
}

结果是正确的:

65283 一零二三

因此,我对原始源代码进行了更正(为了节省空间,在原始文章中进行了更改)。

另外,我正在做memcpy来从缓冲区复制数据。

代码语言:javascript
复制
memset(bytes, '\0', sizeof(char)*params[j-1].PnB/8);
memcpy(bytes, databuf+((i*data->PAR*2)+(j*params[j-1].PnB/8)), params[j-1].PnB/8);

但我还是得到了不正确的数据。这可能与如何转换数据有关。我只是在网上找不到任何信息,我相信FlowJo的制造者不会愿意分享这个秘密;)我会继续找,看看我找到了什么。

更新3

很抱歉让它变得更长,但是更多的信息:

代码语言:javascript
复制
typedef struct _fcs_parameter {
    double f1;          // logarithmic decade
    double f2;          // minimum value on log scale
    unsigned int PnB;   // bitwidth
    unsigned int PnR;   // range
    fcs_events *events; // event data
    char *sname;        // short name
    char *lname;        // filter name
} fcs_parameter;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-07 18:23:32

问题是我用来计算偏移量的公式。

我应该使用以下方法:

代码语言:javascript
复制
for (int i = 0; i < data->TOT; ++i)
    {
        for (int j = 0; j < data->PAR; ++j)
        {

        // code removed for brevity

        memset(bytes, '\0', sizeof(char)*params[j].PnB/8);
        memcpy(bytes, databuf+((i*data->PAR*params[j].PnB/8)+(j*params[j].PnB/8)), params[j].PnB/8);

        // more code here
        }
}

谢谢你的帮助!如果您没有提到PnB问题,我不会意识到问题在于我计算偏移量的方式。

票数 0
EN

Stack Overflow用户

发布于 2014-02-07 01:06:48

仔细看看您显示的memset()memcpy()行。由于您还没有展示i是如何设置的,也没有展示params结构数组中的内容,所以很难解释。但是,如果PnB成员中有任何不同的大小,那么我认为您的memcpy()偏移量计算是假的。

下面是一些代码和它的输出;您必须将其稍微修改一下以适应您的场景。最后一节试图模拟您的memset/memcpy代码,因为没有对您显示的许多变量进行解释。它包括一种似乎更有意义的替代解释。

假设您有static inline,您可以将其中一些函数转换为C99。还有其他一些代码也假设为C99。将其修复到C89并不难,但我不会为您这样做。

代码语言:javascript
复制
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static uint16_t convert_uint16be(uint8_t const *bytes)
{
    uint16_t r = (bytes[0] << 8) | bytes[1];
    return r;
}

static uint32_t convert_uint32be(uint8_t const *bytes)
{
    uint32_t r = (((((bytes[0] << 8) | bytes[1]) << 8) | bytes[2]) << 8) | bytes[3];
    return r;
}

static void print16(uint8_t const *bytes)
{
  uint16_t r1 = convert_uint16be(bytes);
  int16_t  r2 = convert_uint16be(bytes);
  printf("0x%.2X 0x%.2X = 0x%.4" PRIX16 " = %6" PRId16 "\n", bytes[0], bytes[1], r1, r2);
}

static void print32(uint8_t const *bytes)
{
  uint32_t r1 = convert_uint32be(bytes);
  int32_t  r2 = convert_uint32be(bytes);
  printf("0x%.2X 0x%.2X 0x%.2X 0x%.2X = 0x%.8" PRIX32 " = %11" PRId32 "\n", bytes[0], bytes[1], bytes[2], bytes[3], r1, r2);
}

int main(void)
{
    int PnB = 16; // bitwidth of data stored for a specific channel value
    // for example the data value for sample A is stored in 16 bits.
    char bytes[PnB/8];
    unsigned int lebyte[PnB/8];
    unsigned int cx = 0;
    unsigned int b0, b1;

    /*  |  [0] |  [1] |
     *  | 0xff | 0x03 |
     */
    bytes[0] = 0xff;
    bytes[1] = 0x03;

    // in big endian print out
    b0 = (bytes[0] & 0xff) << 8u;
    b1 = bytes[1] & 0xff;
    cx = b0 | b1;

    printf("%5d = 0x%.4X\n", cx, cx);

    // convert to little endian
    cx = 0;
    for (int i = 0; i < PnB/8; ++i)
    {
        lebyte[i] = (bytes[i] & 0xff) << i*8u;
        cx |= lebyte[i];
    }
    printf("%5d = 0x%.4X\n", cx, cx);

    print16((uint8_t *)bytes);

    uint8_t data[] =
    {
      0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x03, 0xFF,
      0x00, 0x00, 0xFF, 0xFF,
      0x08, 0x08, 0x09, 0xC0,
      0x80, 0x80, 0x90, 0x0C,
      0xFF, 0xFF, 0xED, 0xBC,
    };
    int data_size = sizeof(data) / sizeof(data[0]);

    for (int i = 0; i < data_size; i += 2)
      print16(&data[i]);
    for (int i = 0; i < data_size; i += 4)
      print32(&data[i]);

    {
      struct { int PnB; } params[] = { { 16 }, { 16 }, { 32 }, { 16 }, { 16 }, };
      int num_params = sizeof(params) / sizeof(params[0]);
      uint8_t value[4];
      int i = 0;
      int num = num_params;
      int offset = 0;
      for (int j = 1; j <= num; j++)
      {
        memset(value, '\0', sizeof(char)*params[j-1].PnB/8);
        printf("i = %2d; j = %2d; offset = %2d; calc = %2d; size = %2d\n",
               i, j, offset, ((i*7*2)+(j*params[j-1].PnB/8)), params[j-1].PnB/8);
        /* The calculation works plausibly when all params[n].PnB are the same
         * size, but not otherwise
         */
        memcpy(value, data+((i*7*2)+(j*params[j-1].PnB/8)), params[j-1].PnB/8);
        if (params[j].PnB == 16)
          print16(value);
        else
          print32(value);
        memcpy(value, data+offset, params[j-1].PnB/8);
        if (params[j].PnB == 16)
          print16(value);
        else
          print32(value);
        offset += params[j-1].PnB/8;
      }
    }

    return 0;
}

样本输出:

代码语言:javascript
复制
65283 = 0xFF03
 1023 = 0x03FF
0xFF 0x03 = 0xFF03 =   -253
0x00 0x00 = 0x0000 =      0
0x00 0x00 = 0x0000 =      0
0x00 0x00 = 0x0000 =      0
0x03 0xFF = 0x03FF =   1023
0x00 0x00 = 0x0000 =      0
0xFF 0xFF = 0xFFFF =     -1
0x08 0x08 = 0x0808 =   2056
0x09 0xC0 = 0x09C0 =   2496
0x80 0x80 = 0x8080 = -32640
0x90 0x0C = 0x900C = -28660
0xFF 0xFF = 0xFFFF =     -1
0xED 0xBC = 0xEDBC =  -4676
0x00 0x00 0x00 0x00 = 0x00000000 =           0
0x00 0x00 0x03 0xFF = 0x000003FF =        1023
0x00 0x00 0xFF 0xFF = 0x0000FFFF =       65535
0x08 0x08 0x09 0xC0 = 0x080809C0 =   134744512
0x80 0x80 0x90 0x0C = 0x8080900C = -2139058164
0xFF 0xFF 0xED 0xBC = 0xFFFFEDBC =       -4676
i =  0; j =  1; offset =  0; calc =  2; size =  2
0x00 0x00 = 0x0000 =      0
0x00 0x00 = 0x0000 =      0
i =  0; j =  2; offset =  2; calc =  4; size =  2
0x00 0x00 0x00 0x00 = 0x00000000 =           0
0x00 0x00 0x00 0x00 = 0x00000000 =           0
i =  0; j =  3; offset =  4; calc = 12; size =  4
0x08 0x08 = 0x0808 =   2056
0x00 0x00 = 0x0000 =      0
i =  0; j =  4; offset =  8; calc =  8; size =  2
0x00 0x00 = 0x0000 =      0
0x00 0x00 = 0x0000 =      0
i =  0; j =  5; offset = 10; calc = 10; size =  2
0xFF 0xFF 0x03 0xFF = 0xFFFF03FF =      -64513
0xFF 0xFF 0x03 0xFF = 0xFFFF03FF =      -64513
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21613501

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档