# -*- coding: utf-8 -*-"""A class providing a convenient interface for subsets"""fromitertoolsimportzip_longestimportloggingfrom.subsetimport_Subsetfrom.tableimport_Tablelogger=logging.getLogger(__name__)
class_Subsets(_Table):"""The Subsets class handles the subsets for a single configuration. Parameters ---------- configuration : _Configuration The configuration to work with. logger : Logger The logger to use, defaults to the one for this module. """def__init__(self,configuration,logger=logger):self._configuration=configurationself.logger=loggerself._cid=configuration.idself._system_db=configuration.system_dbsuper().__init__(self._system_db,"subset")self._sa_table=self._system_db["subset_atom"]def__eq__(self,other):"""Return a boolean if this object is equal to another"""raiseNotImplementedError()@propertydefn_subsets(self):"""The number of subsets for a configuration. Returns ------- int The number of subsets in the configuration. """sql="""\ SELECT COUNT(*) FROM subset WHERE configuration = ? """self.cursor.execute(sql,(self._cid,))result=self.cursor.fetchone()[0]returnresultdefappend(self,n=None,**kwargs):"""Append one or more rows The keywords are the names of attributes and the value to use. The default value for any attributes not given is used unless it is 'None' in which case an error is thrown. It is an error if there is not an exisiting attribute corresponding to any given as arguments. Parameters ---------- n : int = None The number of rows to create, defaults to the number of items in the longest attribute given. kwargs : any number <attribute name> = <value> keyword arguments giving existing attributes and values. Returns ------- [int] The ids of the created rows. """kwargs["configuration"]=self._cidids=super().append(n,**kwargs)returnidsdefcreate(self,template,atoms=None,templateatoms=None):"""Create a subset given a template and optionally atoms. Parameters ---------- template : int or _Template The template for the subset atoms : [int] = None Optional list of atom ids to connect to the subset. templateatoms : [int] = None Optional list of template atoms to connect to the atoms in the subset. Returns ------- _Subset The subset. """ifisinstance(template,int):tid=templateelse:tid=template.idsid=self.append(template=tid)[0]ifatomsisnotNone:iftemplateatomsisnotNone:self._sa_table.append(subset=sid,atom=atoms,templateatom=templateatoms)else:self._sa_table.append(subset=sid,atom=atoms)return_Subset(self.system_db,sid)defdelete(self,ids):"""Remove one or more subsets Parameters ---------- ids : [int] of 'all' The subsets to delete. Returns ------- None """ifids=="all":sql="""\ DELETE FROM subset WHERE configuration = ? """self.db.execute(sql,(self._cid,))else:ifisinstance(ids,int):self.db.execute("DELETE FROM subset WHERE id = ?",(ids,))else:self.db.executemany("DELETE FROM subset WHERE id = ?",ids)defgenerate(self,template):"""Generate the subsets matching a full template. Parameters ---------- template : int or _Template The template. Returns ------- [_Subset] The subsets. """passdefget(self,template):"""Get the subsets given a template. Parameters ---------- template : int or _Template The template. Returns ------- [_Subset] The subsets. """ifisinstance(template,int):tid=templateelse:tid=template.idreturn[_Subset(self.system_db,x)forxinself.get_ids(tid)]defget_ids(self,template):"""Find ids of subsets given a template. Parameters ---------- template : int or _Template The template for the subset Returns ------- [int] The ids of the subsets, and empty list if there are none. """ifisinstance(template,int):tid=templateelse:tid=template.idsql=""" SELECT id FROM subset WHERE template = ? AND configuration = ? """return[x[0]forxinself.db.execute(sql,(tid,self._cid))]defget_counts(self,configuration="all"):"""Get the counts of subsets per template for configurations. Parameters ---------- configuration : int or MolSystem._Configuration or "all" The configuration, as an object or its id, or "all" for all configurations. Default is "all". Returns ------- [[configuration_id, name, count]] """ifconfiguration=="all":sql=("SELECT subset.configuration, name, count(1) FROM subset, template "" WHERE template = template.id "" GROUP BY subset.configuration, name "" ORDER BY subset.configuration")return[[*x]forxinself.db.execute(sql)]else:raiseNotImplementedError("get_counts only take 'all' configurations")