From 8ff17dd6396396068987144330d9a518c5dba74b Mon Sep 17 00:00:00 2001 From: NoahHenrikKleinschmidt Date: Tue, 31 Oct 2023 13:54:01 +0100 Subject: [PATCH 1/3] build(deps): update README.md and setup.py --- README.md | 2 +- setup.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c72c615..64f3ba0 100644 --- a/README.md +++ b/README.md @@ -79,5 +79,5 @@ On the other hand the `qpcr.Normaliser` will perform actions on a single Assay u #### Citation -Kleinschmidt, N. (2023). qpcr - a python package for easy and versatile qPCR data analysis for small-scale datasets and high-throughput (Version 4.1.1) [Computer software]. https://github.com/NoahHenrikKleinschmidt/qpcr.git +Kleinschmidt, N. (2023). qpcr - a python package for easy and versatile qPCR data analysis for small-scale datasets and high-throughput (Version 4.1.3) [Computer software]. https://github.com/NoahHenrikKleinschmidt/qpcr.git diff --git a/setup.py b/setup.py index 6367a29..8983d94 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="qpcr", - version="4.1.2", + version="4.1.3", author="Noah H. Kleinschmidt", author_email="noah.kleinschmidt@students.unibe.ch", description="A python package to perform analysis of qPCR data", @@ -42,5 +42,5 @@ "Operating System :: OS Independent", "Topic :: Scientific/Engineering :: Bio-Informatics", ], - python_requires='>=3.8', + python_requires=">=3.8", ) From de99849a29a2b3d8d33419605d29b58bf543717b Mon Sep 17 00:00:00 2001 From: NoahHenrikKleinschmidt Date: Tue, 31 Oct 2023 13:56:33 +0100 Subject: [PATCH 2/3] =?UTF-8?q?=E2=9C=A8feature:=20add=20copy=20feature=20?= =?UTF-8?q?to=20all=20ID-ed=20objects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- qpcr/_auxiliary/__init__.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/qpcr/_auxiliary/__init__.py b/qpcr/_auxiliary/__init__.py index 0836887..52dfee5 100644 --- a/qpcr/_auxiliary/__init__.py +++ b/qpcr/_auxiliary/__init__.py @@ -7,6 +7,7 @@ import re import qpcr.defaults as defaults import logging +from copy import deepcopy def pseudo_isinstance(obj, ref_name: str): @@ -63,7 +64,6 @@ def log(filename=None, level=None, format=None, name="qpcr"): handler = logging.StreamHandler() else: if filename is None: - # try to use a fileHandler but if we have a jupyter notebook or terminal # just use StreamHandler instead... try: @@ -72,7 +72,9 @@ def log(filename=None, level=None, format=None, name="qpcr"): filename = f"{os.path.dirname( __main__.__file__ )}/{name}.log" except Exception as e: logger.info(e) - logger.info("Could not generate a filename for the log file. Using stdout instead.") + logger.info( + "Could not generate a filename for the log file. Using stdout instead." + ) return log(filename="stdout", level=level, format=format, name=name) elif not filename.endswith(".log"): @@ -153,7 +155,14 @@ class _ID: A meta_superclass that simply adds an ID getter-setter to itself """ - __slots__ = ["_id", "_id_was_set", "_id_label", "_id_label_was_set", "_id_func", "__dict__"] + __slots__ = [ + "_id", + "_id_was_set", + "_id_label", + "_id_label_was_set", + "_id_func", + "__dict__", + ] def __init__(self): self._id = uuid.uuid1() @@ -274,6 +283,15 @@ def id_reset(self): self._id_label_was_set = False self._id_was_set = False + def copy(self): + """ + Returns a deepcopy of itself + """ + new = deepcopy(self) + new.id_reset() + new._id = str(uuid.uuid1()) + return new + def fileID(filename): """ @@ -289,7 +307,6 @@ def fileID(filename): logger = default_logger() if __name__ == "__main__": - obj1 = _ID() obj1.id("Hnrnp l_nmd") obj1.split_id("_") From 5e6dd291be039c626e52e19ea5a1d9a29387737a Mon Sep 17 00:00:00 2001 From: NoahHenrikKleinschmidt Date: Tue, 31 Oct 2023 13:57:11 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=E2=9C=A8feature:=20Let=20Assays=20also=20s?= =?UTF-8?q?et=20Ct=20and=20dCt=20columns=20via=20attributes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- qpcr/main/Assay.py | 73 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/qpcr/main/Assay.py b/qpcr/main/Assay.py index 7baa3f2..574e918 100644 --- a/qpcr/main/Assay.py +++ b/qpcr/main/Assay.py @@ -106,15 +106,31 @@ class Assay(aux._ID): group will be inferred automatically. Otherwise, default group names will be set if no `group_names` are provided. """ - __slots__ = ["_df", "_id", "_efficiency", "_efficiency", "_replicates", "_group_names", "_groups"] - - def __init__(self, df: pd.DataFrame, id: str = None, replicates: (int or tuple or str) = None, group_names: list = None): + __slots__ = [ + "_df", + "_id", + "_efficiency", + "_efficiency", + "_replicates", + "_group_names", + "_groups", + ] + + def __init__( + self, + df: pd.DataFrame, + id: str = None, + replicates: (int or tuple or str) = None, + group_names: list = None, + ): super().__init__() if isinstance(df, pd.DataFrame): self._df = df else: - raise TypeError(f"df argument must be a pandas DataFrame (got {type(df).__name__})") + raise TypeError( + f"df argument must be a pandas DataFrame (got {type(df).__name__})" + ) if id is not None: self._id = id @@ -158,11 +174,15 @@ def efficiency(self, eff: float = None): if isinstance(eff, float): self._efficiency = eff self._eff = 2 * self._efficiency - logger.info(f"New efficiency set to {self._efficiency} (computes as binary factor {self._efficiency} * 2 = {self._eff})") + logger.info( + f"New efficiency set to {self._efficiency} (computes as binary factor {self._efficiency} * 2 = {self._eff})" + ) elif eff is None: return self._efficiency else: - raise TypeError(f"Expected a float efficiency but got type {type(eff).__name__}") + raise TypeError( + f"Expected a float efficiency but got type {type(eff).__name__}" + ) def save(self, filename: str): """ @@ -294,6 +314,13 @@ def Ct(self): Ct.name = f"{self.id()}_Ct" return Ct + @Ct.setter + def Ct(self, Ct): + """ + Sets the Ct values of the Assay. + """ + self._df[raw_col_names[1]] = Ct + @property def dCt(self): """ @@ -307,6 +334,13 @@ def dCt(self): dCt.name = f"{self.id()}_dCt" return dCt + @dCt.setter + def dCt(self, dCt): + """ + Sets the Delta-Ct values of the Assay. + """ + self._df["dCt"] = dCt + @property def ddCt(self): """ @@ -496,8 +530,14 @@ def replicates(self, replicates: (int or tuple or str) = None): if self._vet_replicates(replicates): self._replicates = replicates else: - logger.critical(aw.AssayError("reps_dont_cover", n_samples=self.n(), reps=replicates)) - raise aw.AssayError("reps_dont_cover", n_samples=self.n(), reps=replicates) + logger.critical( + aw.AssayError( + "reps_dont_cover", n_samples=self.n(), reps=replicates + ) + ) + raise aw.AssayError( + "reps_dont_cover", n_samples=self.n(), reps=replicates + ) return self._replicates def group(self, replicates: (int or tuple or str) = None, infer_names=True): @@ -644,7 +684,9 @@ def _identically_named(self): names_set = names.unique() # names_set = aux.sorted_set(names) first_name = names_set[0] - group0 = self._df.query(f"{raw_col_names[0]} == '{first_name}'")[raw_col_names[0]] + group0 = self._df.query(f"{raw_col_names[0]} == '{first_name}'")[ + raw_col_names[0] + ] entries = len(group0) all_identical = entries > 1 else: @@ -669,7 +711,11 @@ def _rename_per_key(self, names): new_names = new_names.split("$") return new_names else: - e = aw.AssayError("groupnames_dont_colver", current_groups=current_names, new_received=names) + e = aw.AssayError( + "groupnames_dont_colver", + current_groups=current_names, + new_received=names, + ) logger.critical(e) raise e @@ -691,7 +737,11 @@ def _rename_per_index(self, names): new_names = new_names.split("$") return new_names else: - e = aw.AssayError("groupnames_dont_colver", current_groups=current_names, new_received=names) + e = aw.AssayError( + "groupnames_dont_colver", + current_groups=current_names, + new_received=names, + ) logger.critical(e) raise e @@ -750,7 +800,6 @@ def _vet_replicates(self, replicates: (int or tuple)): return verdict def __str__(self): - _length = len(str(self._df).split("\n")[0]) s = f""" {"-" * _length}