mirror of
https://github.com/biopython/biopython.git
synced 2025-10-20 13:43:47 +08:00
340 lines
13 KiB
Python
340 lines
13 KiB
Python
# This code is part of the Biopython distribution and governed by its
|
|
# license. Please see the LICENSE file that should have been included
|
|
# as part of this package.
|
|
|
|
"""Tests for Affy module."""
|
|
|
|
import unittest
|
|
|
|
import struct
|
|
import os
|
|
import sys
|
|
|
|
try:
|
|
from numpy import array
|
|
import numpy.testing
|
|
except ImportError:
|
|
from Bio import MissingPythonDependencyError
|
|
|
|
raise MissingPythonDependencyError(
|
|
"Install NumPy if you want to use Bio.Affy.CelFile"
|
|
) from None
|
|
|
|
from Bio.Affy import CelFile
|
|
|
|
|
|
class AffyTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.affy3 = "Affy/affy_v3_example.CEL"
|
|
self.affy4 = "Affy/affy_v4_example.CEL"
|
|
self.affy4Bad = "Affy/affy_v4_bad_example.CEL"
|
|
with open(self.affy4Bad, "wb") as f:
|
|
self.writeExampleV4(f, bad=True)
|
|
|
|
def tearDown(self):
|
|
os.remove(self.affy4Bad)
|
|
|
|
# tests the Affymetrix v3 parser
|
|
def testAffy3(self):
|
|
with open(self.affy3) as f:
|
|
record = CelFile.read(f)
|
|
self.assertGreater(len(record.DatHeader), 0)
|
|
self.assertEqual(record.intensities.shape, (5, 5))
|
|
self.assertEqual(record.intensities.shape, record.stdevs.shape)
|
|
self.assertEqual(record.intensities.shape, record.npix.shape)
|
|
self.assertEqual(record.ncols, 5)
|
|
self.assertEqual(record.nrows, 5)
|
|
self.assertEqual(record.version, 3)
|
|
self.assertEqual(record.GridCornerUL, (206, 129))
|
|
self.assertEqual(record.GridCornerUR, (3570, 107))
|
|
self.assertEqual(record.GridCornerLR, (3597, 3470))
|
|
self.assertEqual(record.GridCornerLL, (234, 3492))
|
|
self.assertEqual(record.DatHeader["filename"], "1g_A9AF")
|
|
self.assertEqual(record.DatHeader["CLS"], 3684)
|
|
self.assertEqual(record.DatHeader["RWS"], 3684)
|
|
self.assertEqual(record.DatHeader["XIN"], 1)
|
|
self.assertEqual(record.DatHeader["YIN"], 1)
|
|
self.assertEqual(record.DatHeader["VE"], 30)
|
|
self.assertAlmostEqual(record.DatHeader["laser-power"], 2.0)
|
|
self.assertEqual(record.DatHeader["scan-date"], "08/23/07")
|
|
self.assertEqual(record.DatHeader["scan-time"], "11:23:24")
|
|
self.assertEqual(record.DatHeader["scanner-id"], "50205880")
|
|
self.assertEqual(record.DatHeader["scanner-type"], "M10")
|
|
self.assertEqual(record.DatHeader["array-type"], "Tgondii_SNP1.1sq")
|
|
self.assertEqual(record.DatHeader["image-orientation"], 6)
|
|
self.assertEqual(record.Algorithm, "Percentile")
|
|
self.assertEqual(len(record.AlgorithmParameters), 16)
|
|
self.assertEqual(record.AlgorithmParameters["Percentile"], 75)
|
|
self.assertEqual(record.AlgorithmParameters["CellMargin"], 2)
|
|
self.assertAlmostEqual(record.AlgorithmParameters["OutlierHigh"], 1.500)
|
|
self.assertAlmostEqual(record.AlgorithmParameters["OutlierLow"], 1.004)
|
|
self.assertEqual(record.AlgorithmParameters["AlgVersion"], "6.0")
|
|
self.assertEqual(
|
|
record.AlgorithmParameters["FixedCellSize"], True
|
|
) # noqa: A502
|
|
self.assertEqual(record.AlgorithmParameters["FullFeatureWidth"], 7)
|
|
self.assertEqual(record.AlgorithmParameters["FullFeatureHeight"], 7)
|
|
self.assertEqual(
|
|
record.AlgorithmParameters["IgnoreOutliersInShiftRows"], False
|
|
) # noqa: A502
|
|
self.assertEqual(
|
|
record.AlgorithmParameters["FeatureExtraction"], True
|
|
) # noqa: A502
|
|
self.assertEqual(record.AlgorithmParameters["PoolWidthExtenstion"], 2)
|
|
self.assertEqual(record.AlgorithmParameters["PoolHeightExtension"], 2)
|
|
self.assertEqual(
|
|
record.AlgorithmParameters["UseSubgrids"], False
|
|
) # noqa: A502
|
|
self.assertEqual(
|
|
record.AlgorithmParameters["RandomizePixels"], False
|
|
) # noqa: A502
|
|
self.assertEqual(record.AlgorithmParameters["ErrorBasis"], "StdvMean")
|
|
self.assertAlmostEqual(record.AlgorithmParameters["StdMult"], 1.0)
|
|
self.assertEqual(record.NumberCells, 25)
|
|
|
|
global message
|
|
try:
|
|
numpy.testing.assert_allclose(
|
|
record.intensities,
|
|
[
|
|
[234.0, 170.0, 22177.0, 164.0, 22104.0],
|
|
[188.0, 188.0, 21871.0, 168.0, 21883.0],
|
|
[188.0, 193.0, 21455.0, 198.0, 21300.0],
|
|
[188.0, 182.0, 21438.0, 188.0, 20945.0],
|
|
[193.0, 20370.0, 174.0, 20605.0, 168.0],
|
|
],
|
|
)
|
|
message = None
|
|
except AssertionError as err:
|
|
message = str(err)
|
|
if message is not None:
|
|
self.fail(message)
|
|
try:
|
|
numpy.testing.assert_allclose(
|
|
record.stdevs,
|
|
[
|
|
[24.0, 34.5, 2669.0, 19.7, 3661.2],
|
|
[29.8, 29.8, 2795.9, 67.9, 2792.4],
|
|
[29.8, 88.7, 2976.5, 62.0, 2914.5],
|
|
[29.8, 76.2, 2759.5, 49.2, 2762.0],
|
|
[38.8, 2611.8, 26.6, 2810.7, 24.1],
|
|
],
|
|
)
|
|
message = None
|
|
except AssertionError as err:
|
|
message = str(err)
|
|
if message is not None:
|
|
self.fail(message)
|
|
try:
|
|
numpy.testing.assert_array_equal(
|
|
record.npix,
|
|
[
|
|
[25, 25, 25, 25, 25],
|
|
[25, 25, 25, 25, 25],
|
|
[25, 25, 25, 25, 25],
|
|
[25, 25, 25, 25, 25],
|
|
[25, 25, 25, 25, 25],
|
|
],
|
|
)
|
|
message = None
|
|
except AssertionError as err:
|
|
message = str(err)
|
|
if message is not None:
|
|
self.fail(message)
|
|
self.assertEqual(record.nmask, 3)
|
|
try:
|
|
numpy.testing.assert_array_equal(
|
|
record.mask,
|
|
[
|
|
[False, False, False, False, False],
|
|
[False, False, False, True, True],
|
|
[False, False, False, False, True],
|
|
[False, False, False, False, False],
|
|
[False, False, False, False, False],
|
|
],
|
|
)
|
|
message = None
|
|
except AssertionError as err:
|
|
message = str(err)
|
|
if message is not None:
|
|
self.fail(message)
|
|
self.assertEqual(record.noutliers, 3)
|
|
try:
|
|
numpy.testing.assert_array_equal(
|
|
record.outliers,
|
|
[
|
|
[False, False, False, False, False],
|
|
[False, True, True, False, False],
|
|
[False, False, False, False, False],
|
|
[False, True, False, False, False],
|
|
[False, False, False, False, False],
|
|
],
|
|
)
|
|
message = None
|
|
except AssertionError as err:
|
|
message = str(err)
|
|
if message is not None:
|
|
self.fail(message)
|
|
self.assertEqual(record.nmodified, 3)
|
|
try:
|
|
numpy.testing.assert_allclose(
|
|
record.modified,
|
|
[
|
|
[0.0, 0.0, 0.0, 0.0, 0.0],
|
|
[0.0, 0.0, 0.0, 189.0, 220.0],
|
|
[0.0, 0.0, 0.0, 21775.0, 0.0],
|
|
[0.0, 0.0, 0.0, 0.0, 0.0],
|
|
[0.0, 0.0, 0.0, 0.0, 0.0],
|
|
],
|
|
)
|
|
message = None
|
|
except AssertionError as err:
|
|
message = str(err)
|
|
if message is not None:
|
|
self.fail(message)
|
|
|
|
def testAffy4(self):
|
|
with open(self.affy4, "rb") as f:
|
|
record = CelFile.read(f)
|
|
self.assertEqual(record.intensities.shape, (5, 5))
|
|
self.assertEqual(record.intensities.shape, record.stdevs.shape)
|
|
self.assertEqual(record.intensities.shape, record.npix.shape)
|
|
self.assertEqual(record.ncols, 5)
|
|
self.assertEqual(record.nrows, 5)
|
|
global message
|
|
try:
|
|
numpy.testing.assert_allclose(
|
|
record.intensities,
|
|
[
|
|
[0.0, 1.0, 2.0, 3.0, 4.0],
|
|
[5.0, 6.0, 7.0, 8.0, 9.0],
|
|
[10.0, 11.0, 12.0, 13.0, 14.0],
|
|
[15.0, 16.0, 17.0, 18.0, 19.0],
|
|
[20.0, 21.0, 22.0, 23.0, 24.0],
|
|
],
|
|
)
|
|
message = None
|
|
except AssertionError as err:
|
|
message = str(err)
|
|
if message is not None:
|
|
self.fail(message)
|
|
try:
|
|
numpy.testing.assert_allclose(
|
|
record.stdevs,
|
|
[
|
|
[0.0, -1.0, -2.0, -3.0, -4.0],
|
|
[-5.0, -6.0, -7.0, -8.0, -9.0],
|
|
[-10.0, -11.0, -12.0, -13.0, -14.0],
|
|
[-15.0, -16.0, -17.0, -18.0, -19.0],
|
|
[-20.0, -21.0, -22.0, -23.0, -24.0],
|
|
],
|
|
)
|
|
message = None
|
|
except AssertionError as err:
|
|
message = str(err)
|
|
if message is not None:
|
|
self.fail(message)
|
|
try:
|
|
numpy.testing.assert_allclose(
|
|
record.npix,
|
|
[
|
|
[9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9],
|
|
],
|
|
)
|
|
message = None
|
|
except AssertionError as err:
|
|
message = str(err)
|
|
if message is not None:
|
|
self.fail(message)
|
|
self.assertEqual(len(record.AlgorithmParameters), 329)
|
|
self.assertEqual(len(record.GridCornerUL), 7)
|
|
self.assertEqual(record.AlgorithmParameters[-3:], "169")
|
|
|
|
def testAffyBadHeader(self):
|
|
with self.assertRaises(CelFile.ParserError):
|
|
with open(self.affy4Bad, "rb") as f:
|
|
record = CelFile.read(f)
|
|
|
|
def testAffyWrongModeReadV3(self):
|
|
with self.assertRaises(ValueError):
|
|
with open(self.affy3, "rb") as f:
|
|
record = CelFile.read(f, version=3)
|
|
|
|
def testAffyWrongModeReadV4(self):
|
|
with self.assertRaises(ValueError):
|
|
with open(self.affy4) as f:
|
|
record = CelFile.read(f, version=4)
|
|
|
|
# Writes a small example Affymetrix V4 CEL File
|
|
def writeExampleV4(self, f, bad=False):
|
|
preHeaders = {
|
|
"cellNo": 25,
|
|
"columns": 5,
|
|
"headerLen": 752,
|
|
"magic": 64,
|
|
"rows": 5,
|
|
"version": 4,
|
|
}
|
|
goodH = {"Axis-invertX": b"0"}
|
|
badH = {"Axis-invertX": b"1"}
|
|
|
|
headers = {
|
|
"Algorithm": b"Percentile",
|
|
"AlgorithmParameters": b"Percentile:75;CellMargin:4;Outlie"
|
|
b"rHigh:1.500;OutlierLow:1.004;AlgVersion:6.0;FixedCellSize"
|
|
b":TRUE;FullFeatureWidth:7;FullFeatureHeight:7;IgnoreOutlie"
|
|
b"rsInShiftRows:FALSE;FeatureExtraction:TRUE;PoolWidthExten"
|
|
b"stion:1;PoolHeightExtension:1;UseSubgrids:FALSE;Randomize"
|
|
b"Pixels:FALSE;ErrorBasis:StdvMean;StdMult:1.000000;NumDATS"
|
|
b"ubgrids:169",
|
|
"AxisInvertY": b"0",
|
|
"Cols": b"5",
|
|
"DatHeader": b"[0..65534] 20_10N:CLS=19420RWS=19420XIN=0"
|
|
b" YIN=0 VE=30 2.0 05/25/05 23:19:07 50102310 M10 "
|
|
b" \x14 \x14 HuEx-1_0-st-v2.1sq \x14 \x14 \x14 \x14 "
|
|
b"\x14570 \x14 25540.671875 \x14 3.500000 \x14 0.7000 \x14"
|
|
b" 3",
|
|
"GridCornerLL": b"518 18668",
|
|
"GridCornerLR": b"18800 18825",
|
|
"GridCornerUL": b"659 469",
|
|
"GridCornerUR": b"18942 623",
|
|
"OffsetX": b"0",
|
|
"OffsetY": b"0",
|
|
"Rows": b"5",
|
|
"TotalX": b"2560",
|
|
"TotalY": b"2560",
|
|
"swapXY": b"0",
|
|
}
|
|
if not bad:
|
|
headers.update(goodH)
|
|
else:
|
|
headers.update(badH)
|
|
prePadding = b"this text doesn't matter and is ignored\x04"
|
|
preHeadersOrder = ["magic", "version", "columns", "rows", "cellNo", "headerLen"]
|
|
headersEncoded = struct.pack(
|
|
"<" + "i" * len(preHeadersOrder),
|
|
*(preHeaders[header] for header in preHeadersOrder),
|
|
)
|
|
|
|
f.write(headersEncoded)
|
|
for header in headers:
|
|
try:
|
|
f.write(
|
|
bytes(header, encoding="utf-8") + b"=" + headers[header] + b"\n"
|
|
)
|
|
except TypeError:
|
|
f.write(header + b"=" + headers[header] + b"\n")
|
|
f.write(prePadding)
|
|
f.write(b"\x00" * 15)
|
|
for i in range(25):
|
|
f.write(struct.pack("< f f h", i, -i, 9)) # intensity, sdev, pixel
|
|
|
|
|
|
if __name__ == "__main__":
|
|
runner = unittest.TextTestRunner(verbosity=2)
|
|
unittest.main(testRunner=runner)
|