Skip to content

Commit e8057ec

Browse files
author
iainrb
committed
Fixed numerical discrepancies for consistency with versions <= 1.8; added normalization test
1 parent 37786e6 commit e8057ec

File tree

5 files changed

+159
-52
lines changed

5 files changed

+159
-52
lines changed

Fcr.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,14 @@ void FcrWriter::write(Egt *egt, Manifest *manifest, ostream *outStream,
169169
else sampleName = gtc->sampleName;
170170
for (unsigned int j = 0; j < manifest->snps.size(); j++) {
171171
string snpName = manifest->snps[j].name;
172-
double x_raw = gtc->xRawIntensity[j];
173-
double y_raw = gtc->yRawIntensity[j];
172+
unsigned short x_raw = gtc->xRawIntensity[j];
173+
unsigned short y_raw = gtc->yRawIntensity[j];
174174
float score = gtc->scores[j];
175175
double x_norm;
176176
double y_norm;
177177
unsigned int norm_id = manifest->normIdMap[manifest->snps[j].normId];
178-
gtc->normalizeIntensity(x_raw, y_raw, x_norm, y_norm, norm_id);
178+
XFormClass xf = gtc->XForm[norm_id];
179+
xf.normalize(x_raw, y_raw, x_norm, y_norm);
179180
// correction of negative intensities, for consistency with GenomeStudio
180181
if (x_norm < epsilon) { x_norm = 0.0; }
181182
if (y_norm < epsilon) { y_norm = 0.0; }

Gtc.cpp

Lines changed: 95 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,86 @@
3434
//
3535
#include "Gtc.h"
3636
#include <cstring>
37+
#include <cstdio>
3738
#include <iostream>
3839
#include <fstream>
3940
#include <sstream>
4041
#include <vector>
4142

4243
using namespace std;
4344

44-
XFormClass::XFormClass(void)
45+
XFormClass::XFormClass(int version, float xOffset, float yOffset,
46+
float xScale, float yScale, float shear, float theta)
4547
{
48+
this->version = version;
49+
this->xOffset = xOffset;
50+
this->yOffset = yOffset;
51+
this->xScale = xScale;
52+
this->yScale = yScale;
53+
this->shear = shear;
54+
this->theta = theta;
55+
}
56+
57+
void XFormClass::normalize(unsigned short x_raw, unsigned short y_raw,
58+
double &x_norm, double &y_norm)
59+
{
60+
// This is the intensity normalization calculation, according to Illumina
61+
double tempx = x_raw - xOffset;
62+
double tempy = y_raw - yOffset;
63+
double cos_theta = cos(theta);
64+
double sin_theta = sin(theta);
65+
double tempx2 = cos_theta * tempx + sin_theta * tempy;
66+
double tempy2 = -sin_theta * tempx + cos_theta * tempy;
67+
double tempx3 = tempx2 - shear * tempy2;
68+
double tempy3 = tempy2;
69+
x_norm = tempx3 / xScale;
70+
y_norm = tempy3 / yScale;
71+
}
72+
73+
string XFormClass::toString(void)
74+
{
75+
int bufSize = 1000;
76+
char buffer[bufSize];
77+
string v, xoff, yoff, xsca, ysca, shr, th;
78+
int n;
79+
const char *float_format = "%.6f";
80+
try { // attempt to convert other data types to strings
81+
n = snprintf(buffer, bufSize, "%d", version);
82+
if (n >= bufSize) { throw 1; }
83+
v = string(buffer, n);
84+
85+
n = snprintf(buffer, bufSize, float_format, xOffset);
86+
if (n >= bufSize) { throw 1; }
87+
xoff = string(buffer, n);
88+
89+
n = snprintf(buffer, bufSize, float_format, yOffset);
90+
if (n >= bufSize) { throw 1; }
91+
yoff = string(buffer, n);
92+
93+
n = snprintf(buffer, bufSize, float_format, xScale);
94+
if (n >= bufSize) { throw 1; }
95+
xsca = string(buffer, n);
96+
97+
n = snprintf(buffer, bufSize, float_format, yScale);
98+
if (n >= bufSize) { throw 1; }
99+
ysca = string(buffer, n);
100+
101+
n = snprintf(buffer, bufSize, float_format, shear);
102+
if (n >= bufSize) { throw 1; }
103+
shr = string(buffer, n);
104+
105+
n = snprintf(buffer, bufSize, float_format, theta);
106+
if (n >= bufSize) { throw 1; }
107+
th = string(buffer, n);
108+
} catch (int param) {
109+
cerr << "Error: Unable to convert variable from GTC XForm to "
110+
<< "string format. Bad input or corrupt GTC file?" << endl;
111+
throw;
112+
}
113+
string xf = "Version: "+v+"\nXOffset: "+xoff+"\nYOffset: "+yoff\
114+
+"\nXScale: "+xsca+"\nYScale: "+ysca+"\nShear: "+shr+"\nTheta: "+th;
115+
return xf;
116+
46117
}
47118

48119
Gtc::Gtc(void)
@@ -219,48 +290,38 @@ string Gtc::json_dump(void)
219290
return s.str();
220291
}
221292

222-
void Gtc::normalizeIntensity(double x_raw, double y_raw,
223-
double &x_norm, double &y_norm,
224-
unsigned int norm_id) {
225-
// This is the normalization calculation, according to Illumina
226-
XFormClass *XF = &(this->XForm[norm_id]);
227-
double tempx = x_raw - XF->xOffset;
228-
double tempy = y_raw - XF->yOffset;
229-
double cos_theta = cos(XF->theta);
230-
double sin_theta = sin(XF->theta);
231-
double tempx2 = cos_theta * tempx + sin_theta * tempy;
232-
double tempy2 = -sin_theta * tempx + cos_theta * tempy;
233-
double tempx3 = tempx2 - XF->shear * tempy2;
234-
double tempy3 = tempy2;
235-
x_norm = tempx3 / XF->xScale;
236-
y_norm = tempy3 / XF->yScale;
237-
}
238-
239293
void Gtc::readXForm(ifstream &file, int offset)
240294
{
241295
int arrayLen;
296+
int total_reserved = 6; // 'reserved' floats after the xform fields
242297
float reserved;
243298

299+
int version;
300+
float xOffset;
301+
float yOffset;
302+
float xScale;
303+
float yScale;
304+
float shear;
305+
float theta;
306+
244307
ios::pos_type pos = file.tellg();
245308
file.seekg(offset);
246309
file.read((char*)&arrayLen,4);
247310

248-
for (int n=0; n<arrayLen; n++) {
249-
XFormClass X;
250-
file.read((char*)&X.version, 4);
251-
file.read((char*)&X.xOffset, 4);
252-
file.read((char*)&X.yOffset, 4);
253-
file.read((char*)&X.xScale, 4);
254-
file.read((char*)&X.yScale, 4);
255-
file.read((char*)&X.shear, 4);
256-
file.read((char*)&X.theta, 4);
257-
file.read((char*)&reserved, 4);
258-
file.read((char*)&reserved, 4);
259-
file.read((char*)&reserved, 4);
260-
file.read((char*)&reserved, 4);
261-
file.read((char*)&reserved, 4);
262-
file.read((char*)&reserved, 4);
263-
this->XForm.push_back(X);
311+
for (int i=0; i<arrayLen; i++) {
312+
file.read((char*)&version, 4);
313+
file.read((char*)&xOffset, 4);
314+
file.read((char*)&yOffset, 4);
315+
file.read((char*)&xScale, 4);
316+
file.read((char*)&yScale, 4);
317+
file.read((char*)&shear, 4);
318+
file.read((char*)&theta, 4);
319+
XFormClass X = XFormClass(version, xOffset, yOffset, xScale,
320+
yScale, shear, theta);
321+
this->XForm.push_back(X);
322+
for (int j=0; j<total_reserved; j++) {
323+
file.read((char*)&reserved, 4);
324+
}
264325
}
265326
file.seekg(pos);
266327
}

Gtc.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,21 @@ using namespace std;
4545

4646
class XFormClass {
4747
public:
48-
XFormClass();
49-
int version;
50-
float xOffset;
51-
float yOffset;
52-
float xScale;
53-
float yScale;
54-
float shear;
55-
float theta;
48+
XFormClass(int version, float xOffset, float yOffset, float xScale,
49+
float yScale, float shear, float theta);
50+
int version;
51+
float xOffset;
52+
float yOffset;
53+
float xScale;
54+
float yScale;
55+
float shear;
56+
float theta;
57+
58+
void normalize(unsigned short x_raw, unsigned short y_raw,
59+
double &x_norm, double &y_norm);
60+
61+
string toString();
62+
5663
};
5764

5865
class BaseCallClass {
@@ -81,8 +88,6 @@ class Gtc {
8188
double passRate(double cutoff);
8289
double correctedPassRate(double cutoff);
8390

84-
void normalizeIntensity(double x_raw, double y_raw, double &x_norm, double &y_norm, unsigned int norm_id);
85-
8691
string errorMsg;
8792
string filename;
8893
int version; // file version (expected to be 3

commands.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,12 @@ void Commander::commandCreate(string infile, string outfile, bool normalize, str
218218
double xn;
219219
double yn;
220220
int idx = snp->index - 1; // index is zero based in arrays, but starts from 1 in the map file
221-
double x_raw = gtc->xRawIntensity[idx];
222-
double y_raw = gtc->yRawIntensity[idx];
221+
unsigned short x_raw = gtc->xRawIntensity[idx];
222+
unsigned short y_raw = gtc->yRawIntensity[idx];
223223
unsigned int norm_id = manifest->normIdMap[snp->normId];
224224
if (normalize) {
225-
gtc->normalizeIntensity(x_raw, y_raw, xn, yn, norm_id);
225+
XFormClass xf = gtc->XForm[norm_id];
226+
xf.normalize(x_raw, y_raw, xn, yn);
226227
} else {
227228
xn = gtc->xRawIntensity[idx];
228229
yn = gtc->yRawIntensity[idx];

test_simtools.h

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ class FcrTest : public TestBase
232232
}
233233
};
234234

235-
class NormalizeTest : public TestBase
235+
class ManifestTest : public TestBase
236236
{
237237
public:
238238

@@ -257,7 +257,7 @@ class NormalizeTest : public TestBase
257257
TS_TRACE("Finished manifest test");
258258
}
259259

260-
void testNormalize(void)
260+
void testManifestNormalize(void)
261261
{
262262
// compare normalized output with reference file
263263
string infile = "data/mock.bpm.csv";
@@ -489,5 +489,44 @@ class Win2UnixTest : public TestBase
489489

490490
};
491491

492+
class XFormTest : public TestBase
493+
{
494+
// tests the intensity normalization for writing .sim files
495+
496+
public:
497+
498+
void testXForm(void) {
499+
500+
int version= 1;
501+
float xOffset = 150.0;
502+
float yOffset = 90.0;
503+
float xScale = 12000.0;
504+
float yScale = 8000.0;
505+
float shear = 0.02;
506+
float theta = 0.01;
507+
508+
XFormClass *X;
509+
TS_ASSERT_THROWS_NOTHING(X = new XFormClass(version, xOffset, yOffset,
510+
xScale, yScale, shear, theta)
511+
);
512+
TS_TRACE("Created XFormClass object");
513+
514+
unsigned short x_raw = 400;
515+
unsigned short y_raw = 200;
516+
double x_norm;
517+
double y_norm;
518+
double x_norm_expected = 0.020744799066257; // 14 significant digits
519+
double y_norm_expected = 0.013436817602487;
520+
TS_ASSERT_THROWS_NOTHING(X->normalize(x_raw, y_raw, x_norm, y_norm));
521+
TS_TRACE("Ran intensity normalization");
522+
523+
double epsilon = 1e-14;
524+
TS_ASSERT(abs(x_norm - x_norm_expected) < epsilon);
525+
TS_ASSERT(abs(y_norm - y_norm_expected) < epsilon);
526+
TS_TRACE("Normalized intensities checked against expected values");
527+
}
528+
529+
};
530+
492531
// Putting TestSuite classes in separate files appears not to work
493532
// See Cxx manual section 4.4; possible issue with compiler options

0 commit comments

Comments
 (0)