def main():
    option_parser, opts, args = parse_command_line_parameters(**script_info)

    # Create the output dir if it doesn't already exist.
    output_dir = opts.output_dir
    try:
        create_dir(output_dir)
    except:
        option_parser.error("Could not create or access output directory "
                            "specified with the -o/--output_dir option.")

    otu_table_fp = opts.otu_table_fp
    table = load_table(otu_table_fp)

    estimator = ObservationRichnessEstimator(table,
                                             Chao1MultinomialPointEstimator)
    results = estimator(opts.min, opts.max, opts.num_steps,
                        opts.confidence_level)

    out_fp = join(output_dir, 'estimates_table.txt')
    with open(out_fp, 'w') as out_f:
        results.toTable(out_f)
 def setUp(self):
     """Define some sample data that will be used by the tests."""
     # Single sample, 6 observations, one of which isn't observed in sample.
     self.biom_table1 = parse_biom_table(biom_table_str1)
     self.estimator1 = ObservationRichnessEstimator(
         self.biom_table1, Chao1MultinomialPointEstimator)
 def setUp(self):
     """Define some sample data that will be used by the tests."""
     # Single sample, 6 observations, one of which isn't observed in sample.
     self.biom_table1 = parse_biom_table(biom_table_str1)
     self.estimator1 = ObservationRichnessEstimator(self.biom_table1,
             Chao1MultinomialPointEstimator)
class ObservationRichnessEstimatorTests(TestCase):
    """Tests for the ObservationRichnessEstimator class."""
    def setUp(self):
        """Define some sample data that will be used by the tests."""
        # Single sample, 6 observations, one of which isn't observed in sample.
        self.biom_table1 = parse_biom_table(biom_table_str1)
        self.estimator1 = ObservationRichnessEstimator(
            self.biom_table1, Chao1MultinomialPointEstimator)

    def test_constructor(self):
        """Test instantiating an ObservationRichnessEstimator."""
        self.assertTrue(
            isinstance(self.estimator1, ObservationRichnessEstimator))

    def test_constructor_empty_table(self):
        """Test instantiating an estimator with an empty table."""
        empty_table = Table(array([]), [], [])
        self.assertRaises(EmptyTableError, ObservationRichnessEstimator,
                          empty_table, Chao1MultinomialPointEstimator)

    def test_getSampleCount(self):
        """Test estimator returns correct number of samples."""
        self.assertEqual(self.estimator1.getSampleCount(), 1)

    def test_call_interpolate(self):
        """Test __call__ computes correct estimates (interpolation)."""
        # Verified with iNEXT (http://glimmer.rstudio.com/tchsieh/inext/).
        # SE estimates differ because they use a different technique. SE
        # estimates have been verified against values in Colwell 2012 instead
        # (in separate unit tests).

        # Just reference.
        obs = self.estimator1(start=15, stop=15, num_steps=1)
        self.assertEqual(obs.getSampleCount(), 1)
        self.assertFloatEqual(
            obs.getEstimates('S1'),
            [(15, 5, 0.674199862463, 3.67859255119, 6.32140744881)])

        # start=1 and reference.
        obs = self.estimator1(start=1, stop=1, num_steps=1)
        self.assertEqual(obs.getSampleCount(), 1)
        self.assertFloatEqual(
            obs.getEstimates('S1'),
            [(1, 1.0, 0.250252397843, 0.509514313183, 1.49048568682),
             (15, 5, 0.674199862463, 3.67859255119, 6.32140744881)])

        # Points in between start=1 and reference.
        obs = self.estimator1(start=1, stop=15, num_steps=3)
        self.assertEqual(obs.getSampleCount(), 1)
        self.assertFloatEqual(
            obs.getEstimates('S1'),
            [(1, 1.0, 0.250252397843, 0.509514313183, 1.49048568682),
             (5, 3.40326340326, 0.655024590447, 2.119438797, 4.68708800953),
             (9, 4.4001998002, 0.680106580075, 3.0672153976, 5.7331842028),
             (13, 4.85714285714, 0.665379090563, 3.55302380357, 6.16126191071),
             (15, 5, 0.674199862463, 3.67859255119, 6.32140744881)])

    def test_call_extrapolate(self):
        """Test __call__ computes correct estimates (extrapolation)."""
        # Verified with iNEXT. Differs slightly from their output because
        # they've slightly modified Colwell 2012 equation 9, and we're using
        # the original one. SE estimates differ because they use a different
        # technique. SE estimates have been verified against values in Colwell
        # 2012 instead (in separate unit tests).

        obs = self.estimator1(start=15, stop=30, num_steps=1)
        self.assertEqual(obs.getSampleCount(), 1)
        self.assertFloatEqual(
            obs.getEstimates('S1'),
            [(15, 5, 0.674199862463, 3.67859255119, 6.32140744881),
             (30, 5.4415544562981095, 1.073911829557642, 3.33672594779,
              7.5463829648)])

        obs = self.estimator1(start=20, stop=30, num_steps=2)
        self.assertEqual(obs.getSampleCount(), 1)
        self.assertFloatEqual(
            obs.getEstimates('S1'),
            [(15, 5, 0.674199862463, 3.67859255119, 6.32140744881),
             (20, 5.2555272427983537, 0.77331345626875192, 3.73986071975,
              6.77119376585),
             (25, 5.38046614197245, 0.93220670591157662, 3.55337457224,
              7.20755771171),
             (30, 5.4415544562981095, 1.073911829557642, 3.33672594779,
              7.5463829648)])

    def test_get_points_to_estimate_invalid_input(self):
        """Raises an error on invalid input."""
        # Invalid min.
        self.assertRaises(ValueError, self.estimator1._get_points_to_estimate,
                          5, 0, 10, 1)

        # Invalid num_steps.
        self.assertRaises(ValueError, self.estimator1._get_points_to_estimate,
                          5, 1, 10, 0)

        # max < min.
        self.assertRaises(ValueError, self.estimator1._get_points_to_estimate,
                          5, 1, -1, 1)

    def test_get_points_to_estimate(self):
        """Correctly calculates estimation points given range parameters."""
        # Ref in range.
        obs = self.estimator1._get_points_to_estimate(4, 1, 5, 4)
        self.assertEqual(obs, [1, 2, 3, 4, 5])

        # Ref not in range.
        obs = self.estimator1._get_points_to_estimate(4, 5, 10, 2)
        self.assertEqual(obs, [4, 5, 7, 9])

        # stop not supplied.
        obs = self.estimator1._get_points_to_estimate(5, 5, num_steps=2)
        self.assertEqual(obs, [5, 17, 29])
class ObservationRichnessEstimatorTests(TestCase):
    """Tests for the ObservationRichnessEstimator class."""

    def setUp(self):
        """Define some sample data that will be used by the tests."""
        # Single sample, 6 observations, one of which isn't observed in sample.
        self.biom_table1 = parse_biom_table(biom_table_str1)
        self.estimator1 = ObservationRichnessEstimator(self.biom_table1,
                Chao1MultinomialPointEstimator)

    def test_constructor(self):
        """Test instantiating an ObservationRichnessEstimator."""
        self.assertTrue(isinstance(self.estimator1,
                                   ObservationRichnessEstimator))

    def test_constructor_empty_table(self):
        """Test instantiating an estimator with an empty table."""
        empty_table = Table(array([]), [], [])
        self.assertRaises(EmptyTableError, ObservationRichnessEstimator,
                          empty_table, Chao1MultinomialPointEstimator)

    def test_getSampleCount(self):
        """Test estimator returns correct number of samples."""
        self.assertEqual(self.estimator1.getSampleCount(), 1)

    def test_call_interpolate(self):
        """Test __call__ computes correct estimates (interpolation)."""
        # Verified with iNEXT (http://glimmer.rstudio.com/tchsieh/inext/).
        # SE estimates differ because they use a different technique. SE
        # estimates have been verified against values in Colwell 2012 instead
        # (in separate unit tests).

        # Just reference.
        obs = self.estimator1(start=15, stop=15, num_steps=1)
        self.assertEqual(obs.getSampleCount(), 1)
        self.assertFloatEqual(obs.getEstimates('S1'),
                [(15, 5, 0.674199862463, 3.67859255119, 6.32140744881)])

        # start=1 and reference.
        obs = self.estimator1(start=1, stop=1, num_steps=1)
        self.assertEqual(obs.getSampleCount(), 1)
        self.assertFloatEqual(obs.getEstimates('S1'),
                [(1, 1.0, 0.250252397843, 0.509514313183, 1.49048568682),
                 (15, 5, 0.674199862463, 3.67859255119, 6.32140744881)])

        # Points in between start=1 and reference.
        obs = self.estimator1(start=1, stop=15, num_steps=3)
        self.assertEqual(obs.getSampleCount(), 1)
        self.assertFloatEqual(obs.getEstimates('S1'),
                [(1, 1.0, 0.250252397843, 0.509514313183, 1.49048568682),
                 (5, 3.40326340326, 0.655024590447, 2.119438797,
                  4.68708800953),
                 (9, 4.4001998002, 0.680106580075, 3.0672153976, 5.7331842028),
                 (13, 4.85714285714, 0.665379090563, 3.55302380357,
                  6.16126191071),
                 (15, 5, 0.674199862463, 3.67859255119, 6.32140744881)])

    def test_call_extrapolate(self):
        """Test __call__ computes correct estimates (extrapolation)."""
        # Verified with iNEXT. Differs slightly from their output because
        # they've slightly modified Colwell 2012 equation 9, and we're using
        # the original one. SE estimates differ because they use a different
        # technique. SE estimates have been verified against values in Colwell
        # 2012 instead (in separate unit tests).

        obs = self.estimator1(start=15, stop=30, num_steps=1)
        self.assertEqual(obs.getSampleCount(), 1)
        self.assertFloatEqual(obs.getEstimates('S1'),
                [(15, 5, 0.674199862463, 3.67859255119, 6.32140744881),
                 (30, 5.4415544562981095, 1.073911829557642, 3.33672594779,
                  7.5463829648)])

        obs = self.estimator1(start=20, stop=30, num_steps=2)
        self.assertEqual(obs.getSampleCount(), 1)
        self.assertFloatEqual(obs.getEstimates('S1'),
                [(15, 5, 0.674199862463, 3.67859255119, 6.32140744881),
                 (20, 5.2555272427983537, 0.77331345626875192, 3.73986071975,
                  6.77119376585),
                 (25, 5.38046614197245, 0.93220670591157662, 3.55337457224,
                  7.20755771171),
                 (30, 5.4415544562981095, 1.073911829557642, 3.33672594779,
                  7.5463829648)])

    def test_get_points_to_estimate_invalid_input(self):
        """Raises an error on invalid input."""
        # Invalid min.
        self.assertRaises(ValueError, self.estimator1._get_points_to_estimate,
                          5, 0, 10, 1)

        # Invalid num_steps.
        self.assertRaises(ValueError, self.estimator1._get_points_to_estimate,
                          5, 1, 10, 0)

        # max < min.
        self.assertRaises(ValueError, self.estimator1._get_points_to_estimate,
                          5, 1, -1, 1)

    def test_get_points_to_estimate(self):
        """Correctly calculates estimation points given range parameters."""
        # Ref in range.
        obs = self.estimator1._get_points_to_estimate(4, 1, 5, 4)
        self.assertEqual(obs, [1, 2, 3, 4, 5])

        # Ref not in range.
        obs = self.estimator1._get_points_to_estimate(4, 5, 10, 2)
        self.assertEqual(obs, [4, 5, 7, 9])

        # stop not supplied.
        obs = self.estimator1._get_points_to_estimate(5, 5, num_steps=2)
        self.assertEqual(obs, [5, 17, 29])