diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index aa15879bf..e60459489 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -1233,6 +1233,7 @@ class Orientation(Rotation): array([[ 0.000, 0.000, 0.000], [ 0.577, -0.000, 0.816], [ 0.000, 0.000, 0.000]]) + """ d = self.to_frame(uvw=self.kinematics[mode]['direction'],with_symmetry=False) p = self.to_frame(hkl=self.kinematics[mode]['plane'] ,with_symmetry=False) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index a77c40ca5..60dd055c6 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -682,7 +682,7 @@ class Rotation: @staticmethod def from_random(shape = None, - seed = None, + rng_seed = None, **kwargs): """ Draw random rotation. @@ -694,12 +694,12 @@ class Rotation: shape : tuple of ints, optional Shape of the sample. Defaults to None which gives a single rotation - seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None. If None, then fresh, unpredictable entropy will be pulled from the OS. """ - rng = np.random.default_rng(seed) + rng = np.random.default_rng(rng_seed) r = rng.random(3 if shape is None else tuple(shape)+(3,) if hasattr(shape, '__iter__') else (shape,3)) A = np.sqrt(r[...,2]) @@ -718,7 +718,7 @@ class Rotation: N = 500, degrees = True, fractions = True, - seed = None, + rng_seed = None, **kwargs): """ Sample discrete values from a binned ODF. @@ -737,7 +737,7 @@ class Rotation: fractions : boolean, optional ODF values correspond to volume fractions, not probability density. Defaults to True. - seed: {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed: {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None, i.e. unpredictable entropy will be pulled from the OS. @@ -768,7 +768,7 @@ class Rotation: dg = 1.0 if fractions else _dg(Eulers,degrees) dV_V = dg * np.maximum(0.0,weights.squeeze()) - return Rotation.from_Eulers(Eulers[util.hybrid_IA(dV_V,N,seed)],degrees) + return Rotation.from_Eulers(Eulers[util.hybrid_IA(dV_V,N,rng_seed)],degrees) @staticmethod @@ -776,7 +776,7 @@ class Rotation: sigma, N = 500, degrees = True, - seed = None, + rng_seed = None, **kwargs): """ Calculate set of rotations with Gaussian distribution around center. @@ -791,12 +791,12 @@ class Rotation: Number of samples, defaults to 500. degrees : boolean, optional sigma is given in degrees. - seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None, i.e. unpredictable entropy will be pulled from the OS. """ - rng = np.random.default_rng(seed) + rng = np.random.default_rng(rng_seed) sigma = np.radians(sigma) if degrees else sigma u,Theta = (rng.random((N,2)) * 2.0 * np.array([1,np.pi]) - np.array([1.0, 0])).T omega = abs(rng.normal(scale=sigma,size=N)) @@ -813,7 +813,7 @@ class Rotation: sigma = 0.0, N = 500, degrees = True, - seed = None, + rng_seed = None, **kwargs): """ Calculate set of rotations with Gaussian distribution around direction. @@ -831,12 +831,12 @@ class Rotation: Number of samples, defaults to 500. degrees : boolean, optional sigma, alpha, and beta are given in degrees. - seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None, i.e. unpredictable entropy will be pulled from the OS. """ - rng = np.random.default_rng(seed) + rng = np.random.default_rng(rng_seed) sigma_,alpha_,beta_ = map(np.radians,(sigma,alpha,beta)) if degrees else (sigma,alpha,beta) d_cr = np.array([np.sin(alpha_[0])*np.cos(alpha_[1]), np.sin(alpha_[0])*np.sin(alpha_[1]), np.cos(alpha_[0])]) diff --git a/python/damask/seeds.py b/python/damask/seeds.py index 9aab953d0..717fc620b 100644 --- a/python/damask/seeds.py +++ b/python/damask/seeds.py @@ -5,7 +5,7 @@ from . import util from . import grid_filters -def from_random(size,N_seeds,grid=None,seed=None): +def from_random(size,N_seeds,grid=None,rng_seed=None): """ Random seeding in space. @@ -18,12 +18,12 @@ def from_random(size,N_seeds,grid=None,seed=None): grid : numpy.ndarray of shape (3), optional. If given, ensures that all seeds initiate one grain if using a standard Voronoi tessellation. - seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None. If None, then fresh, unpredictable entropy will be pulled from the OS. """ - rng = _np.random.default_rng(seed) + rng = _np.random.default_rng(rng_seed) if grid is None: coords = rng.random((N_seeds,3)) * size else: @@ -34,7 +34,7 @@ def from_random(size,N_seeds,grid=None,seed=None): return coords -def from_Poisson_disc(size,N_seeds,N_candidates,distance,periodic=True,seed=None): +def from_Poisson_disc(size,N_seeds,N_candidates,distance,periodic=True,rng_seed=None): """ Seeding in space according to a Poisson disc distribution. @@ -50,12 +50,12 @@ def from_Poisson_disc(size,N_seeds,N_candidates,distance,periodic=True,seed=None Minimum acceptable distance to other seeds. periodic : boolean, optional Calculate minimum distance for periodically repeated grid. - seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional A seed to initialize the BitGenerator. Defaults to None. If None, then fresh, unpredictable entropy will be pulled from the OS. """ - rng = _np.random.default_rng(seed) + rng = _np.random.default_rng(rng_seed) coords = _np.empty((N_seeds,3)) coords[0] = rng.random(3) * size diff --git a/python/damask/util.py b/python/damask/util.py index 49e85c9f5..fb122bd11 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -42,7 +42,7 @@ def srepr(arg,glue = '\n'): arg : iterable Items to join. glue : str, optional - Defaults to \n. + Glue used for joining operation. Defaults to \n. """ if (not hasattr(arg, "strip") and @@ -163,7 +163,15 @@ def show_progress(iterable,N_iter=None,prefix='',bar_length=50): def scale_to_coprime(v): - """Scale vector to co-prime (relatively prime) integers.""" + """ + Scale vector to co-prime (relatively prime) integers. + + Parameters + ---------- + v : numpy.ndarray of shape (:) + Vector to scale. + + """ MAX_DENOMINATOR = 1000000 def get_square_denominator(x): @@ -214,7 +222,21 @@ def execution_stamp(class_name,function_name=None): return f'damask.{class_name}{_function_name} v{version} ({now})' -def hybrid_IA(dist,N,seed=None): +def hybrid_IA(dist,N,rng_seed=None): + """ + Hybrid integer approximation. + + Parameters + ---------- + dist : numpy.ndarray + Distribution to be approximated + N : int + Number of samples to draw. + rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional + A seed to initialize the BitGenerator. Defaults to None. + If None, then fresh, unpredictable entropy will be pulled from the OS. + + """ N_opt_samples,N_inv_samples = (max(np.count_nonzero(dist),N),0) # random subsampling if too little samples requested scale_,scale,inc_factor = (0.0,float(N_opt_samples),1.0) @@ -225,7 +247,7 @@ def hybrid_IA(dist,N,seed=None): if N_inv_samples < N_opt_samples else \ (scale_,0.5*(scale_ + scale), 1.0) - return np.repeat(np.arange(len(dist)),repeats)[np.random.default_rng(seed).permutation(N_inv_samples)[:N]] + return np.repeat(np.arange(len(dist)),repeats)[np.random.default_rng(rng_seed).permutation(N_inv_samples)[:N]] def shapeshifter(fro,to,mode='left',keep_ones=False): diff --git a/python/tests/conftest.py b/python/tests/conftest.py index f402c4614..9410ba15a 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -18,6 +18,7 @@ def patch_damask_version(monkeypatch): """Set damask.version for reproducible tests results.""" monkeypatch.setattr(damask, 'version', patched_version) + patched_date = datetime.datetime(2019, 11, 2, 11, 58, 0) @pytest.fixture def patch_datetime_now(monkeypatch): @@ -29,6 +30,7 @@ def patch_datetime_now(monkeypatch): monkeypatch.setattr(datetime, 'datetime', mydatetime) + @pytest.fixture def patch_execution_stamp(monkeypatch): """Set damask.util.execution_stamp for reproducible tests results.""" @@ -38,6 +40,7 @@ def patch_execution_stamp(monkeypatch): monkeypatch.setattr(damask.util, 'execution_stamp', execution_stamp) + @pytest.fixture def patch_plt_show(monkeypatch): def _None(block=None): @@ -50,16 +53,19 @@ def pytest_addoption(parser): action="store_true", default=False) + @pytest.fixture def update(request): """Store current results as new reference results.""" return request.config.getoption("--update") + @pytest.fixture def reference_dir_base(): """Directory containing reference results.""" return Path(__file__).parent/'reference' + @pytest.fixture def set_of_quaternions(): """A set of n random rotations.""" diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index fe35bda14..3e6aad134 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -125,9 +125,9 @@ class TestOrientation: def test_from_fiber_component(self): r = Rotation.from_fiber_component(alpha=np.zeros(2),beta=np.zeros(2), - sigma=0.0,N=1,seed=0) + sigma=0.0,N=1,rng_seed=0) assert np.all(Orientation.from_fiber_component(alpha=np.zeros(2),beta=np.zeros(2), - sigma=0.0,N=1,seed=0,lattice='triclinic').quaternion + sigma=0.0,N=1,rng_seed=0,lattice='triclinic').quaternion == r.quaternion) @pytest.mark.parametrize('kwargs',[ @@ -175,8 +175,8 @@ class TestOrientation: @pytest.mark.parametrize('lattice',Orientation.crystal_families) @pytest.mark.parametrize('N',[1,8,32]) def test_disorientation(self,lattice,N): - o = Orientation.from_random(lattice=lattice,shape=N,seed=0) - p = Orientation.from_random(lattice=lattice,shape=N,seed=1) + o = Orientation.from_random(lattice=lattice,shape=N) + p = Orientation.from_random(lattice=lattice,shape=N) d,ops = o.disorientation(p,return_operators=True) @@ -198,8 +198,8 @@ class TestOrientation: (None,None), ]) def test_disorientation_blending(self,lattice,a,b): - o = Orientation.from_random(lattice=lattice,shape=a,seed=0) - p = Orientation.from_random(lattice=lattice,shape=b,seed=1) + o = Orientation.from_random(lattice=lattice,shape=a) + p = Orientation.from_random(lattice=lattice,shape=b) blend = util.shapeblender(o.shape,p.shape) for loc in np.random.randint(0,blend,(10,len(blend))): assert o[tuple(loc[:len(o.shape)])].disorientation(p[tuple(loc[-len(p.shape):])]) \ @@ -214,7 +214,7 @@ class TestOrientation: @pytest.mark.parametrize('lattice',Orientation.crystal_families) @pytest.mark.parametrize('shape',[(1),(2,3),(4,3,2)]) def test_reduced_vectorization(self,lattice,shape): - o = Orientation.from_random(lattice=lattice,shape=shape,seed=0) + o = Orientation.from_random(lattice=lattice,shape=shape) for r, theO in zip(o.reduced.flatten(),o.flatten()): assert r == theO.reduced @@ -223,7 +223,7 @@ class TestOrientation: @pytest.mark.parametrize('vector',np.array([[1,0,0],[1,2,3],[-1,1,-1]])) @pytest.mark.parametrize('proper',[True,False]) def test_to_SST_vectorization(self,lattice,shape,vector,proper): - o = Orientation.from_random(lattice=lattice,shape=shape,seed=0) + o = Orientation.from_random(lattice=lattice,shape=shape) for r, theO in zip(o.to_SST(vector=vector,proper=proper).reshape((-1,3)),o.flatten()): assert np.allclose(r,theO.to_SST(vector=vector,proper=proper)) @@ -232,7 +232,7 @@ class TestOrientation: @pytest.mark.parametrize('vector',np.array([[1,0,0],[1,2,3],[-1,1,-1]])) @pytest.mark.parametrize('proper',[True,False]) def test_IPF_color_vectorization(self,lattice,shape,vector,proper): - o = Orientation.from_random(lattice=lattice,shape=shape,seed=0) + o = Orientation.from_random(lattice=lattice,shape=shape) poles = o.to_SST(vector=vector,proper=proper) for r, theO in zip(o.IPF_color(poles,proper=proper).reshape((-1,3)),o.flatten()): assert np.allclose(r,theO.IPF_color(theO.to_SST(vector=vector,proper=proper),proper=proper)) @@ -245,7 +245,7 @@ class TestOrientation: (None,(3,)), ]) def test_to_SST_blending(self,lattice,a,b): - o = Orientation.from_random(lattice=lattice,shape=a,seed=0) + o = Orientation.from_random(lattice=lattice,shape=a) v = np.random.random(b+(3,)) blend = util.shapeblender(o.shape,b) for loc in np.random.randint(0,blend,(10,len(blend))): diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index fe30726e3..fe90e2aea 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -778,7 +778,7 @@ class TestRotation: assert r.shape == shape def test_equal(self): - assert Rotation.from_random(seed=1) == Rotation.from_random(seed=1) + assert Rotation.from_random(rng_seed=1) == Rotation.from_random(rng_seed=1) def test_inversion(self): r = Rotation.from_random()