class TestHollowCylinder(unittest.TestCase):
    """ Unit tests for calculate_ER (Hollowcylinder model) """
    def setUp(self):
        from sas.models.HollowCylinderModel import HollowCylinderModel
        from sas.models.DiamCylFunc import DiamCylFunc
        self.comp = HollowCylinderModel()
        self.diam = DiamCylFunc()

    def test(self):
        """ Test 1D model for a Hollowcylinder """
        self.comp.setParam("radius", 20)
        self.comp.setParam("length", 400)
        self.diam.setParam("radius", 20)
        self.diam.setParam("length", 400)
        self.assertAlmostEqual(self.comp.calculate_ER(),
                               self.diam.run(0.1) / 2)
class TestHollowCylinder(unittest.TestCase):
    """ Unit tests for calculate_ER (Hollowcylinder model) """
    
    def setUp(self):
        from sas.models.HollowCylinderModel import HollowCylinderModel
        from sas.models.DiamCylFunc import DiamCylFunc
        self.comp = HollowCylinderModel()
        self.diam = DiamCylFunc()
        
    def test(self):
        """ Test 1D model for a Hollowcylinder """
        self.comp.setParam("radius", 20)
        self.comp.setParam("length",400)
        self.diam.setParam("radius", 20)
        self.diam.setParam("length",400)       
        self.assertAlmostEqual(self.comp.calculate_ER(), self.diam.run(0.1)/2)        
class TestCoreShellCylinder(unittest.TestCase):
    """ Unit tests for calculate_ER (CoreShellcylinder model) """
    def setUp(self):
        from sas.models.CoreShellCylinderModel import CoreShellCylinderModel
        from sas.models.DiamCylFunc import DiamCylFunc
        self.comp = CoreShellCylinderModel()
        self.diam = DiamCylFunc()

    def test(self):
        """ Test 1D model for a CoreShellCylinder """
        self.comp.setParam("radius", 20)
        self.comp.setParam("thickness", 10)
        self.comp.setParam("length", 400)
        self.diam.setParam("radius", 30)
        self.diam.setParam("length", 420)
        self.assertAlmostEqual(self.comp.calculate_ER(),
                               self.diam.run(0.1) / 2)
class TestCoreShellCylinder(unittest.TestCase):
    """ Unit tests for calculate_ER (CoreShellcylinder model) """
    
    def setUp(self):
        from sas.models.CoreShellCylinderModel import CoreShellCylinderModel
        from sas.models.DiamCylFunc import DiamCylFunc
        self.comp = CoreShellCylinderModel()
        self.diam = DiamCylFunc()
        
    def test(self):
        """ Test 1D model for a CoreShellCylinder """
        self.comp.setParam("radius", 20)
        self.comp.setParam("thickness", 10)
        self.comp.setParam("length",400)
        self.diam.setParam("radius", 30)
        self.diam.setParam("length",420)       
        self.assertAlmostEqual(self.comp.calculate_ER(), self.diam.run(0.1)/2)   
class TestParallelepiped(unittest.TestCase):
    """ Unit tests for calculate_ER (Parallelepipedmodel) """
    def setUp(self):
        from sas.models.ParallelepipedModel import ParallelepipedModel
        from sas.models.DiamCylFunc import DiamCylFunc
        self.comp = ParallelepipedModel()
        self.diam = DiamCylFunc()

    def test(self):
        """ Test 1D model for a Parallelepiped """
        self.comp.setParam("short_a", 35)
        self.comp.setParam("short_b", 75)
        self.comp.setParam("long_c", 400)
        r_value = math.sqrt(35 * 75 / math.pi)
        self.diam.setParam("radius", r_value)
        self.diam.setParam("length", 400)
        self.assertAlmostEqual(self.comp.calculate_ER(),
                               self.diam.run(0.1) / 2)
class TestEllipticalCylinder(unittest.TestCase):
    """ Unit tests for calculate_ER (EllipticalCylindermodel) """
    def setUp(self):
        from sas.models.EllipticalCylinderModel import EllipticalCylinderModel
        from sas.models.DiamCylFunc import DiamCylFunc
        self.comp = EllipticalCylinderModel()
        self.diam = DiamCylFunc()

    def test(self):
        """ Test 1D model for a EllipticalCylinder """
        self.comp.setParam("r_minor", 20)
        self.comp.setParam("r_ratio", 1.5)
        self.comp.setParam("length", 400)
        r_value = math.sqrt(20 * 20 * 1.5)
        self.diam.setParam("radius", r_value)
        self.diam.setParam("length", 400)
        self.assertAlmostEqual(self.comp.calculate_ER(),
                               self.diam.run(0.1) / 2)
class TestStackedDisksModel(unittest.TestCase):
    """ Unit tests for calculate_ER (StackedDisks model) """
    def setUp(self):
        from sas.models.StackedDisksModel import StackedDisksModel
        from sas.models.DiamCylFunc import DiamCylFunc
        self.comp = StackedDisksModel()
        self.diam = DiamCylFunc()

    def test(self):
        """ Test 1D model for a StackedDisks """
        self.comp.setParam("radius", 3000)
        self.comp.setParam("n_stacking", 2)
        self.comp.setParam("core_thick", 10)
        self.comp.setParam("layer_thick", 15)
        self.diam.setParam("radius", 3000)
        self.diam.setParam("length", 80)
        self.assertAlmostEqual(self.comp.calculate_ER(),
                               self.diam.run(0.1) / 2)
class TestParallelepiped(unittest.TestCase):
    """ Unit tests for calculate_ER (Parallelepipedmodel) """
    
    def setUp(self):
        from sas.models.ParallelepipedModel import ParallelepipedModel
        from sas.models.DiamCylFunc import DiamCylFunc
        self.comp = ParallelepipedModel()
        self.diam = DiamCylFunc()
        
    def test(self):
        """ Test 1D model for a Parallelepiped """
        self.comp.setParam("short_a", 35)
        self.comp.setParam("short_b", 75)  
        self.comp.setParam("long_c",400)  
        r_value = math.sqrt(35*75/math.pi)    
        self.diam.setParam("radius", r_value)
        self.diam.setParam("length",400)   
        self.assertAlmostEqual(self.comp.calculate_ER(), self.diam.run(0.1)/2)   
class TestEllipticalCylinder(unittest.TestCase):
    """ Unit tests for calculate_ER (EllipticalCylindermodel) """
    
    def setUp(self):
        from sas.models.EllipticalCylinderModel import EllipticalCylinderModel
        from sas.models.DiamCylFunc import DiamCylFunc
        self.comp = EllipticalCylinderModel()
        self.diam = DiamCylFunc()
        
    def test(self):
        """ Test 1D model for a EllipticalCylinder """
        self.comp.setParam("r_minor", 20)
        self.comp.setParam("r_ratio",1.5)  
        self.comp.setParam("length",400)  
        r_value = math.sqrt(20*20*1.5)    
        self.diam.setParam("radius", r_value)
        self.diam.setParam("length",400)       
        self.assertAlmostEqual(self.comp.calculate_ER(), self.diam.run(0.1)/2)  
class TestStackedDisksModel(unittest.TestCase):
    """ Unit tests for calculate_ER (StackedDisks model) """
    
    def setUp(self):
        from sas.models.StackedDisksModel import StackedDisksModel
        from sas.models.DiamCylFunc import DiamCylFunc
        self.comp = StackedDisksModel()
        self.diam = DiamCylFunc()
        
    def test(self):
        """ Test 1D model for a StackedDisks """
        self.comp.setParam("radius", 3000)
        self.comp.setParam("n_stacking", 2)
        self.comp.setParam("core_thick",10)
        self.comp.setParam("layer_thick", 15)
        self.diam.setParam("radius", 3000)
        self.diam.setParam("length",80)       
        self.assertAlmostEqual(self.comp.calculate_ER(), self.diam.run(0.1)/2)  
class TestcylinderHayterM(unittest.TestCase):
    """ 
        Unit tests for CylinderModel(Q) * HayterMSAStructure(Q)
    """
    def setUp(self):
        from sas.models.CylinderModel import CylinderModel
        from sas.models.HayterMSAStructure import HayterMSAStructure
        from sas.models.DiamCylFunc import DiamCylFunc
        from sas.models.MultiplicationModel import MultiplicationModel

        self.model = CylinderModel()
        self.model2 = HayterMSAStructure()
        self.model3 = MultiplicationModel(self.model, self.model2)  
        self.modelD = DiamCylFunc()

    #Radius of model1.calculate_ER should be equal to the output/2 of DiamFunctions
    def test_multplication_radius(self):
        """
            test multiplication model (check the effective radius & the output
             of the multiplication)
        """
        self.model.setParam("radius", 60)
        self.modelD.setParam("radius", 60)
        modelDrun = self.modelD.run(0.1)/2
        self.model2.setParam("volfraction", 0.2)
        self.model2.setParam("effect_radius", modelDrun )
        
        #Compare new method with old method         
        self.assertEqual(self.model3.run(0.1), self.model.run(0.1)*self.model2.run(0.1))
        
        #Compare radius from two different calculations. Note: modelD.run(0.0) is DIAMETER
        self.assertEqual(self.model.calculate_ER(), modelDrun)
        
        
    def testMultiplicationParam(self):
        """ Test Multiplication  (check the parameters)"""
        ## test details dictionary

        ## test parameters list
        list3= self.model3.getParamList()

        for item in self.model.getParamList():
            if not 'scale' in item:  
                self.assert_(item in list3)
        for item in self.model2.getParamList():
            #model3 parameters should not include effect_radius*
            if not 'effect_radius' in item:  
                self.assert_(item in list3)
            
        ## test set value for parameters and get paramaters
        #self.model3.setParam("scale", 15)
        #self.assertEqual(self.model3.getParam("scale"), 15)
        self.model3.setParam("scale_factor", 15)
        self.assertEqual(self.model3.getParam("scale_factor"), 15)
        self.model3.setParam("radius", 20)
        self.assertEqual(self.model3.getParam("radius"), 20)
        self.model3.setParam("radius.width", 15)
        self.assertEqual(self.model3.getParam("radius.width"), 15)
        self.model3.setParam("scale_factor", 15)
        self.assertEqual(self.model3.getParam("scale_factor"), 15)
        self.assertEqual(self.model3.getParam("volfraction"), self.model.getParam("scale"))
        
        ## Dispersity 
        list3= self.model3.getDispParamList()
        self.assertEqual(list3, ['radius.npts', 'radius.nsigmas', 'radius.width', 'length.npts', \
         'length.nsigmas', 'length.width', 'cyl_theta.npts', 'cyl_theta.nsigmas', 'cyl_theta.width',\
          'cyl_phi.npts', 'cyl_phi.nsigmas', 'cyl_phi.width'])
        
        from sas.models.dispersion_models import ArrayDispersion
        disp_th = ArrayDispersion()
        
        values_th = numpy.zeros(100)
        weights   = numpy.zeros(100)
        for i in range(100):
            values_th[i]=(math.pi/99.0*i)
            weights[i]=(1.0)
    
        disp_th.set_weights(values_th, weights)
        
        self.model3.set_dispersion('radius', disp_th)        

        model4= self.model3.clone()
        self.assertEqual(model4.getParam("radius"), 20)        
class TestcylinderHayterM(unittest.TestCase):
    """ 
        Unit tests for CylinderModel(Q) * HayterMSAStructure(Q)
    """
    def setUp(self):
        from sas.models.CylinderModel import CylinderModel
        from sas.models.HayterMSAStructure import HayterMSAStructure
        from sas.models.DiamCylFunc import DiamCylFunc
        from sas.models.MultiplicationModel import MultiplicationModel

        self.model = CylinderModel()
        self.model2 = HayterMSAStructure()
        self.model3 = MultiplicationModel(self.model, self.model2)  
        self.modelD = DiamCylFunc()

    #Radius of model1.calculate_ER should be equal to the output/2 of DiamFunctions
    def test_multplication_radius(self):
        """
            test multiplication model (check the effective radius & the output
             of the multiplication)
        """
        self.model.setParam("radius", 60)
        self.modelD.setParam("radius", 60)
        modelDrun = self.modelD.run(0.1)/2
        self.model2.setParam("volfraction", 0.2)
        self.model2.setParam("effect_radius", modelDrun )
        
        #Compare new method with old method         
        self.assertEqual(self.model3.run(0.1), self.model.run(0.1)*self.model2.run(0.1))
        
        #Compare radius from two different calculations. Note: modelD.run(0.0) is DIAMETER
        self.assertEqual(self.model.calculate_ER(), modelDrun)
        
        
    def testMultiplicationParam(self):
        """ Test Multiplication  (check the parameters)"""
        ## test details dictionary

        ## test parameters list
        list3= self.model3.getParamList()

        for item in self.model.getParamList():
            if not 'scale' in item:  
                self.assert_(item in list3)
        for item in self.model2.getParamList():
            #model3 parameters should not include effect_radius*
            if not 'effect_radius' in item:  
                self.assert_(item in list3)
            
        ## test set value for parameters and get paramaters
        #self.model3.setParam("scale", 15)
        #self.assertEqual(self.model3.getParam("scale"), 15)
        self.model3.setParam("scale_factor", 15)
        self.assertEqual(self.model3.getParam("scale_factor"), 15)
        self.model3.setParam("radius", 20)
        self.assertEqual(self.model3.getParam("radius"), 20)
        self.model3.setParam("radius.width", 15)
        self.assertEqual(self.model3.getParam("radius.width"), 15)
        self.model3.setParam("scale_factor", 15)
        self.assertEqual(self.model3.getParam("scale_factor"), 15)
        self.assertEqual(self.model3.getParam("volfraction"), self.model.getParam("scale"))
        
        ## Dispersity 
        list3= self.model3.getDispParamList()
        self.assertEqual(list3, ['radius.npts', 'radius.nsigmas', 'radius.width', 'length.npts', \
         'length.nsigmas', 'length.width', 'cyl_theta.npts', 'cyl_theta.nsigmas', 'cyl_theta.width',\
          'cyl_phi.npts', 'cyl_phi.nsigmas', 'cyl_phi.width'])
        
        from sas.models.dispersion_models import ArrayDispersion
        disp_th = ArrayDispersion()
        
        values_th = numpy.zeros(100)
        weights   = numpy.zeros(100)
        for i in range(100):
            values_th[i]=(math.pi/99.0*i)
            weights[i]=(1.0)
    
        disp_th.set_weights(values_th, weights)
        
        self.model3.set_dispersion('radius', disp_th)        

        model4= self.model3.clone()
        self.assertEqual(model4.getParam("radius"), 20)