#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2014 The ProteinDF development team.
# see also AUTHORS and README if provided.
#
# This file is a part of the ProteinDF software package.
#
# The ProteinDF is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# The ProteinDF is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ProteinDF. If not, see <http://www.gnu.org/licenses/>.
import re
import warnings
from .atom import Atom
from .position import Position
from .str_processing import StrUtils
import logging
logger = logging.getLogger(__name__)
[docs]
class Select(object):
"""
Selecter interface class.
"""
[docs]
def is_match(self, obj):
"""
Return True if the condition is matched.
Subclasses must implement this method.
"""
return False
[docs]
class Select_Symbol(Select):
"""
Select by atomic symbol.
"""
def __init__(self, atom_symbol):
self._atom_symbol = atom_symbol.upper()
[docs]
def is_match(self, obj):
answer = False
if isinstance(obj, Atom):
symbol = obj.symbol.upper()
if symbol == self._atom_symbol:
answer = True
return answer
[docs]
class Select_Name(Select):
def __init__(self, query):
self.query = StrUtils.to_unicode(query)
[docs]
def is_match(self, obj):
answer = False
name = obj.name.strip().rstrip()
if name == self.query:
answer = True
return answer
[docs]
class Select_Path(Select):
"""
.. deprecated::
Use :class:`Select_Path_wildcard` instead.
Will be removed in a future version.
"""
def __init__(self, query, use_wildcard=True):
warnings.warn(
"Select_Path is deprecated, use Select_Path_wildcard instead.",
DeprecationWarning,
stacklevel=2,
)
self._query = StrUtils.to_unicode(query)
self._is_used_wildcard = use_wildcard
if use_wildcard:
self._regex_selecter = self._prepare(query)
def _prepare(self, query):
query = re.sub(r"(?<!\\)\*", ".*", query)
query = re.sub(r"(?<!\\)\?", "?", query)
query = "^" + query + "$"
return Select_PathRegex(query)
[docs]
def is_match(self, obj):
if self._is_used_wildcard:
return self._regex_selecter.is_match(obj)
else:
return self._is_match_nowildcard(obj)
def _is_match_nowildcard(self, obj):
answer = False
path = obj.path
if self._query == path:
answer = True
return answer
[docs]
class Select_Path_simple(Select):
""" """
def __init__(self, query):
self._query = StrUtils.to_unicode(query)
[docs]
def is_match(self, obj):
answer = False
path = obj.path
if self._query == path:
answer = True
return answer
[docs]
class Select_Path_wildcard(Select):
"""selector using path with wildcard"""
def __init__(self, query):
self._query = StrUtils.to_unicode(query)
self._regex_selecter = self._prepare(query)
def _prepare(self, query):
query = re.sub(r"(?<!\\)\*", ".*", query)
query = re.sub(r"(?<!\\)\?", "?", query)
query = "^" + query + "$"
return Select_PathRegex(query)
[docs]
def is_match(self, obj):
return self._regex_selecter.is_match(obj)
[docs]
class Select_PathRegex(Select):
"""
Select by a regular expression matched against the path.
"""
def __init__(self, query):
self._query = StrUtils.to_unicode(query)
self._regex = re.compile(query)
[docs]
def is_match(self, obj):
answer = False
path = obj.path
if self._regex.search(path) != None:
# print("path=[%s] regex=[%s]" % (path, self._query))
answer = True
return answer
[docs]
class Select_Range(Select):
"""
Select by radius.
"""
def __init__(self, pos, d):
self._pos = Position(pos)
d = float(d)
self._d = d
self._d2 = d * d
[docs]
def is_match(self, obj):
answer = False
if isinstance(obj, Atom):
# d = self._pos.distance_from(obj.xyz)
d2 = self._pos.square_distance_from(obj.xyz)
if d2 < self._d2:
answer = True
return answer
[docs]
class Select_Atom(Select):
""" """
def __init__(self, atom, distance=0.1):
from .atom import Atom
self._atom = Atom(atom)
self._distance2 = distance * distance
[docs]
def is_match(self, obj):
answer = False
if isinstance(obj, Atom):
if (self._atom.atomic_number == obj.atomic_number) and (
self._atom.xyz.square_distance_from(obj.xyz) < self._distance2
):
answer = True
# else:
# logger.warning("type mismatch in Select_Atom(): {}".format(str(obj)))
return answer
[docs]
class Select_AtomGroup(Select):
"""Return the atoms that also exist in the reference atomgroup."""
def __init__(self, ref_atomgroup, range=1.0e-5):
from .atomgroup import AtomGroup
assert isinstance(ref_atomgroup, AtomGroup)
self._ref_atoms = ref_atomgroup.get_atom_list()
self._range = range
[docs]
def is_match(self, obj):
answer = False
if isinstance(obj, Atom):
for ref_atom in self._ref_atoms:
# if ref_atom == obj:
if (ref_atom.atomic_number == obj.atomic_number) and (
ref_atom.xyz.distance_from(obj.xyz) < self._range
):
answer = True
break
return answer