<commit_before># Copyright (c) 2016, Science and Technology Facilities Council
# This software is distributed under a BSD licence. See LICENSE.txt.

"""
Tests for mrcfile __init__.py validate function.
"""

# Import Python 3 features for future-proofing
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import io
import os
import shutil
import tempfile
import unittest
import warnings

import numpy as np

import mrcfile
from . import helpers


class ValidationTest(helpers.AssertRaisesRegexMixin, unittest.TestCase):
    
    """Unit tests for MRC validation function.
    
    """
    
    def setUp(self):
        super(ValidationTest, self).setUp()
        
        # Set up test files and names to be used
        self.test_data = helpers.get_test_data_path()
        self.test_output = tempfile.mkdtemp()
        self.temp_mrc_name = os.path.join(self.test_output, 'test_mrcfile.mrc')
        self.example_mrc_name = os.path.join(self.test_data, 'EMD-3197.map')
        self.gzip_mrc_name = os.path.join(self.test_data, 'emd_3197.map.gz')
        self.ext_header_mrc_name = os.path.join(self.test_data, 'EMD-3001.map')
        
        # Set up stream to catch print output from validate()
        self.print_stream = io.StringIO()
    
    def tearDown(self):
        self.print_stream.close()
        if os.path.exists(self.test_output):
            shutil.rmtree(self.test_output)
        super(ValidationTest, self).tearDown()
    
    def test_good_file(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(36, dtype=np.float32).reshape(3, 3, 4))
            mrc.voxel_size = 2.3
        result = mrcfile.validate(self.temp_mrc_name, self.print_stream)
        assert result == True
        print_output = self.print_stream.getvalue()
        assert len(print_output) == 0
    
    def test_emdb_file(self):
        result = mrcfile.validate(self.example_mrc_name, self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert print_output.strip() == ("File does not declare MRC format "
                                        "version 20140: nversion = 0")
    
    def test_gzip_emdb_file(self):
        result = mrcfile.validate(self.gzip_mrc_name, self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert print_output.strip() == ("File does not declare MRC format "
                                        "version 20140: nversion = 0")
    
    def test_emdb_cryst_file(self):
        result = mrcfile.validate(self.ext_header_mrc_name, self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert print_output.strip() == ("File does not declare MRC format "
                                        "version 20140: nversion = 0\n"
                                        "Extended header type is undefined or "
                                        "unrecognised: exttyp = ''")
    
    def test_incorrect_map_id(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.map = b'fake'
        with self.assertRaisesRegex(ValueError, "Map ID string not found"):
            mrcfile.validate(self.temp_mrc_name)
    
    def test_incorrect_machine_stamp(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.machst = bytearray(b'    ')
        with self.assertRaisesRegex(ValueError, "Unrecognised machine stamp"):
            mrcfile.validate(self.temp_mrc_name)
    
    def test_invalid_mode(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(12, dtype=np.float32).reshape(1, 3, 4))
            mrc.header.mode = 8
        with self.assertRaisesRegex(ValueError, "Unrecognised mode"):
            mrcfile.validate(self.temp_mrc_name)
    
    def test_file_too_small(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(12, dtype=np.float32).reshape(1, 3, 4))
            mrc.header.nz = 2
        with self.assertRaisesRegex(ValueError, "Expected \d+ bytes but could only read \d+"):
            mrcfile.validate(self.temp_mrc_name)
    
    def test_file_too_large(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(36, dtype=np.float32).reshape(3, 3, 4))
            mrc.header.nz = 2
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            result = mrcfile.validate(self.temp_mrc_name,
                                      print_file=self.print_stream)
            assert result == False
            print_output = self.print_stream.getvalue()
            assert "larger than expected" in print_output
            assert len(w) == 1
            assert issubclass(w[0].category, RuntimeWarning)
            assert "larger than expected" in str(w[0].message)
    
    def test_negative_mx(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.mx = -10
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Header field 'mx' is negative" in print_output
    
    def test_negative_my(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.my = -10
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Header field 'my' is negative" in print_output
    
    def test_negative_mz(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.mz = -10
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Header field 'mz' is negative" in print_output
    
    def test_negative_ispg(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.ispg = -10
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Header field 'ispg' is negative" in print_output
    
    def test_negative_nlabl(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.nlabl = -3
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Header field 'nlabl' is negative" in print_output
    
    def test_negative_cella_x(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.cella.x = -10
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Cell dimension 'x' is negative" in print_output
    
    def test_invalid_axis_mapping(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.mapc = 3
            mrc.header.mapr = 4
            mrc.header.maps = -200
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Invalid axis mapping: found [-200, 3, 4]" in print_output
    
    def test_mz_for_volume_stack(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(120, dtype=np.float32).reshape(3, 2, 4, 5))
            mrc.header.mz = 5
        with warnings.catch_warnings(record=True):
            result = mrcfile.validate(self.temp_mrc_name,
                                      print_file=self.print_stream)
            assert result == False
            print_output = self.print_stream.getvalue()
            assert ("Error in dimensions for volume stack: nz should be "
                    "divisible by mz. Found nz = 6, mz = 5" in print_output)
    
    def test_nlabl_too_large(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.label[1] = 'test label'
            mrc.header.nlabl = 3
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert ("Error in header labels: "
                "nlabl is 3 but 2 labels contain text" in print_output)
    <commit_msg>Add test for correct mz in volume stack validation<commit_after># Copyright (c) 2016, Science and Technology Facilities Council
# This software is distributed under a BSD licence. See LICENSE.txt.

"""
Tests for mrcfile __init__.py validate function.
"""

# Import Python 3 features for future-proofing
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import io
import os
import shutil
import tempfile
import unittest
import warnings

import numpy as np

import mrcfile
from . import helpers


class ValidationTest(helpers.AssertRaisesRegexMixin, unittest.TestCase):
    
    """Unit tests for MRC validation function.
    
    """
    
    def setUp(self):
        super(ValidationTest, self).setUp()
        
        # Set up test files and names to be used
        self.test_data = helpers.get_test_data_path()
        self.test_output = tempfile.mkdtemp()
        self.temp_mrc_name = os.path.join(self.test_output, 'test_mrcfile.mrc')
        self.example_mrc_name = os.path.join(self.test_data, 'EMD-3197.map')
        self.gzip_mrc_name = os.path.join(self.test_data, 'emd_3197.map.gz')
        self.ext_header_mrc_name = os.path.join(self.test_data, 'EMD-3001.map')
        
        # Set up stream to catch print output from validate()
        self.print_stream = io.StringIO()
    
    def tearDown(self):
        self.print_stream.close()
        if os.path.exists(self.test_output):
            shutil.rmtree(self.test_output)
        super(ValidationTest, self).tearDown()
    
    def test_good_file(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(36, dtype=np.float32).reshape(3, 3, 4))
            mrc.voxel_size = 2.3
        result = mrcfile.validate(self.temp_mrc_name, self.print_stream)
        assert result == True
        print_output = self.print_stream.getvalue()
        assert len(print_output) == 0
    
    def test_emdb_file(self):
        result = mrcfile.validate(self.example_mrc_name, self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert print_output.strip() == ("File does not declare MRC format "
                                        "version 20140: nversion = 0")
    
    def test_gzip_emdb_file(self):
        result = mrcfile.validate(self.gzip_mrc_name, self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert print_output.strip() == ("File does not declare MRC format "
                                        "version 20140: nversion = 0")
    
    def test_emdb_cryst_file(self):
        result = mrcfile.validate(self.ext_header_mrc_name, self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert print_output.strip() == ("File does not declare MRC format "
                                        "version 20140: nversion = 0\n"
                                        "Extended header type is undefined or "
                                        "unrecognised: exttyp = ''")
    
    def test_incorrect_map_id(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.map = b'fake'
        with self.assertRaisesRegex(ValueError, "Map ID string not found"):
            mrcfile.validate(self.temp_mrc_name)
    
    def test_incorrect_machine_stamp(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.machst = bytearray(b'    ')
        with self.assertRaisesRegex(ValueError, "Unrecognised machine stamp"):
            mrcfile.validate(self.temp_mrc_name)
    
    def test_invalid_mode(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(12, dtype=np.float32).reshape(1, 3, 4))
            mrc.header.mode = 8
        with self.assertRaisesRegex(ValueError, "Unrecognised mode"):
            mrcfile.validate(self.temp_mrc_name)
    
    def test_file_too_small(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(12, dtype=np.float32).reshape(1, 3, 4))
            mrc.header.nz = 2
        with self.assertRaisesRegex(ValueError, "Expected \d+ bytes but could only read \d+"):
            mrcfile.validate(self.temp_mrc_name)
    
    def test_file_too_large(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(36, dtype=np.float32).reshape(3, 3, 4))
            mrc.header.nz = 2
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            result = mrcfile.validate(self.temp_mrc_name,
                                      print_file=self.print_stream)
            assert result == False
            print_output = self.print_stream.getvalue()
            assert "larger than expected" in print_output
            assert len(w) == 1
            assert issubclass(w[0].category, RuntimeWarning)
            assert "larger than expected" in str(w[0].message)
    
    def test_negative_mx(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.mx = -10
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Header field 'mx' is negative" in print_output
    
    def test_negative_my(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.my = -10
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Header field 'my' is negative" in print_output
    
    def test_negative_mz(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.mz = -10
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Header field 'mz' is negative" in print_output
    
    def test_negative_ispg(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.ispg = -10
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Header field 'ispg' is negative" in print_output
    
    def test_negative_nlabl(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.nlabl = -3
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Header field 'nlabl' is negative" in print_output
    
    def test_negative_cella_x(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.cella.x = -10
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Cell dimension 'x' is negative" in print_output
    
    def test_invalid_axis_mapping(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.mapc = 3
            mrc.header.mapr = 4
            mrc.header.maps = -200
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert "Invalid axis mapping: found [-200, 3, 4]" in print_output
    
    def test_mz_correct_for_volume_stack(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(120, dtype=np.float32).reshape(3, 2, 4, 5))
        with warnings.catch_warnings(record=True):
            result = mrcfile.validate(self.temp_mrc_name,
                                      print_file=self.print_stream)
            assert result == True
    
    def test_mz_incorrect_for_volume_stack(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.set_data(np.arange(120, dtype=np.float32).reshape(3, 2, 4, 5))
            mrc.header.mz = 5
        with warnings.catch_warnings(record=True):
            result = mrcfile.validate(self.temp_mrc_name,
                                      print_file=self.print_stream)
            assert result == False
            print_output = self.print_stream.getvalue()
            assert ("Error in dimensions for volume stack: nz should be "
                    "divisible by mz. Found nz = 6, mz = 5" in print_output)
    
    def test_nlabl_too_large(self):
        with mrcfile.new(self.temp_mrc_name) as mrc:
            mrc.header.label[1] = 'test label'
            mrc.header.nlabl = 3
        result = mrcfile.validate(self.temp_mrc_name,
                                  print_file=self.print_stream)
        assert result == False
        print_output = self.print_stream.getvalue()
        assert ("Error in header labels: "
                "nlabl is 3 but 2 labels contain text" in print_output)
    
{'fraction_non_alphanumeric': 0.08937633000491078, 'fraction_numerical': 0.012386097015332569, 'mean_word_length': 2.1048619346095205, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 31, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3186832', 'n_tokens_mistral': 5791, 'n_tokens_neox': 5601, 'n_words': 1181}