tests/testthat/test-write_fs_mgh.R

test_that("An one-dimensional MGH file of double values can be written", {
  output_file = tempfile();

  # generate data
  data_length = 149244;
  data = rep(1.25, data_length);
  data_array = array(data);

  # write data to file
  write.fs.mgh(output_file, data_array);

  # load data again and check it
  mgh = read.fs.mgh(output_file, with_header=TRUE);
  read_data = mgh$data
  header = mgh$header
  expect_equal(header$mr_params, c(0,0,0,0,0));
  expect_equal(header$dtype, 3); #MRI_FLOAT
  expect_equal(header$ras_good_flag, -1L);

  # Check data dimensions: we should get 4 dimensions back. Since we wrote a vector of data only, the last 3 should be 1.
  expect_equal(typeof(read_data), "double");
  expect_equal(length(dim(read_data)), 4L);
  expect_equal((dim(read_data)[1]), data_length);
  expect_equal((dim(read_data)[2]), 1L);
  expect_equal((dim(read_data)[3]), 1L);
  expect_equal((dim(read_data)[4]), 1L);

  # Check the data values
  expect_equal(length(data), length(as.vector(read_data)));
  expect_equal(data_length, length(as.vector(read_data)));
  expect_equal(data, as.vector(read_data));
})


test_that("A three-dimensional MGH file with realistic size can be written", {
  output_file = tempfile();

  # generate data
  data_array = array(data=rep(1, 256*256*256), dim=c(256,256,256));

  # write data to file
  write.fs.mgh(output_file, data_array);

  # load data again and check it
  read_data = read.fs.mgh(output_file);

  # Check data dimensions: we should get 4 dimensions back. Since we wrote a vector of data only, the last 3 should be 1.
  expect_equal(length(dim(read_data)), 4);
  expect_equal((dim(read_data)[1]), 256);
  expect_equal((dim(read_data)[2]), 256);
  expect_equal((dim(read_data)[3]), 256);
  expect_equal((dim(read_data)[4]), 1);

  # Check the data values
  expect_equal(length(data_array), length(read_data));
  expect_equal(data_array, read_data[,,,1]);
})


test_that("An one-dimensional uncompressed MGH file of integer values can be written", {
  output_file = tempfile(fileext = ".mgh");

  # generate data
  data_length = 111111L;
  data = rep.int(1L, data_length);
  data[10000:20000] = 0L;         # Set some of the values to zero.
  expect_true(is.integer(data));
  expect_equal(range(data), c(0L, 1L));

  # write data to file
  write.fs.mgh(output_file, data);

  # load data again and check it
  mgh = read.fs.mgh(output_file, with_header=TRUE);
  read_data = mgh$data;
  header = mgh$header;
  expect_equal(header$mr_params, c(0,0,0,0,0));
  expect_equal(header$dtype, 1); #MRI_INT
  expect_equal(header$ras_good_flag, -1L);

  # Check data dimensions: we should get 4 dimensions back. Since we wrote a vector of data only, the last 3 should be 1.
  expect_equal(length(dim(read_data)), 4L);
  expect_equal(typeof(read_data), "integer");
  expect_equal((dim(read_data)[1]), data_length);
  expect_equal((dim(read_data)[2]), 1L);
  expect_equal((dim(read_data)[3]), 1L);
  expect_equal((dim(read_data)[4]), 1L);

  # Check the data values
  expect_equal(length(data), length(as.vector(read_data)));
  expect_equal(data_length, length(as.vector(read_data)));
  expect_equal(data, as.vector(read_data));
  expect_equal(range(read_data), c(0L, 1L));
})


test_that("An one-dimensional compressed MGZ file of integer values can be written", {
  # This test is very similar to the last one, but it uses MGZ instead of MGH.
  output_file = tempfile(fileext = ".mgz");

  # generate data
  data_length = 111111L;
  data = rep.int(1L, data_length);
  data[10000:20000] = 0L;         # Set some of the values to zero.
  expect_true(is.integer(data));
  expect_equal(range(data), c(0L, 1L));

  # write data to file
  write.fs.mgh(output_file, data);

  # load data again and check it
  mgh = read.fs.mgh(output_file, with_header=TRUE);
  read_data = mgh$data;
  header = mgh$header;
  expect_equal(header$mr_params, c(0,0,0,0,0));
  expect_equal(header$dtype, 1); #MRI_INT
  expect_equal(header$ras_good_flag, -1L);

  # Check data dimensions: we should get 4 dimensions back. Since we wrote a vector of data only, the last 3 should be 1.
  expect_equal(length(dim(read_data)), 4L);
  expect_equal(typeof(read_data), "integer");
  expect_equal((dim(read_data)[1]), data_length);
  expect_equal((dim(read_data)[2]), 1L);
  expect_equal((dim(read_data)[3]), 1L);
  expect_equal((dim(read_data)[4]), 1L);

  # Check the data values
  expect_equal(length(data), length(as.vector(read_data)));
  expect_equal(data_length, length(as.vector(read_data)));
  expect_equal(data, as.vector(read_data));
  expect_equal(range(read_data), c(0L, 1L));
})


test_that("Logical data can be written and re-read from MGH and MGZ files", {
  # This test is very similar to the last one, but it uses MGZ instead of MGH.
  output_file_mgh = tempfile(fileext = ".mgh");
  output_file_mgz = tempfile(fileext = ".mgz");

  # generate data
  data_int = sample(0:1, 2000, replace=TRUE); # only zeroes and ones
  data_logical = as.logical(data_int);

  # write data to files, re-read and check
  write.fs.mgh(output_file_mgh, data_logical);
  mgh = read.fs.mgh(output_file_mgh, with_header = TRUE, drop_empty_dims = TRUE);
  expect_equal(mgh$data, data_int);
  expect_equal(mgh$header$dtype, translate.mri.dtype("MRI_UCHAR"));

  write.fs.mgh(output_file_mgz, data_logical, mr_params = c(0., 0., 0., 0.));
  mgz = read.fs.mgh(output_file_mgz, with_header = TRUE, drop_empty_dims = TRUE);
  expect_equal(mgz$data, data_int);
  expect_equal(mgz$header$dtype, translate.mri.dtype("MRI_UCHAR"));

  # Also write integer data as MRI_SHORT and _UCHAR for completeness
  write.fs.mgh(tempfile(fileext = ".mgz"), data_int, mri_dtype = 'MRI_SHORT');
  write.fs.mgh(tempfile(fileext = ".mgz"), data_int, mri_dtype = 'MRI_UCHAR');

  # There should be warning for unsiotable data range / dtype combinations
  data_int_large = c(12L, 288L, 343456L); # integer data with values outside of range for MRI_SHORT and _UCHAR
  expect_warning(write.fs.mgh(tempfile(fileext = ".mgz"), data_int_large, mri_dtype = 'MRI_SHORT'));
  expect_warning(write.fs.mgh(tempfile(fileext = ".mgz"), data_int_large, mri_dtype = 'MRI_UCHAR'));
  # ... and for invalid input data type.
  data_char = rep("hi", 42L);
  expect_warning(write.fs.mgh(tempfile(fileext = ".mgz"), data_char, mri_dtype = 'MRI_SHORT'));
  expect_warning(write.fs.mgh(tempfile(fileext = ".mgz"), data_char, mri_dtype = 'MRI_UCHAR'));
  expect_warning(write.fs.mgh(tempfile(fileext = ".mgz"), data_char, mri_dtype = 'MRI_INT'));
  expect_warning(write.fs.mgh(tempfile(fileext = ".mgz"), data_char, mri_dtype = 'MRI_FLOAT'));
})


test_that("Improper use of write.fs.mgh leads to errors", {
  data_int = sample(0:1, 2000, replace=TRUE);
  filepath = tempfile(fileext = '.mgh');

  expect_error(write.fs.mgh(123, data_int)); # 123 is not a valid file path (not a string)
  expect_error(write.fs.mgh(filepath, data_int, mr_params = c(0., 0))); # invalid length of mr_params
  expect_error(write.fs.mgh(filepath, data_int, mr_params = "hi")); # invalid mr_params, must be double
  expect_error(write.fs.mgh(filepath, data_int, mr_params = "what"));   # mr_params must be double
  expect_error(write.fs.mgh(filepath, data_int, vox2ras_matrix = "what"));   # vox2ras_matrix must be double matrix
  expect_error(write.fs.mgh(filepath, data_int, vox2ras_matrix = matrix(seq(6), nrow=2)));   # vox2ras_matrix must be a 4x4 matrix
  expect_error(write.fs.mgh(filepath, data_int, mri_dtype = 3));   # mri_dtype must be a character string
  expect_error(write.fs.mgh(filepath, data_int, mri_dtype = "no such MRI dtype I guess"));   # mri_dtype must be valid
  expect_error(write.fs.mgh(filepath, data=NULL)); # invalid data
  expect_error(write.fs.mgh(filepath, data=array(seq.int(6), dim=rep(1L, 6L)))); # invalid data: too many dimensions (>5)
  expect_error(write.fs.mgh(filepath, data=rep("hi", 100L))); # invalid data: character strings not supported, no suitable MRI_DTYPE
})

Try the freesurferformats package in your browser

Any scripts or data that you put into this service are public.

freesurferformats documentation built on May 29, 2024, 5:29 a.m.