diff --git a/fishbook/frontend/frontend_classes.py b/fishbook/frontend/frontend_classes.py index 542e87b..3e3fc0b 100644 --- a/fishbook/frontend/frontend_classes.py +++ b/fishbook/frontend/frontend_classes.py @@ -7,6 +7,8 @@ from IPython import embed from fishbook.backend.util import progress class Cell: + """The Cell class represents a recorded cell. It is characterized by *id*, the cell *type*, the *firing_rate*, and the recording *location*. + """ def __init__(self, cell_id=None, tuple=None): if tuple: self.__tuple = tuple @@ -20,18 +22,40 @@ class Cell: @property def id(self): + """The id of the cell. Unsually the same as the dataset name. + + Returns: + str: the id + """ return self.__tuple["cell_id"] if "cell_id" in self.__tuple.keys() else "" @property def type(self): + """The cell type. + + Returns: + str: the cell type + """ return self.__tuple["cell_type"] if "cell_type" in self.__tuple.keys() else "" @property def firing_rate(self): + """The firing rate of the neuron, if applicable, else 0.0. + + Returns: + float: the firing rate. + """ return self.__tuple["firing_rate"] if "firing_rate" in self.__tuple.keys() else 0.0 @property def location(self): + """The recording location which consists of the structure (e.g. brain), the region (e.g. ELL), the subregion (e.g. lateral segment), + the depth below surface, the lateral position and the transversal section if applicable. The latter two are given according to the + [Apteronotus brain atlas](http://nelson.beckman.illinois.edu/atlas.html). + + Returns: + dict: the recording location + """ keys = ["structure", "region", "subregion", "depth", "lateral_pos", "transversal_section"] loc = {} for k in keys: @@ -43,23 +67,55 @@ class Cell: @property def subject(self): + """The subject in which this cell was recorded. + + Returns: + fishbook.Subject: the subject + """ return Subject(tuple=(Subjects & {"subject_id": self.__tuple["subject_id"]}).fetch(limit=1, as_dict=True)[0]) @property def datasets(self): + """All datasets that have been collected from this cell. + + Returns: + list of fishbook.Dataset: the linked datasets + """ return [Dataset(tuple=d) for d in (Datasets & (CellDatasetMap & {"cell_id": self.id})).fetch(as_dict=True)] @property def repro_runs(self): + """All relacs RePros that have been run while recording this cell. + + Returns: + list of fishbook.RePro: the repros + """ repros = (Repros & "cell_id = '%s'" % self.id) return [RePro(tuple=r) for r in repros] @staticmethod def unique_cell_types(): + """List of unique cell types stored in the database. + + Returns: + np.array of str: the cell types + """ return np.unique(Cells.fetch("cell_type")) @staticmethod - def find(cell_type=None, species=None, quality="good"): + def find(cell_type=None, species=None, quality="good", test=False): + """Find cells that match with respect to cell type, subject species, and recording quality. + + Args: + cell_type (str, optional): The desired cell type, case insensitive. Defaults to None. + species (str, optional): The species name, or parts of it. Defaults to None. + quality (str, optional): The desired qulality. Defaults to "good". + test (bool, optional): Whether or not this query is a test run. Defaults to False. + + Returns: + list of fishbook.Cell: the matching cells, empty it test==True. + int : the number of matches + """ cs = Cells * CellDatasetMap * Datasets * Subjects if cell_type: cs = cs & "cell_type like '{0:s}'".format(cell_type) @@ -67,11 +123,19 @@ class Cell: cs = cs & "species like '%{0:s}%'".format(species) if quality: cs = cs & "quality like '{0:s}'".format(quality) - return [Cell(tuple=c) for c in cs] + results = [] + total = len(cs) + if not test: + for i, c in enumerate(cs): + progress(i+1, total, "fetching %i matches" % total) + results.append(Cell(tuple=c)) + return results, total def __str__(self): str = "" - str += "Cell: %s \t type: %s\n"%(self.id, self.type) + str += "Cell: %s \t type: %s\n" % (self.id, self.type) + str += "Baseline firing: %.3f\n" % self.firing_rate + str += "structure: %s \t region: %s\t subregion: %s\n" % (self.__tuple["structure"], self.__tuple["region"], self.__tuple["subregion"]) return str @property @@ -286,15 +350,15 @@ class Dataset: return self.__tuple.copy() def __str__(self): - str = "id: %s\n" % self.id + str = "dataset id: %s\n" % self.id str += "recorded: %s \t by: %s\n" % (self.recording_date, self.experimenter) - str += "duration: %ss \t quality: %s\n" % (self.recording_duration, self.quality) + str += "duration: %s min \t quality: %s\n" % (self.recording_duration, self.quality) str += "comment: %s" % self.comment return str class RePro: - """Repro class represents an entry in the repro table. This is a run of a certain relacs "Research Protocol". + """The RePro class represents an entry in the repro table. This is a run of a certain relacs "Research Protocol". """ def __init__(self, repro_id=None, tuple=None): @@ -406,6 +470,12 @@ class RePro: def _tuple(self): return self.__tuple.copy() + def __str__(self): + str = "RePro: %s\t id: %s\n" % (self.name, self.id) + str += "run: %i\t on cell: %s\n" %(self.run, self.cell_id) + str += "start time: %s\t duration: %s\n" % (self.start, self.duration) + return str + class Stimulus: """The stimulus class represents a Stimulus that was presented. A Stimulus has several properties @@ -510,6 +580,11 @@ class Stimulus: class Subject: + """Representation of the recorded subject's properties. + A subject is defined by the its *id*, and its *species*. + + The + """ def __init__(self, subject_id=None, tuple=None): if tuple: self.__tuple = tuple @@ -544,6 +619,15 @@ class Subject: @staticmethod def find(species=None, test=False): + """Find all subjects matching the given species. + + Args: + species ([type], optional): [description]. Defaults to None. + test (bool, optional): [description]. Defaults to False. + + Returns: + [type]: [description] + """ subjs = Subjects & True if species: subjs = (Subjects & "species like '%{0:s}%'".format(species)) @@ -559,9 +643,18 @@ class Subject: @staticmethod def unique_species(): + """Unique list of species names. + + Returns: + np.array: unique names + """ all_species = (Subjects & True).fetch("species") return np.unique(all_species) + def __str__(self): + str = "Subject: %s\n" % self.id + str += "" + if __name__ == "__main__": from IPython import embed