def DONTtest_summary_displays_v_usage_graph(self): cf = ClonoFilter(sample=self.s) cf.save() url = "%s?clonofilter=%s" % ( reverse('samples.views.summary', args=[self.s.id]), cf.id) v_usage_graph_url = reverse('clonotypes.views.v_usage_graph', args=[cf.id]) response = self.client.get(url) self.assertIn(v_usage_graph_url, response.content)
def DONTtest_summary_clonofilter_id_bubble(self): cf = ClonoFilter(sample=self.s) cf.save() url = "%s?clonofilter=%s" % ( reverse('samples.views.summary', args=[self.s.id]), cf.id) bubble_url = "%s?clonofilter=%s" % ( reverse('clonotypes.views.bubble_default', args=[self.s.id]), cf.id) response = self.client.get(url) self.assertIn(bubble_url, response.content)
def test_bubble_default_applies_clonofilter_passed_in_through_get(self): s = Sample.objects.get() cf = ClonoFilter(sample=s) cf.save() self.request = FakeRequestFactory(GET={'clonofilter': cf.id}) with patch('clonotypes.views.bubble', bubble_patch): (request_echo, clonofilter_echo) = bubble_default( self.request, s.id) self.assertEqual(cf.id, clonofilter_echo.id) self.assertEqual(cf, clonofilter_echo)
def test_summary_should_fill_out_form_if_clonofilter_is_passed_through_get(self): cf = ClonoFilter(sample=self.s, min_count=10) cf.save() self.request = FakeRequestFactory(GET={'clonofilter': cf.id}) mock_response = summary(self.request, self.s.id) # self.assertEqual({'min_copy': 10, 'sample': 1}, # mock_response.get('filter_form').initial) self.assertEqual( 10, mock_response.get('filter_form').initial['min_count']) self.assertEqual(1, mock_response.get('filter_form').initial['sample'])
def add_samples(self, samples): ''' Given an array of sample ids, add them to the current comparison and then return a new comparison ''' cfs = list(self.clonofilters_all()) new_cfs = [ClonoFilter.default_from_sample(sample) for sample in samples] comparison, created = Comparison.get_or_create_from_clonofilters( cfs+new_cfs) return comparison
def default_from_samples(samples): ''' In the case where samples are known, but no clonofilter has yet been defined, take in a list of samples, generate the default clonofilter, populate the Comparison object and save the object. ''' # Get a list of default clonofilters for the samples default_clonofilters = [ClonoFilter.default_from_sample(sample) for sample in samples] comparison, created = Comparison.get_or_create_from_clonofilters( default_clonofilters) return comparison
def test_get_or_create_from_clonofilters_does_not_create_a_new_comparison_if_one_already_exists_for_the_set_of_clonofilters(self): cf_1 = ClonoFilter(sample=self.s) cf_1.save() cf_2 = ClonoFilter(sample=self.s) cf_2.save() Comparison.get_or_create_from_clonofilters([cf_1, cf_2]) Comparison.get_or_create_from_clonofilters([cf_1, cf_2]) self.assertEqual(1, Comparison.objects.all().count())
def summary(request, sample_id): ''' summary takes in a request and a sample id and displays an array of summary images and statistics. It can also take a clonofilter via POST or GET ''' s = Sample.objects.get(id=sample_id) if request.method == 'POST': # Handling changes to filter form via POST cf_form = ClonoFilterForm(request.POST) if cf_form.is_valid(): # This code does not create a new clonofilter object if one # with the same form parameters has already been generated cf, created = ClonoFilter.objects.get_or_create( **cf_form.cleaned_data) url = "%s?clonofilter=%s" % ( reverse('samples.views.summary', args=[cf.sample.id]), cf.id) else: url = reverse('samples.views.summary', args=[s.id]) return HttpResponseRedirect(url) else: # Handling requests via GET # Sets up the form to reflect the clonofilter supplied by GET if 'clonofilter' in request.GET: cf_id = request.GET['clonofilter'] try: cf = ClonoFilter.objects.get(id=cf_id) f = ClonoFilterForm( initial=ClonoFilter.objects.filter(id=cf_id).values()[0]) except: return HttpResponseRedirect(reverse('samples.views.summary', args=[s.id])) # If there is no clonofilter specified, just return the default # clonofilter with no values else: f = ClonoFilterForm(initial={'sample': s.id}) cf = ClonoFilter.default_from_sample(s) context = {'sample': s, 'filter_form': f, 'clonofilter': cf, } return render(request, 'summary.html', context)
def test_summary_should_try_to_read_in_clonofilter_from_get(self): cf = ClonoFilter(sample=self.s) cf.save() self.request = FakeRequestFactory(GET={'clonofilter': cf.id}) mock_response = summary(self.request, self.s.id) self.assertEqual(mock_response.get('clonofilter'), cf) cf2 = ClonoFilter(sample=self.s) cf2.save() self.request = FakeRequestFactory(GET={'clonofilter': cf2.id}) mock_response = summary(self.request, self.s.id) self.assertEqual(mock_response.get('clonofilter'), cf2)
def test_v_usage_graph_returns_a_png(self): s = Sample.objects.get() clonofilter = ClonoFilter(sample=s) clonofilter.save() response = v_usage_graph(self.request, clonofilter.id) self.assertEqual('image/png', response['content-type'])
def test_default_from_sample_creates_a_default_clonofilter_if_one_does_not_exist(self): ClonoFilter.objects.all().delete() cf = ClonoFilter.default_from_sample(self.s) self.assertEqual(cf, ClonoFilter.objects.get())
def test_default_from_sample_does_not_create_a_default_if_one_exists(self): ClonoFilter.objects.all().delete() ClonoFilter.default_from_sample(self.s) ClonoFilter.default_from_sample(self.s) self.assertEqual(1, ClonoFilter.objects.all().count())
def test_v_usage_considers_norm_factor(self): cf = ClonoFilter(sample=self.s, norm_factor=2) v_usage_dict = cf.v_usage_dict() self.assertEqual({u'TRBV1-1': 0.5, u'TRBV25-1': 1.5}, v_usage_dict)
def test_j_usage_considers_norm_factor(self): cf = ClonoFilter(sample=self.s, norm_factor=2) j_usage_dict = cf.j_usage_dict() self.assertEqual({u'TRBJ2-4': 0.5, u'TRBJ1-1': 1.5}, j_usage_dict)
def setUp(self): make_fake_patient_with_3_clonotypes() self.s = Sample.objects.get() self.f = ClonoFilter(sample=self.s) self.f.save()
class ClonoFilterModelTest(TestCase): def setUp(self): make_fake_patient_with_3_clonotypes() self.s = Sample.objects.get() self.f = ClonoFilter(sample=self.s) self.f.save() def test_top_clones_returns_top_clones(self): self.assertEqual(2, self.f.top_clones(1)[0].count) self.assertEqual(1, self.f.top_clones(2)[1].count) def test_entropy_returns_entropy(self): self.assertEqual(1.0397207708399179, self.f.entropy()) def test_min_copy_defaults_to_min_copy_for_that_sample(self): from django.db.models import Min aggregate = Clonotype.objects.aggregate(Min('count')) min_count = aggregate['count__min'] self.assertEqual(self.f.min_count, min_count) def test_css_class_returns_clonofilter_class_string(self): self.assertEqual(self.f.css_class(), "cf-1") def test_update_generates_a_new_clonofilter_and_merges_filters_with_existing(self): from django.forms.models import model_to_dict self.f.min_copy = 1 self.f.save() new_cf, new_created = self.f.update({'max_length': 50}) test_cf, test_created = ClonoFilter.objects.get_or_create(**{ 'sample': self.s, 'min_count': 1, 'max_length': 50 }) self.assertEqual(new_created, True) self.assertEqual(test_created, False) self.assertEqual( model_to_dict(new_cf), model_to_dict(test_cf) ) self.assertEqual(new_cf.id, test_cf.id) self.assertEqual(new_cf.id, 2) self.assertEqual(self.f.id, 1) def test_functionality_dict_contains_all_functional_groups_as_ratios(self): self.assertEqual({u'Out of frame': 0.5, u'Productive': 0.5}, self.f.functionality_dict()) def test_functionality_dict_returns_dict(self): self.assertIsInstance(self.f.functionality_dict(), dict) def test_j_usage_considers_norm_factor(self): cf = ClonoFilter(sample=self.s, norm_factor=2) j_usage_dict = cf.j_usage_dict() self.assertEqual({u'TRBJ2-4': 0.5, u'TRBJ1-1': 1.5}, j_usage_dict) def test_j_usage_dict_returns_dict_indexed_by_j_gene(self): j_usage_dict = self.f.j_usage_dict() self.assertIsInstance(j_usage_dict, dict) self.assertEqual({u'TRBJ2-4': 0.25, u'TRBJ1-1': 0.75}, j_usage_dict) def test_v_usage_considers_norm_factor(self): cf = ClonoFilter(sample=self.s, norm_factor=2) v_usage_dict = cf.v_usage_dict() self.assertEqual({u'TRBV1-1': 0.5, u'TRBV25-1': 1.5}, v_usage_dict) def test_v_usage_dict_returns_dict_indexed_by_v_family(self): v_usage_dict = self.f.v_usage_dict() self.assertIsInstance(v_usage_dict, dict) self.assertEqual({u'TRBV1-1': 0.25, u'TRBV25-1': 0.75}, v_usage_dict) def test_normalization_factor_initializes_to_sum_of_raw_counts(self): self.f.save() self.assertEqual(self.f.size(), self.f.norm_factor) def test_get_recombinations_filters_properly(self): self.f.min_length = 40 self.f.save() recombinations = Recombination.objects.filter(cdr3_length__gte=40) self.assertEqual(map(repr, recombinations), map(repr, self.f.get_recombinations())) def test_given_a_clonofilter_return_a_recombination_queryset(self): recombination_qs = self.f.get_recombinations() self.assertEqual(map(repr, Recombination.objects.all()), map(repr, recombination_qs)) def test_count_method_returns_number_of_recombinations(self): self.assertEqual(3, self.f.count()) def test_norm_size_method_returns_normalized_sum_of_copy(self): from django.db.models import Sum self.f.norm_factor = 10.0 self.f.save() self.assertEqual(.4, self.f.norm_size()) def test_size_method_returns_sum_of_copy(self): from django.db.models import Sum self.assertEqual(4, self.f.size()) def test_default_from_sample_does_not_create_a_default_if_one_exists(self): ClonoFilter.objects.all().delete() ClonoFilter.default_from_sample(self.s) ClonoFilter.default_from_sample(self.s) self.assertEqual(1, ClonoFilter.objects.all().count()) def test_default_from_sample_creates_a_default_clonofilter_if_one_does_not_exist(self): ClonoFilter.objects.all().delete() cf = ClonoFilter.default_from_sample(self.s) self.assertEqual(cf, ClonoFilter.objects.get()) def test_cdr3_length_sum_utilizes_norm_factor_if_it_exists(self): self.f.norm_factor = 10 norm_cdr3_length_sum = self.f.cdr3_length_sum() self.assertEqual([[36, .1], [39, .1], [42, .2]], norm_cdr3_length_sum) def test_clonofilter_has_min_and_max_length_as_int(self): self.f.min_length = 1 self.f.max_length = 10 self.f.save() f = ClonoFilter.objects.get() self.assertEqual(f.min_length, self.f.min_length) self.assertEqual(f.max_length, self.f.max_length) self.assertIsInstance(f.min_length, int) self.assertIsInstance(f.max_length, int) def test_clonofilter_filters_on_min_and_max_length(self): filtered_clonotypes = Clonotype.objects.filter( recombination__cdr3_length__gte=37, recombination__cdr3_length__lte=40) self.f.min_length = 37 self.f.max_length = 40 self.assertQuerysetEqual(filtered_clonotypes, map(repr, self.f.get_clonotypes())) def test_clonofilter_filters_on_v_family(self): filtered_clonotypes = Clonotype.objects.filter( recombination__v_gene_name=9) self.f.v_family_name = 9 self.f.save() self.assertQuerysetEqual(filtered_clonotypes, map(repr, self.f.get_clonotypes())) def test_clonofilter_filters_on_j_gene_name(self): filtered_clonotypes = Clonotype.objects.filter( recombination__j_gene_name='TRBJ2-4') self.f.j_gene_name = 'TRBJ2-4' self.f.save() self.assertQuerysetEqual(filtered_clonotypes, map(repr, self.f.get_clonotypes())) def test_clonofilter_has_normalization_factor_as_a_float(self): self.f.norm_factor = 1 self.f.save() f = ClonoFilter.objects.get() self.assertEqual(f.norm_factor, self.f.norm_factor) self.assertIsInstance(f.norm_factor, float) def test_clonofilter_get_clonotypes_should_not_filter_on_a_parameter_if_it_is_not_included(self): try: self.f.get_clonotypes() except ValueError: self.fail('clonofilter.get_clonotypes should not fail if sample exists but no other filtering attributes are given') def test_clonofilter_filters_on_min_copy(self): min_clonotypes = Clonotype.objects.filter(count__gte=2) self.f.min_count = 2 self.assertQuerysetEqual(min_clonotypes, map(repr, self.f.get_clonotypes())) def test_clonofilter_has_min_copy(self): self.f.min_copy = 0 self.assertEqual(0, self.f.min_copy) def test_clonofilter_has_sample(self): f = ClonoFilter.objects.get() self.assertEqual(self.s, self.f.sample) def test_vj_counts_dict_returns_a_nested_dict(self): ''' dict should be indexed by: dict['v_family']['j_gene'] = count ''' vj_counts = self.f.vj_counts_dict() self.assertIsInstance(vj_counts, dict) assert(vj_counts) for v_family in vj_counts.values(): self.assertIsInstance(v_family, dict) self.assertEqual(vj_counts['TRBV1-1']['TRBJ1-1'], 0.25) def test_vj_counts_utilizes_norm_factor_if_it_exists(self): self.f.norm_factor = 10 norm_vj_counts = self.f.vj_counts() self.assertEqual(.2, norm_vj_counts[0][0]) def test_vj_counts_returns_an_empty_2d_list_with_dimensions_len_vfam_by_jgene(self): v_family_names = Recombination.v_gene_names() j_gene_names = Recombination.j_gene_names() vj_counts = self.f.vj_counts() self.assertEqual(len(v_family_names), len(vj_counts)) self.assertEqual(len(j_gene_names), len(vj_counts[0])) def test_vj_counts_returns_a_2d_list_of_v_j_and_sum_of_copies(self): # from collections import defaultdict vj_counts = self.f.vj_counts() self.assertIsInstance(vj_counts[0], list) self.assertEqual( ['[0.5, 0.25]', '[0.25, 0]'], map(repr, vj_counts)) def test_cdr3_length_sum_returns_a_list(self): sums = self.f.cdr3_length_sum() self.assertIsInstance(sums, list) def test_cdr3_length_sum_returns_a_nested_list_of_cdr3_lengths_and_their_counts(self): hist = self.f.cdr3_length_sum() self.assertEqual([[36, 0.25], [39, .25], [42, 0.5]], hist) def test_cdr3_length_sum_should_sort_output_by_cdr3_length(self): r = RecombinationFactory( cdr3_length=10 ) ClonotypeFactory( sample=self.s, recombination=r, frequency=9.336458E-6, count=1, ) self.assertEqual( [[36, 0.25], [39, 0.25], [42, .5]], self.f.cdr3_length_sum())