Skip to content

Commit

Permalink
Merge branch 'dev_next' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahHenrikKleinschmidt committed Oct 31, 2023
2 parents 2f0963d + 5e6dd29 commit 514f588
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 19 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

25 changes: 21 additions & 4 deletions qpcr/_auxiliary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import re
import qpcr.defaults as defaults
import logging
from copy import deepcopy


def pseudo_isinstance(obj, ref_name: str):
Expand Down Expand Up @@ -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:
Expand All @@ -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"):
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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):
"""
Expand All @@ -289,7 +307,6 @@ def fileID(filename):
logger = default_logger()

if __name__ == "__main__":

obj1 = _ID()
obj1.id("Hnrnp l_nmd")
obj1.split_id("_")
Expand Down
73 changes: 61 additions & 12 deletions qpcr/main/Assay.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
"""
Expand Down Expand Up @@ -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):
"""
Expand All @@ -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):
"""
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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:
Expand All @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -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}
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -42,5 +42,5 @@
"Operating System :: OS Independent",
"Topic :: Scientific/Engineering :: Bio-Informatics",
],
python_requires='>=3.8',
python_requires=">=3.8",
)

0 comments on commit 514f588

Please sign in to comment.