tests.test_scsv
PyDRex: tests for the SCSV plain text file format.
1"""> PyDRex: tests for the SCSV plain text file format.""" 2 3import tempfile 4 5import numpy as np 6import pytest 7from numpy import testing as nt 8from pydrex import exceptions as _err 9from pydrex import io as _io 10from pydrex import logger as _log 11from pydrex import utils as _utils 12 13 14def test_validate_schema(console_handler): 15 """Test SCSV schema validation.""" 16 schema_nofill = { 17 "delimiter": ",", 18 "missing": "-", 19 "fields": [{"name": "nofill", "type": "float"}], 20 } 21 schema_nomissing = { 22 "delimiter": ",", 23 "fields": [{"name": "nomissing", "type": "float", "fill": "NaN"}], 24 } 25 schema_nofields = {"delimiter": ",", "missing": "-"} 26 schema_badfieldname = { 27 "delimiter": ",", 28 "missing": "-", 29 "fields": [{"name": "bad name", "type": "float", "fill": "NaN"}], 30 } 31 schema_delimiter_eq_missing = { 32 "delimiter": ",", 33 "missing": ",", 34 "fields": [{"name": "baddelim", "type": "float", "fill": "NaN"}], 35 } 36 schema_delimiter_in_missing = { 37 "delimiter": ",", 38 "missing": "-,", 39 "fields": [{"name": "baddelim", "type": "float", "fill": "NaN"}], 40 } 41 schema_long_delimiter = { 42 "delimiter": ",,", 43 "missing": "-", 44 "fields": [{"name": "baddelim", "type": "float", "fill": "NaN"}], 45 } 46 47 # NOTE: NamedTemporaryFile() already opens the file. 48 # Attempting to open it again will cause a crash on Windows so close the file first. 49 with _log.handler_level("CRITICAL", console_handler): 50 with pytest.raises(_err.SCSVError): 51 temp = tempfile.NamedTemporaryFile() 52 temp.close() 53 _io.save_scsv(temp.name, schema_nofill, [[0.1]]) 54 with pytest.raises(_err.SCSVError): 55 temp = tempfile.NamedTemporaryFile() 56 temp.close() 57 _io.save_scsv(temp.name, schema_nomissing, [[0.1]]) 58 with pytest.raises(_err.SCSVError): 59 temp = tempfile.NamedTemporaryFile() 60 temp.close() 61 _io.save_scsv(temp.name, schema_nofields, [[0.1]]) 62 with pytest.raises(_err.SCSVError): 63 temp = tempfile.NamedTemporaryFile() 64 temp.close() 65 _io.save_scsv(temp.name, schema_badfieldname, [[0.1]]) 66 with pytest.raises(_err.SCSVError): 67 temp = tempfile.NamedTemporaryFile() 68 temp.close() 69 _io.save_scsv(temp.name, schema_delimiter_eq_missing, [[0.1]]) 70 with pytest.raises(_err.SCSVError): 71 temp = tempfile.NamedTemporaryFile() 72 temp.close() 73 _io.save_scsv(temp.name, schema_delimiter_in_missing, [[0.1]]) 74 # CSV module already raises a TypeError on long delimiters. 75 with pytest.raises(TypeError): 76 temp = tempfile.NamedTemporaryFile() 77 temp.close() 78 _io.save_scsv(temp.name, schema_long_delimiter, [[0.1]]) 79 80 81def test_read_specfile(): 82 """Test SCSV spec file parsing.""" 83 data = _io.read_scsv(_io.data("specs") / "spec.scsv") 84 assert data._fields == ( 85 "first_column", 86 "second_column", 87 "third_column", 88 "float_column", 89 "bool_column", 90 "complex_column", 91 ) 92 nt.assert_equal(data.first_column, ["s1", "MISSING", "s3"]) 93 nt.assert_equal(data.second_column, ["A", "B, b", ""]) 94 nt.assert_equal(data.third_column, [999999, 10, 1]) 95 nt.assert_equal(data.float_column, [1.1, np.nan, 1.0]) 96 nt.assert_equal(data.bool_column, [True, False, True]) 97 nt.assert_equal(data.complex_column, [0.1 + 0 * 1j, np.nan + 0 * 1j, 1.0 + 1 * 1j]) 98 99 100@pytest.mark.skipif(_utils.in_ci("win32"), reason="Items are not equal") 101def test_save_specfile(outdir, named_tempfile_kwargs): 102 """Test SCSV spec file reproduction.""" 103 schema = { 104 "delimiter": ",", 105 "missing": "-", 106 "fields": [ 107 { 108 "name": "first_column", 109 "type": "string", 110 "fill": "MISSING", 111 "unit": "percent", 112 }, 113 {"name": "second_column"}, 114 {"name": "third_column", "type": "integer", "fill": "999999"}, 115 {"name": "float_column", "type": "float", "fill": "NaN"}, 116 {"name": "bool_column", "type": "boolean"}, 117 {"name": "complex_column", "type": "complex", "fill": "NaN"}, 118 ], 119 } 120 schema_alt = { 121 "delimiter": ",", 122 "missing": "-", 123 "fields": [ 124 { 125 "name": "first_column", 126 "type": "string", 127 "unit": "percent", 128 }, 129 {"name": "second_column"}, 130 {"name": "third_column", "type": "integer", "fill": "999991"}, 131 {"name": "float_column", "type": "float", "fill": "0.0"}, 132 {"name": "bool_column", "type": "boolean"}, 133 {"name": "complex_column", "type": "complex", "fill": "NaN"}, 134 ], 135 } 136 137 data = [ 138 ["s1", "MISSING", "s3"], 139 ["A", "B, b", ""], 140 [999999, 10, 1], 141 [1.1, np.nan, 1.0], 142 [True, False, True], 143 [0.1 + 0 * 1j, np.nan + 0 * 1j, 1.0 + 1 * 1j], 144 ] 145 data_alt = [ 146 ["s1", "", "s3"], 147 ["A", "B, b", ""], 148 [999991, 10, 1], 149 [1.1, 0.0, 1.0], 150 [True, False, True], 151 [0.1 + 0 * 1j, np.nan + 0 * 1j, 1.0 + 1 * 1j], 152 ] 153 154 # The test writes two variants of the file, with identical CSV contents but 155 # different YAML header specs. Contents after the header must match. 156 if outdir is not None: 157 _io.save_scsv(f"{outdir}/spec_out.scsv", schema, data) 158 _io.save_scsv(f"{outdir}/spec_out_alt.scsv", schema_alt, data_alt) 159 160 # https://docs.python.org/3/library/tempfile.html#tempfile.NamedTemporaryFile 161 temp = tempfile.NamedTemporaryFile(**named_tempfile_kwargs) 162 temp_alt = tempfile.NamedTemporaryFile(**named_tempfile_kwargs) 163 _io.save_scsv(temp.name, schema, data) 164 _io.save_scsv(temp_alt.name, schema_alt, data_alt) 165 raw_read = [] 166 raw_read_alt = [] 167 with open(temp.name) as stream: 168 raw_read = stream.readlines()[23:] # Extra spec for first column 'fill' value. 169 with open(temp_alt.name) as stream: 170 raw_read_alt = stream.readlines()[22:] 171 _log.debug("\n first file: %s\n second file: %s", raw_read, raw_read_alt) 172 nt.assert_equal(raw_read, raw_read_alt) 173 174 175def test_read_Kaminski2002(): 176 data = _io.read_scsv(_io.data("thirdparty") / "Kaminski2002_ISAtime.scsv") 177 assert data._fields == ("time_ISA", "vorticity") 178 # fmt: off 179 nt.assert_equal( 180 data.time_ISA, 181 np.array( 182 [2.48, 2.50, 2.55, 2.78, 3.07, 3.58, 4.00, 4.88, 4.01, 3.79, 183 3.72, 3.66, 3.71, 4.22, 4.73, 3.45, 1.77, 0.51] 184 ), 185 ) 186 nt.assert_equal( 187 data.vorticity, 188 np.array( 189 [0.05, 0.10, 0.20, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 190 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00] 191 ), 192 ) 193 # fmt: on 194 195 196def test_save_scsv_errors(named_tempfile_kwargs): 197 """Check that we raise errors when attempting to write bad SCSV data.""" 198 schema = { 199 "delimiter": ",", 200 "missing": "-", 201 "fields": [ 202 { 203 "name": "foo", 204 "type": "integer", 205 "fill": 999999, 206 } 207 ], 208 } 209 # https://docs.python.org/3/library/tempfile.html#tempfile.NamedTemporaryFile 210 temp = tempfile.NamedTemporaryFile(**named_tempfile_kwargs) 211 with pytest.raises(_err.SCSVError): 212 foo = [1, 5, 0.2] 213 _io.save_scsv(temp.name, schema, [foo]) 214 foo = [1, "foo"] 215 _io.save_scsv(temp.name, schema, [foo]) 216 foo = ["foo"] 217 _io.save_scsv(temp.name, schema, [foo]) 218 foo = [True] 219 _io.save_scsv(temp.name, schema, [foo]) 220 foo = [1, 2, 3] 221 bar = [1, 2, 3] 222 _io.save_scsv(temp.name, schema, [foo, bar]) 223 224 225def test_read_Kaminski2004(): 226 data = _io.read_scsv(_io.data("thirdparty") / "Kaminski2004_AaxisDynamicShear.scsv") 227 assert data._fields == ("time", "meanA_X0", "meanA_X02", "meanA_X04") 228 # fmt: off 229 nt.assert_equal( 230 data.time, 231 np.array( 232 [-0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 233 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 234 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 235 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 236 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0] 237 ), 238 ) 239 nt.assert_equal( 240 data.meanA_X02, 241 np.array( 242 [-0.54, -0.54, -0.27, 0.13, 0.94, 2.82, 5.37, 9.53, 14.77, 20.40, 243 26.58, 32.89, 39.73, 47.25, 53.69, 58.66, 60.81, 60.81, 59.73, 58.52, 58.12, 244 56.64, 54.09, 53.69, 55.57, 57.05, 58.66, 60.54, 60.81, 61.21, 61.21, 61.61, 245 61.48, 61.61, 61.61, 61.61, 61.21, 61.21, 61.07, 60.81, 60.81, 60.54, 60.00, 246 59.60, 59.33, 58.52, 58.12, 57.85, 57.45, 57.05, 57.05] 247 ), 248 ) 249 # fmt: on 250 251 252def test_read_Skemer2016(): 253 data = _io.read_scsv(_io.data("thirdparty") / "Skemer2016_ShearStrainAngles.scsv") 254 assert data._fields == ( 255 "study", 256 "sample_id", 257 "shear_strain", 258 "angle", 259 "fabric", 260 "M_index", 261 ) 262 # fmt: off 263 nt.assert_equal( 264 data.study, 265 ["Z&K 1200 C", "Z&K 1200 C", "Z&K 1200 C", "Z&K 1200 C", "Z&K 1200 C", 266 "Z&K 1300 C", "Z&K 1300 C", "Z&K 1300 C", "Z&K 1300 C", "Z&K 1300 C", 267 "Z&K 1300 C", "Z&K 1300 C", "Bystricky 2000", "Bystricky 2000", "Bystricky 2000", 268 "Bystricky 2000", "Warren 2008", "Warren 2008", "Warren 2008", "Warren 2008", 269 "Warren 2008", "Warren 2008", "Warren 2008", "Warren 2008", "Warren 2008", 270 "Skemer 2011", "Skemer 2011", "Skemer 2011", "Webber 2010", "Webber 2010", 271 "Webber 2010", "Webber 2010", "Webber 2010", "Webber 2010", "Webber 2010", 272 "Katayama 2004", "Katayama 2004", "Katayama 2004", "Katayama 2004", "Katayama 2004", 273 "Katayama 2004", "Skemer 2010", "Skemer 2010", "Skemer 2010", "Skemer 2010", 274 "Skemer 2010", "Jung 2006", "Jung 2006", "Jung 2006", "Jung 2006", 275 "Jung 2006", "Jung 2006", "Hansen 2014", "Hansen 2014", "Hansen 2014", 276 "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", 277 "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", 278 "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", 279 "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", 280 "Hansen 2014", "Hansen 2014", "Hansen 2014", "H&W 2015", "H&W 2015", 281 "H&W 2015", "H&W 2015", "H&W 2015", "H&W 2015", "H&W 2015", 282 "H&W 2015", "H&W 2015", "H&W 2015", "H&W 2015", "H&W 2015", 283 "H&W 2015", "H&W 2015", "H&W 2015", "H&W 2015"], 284 ) 285 nt.assert_equal( 286 data.sample_id, 287 ["PI-148", "PI-150", "PI-154", "PI-158", "PI-284", "MIT-5", "MIT-20", "MIT-6", 288 "MIT-21", "MIT-17", "MIT-18", "MIT-19", "", "", "", "", "3923J01", 289 "3923J11", "3923J13", "3923J14", "3924J06", "3924J09a", "3924J09b", "3924J08", 290 "3924J10", "PIP-20", "PIP-21", "PT-484", "", "", "", "", "", "", "", "GA10", 291 "GA38", "GA23", "GA12", "GA45", "GA25", "3925G08", "3925G05", "3925G02", 292 "3925G01", "PT-248_4", "JK43", "JK21B", "JK26", "JK11", "JK18", "JK23", 293 "PT0535", "PT0248_1", "", "PT0655", "PT0248_2", "PI-284", "PT0248_3", "PT0503_5", 294 "PT0248_4", "PT0248_5", "PT0503_4", "PT0640", "PT0503_3", "", "PT0494", 295 "PT0538", "PT0503_2", "PT0541", "PT0503_1", "PT0633", "PT0552", "PT0505", 296 "PT0651", "PT0499", "PT619", "PT0484", "3923J06", "3923J07", "3923J09", 297 "3923J08", "3923J13", "3923J12", "3924J06", "3924J05", "JP13-D07", "JP13-D06", 298 "3924J03a", "3924J03b", "3924J09a", "3924J09b", "3924J08", "3924J07"], 299 ) 300 nt.assert_equal( 301 data.shear_strain, 302 np.array( 303 [ 304 17, 30, 45, 65, 110, 11, 7, 65, 58, 100, 305 115, 150, 50, 200, 400, 500, 0, 65, 118, 131, 258, 386, 306 386, 525, 168, 120, 180, 350, 0, 25, 100, 130, 168, 330, 307 330, 60, 60, 80, 120, 260, 630, 60, 150, 1000, 1000, 290, 308 120, 400, 100, 110, 120, 400, 0, 30, 50, 100, 100, 110, 309 210, 270, 290, 390, 390, 400, 490, 500, 590, 680, 680, 760, 310 820, 870, 880, 1020, 1060, 1090, 1420, 1870, 32, 32, 81, 81, 311 118, 118, 258, 258, 286, 286, 337, 337, 386, 386, 525, 525 312 ] 313 ), 314 ) 315 nt.assert_equal( 316 data.angle, 317 np.array( 318 [ 319 43, 37, 38, 24, 20, 36, 28, 18, 10, 5, 320 10, 0, 0, 0, 0, 0, 62, 37, 49, 61, 4, 11, 0, 1, 33, 55, 321 53, 45, 55, 35, 47, 29, 37, 47, 45, -49, -26, -10, -35, 322 -10, -15, -52, -30, -14, -11, 0, 26, 15, 27, 25, 16, 36, 323 -71, -78, 71, 29, 39, 24, 12, 7.3, -3.7, -1.3, -6.1, 0.4, 324 -8.6, 5.4, 0.6, -5.5, -4.3, -8.4, -1.9, -0.9, -8.9, 2.8, 325 -2, -1.5, -4.1, -5.8, 48, 51, 44, 35, 35, 40, 1, 15, 25, 326 28, 28, 39, 1, 8, 4, 11 327 ] 328 ), 329 ) 330 nt.assert_equal( 331 data.fabric, 332 [ 333 "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", 334 "D", "D", "D", "D", "A", "A", "A", "A", "A", "A", "A", "A", 335 "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "E", 336 "E", "E", "E", "E", "E", "E", "E", "E", "E", "D", "A", "B", 337 "C", "C", "C", "C", "D", "D", "D", "D", "D", "D", "D", "D", 338 "D", "D", "D", "D", "D", "A", "A", "A", "A", "A", "A", "A", 339 "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", 340 "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", 341 ], 342 ) 343 nt.assert_equal( 344 data.M_index, 345 np.array( 346 [ 347 np.nan, np.nan, np.nan, np.nan, 0.09, np.nan, np.nan, 348 np.nan, np.nan, np.nan, np.nan, np.nan, 0.05, np.nan, 349 np.nan, 0.17, 0.08, 0.12, 0.16, 0.2, 0.17, 0.06, 0.13, 350 0.14, 0.16, np.nan, np.nan, np.nan, np.nan, np.nan, 351 np.nan, np.nan, np.nan, np.nan, np.nan, 0.17, np.nan, 352 np.nan, 0.28, np.nan, 0.44, 0.03, 0.1, 0.47, 0.37, 353 0.36, 0.06, 0.21, 0.21, 0.23, 0.27, 0.1, 0.01, 0.06, 354 0.05, 0.06, 0.06, 0.09, 0.2, 0.26, 0.36, 0.35, 0.34, 355 0.36, 0.45, 0.17, 0.4, 0.46, 0.46, 0.44, 0.35, 0.39, 356 0.4, 0.69, 0.55, 0.61, 0.51, 0.51, 0.08, 0.2, 0.16, 357 0.12, 0.12, 0.17, 0.18, 0.13, 0.15, 0.09, 0.19, 0.27, 358 0.12, 0.18, 0.14, 0.26, 359 ] 360 ), 361 )
def
test_validate_schema(console_handler):
15def test_validate_schema(console_handler): 16 """Test SCSV schema validation.""" 17 schema_nofill = { 18 "delimiter": ",", 19 "missing": "-", 20 "fields": [{"name": "nofill", "type": "float"}], 21 } 22 schema_nomissing = { 23 "delimiter": ",", 24 "fields": [{"name": "nomissing", "type": "float", "fill": "NaN"}], 25 } 26 schema_nofields = {"delimiter": ",", "missing": "-"} 27 schema_badfieldname = { 28 "delimiter": ",", 29 "missing": "-", 30 "fields": [{"name": "bad name", "type": "float", "fill": "NaN"}], 31 } 32 schema_delimiter_eq_missing = { 33 "delimiter": ",", 34 "missing": ",", 35 "fields": [{"name": "baddelim", "type": "float", "fill": "NaN"}], 36 } 37 schema_delimiter_in_missing = { 38 "delimiter": ",", 39 "missing": "-,", 40 "fields": [{"name": "baddelim", "type": "float", "fill": "NaN"}], 41 } 42 schema_long_delimiter = { 43 "delimiter": ",,", 44 "missing": "-", 45 "fields": [{"name": "baddelim", "type": "float", "fill": "NaN"}], 46 } 47 48 # NOTE: NamedTemporaryFile() already opens the file. 49 # Attempting to open it again will cause a crash on Windows so close the file first. 50 with _log.handler_level("CRITICAL", console_handler): 51 with pytest.raises(_err.SCSVError): 52 temp = tempfile.NamedTemporaryFile() 53 temp.close() 54 _io.save_scsv(temp.name, schema_nofill, [[0.1]]) 55 with pytest.raises(_err.SCSVError): 56 temp = tempfile.NamedTemporaryFile() 57 temp.close() 58 _io.save_scsv(temp.name, schema_nomissing, [[0.1]]) 59 with pytest.raises(_err.SCSVError): 60 temp = tempfile.NamedTemporaryFile() 61 temp.close() 62 _io.save_scsv(temp.name, schema_nofields, [[0.1]]) 63 with pytest.raises(_err.SCSVError): 64 temp = tempfile.NamedTemporaryFile() 65 temp.close() 66 _io.save_scsv(temp.name, schema_badfieldname, [[0.1]]) 67 with pytest.raises(_err.SCSVError): 68 temp = tempfile.NamedTemporaryFile() 69 temp.close() 70 _io.save_scsv(temp.name, schema_delimiter_eq_missing, [[0.1]]) 71 with pytest.raises(_err.SCSVError): 72 temp = tempfile.NamedTemporaryFile() 73 temp.close() 74 _io.save_scsv(temp.name, schema_delimiter_in_missing, [[0.1]]) 75 # CSV module already raises a TypeError on long delimiters. 76 with pytest.raises(TypeError): 77 temp = tempfile.NamedTemporaryFile() 78 temp.close() 79 _io.save_scsv(temp.name, schema_long_delimiter, [[0.1]])
Test SCSV schema validation.
def
test_read_specfile():
82def test_read_specfile(): 83 """Test SCSV spec file parsing.""" 84 data = _io.read_scsv(_io.data("specs") / "spec.scsv") 85 assert data._fields == ( 86 "first_column", 87 "second_column", 88 "third_column", 89 "float_column", 90 "bool_column", 91 "complex_column", 92 ) 93 nt.assert_equal(data.first_column, ["s1", "MISSING", "s3"]) 94 nt.assert_equal(data.second_column, ["A", "B, b", ""]) 95 nt.assert_equal(data.third_column, [999999, 10, 1]) 96 nt.assert_equal(data.float_column, [1.1, np.nan, 1.0]) 97 nt.assert_equal(data.bool_column, [True, False, True]) 98 nt.assert_equal(data.complex_column, [0.1 + 0 * 1j, np.nan + 0 * 1j, 1.0 + 1 * 1j])
Test SCSV spec file parsing.
@pytest.mark.skipif(_utils.in_ci('win32'), reason='Items are not equal')
def
test_save_specfile(outdir, named_tempfile_kwargs):
101@pytest.mark.skipif(_utils.in_ci("win32"), reason="Items are not equal") 102def test_save_specfile(outdir, named_tempfile_kwargs): 103 """Test SCSV spec file reproduction.""" 104 schema = { 105 "delimiter": ",", 106 "missing": "-", 107 "fields": [ 108 { 109 "name": "first_column", 110 "type": "string", 111 "fill": "MISSING", 112 "unit": "percent", 113 }, 114 {"name": "second_column"}, 115 {"name": "third_column", "type": "integer", "fill": "999999"}, 116 {"name": "float_column", "type": "float", "fill": "NaN"}, 117 {"name": "bool_column", "type": "boolean"}, 118 {"name": "complex_column", "type": "complex", "fill": "NaN"}, 119 ], 120 } 121 schema_alt = { 122 "delimiter": ",", 123 "missing": "-", 124 "fields": [ 125 { 126 "name": "first_column", 127 "type": "string", 128 "unit": "percent", 129 }, 130 {"name": "second_column"}, 131 {"name": "third_column", "type": "integer", "fill": "999991"}, 132 {"name": "float_column", "type": "float", "fill": "0.0"}, 133 {"name": "bool_column", "type": "boolean"}, 134 {"name": "complex_column", "type": "complex", "fill": "NaN"}, 135 ], 136 } 137 138 data = [ 139 ["s1", "MISSING", "s3"], 140 ["A", "B, b", ""], 141 [999999, 10, 1], 142 [1.1, np.nan, 1.0], 143 [True, False, True], 144 [0.1 + 0 * 1j, np.nan + 0 * 1j, 1.0 + 1 * 1j], 145 ] 146 data_alt = [ 147 ["s1", "", "s3"], 148 ["A", "B, b", ""], 149 [999991, 10, 1], 150 [1.1, 0.0, 1.0], 151 [True, False, True], 152 [0.1 + 0 * 1j, np.nan + 0 * 1j, 1.0 + 1 * 1j], 153 ] 154 155 # The test writes two variants of the file, with identical CSV contents but 156 # different YAML header specs. Contents after the header must match. 157 if outdir is not None: 158 _io.save_scsv(f"{outdir}/spec_out.scsv", schema, data) 159 _io.save_scsv(f"{outdir}/spec_out_alt.scsv", schema_alt, data_alt) 160 161 # https://docs.python.org/3/library/tempfile.html#tempfile.NamedTemporaryFile 162 temp = tempfile.NamedTemporaryFile(**named_tempfile_kwargs) 163 temp_alt = tempfile.NamedTemporaryFile(**named_tempfile_kwargs) 164 _io.save_scsv(temp.name, schema, data) 165 _io.save_scsv(temp_alt.name, schema_alt, data_alt) 166 raw_read = [] 167 raw_read_alt = [] 168 with open(temp.name) as stream: 169 raw_read = stream.readlines()[23:] # Extra spec for first column 'fill' value. 170 with open(temp_alt.name) as stream: 171 raw_read_alt = stream.readlines()[22:] 172 _log.debug("\n first file: %s\n second file: %s", raw_read, raw_read_alt) 173 nt.assert_equal(raw_read, raw_read_alt)
Test SCSV spec file reproduction.
def
test_read_Kaminski2002():
176def test_read_Kaminski2002(): 177 data = _io.read_scsv(_io.data("thirdparty") / "Kaminski2002_ISAtime.scsv") 178 assert data._fields == ("time_ISA", "vorticity") 179 # fmt: off 180 nt.assert_equal( 181 data.time_ISA, 182 np.array( 183 [2.48, 2.50, 2.55, 2.78, 3.07, 3.58, 4.00, 4.88, 4.01, 3.79, 184 3.72, 3.66, 3.71, 4.22, 4.73, 3.45, 1.77, 0.51] 185 ), 186 ) 187 nt.assert_equal( 188 data.vorticity, 189 np.array( 190 [0.05, 0.10, 0.20, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 191 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00] 192 ), 193 ) 194 # fmt: on
def
test_save_scsv_errors(named_tempfile_kwargs):
197def test_save_scsv_errors(named_tempfile_kwargs): 198 """Check that we raise errors when attempting to write bad SCSV data.""" 199 schema = { 200 "delimiter": ",", 201 "missing": "-", 202 "fields": [ 203 { 204 "name": "foo", 205 "type": "integer", 206 "fill": 999999, 207 } 208 ], 209 } 210 # https://docs.python.org/3/library/tempfile.html#tempfile.NamedTemporaryFile 211 temp = tempfile.NamedTemporaryFile(**named_tempfile_kwargs) 212 with pytest.raises(_err.SCSVError): 213 foo = [1, 5, 0.2] 214 _io.save_scsv(temp.name, schema, [foo]) 215 foo = [1, "foo"] 216 _io.save_scsv(temp.name, schema, [foo]) 217 foo = ["foo"] 218 _io.save_scsv(temp.name, schema, [foo]) 219 foo = [True] 220 _io.save_scsv(temp.name, schema, [foo]) 221 foo = [1, 2, 3] 222 bar = [1, 2, 3] 223 _io.save_scsv(temp.name, schema, [foo, bar])
Check that we raise errors when attempting to write bad SCSV data.
def
test_read_Kaminski2004():
226def test_read_Kaminski2004(): 227 data = _io.read_scsv(_io.data("thirdparty") / "Kaminski2004_AaxisDynamicShear.scsv") 228 assert data._fields == ("time", "meanA_X0", "meanA_X02", "meanA_X04") 229 # fmt: off 230 nt.assert_equal( 231 data.time, 232 np.array( 233 [-0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 234 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 235 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 236 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 237 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0] 238 ), 239 ) 240 nt.assert_equal( 241 data.meanA_X02, 242 np.array( 243 [-0.54, -0.54, -0.27, 0.13, 0.94, 2.82, 5.37, 9.53, 14.77, 20.40, 244 26.58, 32.89, 39.73, 47.25, 53.69, 58.66, 60.81, 60.81, 59.73, 58.52, 58.12, 245 56.64, 54.09, 53.69, 55.57, 57.05, 58.66, 60.54, 60.81, 61.21, 61.21, 61.61, 246 61.48, 61.61, 61.61, 61.61, 61.21, 61.21, 61.07, 60.81, 60.81, 60.54, 60.00, 247 59.60, 59.33, 58.52, 58.12, 57.85, 57.45, 57.05, 57.05] 248 ), 249 ) 250 # fmt: on
def
test_read_Skemer2016():
253def test_read_Skemer2016(): 254 data = _io.read_scsv(_io.data("thirdparty") / "Skemer2016_ShearStrainAngles.scsv") 255 assert data._fields == ( 256 "study", 257 "sample_id", 258 "shear_strain", 259 "angle", 260 "fabric", 261 "M_index", 262 ) 263 # fmt: off 264 nt.assert_equal( 265 data.study, 266 ["Z&K 1200 C", "Z&K 1200 C", "Z&K 1200 C", "Z&K 1200 C", "Z&K 1200 C", 267 "Z&K 1300 C", "Z&K 1300 C", "Z&K 1300 C", "Z&K 1300 C", "Z&K 1300 C", 268 "Z&K 1300 C", "Z&K 1300 C", "Bystricky 2000", "Bystricky 2000", "Bystricky 2000", 269 "Bystricky 2000", "Warren 2008", "Warren 2008", "Warren 2008", "Warren 2008", 270 "Warren 2008", "Warren 2008", "Warren 2008", "Warren 2008", "Warren 2008", 271 "Skemer 2011", "Skemer 2011", "Skemer 2011", "Webber 2010", "Webber 2010", 272 "Webber 2010", "Webber 2010", "Webber 2010", "Webber 2010", "Webber 2010", 273 "Katayama 2004", "Katayama 2004", "Katayama 2004", "Katayama 2004", "Katayama 2004", 274 "Katayama 2004", "Skemer 2010", "Skemer 2010", "Skemer 2010", "Skemer 2010", 275 "Skemer 2010", "Jung 2006", "Jung 2006", "Jung 2006", "Jung 2006", 276 "Jung 2006", "Jung 2006", "Hansen 2014", "Hansen 2014", "Hansen 2014", 277 "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", 278 "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", 279 "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", 280 "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", "Hansen 2014", 281 "Hansen 2014", "Hansen 2014", "Hansen 2014", "H&W 2015", "H&W 2015", 282 "H&W 2015", "H&W 2015", "H&W 2015", "H&W 2015", "H&W 2015", 283 "H&W 2015", "H&W 2015", "H&W 2015", "H&W 2015", "H&W 2015", 284 "H&W 2015", "H&W 2015", "H&W 2015", "H&W 2015"], 285 ) 286 nt.assert_equal( 287 data.sample_id, 288 ["PI-148", "PI-150", "PI-154", "PI-158", "PI-284", "MIT-5", "MIT-20", "MIT-6", 289 "MIT-21", "MIT-17", "MIT-18", "MIT-19", "", "", "", "", "3923J01", 290 "3923J11", "3923J13", "3923J14", "3924J06", "3924J09a", "3924J09b", "3924J08", 291 "3924J10", "PIP-20", "PIP-21", "PT-484", "", "", "", "", "", "", "", "GA10", 292 "GA38", "GA23", "GA12", "GA45", "GA25", "3925G08", "3925G05", "3925G02", 293 "3925G01", "PT-248_4", "JK43", "JK21B", "JK26", "JK11", "JK18", "JK23", 294 "PT0535", "PT0248_1", "", "PT0655", "PT0248_2", "PI-284", "PT0248_3", "PT0503_5", 295 "PT0248_4", "PT0248_5", "PT0503_4", "PT0640", "PT0503_3", "", "PT0494", 296 "PT0538", "PT0503_2", "PT0541", "PT0503_1", "PT0633", "PT0552", "PT0505", 297 "PT0651", "PT0499", "PT619", "PT0484", "3923J06", "3923J07", "3923J09", 298 "3923J08", "3923J13", "3923J12", "3924J06", "3924J05", "JP13-D07", "JP13-D06", 299 "3924J03a", "3924J03b", "3924J09a", "3924J09b", "3924J08", "3924J07"], 300 ) 301 nt.assert_equal( 302 data.shear_strain, 303 np.array( 304 [ 305 17, 30, 45, 65, 110, 11, 7, 65, 58, 100, 306 115, 150, 50, 200, 400, 500, 0, 65, 118, 131, 258, 386, 307 386, 525, 168, 120, 180, 350, 0, 25, 100, 130, 168, 330, 308 330, 60, 60, 80, 120, 260, 630, 60, 150, 1000, 1000, 290, 309 120, 400, 100, 110, 120, 400, 0, 30, 50, 100, 100, 110, 310 210, 270, 290, 390, 390, 400, 490, 500, 590, 680, 680, 760, 311 820, 870, 880, 1020, 1060, 1090, 1420, 1870, 32, 32, 81, 81, 312 118, 118, 258, 258, 286, 286, 337, 337, 386, 386, 525, 525 313 ] 314 ), 315 ) 316 nt.assert_equal( 317 data.angle, 318 np.array( 319 [ 320 43, 37, 38, 24, 20, 36, 28, 18, 10, 5, 321 10, 0, 0, 0, 0, 0, 62, 37, 49, 61, 4, 11, 0, 1, 33, 55, 322 53, 45, 55, 35, 47, 29, 37, 47, 45, -49, -26, -10, -35, 323 -10, -15, -52, -30, -14, -11, 0, 26, 15, 27, 25, 16, 36, 324 -71, -78, 71, 29, 39, 24, 12, 7.3, -3.7, -1.3, -6.1, 0.4, 325 -8.6, 5.4, 0.6, -5.5, -4.3, -8.4, -1.9, -0.9, -8.9, 2.8, 326 -2, -1.5, -4.1, -5.8, 48, 51, 44, 35, 35, 40, 1, 15, 25, 327 28, 28, 39, 1, 8, 4, 11 328 ] 329 ), 330 ) 331 nt.assert_equal( 332 data.fabric, 333 [ 334 "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", 335 "D", "D", "D", "D", "A", "A", "A", "A", "A", "A", "A", "A", 336 "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "E", 337 "E", "E", "E", "E", "E", "E", "E", "E", "E", "D", "A", "B", 338 "C", "C", "C", "C", "D", "D", "D", "D", "D", "D", "D", "D", 339 "D", "D", "D", "D", "D", "A", "A", "A", "A", "A", "A", "A", 340 "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", 341 "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", 342 ], 343 ) 344 nt.assert_equal( 345 data.M_index, 346 np.array( 347 [ 348 np.nan, np.nan, np.nan, np.nan, 0.09, np.nan, np.nan, 349 np.nan, np.nan, np.nan, np.nan, np.nan, 0.05, np.nan, 350 np.nan, 0.17, 0.08, 0.12, 0.16, 0.2, 0.17, 0.06, 0.13, 351 0.14, 0.16, np.nan, np.nan, np.nan, np.nan, np.nan, 352 np.nan, np.nan, np.nan, np.nan, np.nan, 0.17, np.nan, 353 np.nan, 0.28, np.nan, 0.44, 0.03, 0.1, 0.47, 0.37, 354 0.36, 0.06, 0.21, 0.21, 0.23, 0.27, 0.1, 0.01, 0.06, 355 0.05, 0.06, 0.06, 0.09, 0.2, 0.26, 0.36, 0.35, 0.34, 356 0.36, 0.45, 0.17, 0.4, 0.46, 0.46, 0.44, 0.35, 0.39, 357 0.4, 0.69, 0.55, 0.61, 0.51, 0.51, 0.08, 0.2, 0.16, 358 0.12, 0.12, 0.17, 0.18, 0.13, 0.15, 0.09, 0.19, 0.27, 359 0.12, 0.18, 0.14, 0.26, 360 ] 361 ), 362 )