"""
BornAgain functional test.
Transform invariance of a box in the middle layer of a 3-layer system:
Box(50,20,10) rotated around Z then Y reaches the orientation of Box(10,50,20),
so the two must scatter identically.
"""

import unittest
import PyFuTestInfrastructure as infrastruct
from bornagain import *

layer_thickness = 100.0


class BoxTransformationsTest(unittest.TestCase):

    def get_sample(self, particle):
        mAmbience = Vacuum()
        mMiddle = RefractiveMaterial("Teflon", (0.70, 0.73, 0.78), 2.900e-6,
                                     6.019e-9)
        mSubstrate = RefractiveMaterial("Substrate", (0.55, 0.55, 0.55),
                                        3.212e-6, 3.244e-8)

        vacuum_layer = Layer(mAmbience)
        middle_layer = Layer(mMiddle, layer_thickness)
        middle_layer.deposit2D(Dilute2D(0.001, particle))
        substrate = Layer(mSubstrate)

        sample = Sample()
        sample.addLayer(vacuum_layer)
        sample.addLayer(middle_layer)
        sample.addLayer(substrate)
        return sample

    def get_result(self, particle):
        sample = self.get_sample(particle)
        simulation = infrastruct.get_simulation_MiniGISAS(sample)
        simulation.options().setUseAvgMaterials(False)
        return simulation.simulate()

    def testBoxTransform(self):
        """
        Reference box (10,50,20) is compared against box (50,20,10) rotated
        Z then Y into the same orientation, both at the layer midplane.
        """
        mParticle = RefractiveMaterial("Ag", (0.86, 0.24, 0.18), 1.245e-5,
                                       5.419e-7)

        # reference box, centered at the layer midplane
        height = 20
        box = Particle(mParticle, Box(10, 50, height))
        box.translate(R3(0, 0, -layer_thickness / 2 - height / 2))
        reference = self.get_result(box)

        # box that reaches the reference orientation after two rotations
        box = Particle(mParticle, Box(50, 20, 10))
        box.rotate(RotationZ(90 * deg))
        box.rotate(RotationY(90 * deg))
        box.translate(R3(0, 0, -layer_thickness / 2))

        data = self.get_result(box)

        self.assertTrue(checkRelativeDifference(data, reference, 1e-10))


if __name__ == '__main__':
    unittest.main()
