Skip to content

Commit

Permalink
cleaner protocol-based selection in sheet construction; better test o…
Browse files Browse the repository at this point in the history
…rganization, all passing
  • Loading branch information
vreuter committed Jun 27, 2017
1 parent f7cc27e commit 966286b
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 21 deletions.
17 changes: 4 additions & 13 deletions looper/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1038,20 +1038,11 @@ def build_sheet(self, *protocols):
given, else all of this Project's samples
"""
# Use all protocols if none are explicitly specified.
protocols = set(protocols or self.protocols)
if protocols:
protocols = set(protocols)
def include(sample):
try:
return sample.library in protocols
except AttributeError:
return False
else:
def include(_):
return True

samples = self.samples
protocols = {alpha_cased(p) for p in (protocols or self.protocols)}
return _pd.DataFrame(
[s.as_series() for s in self.samples if include(s)])
[s.as_series() for s in samples if
hasattr(s, "library") and alpha_cased(s.library) in protocols])


def make_project_dirs(self):
Expand Down
24 changes: 24 additions & 0 deletions tests/models/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,30 @@ def minimal_project_conf_path(tmpdir):



@pytest.fixture(scope="function")
def path_proj_conf_file(tmpdir, proj_conf):
""" Write basic project configuration data and provide filepath. """
conf_path = os.path.join(tmpdir.strpath, "project_config.yaml")
with open(conf_path, 'w') as conf:
yaml.safe_dump(proj_conf, conf)
return conf_path



@pytest.fixture(scope="function")
def path_anns_file(request, tmpdir, sample_sheet):
""" Write basic annotations, optionally using a different delimiter. """
filepath = os.path.join(tmpdir.strpath, "annotations.csv")
if "delimiter" in request.fixturenames:
delimiter = request.getfixturevalue("delimiter")
else:
delimiter = ","
with open(filepath, 'w') as anns_file:
sample_sheet.to_csv(anns_file, sep=delimiter, index=False)
return filepath



@pytest.fixture(scope="function")
def piface_config_bundles(request, resources):
"""
Expand Down
1 change: 1 addition & 0 deletions tests/models/independent/test_Project.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ def _parse_flags_and_options(command_elements):
return parsed_command_elements



def _write_project_config(config_data, dirpath, filename="proj-conf.yaml"):
"""
Write the configuration file for a Project.
Expand Down
42 changes: 34 additions & 8 deletions tests/models/integration/test_Project_Sample_interaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
import yaml

from looper.models import \
merge_sample, Project, Sample, \
Project, Sample, \
SAMPLE_ANNOTATIONS_KEY, SAMPLE_NAME_COLNAME
from looper.utils import alpha_cased


__author__ = "Vince Reuter"
Expand Down Expand Up @@ -54,7 +55,9 @@ def pytest_generate_tests(metafunc):
argnames="protocols",
argvalues=list(itertools.chain.from_iterable(
itertools.combinations(PROTOCOLS, x)
for x in range(1 + len(PROTOCOLS)))))
for x in range(1 + len(PROTOCOLS)))),
ids=lambda protos:
" protocols = {} ".format(",".join(protos)))
if "delimiter" in metafunc.fixturenames:
metafunc.parametrize(argnames="delimiter", argvalues=[",", "\t"])

Expand Down Expand Up @@ -93,13 +96,27 @@ def path_anns_file(request, tmpdir, sample_sheet):

@pytest.fixture(scope="function")
def samples_rawdata():
return copy.deepcopy(DATA_FOR_SAMPLES)
return copy.deepcopy(DATA)



@pytest.fixture(scope="function")
def sample_sheet(samples_rawdata):
return pd.DataFrame(samples_rawdata)
df = pd.DataFrame(samples_rawdata)
df.columns = [SAMPLE_NAME_COLNAME, "val1", "val2", "library"]
return df



def test_samples_are_generic(path_anns_file, path_proj_conf_file):
""" Regardless of protocol, Samples for sheet are generic. """
# Annotations filepath fixture is also writes that file, so
# it's needed even though that return value isn't used locally.
p = Project(path_proj_conf_file)
assert len(SAMPLE_NAMES) == p.num_samples
samples = list(p.samples)
assert p.num_samples == len(samples)
assert all([Sample is type(s) for s in samples])



Expand Down Expand Up @@ -159,12 +176,21 @@ def test_single_sample(
def test_multiple_samples(
self, protocols, path_anns_file, path_proj_conf_file):
""" Project also processes multiple Sample fine. """
pass

p = Project(path_proj_conf_file)

# Total sample count is constant.
assert len(SAMPLE_NAMES) == sum(1 for _ in p.samples)

def test_samples_are_generic(self, path_anns_file, path_proj_conf_file):
""" Regardless of protocol, Samples for sheet are generic. """
pass
# But the sheet permits filtering to specific protocol(s).
exp_num_samples = len(SAMPLE_NAMES) if not protocols else \
sum(sum(1 for l in LIBRARIES if l == p) for p in protocols)
sheet = p.build_sheet(*protocols)
assert exp_num_samples == len(sheet)
if protocols:
fuzzy_protos = {alpha_cased(p) for p in protocols}
for _, sample_data in sheet.iterrows():
assert alpha_cased(sample_data.library) in fuzzy_protos



Expand Down

0 comments on commit 966286b

Please sign in to comment.