最后一次更新(我保证)
问题的核心是遍历数据,就像Jonathan暗示的那样。二进制数据被“排列”在一个矩阵中。例如,如果我有3个事件和4个位宽8的参数,则二进制数据
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00看起来就像
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00我有两个循环I& j,我需要用它来计算偏移量。
我一开始
(i * PAR * 2) + (j * PnB/8)其中PAR是参数的数量,PnB是位宽度,i从0到总事件,j是从0到PAR。这是不正确的,也不知道我是怎么得到这个公式的。
==
我正在开发一个内部流程分析软件,并且遇到了一些问题。我用来测试软件的FCS示例数据文件是用FACSCaliber在MacOS 9 CellQuest上生成的。当我提取FSC和SSC的数据点时,我不会得到与其他流软件(即FlowJo)相同的结果。我理解在MacOS 9 CellQuest上生成的数据是按大端顺序存储的,并且相信我正在正确地转换数据:
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)。只允许两个不同的值:
如果我不能很好地解释问题,并愿意在必要时进一步澄清任何问题,我将事先表示歉意。任何帮助都将不胜感激。
更新附加图像来说明这一点。图1

更新2
我做了一个简化版本的endian转换器并对其进行了测试。
#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来从缓冲区复制数据。
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
很抱歉让它变得更长,但是更多的信息:
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;发布于 2014-02-07 18:23:32
问题是我用来计算偏移量的公式。
我应该使用以下方法:
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问题,我不会意识到问题在于我计算偏移量的方式。
发布于 2014-02-07 01:06:48
仔细看看您显示的memset()和memcpy()行。由于您还没有展示i是如何设置的,也没有展示params结构数组中的内容,所以很难解释。但是,如果PnB成员中有任何不同的大小,那么我认为您的memcpy()偏移量计算是假的。
下面是一些代码和它的输出;您必须将其稍微修改一下以适应您的场景。最后一节试图模拟您的memset/memcpy代码,因为没有对您显示的许多变量进行解释。它包括一种似乎更有意义的替代解释。
假设您有static inline,您可以将其中一些函数转换为C99。还有其他一些代码也假设为C99。将其修复到C89并不难,但我不会为您这样做。
#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;
}样本输出:
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 = -64513https://stackoverflow.com/questions/21613501
复制相似问题