def testDefaultNumberOfBins(self): """ If no bin count is given to the Histogram class, it must make the expected default number of bins. """ h = Histogram() self.assertEqual(11, h.nBins)
def __init__(self, template): self.template = self.templateToList(template) self.query = Query(self.template) self.subject = Subject(self.template) if len(self.query.pairedFeatures) != len(self.subject.pairedFeatures): raise ValueError( 'The query and subject do not have the same number of paired ' 'features (%d != %d)' % (len(self.query.pairedFeatures), len(self.subject.pairedFeatures))) # Union the landmark and trig point names from the query and subject. self.landmarks = self.query.landmarks | self.subject.landmarks self.trigPoints = self.query.trigPoints | self.subject.trigPoints self.histogram = Histogram(1) for queryPair, subjectPair in zip(self.query.pairedFeatures, self.subject.pairedFeatures): _, queryLandmark, _, queryTrigPoint = queryPair _, subjectLandmark, _, subjectTrigPoint = subjectPair self.histogram.add(0, { 'queryLandmark': queryLandmark, 'queryTrigPoint': queryTrigPoint, 'subjectLandmark': subjectLandmark, 'subjectTrigPoint': subjectTrigPoint, }) self.histogram.finalize()
def testNoData(self): """ If no data is given to the Histogram class, all bins must be empty. """ h = Histogram() for bin_ in h.bins: self.assertEqual(0, len(bin_))
def testActualNumberOfBins(self): """ If a bin count is given to the Histogram class, it must make the expected number of bins. """ h = Histogram(5) self.assertEqual(5, len(h.bins))
def testNoDataMaxAndMin(self): """ If no data is given to the Histogram class, the max and min attributes of the histogram must be None. """ h = Histogram() self.assertIs(None, h.max) self.assertIs(None, h.min)
def testFinalizeWithNoData(self): """ If finalize is called and the histogram has no data, all bins must have zero counts. """ h = Histogram(5) h.finalize() self.assertEqual([0, 0, 0, 0, 0], [len(bin_) for bin_ in h.bins])
def testTenElementsInThreeBinsBinWidth(self): """ If a histogram is created with 10 elements (0-9) placed into 3 bins, the bin width must be 3.0. """ h = Histogram(3) list(map(h.add, range(10))) h.finalize() self.assertEqual(3.0, h.binWidth)
def testAlwaysMustBeTrue(self): """ The Always significance method must return True. """ histogram = Histogram(5) list(map(histogram.add, [1, 1, 1, 1, 1, 6, 7, 8, 9])) histogram.finalize() significance = Always() self.assertTrue(significance.isSignificant(0))
def testOneElementBinWidth(self): """ If a histogram is created with just one element, the bin width must be zero. """ h = Histogram() h.add(3) h.finalize() self.assertEqual(0.0, h.binWidth)
def testNoDataValue(self): """ If an element with no associated datum is added to a histogram, the value that is passed must be stored in the bin. """ h = Histogram(1) h.add(3) h.finalize() self.assertEqual([[3]], h.bins)
def testNineElementsInThreeBins(self): """ If a histogram is created with 9 elements placed into 2 bins, the bins must contain the expected values. """ h = Histogram(3) list(map(h.add, range(9))) h.finalize() self.assertEqual([[0, 1, 2], [3, 4, 5], [6, 7, 8]], h.bins)
def testGetItem(self): """ The __getitem__ method must return the correct bin. """ h = Histogram(3) list(map(h.add, range(9))) h.finalize() self.assertEqual([0, 1, 2], h[0]) self.assertEqual([3, 4, 5], h[1])
def testRepeatedFinalize(self): """ If finalize is called a second time, a RuntimeError must be raised. """ h = Histogram() error = ('^Histogram already finalized$') h.add(3) h.finalize() six.assertRaisesRegex(self, RuntimeError, error, h.finalize)
def testMaxBinHeightIsSignificantWhenNotSignificant(self): """ The isSignificant method must return False if asked about a bin that is not significant. """ histogram = Histogram(5) list(map(histogram.add, [1, 1, 1, 1, 1, 7, 8, 9])) histogram.finalize() significance = MaxBinHeight(histogram, SQUIRRELPOX, DB) self.assertFalse(significance.isSignificant(1))
def testTwoElementsBinWidth(self): """ If a histogram with 5 buckets is created with two elements that differ by 1.0, the bin width should be set to the correct value of 0.2. """ h = Histogram(5) h.add(3) h.add(4) h.finalize() self.assertEqual(0.2, h.binWidth)
def testElementIsStoredInBin(self): """ If a histogram is created with just one element and one bin, the exact element that was passed must be placed in the bin. """ element = object() h = Histogram(1) h.add(3, element) h.finalize() self.assertIs(element, h.bins[0][0])
def testAlwaysSignificanceAnalysis(self): """ The correct analysis must be provided. """ histogram = Histogram(5) list(map(histogram.add, [1, 1, 1, 1, 1, 6, 7, 8, 9])) histogram.finalize() significance = Always() self.assertEqual({'significanceMethod': 'Always'}, significance.analysis)
def testHashFractionIsSignificantWhenSignificant(self): """ The isSignificant method must return True if asked about a bin that is significant. """ histogram = Histogram(5) list(map(histogram.add, [1, 1, 1, 1, 1, 6, 7, 8, 9])) histogram.finalize() significance = HashFraction(histogram, 10, 0.1) self.assertTrue(significance.isSignificant(0))
def testMeanBinHeightIsSignificantWhenSignificant(self): """ The isSignificant method must return True if asked about a bin that is significant. """ histogram = Histogram(5) list(map(histogram.add, [1, 1, 1, 1, 1, 6, 7, 8, 9])) histogram.finalize() significance = MeanBinHeight(histogram, COWPOX, DB) self.assertTrue(significance.isSignificant(0))
def testOneElementMaxMin(self): """ If a histogram is created with just one element, the max and min should be set to that value. """ h = Histogram() h.add(3) h.finalize() self.assertEqual(3, h.max) self.assertEqual(3, h.min)
def testGetItemInvalidIndex(self): """ The __getitem__ method must raise IndexError if passed the index of a non-existent bin. """ h = Histogram(3) list(map(h.add, range(9))) h.finalize() six.assertRaisesRegex(self, IndexError, '^list index out of range$', h.__getitem__, 4)
def testMaxBinHeightSignificanceAnalysis(self): """ The correct analysis must be provided. """ histogram = Histogram(5) list(map(histogram.add, [1, 1, 1, 1, 1, 6, 7, 8, 9])) histogram.finalize() significance = MaxBinHeight(histogram, COWPOX, DB) self.assertEqual({'significanceCutoff': 0.0, 'significanceMethod': 'MaxBinHeight'}, significance.analysis)
def testAddDataAfterFinalized(self): """ If an attempt is made to add to a histogram that has been finalized, a RuntimeError must be raised. """ h = Histogram() error = ('^Additional data cannot be added: histogram already ' 'finalized$') h.add(3) h.finalize() six.assertRaisesRegex(self, RuntimeError, error, h.add, 3)
def testHashFractionSignificanceAnalysis(self): """ The correct analysis must be provided. """ histogram = Histogram(5) list(map(histogram.add, [1, 1, 1, 1, 1, 6, 7, 8, 9])) histogram.finalize() significance = HashFraction(histogram, 10, 0.1) self.assertEqual({'significanceCutoff': 1.0, 'significanceMethod': 'HashFraction'}, significance.analysis)
def testTwoElementsMaxMin(self): """ If a histogram is created with two elements, the max and min should be set to the correct values. """ h = Histogram() h.add(3) h.add(4) h.finalize() self.assertEqual(4, h.max) self.assertEqual(3, h.min)
def _checkPositiveNegative(self, nBins, values): """ When a set of values is put into a histogram, the bin counts that result must be the same (just with the order reversed) as those that result from a histogram made with the same set of values but with opposite sign. @param nBins: The C{int} number of bins to use in the histogram. @param values: A C{list} of values to insert into the histogram. """ # Make a histogram of the values and get all the bin counts. h1 = Histogram(nBins) for value in values: h1.add(value) h1.finalize() counts1 = [len(bin_) for bin_ in h1.bins] # Make a histogram of the negative values and get all the bin counts. h2 = Histogram(nBins) for value in [-x for x in values]: h2.add(value) h2.finalize() counts2 = [len(bin_) for bin_ in h2.bins] counts2.reverse() # Prepare a useful error message, in case there are any differences. differences = ['Counts differ'] for i in range(len(counts1)): if counts1[i] != counts2[i]: h1Low = h1.min + i * h1.binWidth h1High = h1Low + h1.binWidth h2Low = h2.min + i * h2.binWidth h2High = h2Low + h2.binWidth differences.append( ' bin %d (h1 bin range: %.7f to %.7f, h2 bin range: ' '%.7f to %.7f): count %d != count %d' % (i, h1Low, h1High, h2Low, h2High, counts1[i], counts2[i])) # Bin counts must be the same. self.assertEqual(counts1, counts2, '\n'.join(differences))
def testMeanBinHeightSignificanceAnalysis(self): """ The right analysis must be returned. """ histogram = Histogram(5) list(map(histogram.add, [1, 1, 1, 1, 1, 6, 7, 8, 9])) histogram.finalize() significance = MeanBinHeight(histogram, COWPOX, DB) self.assertEqual({'meanBinHeight': 0.0, 'significanceCutoff': 0.0, 'significanceMethod': 'MeanBinHeight', 'standardDeviation': 0.0}, significance.analysis)
def testAAFractionWhenSignificant(self): """ The isSignificant method must return True if asked about a bin that is significant. """ match = { 'subjectLandmark': Landmark('AlphaHelix', 'A', 0, 9), 'subjectTrigPoint': TrigPoint('Peaks', 'P', 21), 'queryLandmark': Landmark('AlphaHelix', 'A', 10, 9), 'queryTrigPoint': TrigPoint('Peaks', 'P', 25), } histogram = Histogram(1) histogram.add(0, match) histogram.finalize() significance = AAFraction(histogram, 10, 0.75) self.assertTrue(significance.isSignificant(0))
def testAAFractionSignificanceAnalysis(self): """ The correct analysis must be provided. """ match = { 'subjectLandmark': Landmark('AlphaHelix', 'A', 0, 9), 'subjectTrigPoint': TrigPoint('Peaks', 'P', 21), 'queryLandmark': Landmark('AlphaHelix', 'A', 10, 9), 'queryTrigPoint': TrigPoint('Peaks', 'P', 25), } histogram = Histogram(3) histogram.add(0, match) histogram.add(1, match) histogram.add(2, match) histogram.finalize() significance = AAFraction(histogram, 10, 0.75) self.assertTrue(significance.isSignificant(0)) self.assertEqual({'significanceCutoff': 7.5, 'significanceMethod': 'AAFraction'}, significance.analysis)
def testFiveBinsMinusTwoPointFiveToPlusTwoPointFiveIntermediates(self): """ If a histogram is created with 5 bins and a data range of -2.5 to +2.5 items that are added between histogram boundaries must be placed in the expected bins. """ for (value, expectedCounts) in ((-2, [1, 0, 0, 0, 0]), (-1, [0, 1, 0, 0, 0]), (+0, [0, 0, 1, 0, 0]), (+1, [0, 0, 0, 1, 0]), (+2, [0, 0, 0, 0, 1])): h = Histogram(5) h.add(-2.5) # Set min value. h.add(2.5) # Set max value. h.add(value) h.finalize() counts = [len(bin_) for bin_ in h.bins] # Subract 1 from the first and last bin counts, to adjust for the # -2.5 and 2.5 boundary values we added manually. counts[0] -= 1 counts[-1] -= 1 self.assertEqual(expectedCounts, counts)