diff --git a/package/MDAnalysis/core/groups.py b/package/MDAnalysis/core/groups.py index 70d826d7675..f50aeca1e18 100644 --- a/package/MDAnalysis/core/groups.py +++ b/package/MDAnalysis/core/groups.py @@ -3111,14 +3111,13 @@ def select_atoms(self, sel, *othersel, periodic=True, rtol=1e-05, radius 5, external radius 10 centered on the COG. In z, the cylinder extends from 10 above the COG to 8 below. Positive values for *zMin*, or negative ones for *zMax*, are allowed. - box *dimensions* *dN_min* *dN_max* *selection* + box *dimensions* *dN_min* *dN_max* [*dN_min* *dN_max*] [*dN_min* *dN_max*] *selection* Select all atoms within a box region centered on the center of geometry (COG) of a given selection. *dimensions* Specifies which dimension(s) to apply - the box selection on. Can be ``x``, ``y``, ``z``, - or any combination like ``xy``, ``yz``, ``zx``, ``xyz`` - (up to 3 characters). *dN_min*, *dN_max* are the minimum and - maximum bounds along the first specified dimension. + the box selection on. Can be ``x``, ``y``, ``z``, ``xy``, + ``yz``, ``xz``, or ``xyz`. *dN_min*, *dN_max* are the minimum + and maximum bounds along each specified dimension. Positive values are above/right/front of the COG, negatives are below/left/behind, and should be specified for each dimension. *selection* specifies the selection diff --git a/package/MDAnalysis/core/selection.py b/package/MDAnalysis/core/selection.py index 6813a2216fd..d66a304b246 100644 --- a/package/MDAnalysis/core/selection.py +++ b/package/MDAnalysis/core/selection.py @@ -540,24 +540,8 @@ def _apply(self, group): class BoxSelection(Selection): token = "box" precedence = 1 - combination = [ - "x", - "y", - "z", - "xy", - "xz", - "yz", - "yx", - "zx", - "zy", - "xyz", - "xzy", - "yxz", - "yzx", - "zxy", - "zyx", - ] axis_map = ["x", "y", "z"] + axis_set = {"x", "y", "z", "xy", "xz", "yz", "xyz"} def __init__(self, parser, tokens): super().__init__(parser, tokens) @@ -566,22 +550,31 @@ def __init__(self, parser, tokens): self.xmin, self.xmax = None, None self.ymin, self.ymax = None, None self.zmin, self.zmax = None, None - if self.direction not in self.combination: - raise ValueError( - "The direction '{}' is not valid. Must be combination of {}" - "".format(self.direction, ["x", "y", "z"]) - ) - else: + + if self.direction in self.axis_set: for d in self.direction: if d == "x": self.xmin = float(tokens.popleft()) self.xmax = float(tokens.popleft()) + if self.xmin > self.xmax: + raise ValueError("xmin must be less than or equal to xmax") elif d == "y": self.ymin = float(tokens.popleft()) self.ymax = float(tokens.popleft()) + if self.ymin > self.ymax: + raise ValueError("ymin must be less than or equal to ymax") elif d == "z": self.zmin = float(tokens.popleft()) self.zmax = float(tokens.popleft()) + if self.zmin > self.zmax: + raise ValueError("zmin must be less than or equal to zmax") + else: + raise ValueError( + "The direction '{}' is not valid. " + "Must be one of {}" + "".format(self.direction, ", ".join(self.axis_set)) + ) + self.sel = parser.parse_expression(self.precedence) @return_empty_on_apply diff --git a/package/doc/sphinx/source/documentation_pages/selections.rst b/package/doc/sphinx/source/documentation_pages/selections.rst index 196446bc9df..9d500e08a27 100644 --- a/package/doc/sphinx/source/documentation_pages/selections.rst +++ b/package/doc/sphinx/source/documentation_pages/selections.rst @@ -280,9 +280,9 @@ cyzone *externalRadius* *zMax* *zMin* *selection* box *dimensions* *dN_min* *dN_max* *selection* Select all atoms within a box region centered on the center of geometry (COG) of a given selection. *dimensions* Specifies - which dimension(s) to apply the box selection on. Can be ``x``, - ``y``, ``z``, or any combination like ``xy``, ``yz``, ``zx``, ``xyz`` - (up to 3 characters). *dN_min*, *dN_max* are the minimum and maximum + which dimension(s) to apply the box selection on. + Can be ``x``, ``y``, ``z``, ``xy``, ``yz``, ``xz``, or ``xyz`. + *dN_min*, *dN_max* are the minimum and maximum bounds along the first specified dimension. Positive values are above/right/front of the COG, negatives are below/left/behind. Should be specified for each dimension. *selection* specifies the selection