def estimate(self, xs, max_iterations=10000):
        self.n = len(xs)
        self.s2 = invgamma.rvs(self.alpha, scale=self.beta)
        self.means = []
        response_sums = []
        self.counts = []
        assignments = []

        assignments.append(0)
        response_sums.append(xs[0])
        self.counts.append(1)
        self.means.append(self.sample_posterior_mean(response_sums[0], 1,
                                                     self.s2, self.m0,
                                                     self.s20))

        for i in range(1, len(xs)):
            weights = self.__create_weight_vector(xs[i], self.means,
                                                  self.counts, self.s2,
                                                  self.m0, self.s20,
                                                  self.m)
            # Sample an assignment for each item and update statistics
            assignment = multinomial_sampling.sample(weights)
            if assignment < len(self.means):
                response_sums[assignment] += xs[i]
                self.counts[assignment] += 1

            # Create a new component
            elif assignment == len(self.means):
                response_sums.append(xs[i])
                self.counts.append(1)
                self.means.append(self.sample_posterior_mean(xs[i], 1,
                                                             self.s2, self.m0,
                                                             self.s20))
            else:
                print("WWWWW Should never get here. WWWWWW")
            assignments.append(assignment)

        for i in xrange(max_iterations):
            # First sample an assignment for each data item

            for j in xrange(len(xs)):
                old_assignment = assignments[j]
                response_sums[old_assignment] -= xs[j]
                self.counts[old_assignment] -= 1

                if self.counts[old_assignment] == 0:
                    self.__fix_hole(assignments, response_sums, self.means,
                                    self.counts, old_assignment)
                weights = self.__create_weight_vector(xs[j], self.means,
                                                      self.counts,
                                                      self.s2, self.m0,
                                                      self.s20, self.m)
                new_assignment = multinomial_sampling.sample(weights)
                # Create a new component
                if new_assignment < len(self.means):
                    response_sums[new_assignment] += xs[j]
                    self.counts[new_assignment] += 1
                elif new_assignment == len(self.means):
                    response_sums.append(xs[j])
                    self.counts.append(1)
                    self.means.append(self.sample_posterior_mean(xs[j], 1,
                                                                 self.s2,
                                                                 self.m0,
                                                                 self.s20))
                else:
                    print("EEEEEEE This should never happenEEEEEEEEEE")
                assignments[j] = new_assignment

            # Sample new values for the means
            for j in xrange(len(self.means)):
                self.means[j] = self.sample_posterior_mean(response_sums[j],
                                                           self.counts[j],
                                                           self.s2, self.m0,
                                                           self.s20)

            # Sample new value for the component variance
            res_sum_squares = self.calculate_res_sum_squares(xs, assignments,
                                                             self.means)
            self.s2 = self.sample_posterior_var(self.n, res_sum_squares,
                                                self.alpha, self.beta)
        return self
 def __rv(self, weights):
     s = multinomial_sampling.sample(weights)
     if s < len(self.means):  # Draw from a component
         return norm.rvs(self. means[s], scale=sqrt(self.s2))
     else:                    # Draw from the marginal
         return norm.rvs(self.m0, scale=sqrt(self.s20 + self.s2))