def test_multiplicity(self, nickel_phase, silicon_carbide_phase): assert np.allclose( ReciprocalLatticePoint.from_min_dspacing( phase=nickel_phase, min_dspacing=1 ).multiplicity, # fmt: off np.array([ 8, 24, 24, 24, 12, 24, 48, 48, 24, 24, 48, 24, 24, 24, 6, 8, 24, 24, 12, 24, 48, 24, 24, 24, 6, 8, 24, 12, 24, 24, 6, 8, 12, 6 ]) # fmt: on ) assert np.allclose( ReciprocalLatticePoint.from_min_dspacing( phase=silicon_carbide_phase, min_dspacing=1 ).multiplicity, # fmt: off np.array([ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1 ]) # fmt: on )
def _get_colors_for_allowed_bands( phase: Phase, highest_hkl: Union[List[int], np.ndarray, None] = None, color_cycle: Optional[List[str]] = None, ): """Return an array of Miller indices of allowed Kikuchi bands for a point group and a corresponding color. The idea with this function is to always get the same color for the same band in the same point group. Parameters ---------- phase A phase container with a space and point group describing the allowed symmetry operations. highest_hkl Highest Miller indices to consider. If None (default), [9, 9, 9] is used. color_cycle A list of color names recognized by Matplotlib. If None (default), a color palette based on EDAX TSL's coloring of bands is cycled through. Returns ------- hkl_color Array with Miller indices and corresponding colors of shape (nhkl, 2, 3), with hkl and color in index 0 and 1 along axis=1, respectively. """ if highest_hkl is None: highest_hkl = [9, 9, 9] rlp = ReciprocalLatticePoint.from_highest_hkl( phase=phase, highest_hkl=highest_hkl, ) rlp2 = rlp[rlp.allowed] # TODO: Replace this ordering with future ordering method in # diffsims g_order = np.argsort(rlp2.gspacing) new_hkl = np.atleast_2d(rlp2.hkl.data)[g_order] rlp3 = ReciprocalLatticePoint(phase=rlp.phase, hkl=new_hkl) hkl = np.atleast_2d(rlp3.hkl.data) families, families_idx = _get_hkl_family(hkl=hkl, reduce=True) if color_cycle is None: color_cycle = TSL_COLORS n_families = len(families) n_times = int(np.ceil(n_families / len(color_cycle))) colors = (color_cycle * n_times)[:n_families] colors = [mcolors.to_rgb(i) for i in colors] hkl_colors = np.zeros(shape=(rlp3.size, 2, 3)) for hkl_idx, color in zip(families_idx.values(), colors): hkl_colors[hkl_idx, 0] = hkl[hkl_idx] hkl_colors[hkl_idx, 1] = color return hkl_colors
def test_unique(self, ferrite_phase): hkl = [[-1, -1, -1], [1, 1, 1], [1, 0, 0], [0, 0, 1]] rlp = ReciprocalLatticePoint(phase=ferrite_phase, hkl=hkl) assert isinstance(rlp.unique(), ReciprocalLatticePoint) assert np.allclose(rlp.unique(use_symmetry=False).hkl.data, hkl) assert np.allclose( rlp.unique(use_symmetry=True).hkl.data, [[1, 1, 1], [1, 0, 0]] )
def test_many_zone_axes_labels_as_markers( self, nickel_ebsd_simulation_generator, nickel_phase ): simgen = nickel_ebsd_simulation_generator rlp = ReciprocalLatticePoint( phase=nickel_phase, hkl=[[1, 1, 1], [2, 0, 0], [2, 2, 0], [3, 1, 1], [1, 2, 3]], ) rlp2 = rlp.symmetrise() sim = simgen.geometrical_simulation(rlp2) _ = sim.zone_axes_labels_as_markers()
def test_gspacing_dspacing_scattering_parameter(self, ferrite_phase): rlp = ReciprocalLatticePoint.from_min_dspacing( phase=ferrite_phase, min_dspacing=2 ) # fmt: off assert np.allclose( rlp.gspacing, np.array([ 1.2084778, 1.04657248, 0.98671799, 0.85452285, 0.78006907, 0.69771498, 0.604238, 0.493359, 0.34885749 ]) ) assert np.allclose( rlp.dspacing, np.array([ 0.82748727, 0.9555, 1.01346079, 1.17024372, 1.28193777, 1.43325, 1.65497455, 2.02692159, 2.8665 ]) ) assert np.allclose( rlp.scattering_parameter, np.array([ 0.6042389, 0.52328624, 0.493359, 0.42726142, 0.39003453, 0.34885749, 0.30211945, 0.2466795, 0.17442875 ]) )
def test_init_from_min_dspacing(self, ferrite_phase, min_dspacing, desired_size): assert ( ReciprocalLatticePoint.from_min_dspacing( phase=ferrite_phase, min_dspacing=min_dspacing ).size == desired_size )
def test_get_hkl(self, silicon_carbide_phase): rlp = ReciprocalLatticePoint.from_min_dspacing( silicon_carbide_phase, min_dspacing=3 ) assert np.allclose(rlp.h, [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]) assert np.allclose(rlp.k, [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]) assert np.allclose(rlp.l, [4, 3, 2, 1, 0, 4, 3, 2, 0, 4, 3, 2])
def test_repr(self, ferrite_phase): rlp = ReciprocalLatticePoint.from_min_dspacing(ferrite_phase, min_dspacing=2) assert repr(rlp) == ( f"ReciprocalLatticePoint (9,)\n" f"Phase: ferrite (m-3m)\n" "[[2 2 2]\n [2 2 1]\n [2 2 0]\n [2 1 1]\n [2 1 0]\n [2 0 0]\n [1 1 1]\n" " [1 1 0]\n [1 0 0]]" )
def test_symmetrise(self): assert np.allclose( ReciprocalLatticePoint(phase=Phase(space_group=225), hkl=[1, 1, 1]) .symmetrise() .hkl.data, np.array( [ [1, 1, 1], [-1, 1, 1], [-1, -1, 1], [1, -1, 1], [1, -1, -1], [1, 1, -1], [-1, 1, -1], [-1, -1, -1], ] ), ) rlp2, multiplicity = ReciprocalLatticePoint( phase=Phase(space_group=186), hkl=[2, 2, 0] ).symmetrise(return_multiplicity=True) assert multiplicity == 12 assert np.allclose( rlp2.hkl.data, [ [2, 2, 0], [-2, 0, 0], [0, -2, 0], [-2, -2, 0], [2, 0, 0], [0, 2, 0], [-2, 2, 0], [0, -2, 0], [2, 0, 0], [2, -2, 0], [0, 2, 0], [-2, 0, 0], ], ) rlp3 = ReciprocalLatticePoint( phase=Phase(space_group=186), hkl=[2, 2, 0] ).symmetrise(antipodal=False) assert np.allclose( rlp3.hkl.data, [[2, 2, 0], [-2, 0, 0], [0, -2, 0], [-2, -2, 0], [2, 0, 0], [0, 2, 0]], )
def test_allowed_b_centering(self): """B centering will never fire since no diffpy.structure space group has 'B' first in the name. """ phase = Phase(space_group=15) phase.space_group.short_name = "B" rlp = ReciprocalLatticePoint( phase=phase, hkl=[[1, 2, 2], [1, 1, -1], [1, 1, 2]] ) assert np.allclose(rlp.allowed, [False, True, False])
def test_init_rlp(self, nickel_phase, hkl): rlp = ReciprocalLatticePoint(phase=nickel_phase, hkl=hkl) assert rlp.phase.name == nickel_phase.name assert isinstance(rlp.hkl, Vector3d) assert rlp.structure_factor[0] is None assert rlp.theta[0] is None assert rlp.size == 2 assert rlp.shape == (2, 3) assert rlp.hkl[0].shape == (1,) assert rlp.hkl.data[0].shape == (3,) assert np.issubdtype(rlp.hkl.data.dtype, int)
def test_init_from_highest_hkl( self, silicon_carbide_phase, highest_hkl, desired_highest_hkl, desired_lowest_hkl, desired_size, ): rlp = ReciprocalLatticePoint.from_highest_hkl( phase=silicon_carbide_phase, highest_hkl=highest_hkl ) assert np.allclose(rlp[0].hkl.data, desired_highest_hkl) assert np.allclose(rlp[-1].hkl.data, desired_lowest_hkl) assert rlp.size == desired_size
def test_get_item(self, ferrite_phase): rlp = ReciprocalLatticePoint.from_min_dspacing( phase=ferrite_phase, min_dspacing=1.5 ) rlp.calculate_structure_factor() rlp.calculate_theta(voltage=20e3) assert rlp[0].size == 1 assert rlp[:2].size == 2 assert np.allclose(rlp[5:7].hkl.data, rlp.hkl[5:7].data) assert np.allclose(rlp[10:13].structure_factor, rlp.structure_factor[10:13]) assert np.allclose(rlp[20:23].theta, rlp.theta[20:23]) assert rlp.phase.space_group.number == rlp[0].phase.space_group.number assert rlp.phase.point_group.name == rlp[10:15].phase.point_group.name assert np.allclose( rlp.phase.structure.lattice.abcABG(), rlp[20:23].phase.structure.lattice.abcABG(), )
def geometrical_simulation( self, reciprocal_lattice_point: Optional[ReciprocalLatticePoint] = None, ) -> GeometricalEBSDSimulation: """Project a set of center positions of Kikuchi bands on the detector, one set for each rotation of the unit cell. Parameters ---------- reciprocal_lattice_point : Crystal planes to project onto the detector. If None, and the generator has a phase with a unit cell with a point group, a set of planes with minimum distance of 1 Å and their symmetrically equivalent planes are used. Returns ------- GeometricalEBSDSimulation Examples -------- >>> from diffsims.crystallography import ReciprocalLatticePoint >>> simgen EBSDSimulationGenerator (1,) EBSDDetector (60, 60), px_size 1 um, binning 1, tilt 0, pc (0.5, 0.5, 0.5) <name: . space group: None. point group: None. proper point group: None. color: tab:blue> Rotation (1,) >>> sim1 = simgen.geometrical_simulation() >>> sim1.bands.size 94 >>> rlp = ReciprocalLatticePoint( ... phase=simgen.phase, hkl=[[1, 1, 1], [2, 0, 0]] ... ) >>> sim2 = simgen.geometrical_simulation() >>> sim2.bands.size 13 """ rlp = reciprocal_lattice_point if rlp is None and (hasattr(self.phase.point_group, "name") and hasattr(self.phase.structure.lattice, "abcABG")): rlp = ReciprocalLatticePoint.from_min_dspacing(self.phase, min_dspacing=1) rlp = rlp[rlp.allowed].symmetrise() elif rlp is None: raise ValueError("A ReciprocalLatticePoint object must be passed") self._rlp_phase_is_compatible(rlp) # Unit cell parameters (called more than once) phase = rlp.phase hkl = rlp._hkldata # Get Kikuchi band coordinates for all bands in all patterns # U_Kstar, transformation from detector frame D to reciprocal crystal # lattice frame Kstar # TODO: Possible bottleneck due to large dot products! Room for # lots of improvements with dask. # Output shape is (3, n, 3) or (3, ny, nx, 3) det2recip = detector2reciprocal_lattice( sample_tilt=self.detector.sample_tilt, detector_tilt=self.detector.tilt, lattice=phase.structure.lattice, rotation=self.rotations, ) # Output shape is (nhkl, n, 3) or (nhkl, ny, nx, 3) band_coordinates = np.tensordot(hkl, det2recip, axes=(1, 0)) # Determine whether a band is visible in a pattern upper_hemisphere = band_coordinates[..., 2] > 0 nav_dim = self.navigation_dimension navigation_axes = (1, 2)[:nav_dim] is_in_some_pattern = np.sum(upper_hemisphere, axis=navigation_axes) != 0 # Get bands that were in some pattern and their coordinates in the # proper shape hkl = hkl[is_in_some_pattern, ...] hkl_in_pattern = upper_hemisphere[is_in_some_pattern, ...].T band_coordinates = np.moveaxis(band_coordinates[is_in_some_pattern], source=0, destination=nav_dim) # And store it all bands = KikuchiBand( phase=phase, hkl=hkl, hkl_detector=band_coordinates, in_pattern=hkl_in_pattern, gnomonic_radius=self.detector.r_max, ) # Get zone axes coordinates # U_K, transformation from detector frame D to direct crystal lattice # frame K # det2direct = detector2direct_lattice( # sample_tilt=self.detector.sample_tilt, # detector_tilt=self.detector.tilt, # lattice=phase.structure.lattice, # orientation=self.orientations, # ) # hkl_transposed_upper = hkl_transposed[..., upper_hemisphere] # axis_coordinates = det2direct.T.dot(hkl_transposed_upper).T # zone_axes = ZoneAxis( # phase=phase, hkl=upper_hkl, coordinates=axis_coordinates # ) return GeometricalEBSDSimulation( detector=self.detector, rotations=self.rotations, bands=bands, # zone_axes=zone_axes, )
def test_allowed(self, space_group, hkl, centering, desired_allowed): rlp = ReciprocalLatticePoint(phase=Phase(space_group=space_group), hkl=hkl) assert rlp.phase.space_group.short_name[0] == centering assert np.allclose(rlp.allowed, desired_allowed)
def test_get_allowed_without_space_group_raises(self): phase = Phase(point_group="432") rlp = ReciprocalLatticePoint(phase=phase, hkl=[1, 1, 1]) with pytest.raises(ValueError, match=f"The phase {phase} must have a"): _ = rlp.allowed
def test_init_without_point_group_raises(self): phase = Phase() with pytest.raises(ValueError, match=f"The phase {phase} must have a"): _ = ReciprocalLatticePoint(phase=phase, hkl=[1, 1, 1])
def nickel_rlp(request, nickel_phase): """A set of reciprocal lattice points for a Nickel crystal structure with a minimum interplanar spacing. """ return ReciprocalLatticePoint(phase=nickel_phase, hkl=request.param)
def test_calculate_structure_factor( self, ferrite_phase, method, voltage, hkl, desired_factor ): rlp = ReciprocalLatticePoint(phase=ferrite_phase, hkl=hkl) rlp.calculate_structure_factor(method=method, voltage=voltage) assert np.allclose(rlp.structure_factor, desired_factor)
def geometrical_simulation( self, reciprocal_lattice_point: Optional[ReciprocalLatticePoint] = None ) -> GeometricalEBSDSimulation: """Project a set of Kikuchi bands and zone axes onto the detector, one set for each rotation of the unit cell. The zone axes are calculated from the Kikuchi bands. Parameters ---------- reciprocal_lattice_point Crystal planes to project onto the detector. If None, and the generator has a phase with a unit cell with a point group, a set of planes with minimum distance of 1 Å and their symmetrically equivalent planes are used. Returns ------- GeometricalEBSDSimulation Examples -------- >>> from diffsims.crystallography import ReciprocalLatticePoint >>> simgen EBSDSimulationGenerator (1,) EBSDDetector (60, 60), px_size 1 um, binning 1, tilt 0, pc (0.5, 0.5, 0.5) <name: . space group: None. point group: None. proper point group: None. color: tab:blue> Rotation (1,) >>> sim1 = simgen.geometrical_simulation() >>> sim1.bands.size 94 >>> rlp = ReciprocalLatticePoint( ... phase=simgen.phase, hkl=[[1, 1, 1], [2, 0, 0]] ... ) >>> sim2 = simgen.geometrical_simulation() >>> sim2.bands.size 13 """ rlp = reciprocal_lattice_point if rlp is None and (hasattr(self.phase.point_group, "name") and hasattr(self.phase.structure.lattice, "abcABG")): rlp = ReciprocalLatticePoint.from_min_dspacing(self.phase, min_dspacing=1) rlp = rlp[rlp.allowed].symmetrise() elif rlp is None: raise ValueError("A ReciprocalLatticePoint object must be passed") self._rlp_phase_is_compatible(rlp) # Unit cell parameters (called more than once) phase = rlp.phase hkl = rlp._hkldata # Get number of navigation dimensions and navigation axes # indices n_nav_dims = self.navigation_dimension navigation_axes = (1, 2)[:n_nav_dims] # Get Kikuchi band coordinates for all bands in all patterns # U_Kstar, transformation from detector frame D to reciprocal # crystal lattice frame Kstar. # Output shape is (3, n, 3) or (3, ny, nx, 3) det2recip = detector2reciprocal_lattice( sample_tilt=self.detector.sample_tilt, detector_tilt=self.detector.tilt, lattice=phase.structure.lattice, rotation=self.rotations, ) # Output shape is (nhkl, n, 3) or (nhkl, ny, nx, 3) hkl_detector = np.tensordot(hkl, det2recip, axes=(1, 0)) if n_nav_dims == 0: hkl_detector = hkl_detector.squeeze() # Get bands that are in some pattern hkl_is_upper, hkl_in_a_pattern = _get_coordinates_in_upper_hemisphere( z_coordinates=hkl_detector[..., 2], navigation_axes=navigation_axes) hkl = hkl[hkl_in_a_pattern, ...] hkl_in_pattern = hkl_is_upper[hkl_in_a_pattern, ...].T # Get coordinates in the proper shape hkl_detector = np.moveaxis(hkl_detector[hkl_in_a_pattern], source=0, destination=n_nav_dims) # And store it all bands = KikuchiBand( phase=phase, hkl=hkl, hkl_detector=hkl_detector, in_pattern=hkl_in_pattern, gnomonic_radius=self.detector.r_max, ) # Get zone axes coordinates from Kikuchi bands uvw = _get_uvw_from_hkl(hkl=hkl) det2direct = detector2direct_lattice( sample_tilt=self.detector.sample_tilt, detector_tilt=self.detector.tilt, lattice=self.phase.structure.lattice, rotation=self.rotations, ) uvw_detector = np.tensordot(uvw, det2direct, axes=(1, 0)) if n_nav_dims == 0: uvw_detector = uvw_detector.squeeze() uvw_is_upper, uvw_in_a_pattern = _get_coordinates_in_upper_hemisphere( z_coordinates=uvw_detector[..., 2], navigation_axes=navigation_axes) uvw = uvw[uvw_in_a_pattern, ...] uvw_in_pattern = uvw_is_upper[uvw_in_a_pattern, ...].T uvw_detector = np.moveaxis(uvw_detector[uvw_in_a_pattern], source=0, destination=n_nav_dims) zone_axes = ZoneAxis( phase=phase, uvw=uvw, uvw_detector=uvw_detector, in_pattern=uvw_in_pattern, gnomonic_radius=self.detector.r_max, ) return GeometricalEBSDSimulation( detector=self.detector, rotations=self.rotations, bands=bands, zone_axes=zone_axes, )
def test_allowed_raises(self, silicon_carbide_phase): with pytest.raises(NotImplementedError): _ = ReciprocalLatticePoint.from_min_dspacing( phase=silicon_carbide_phase, min_dspacing=1 ).allowed
class TestCrystallographicComputations: @pytest.mark.parametrize( "hkl, desired_uvw", [ ([1, 1, 1], np.array([]).reshape((0, 3))), ([[1, 1, 1], [2, 2, 2]], np.array([]).reshape((0, 3))), ([[1, 1, 1], [1, 1, -1]], [[-1, 1, 0], [1, -1, 0]]), ], ) def test_get_uvw_from_hkl(self, hkl, desired_uvw): """Desired uvw from the cross product of hkl.""" assert np.allclose(_get_uvw_from_hkl(hkl), desired_uvw) @pytest.mark.parametrize( ("hkl, desired_family_keys, desired_family_values, desired_indices, " "reduce"), [ ([1, 1, 1], [[1, 1, 1]], [1, 1, 1], [0], False), ([1, 1, 1], [[1, 1, 1]], [1, 1, 1], [0], True), ( [[1, 1, 1], [2, 0, 0]], [[1, 1, 1], [2, 0, 0]], [[[1, 1, 1]], [[2, 0, 0]]], [[0], [1]], False, ), ( ReciprocalLatticePoint(phase=Phase(space_group=225), hkl=[1, 1, 1]).symmetrise().hkl.data, [1, 1, 1], [[ [1, 1, 1], [-1, 1, 1], [-1, -1, 1], [1, -1, 1], [1, -1, -1], [1, 1, -1], [-1, 1, -1], [-1, -1, -1], ]], [np.arange(8)], False, ), ( ReciprocalLatticePoint(phase=Phase(space_group=225), hkl=[[1, 1, 1], [2, 0, 0] ]).symmetrise().hkl.data, [[1, 1, 1], [2, 0, 0]], [ [ [1, 1, 1], [-1, 1, 1], [-1, -1, 1], [1, -1, 1], [1, -1, -1], [1, 1, -1], [-1, 1, -1], [-1, -1, -1], ], [ [2, 0, 0], [0, 2, 0], [-2, 0, 0], [0, -2, 0], [0, 0, 2], [0, 0, -2], ], ], [np.arange(8).tolist(), np.arange(8, 14).tolist()], False, ), ( ReciprocalLatticePoint(phase=Phase(space_group=225), hkl=[[1, 1, 1], [2, 2, 2] ]).symmetrise().hkl.data, [1, 1, 1], [[ [1, 1, 1], [-1, 1, 1], [-1, -1, 1], [1, -1, 1], [1, -1, -1], [1, 1, -1], [-1, 1, -1], [-1, -1, -1], [2, 2, 2], [-2, 2, 2], [-2, -2, 2], [2, -2, 2], [2, -2, -2], [2, 2, -2], [-2, 2, -2], [-2, -2, -2], ]], [np.arange(16)], True, ), ], ) def test_get_hkl_family(self, hkl, desired_family_keys, desired_family_values, desired_indices, reduce): """Desired sets of families and indices.""" families, families_idx = _get_hkl_family(hkl, reduce=reduce) for i, (k, v) in enumerate(families.items()): assert np.allclose(k, desired_family_keys[i]) assert np.allclose(v, desired_family_values[i]) assert np.allclose(families_idx[k], desired_indices[i]) @pytest.mark.parametrize( "highest_hkl, color_cycle, desired_hkl_colors", [ ([1, 1, 1], ["C0", "C1"], [[1, 1, 1], [0.12, 0.47, 0.71]]), ( [2, 2, 2], ["g", "b"], [ [[1, 1, 1], [0, 0.5, 0]], [[2, 0, 0], [0, 0, 1]], [[2, 2, 0], [0, 0.5, 0]], [[2, 2, 2], [0, 0.5, 0]], ], ), ( [2, 2, 2], None, [ [[1, 1, 1], [1, 0, 0]], [[2, 0, 0], [1, 1, 0]], [[2, 2, 0], [0, 1, 0]], [[2, 2, 2], [1, 0, 0]], ], ), ], ) def test_get_colors_for_allowed_bands(self, nickel_phase, highest_hkl, color_cycle, desired_hkl_colors): """Desired colors for bands.""" hkl_colors = _get_colors_for_allowed_bands(phase=nickel_phase, highest_hkl=highest_hkl, color_cycle=color_cycle) assert np.allclose(hkl_colors, desired_hkl_colors, atol=1e-2) def test_get_colors_for_allowed_bands_999(self, nickel_phase): """Not passing `highest_hkl` works fine.""" hkl_colors = _get_colors_for_allowed_bands(phase=nickel_phase) assert np.shape(hkl_colors) == (69, 2, 3)
def test_calculate_theta(self, ferrite_phase, voltage, hkl, desired_theta): rlp = ReciprocalLatticePoint(phase=ferrite_phase, hkl=hkl) rlp.calculate_theta(voltage=voltage) assert np.allclose(rlp.theta, desired_theta)
def test_calculate_structure_factor_raises(self, ferrite_phase): rlp = ReciprocalLatticePoint(phase=ferrite_phase, hkl=[1, 0, 0]) with pytest.raises(ValueError, match="method=man must be among"): rlp.calculate_structure_factor(method="man") with pytest.raises(ValueError, match="'voltage' parameter must be set when"): rlp.calculate_structure_factor(method="doyleturner")
def test_one_point(self, ferrite_phase): rlp = ReciprocalLatticePoint(phase=ferrite_phase, hkl=[1, 1, 0]) assert rlp.size == 1 assert np.allclose(rlp.allowed, True)