def __init__(self, G_input, cap, dr):
     self.G = G_input
     self.capacities = cap
     self.dissipation_rate = dr
     self.pile = Sandpile(self.G, self.capacities, self.dissipation_rate)
	def __init__(self, G_input, cap, dr):
		self.G = G_input
		self.capacities = cap
		self.dissipation_rate = dr
		self.pile = Sandpile(self.G, self.capacities, self.dissipation_rate)
class AnalyzeSandpile:
    def __init__(self, G_input, cap, dr):
        self.G = G_input
        self.capacities = cap
        self.dissipation_rate = dr
        self.pile = Sandpile(self.G, self.capacities, self.dissipation_rate)

    def __repr__(self):
        return 'Sandpile({0}, dissipation {1})'.format( ` self.G `,
                                                        self.dissipation_rate)

    def run_transients(self, transients):
        # Transients
        for i in xrange(transients):
            self.pile.add_sand(False)

    def record_topplings(self, time_steps, file_name, plot_results=False):
        # Record # topplings
        topple_data = []
        num_sands_data = []
        for i in xrange(time_steps):
            topple_count = self.pile.add_sand(False)
            num_sands_data.append(self.pile.number_of_sands())
            if topple_count > 0:
                topple_data.append(topple_count)

        if self.G.number_of_nodes() <= 50:
            print('Sands: ' + ` self.pile.get_sands() `)
            print('Final capacities: ' + ` self.capacities `)
        else:
            random_50_indices = rnd.sample(range(self.G.number_of_nodes()), 50)
            print(
                '50 of the sands: ' +
                ` [self.pile.get_sands_at_node(i)
                   for i in random_50_indices] `)
            print('50 of the capacities: ' +
                  ` [self.capacities[i] for i in random_50_indices] `)
        if time_steps < 50:
            print('Topplings: ' + ` topple_data `)
        else:
            print('Last 50 topplings: ' + ` topple_data[-50:-1] `)

        log_bins = [
            10.0**(float(x) / 5.0)
            for x in xrange(5 * (1 + int(np.log10(max(topple_data)))))
        ]
        log_binned_data = np.histogram(topple_data, log_bins, normed=True)

        # Write the results to a file
        fw = open(file_name + '.txt', 'w')
        fw.write( ` topple_data `)
        fw.close()

        # Convert the topple data to be readable by Mathematica
        fs = open(file_name + '.txt', 'r')
        fo = open(file_name + '_converted.txt', 'w')

        char = fs.read(1)
        while char != '':
            if char == '[':
                fo.write('{')
            elif char == ']':
                fo.write('}')
            elif char == '\'':
                fo.write('"')
            else:
                fo.write(char)
            char = fs.read(1)

        fs.close()
        fo.close()

        if plot_results == True:
            self.plot_topple_data(topple_data, log_binned_data, time_steps,
                                  file_name)

        return topple_data

    def plot_topple_data(self, topple_data, log_binned_data, time_steps,
                         file_name):
        # Clear the current figure
        plt.clf()

        # log y axis
        #plt.subplot(211)
        #plt.hist(topple_data, bins=10, range=None, normed=True, cumulative=False, bottom=None, histtype='step', align='mid', orientation='vertical', rwidth=None, log=True)
        #plt.title('Histogram')

        #plt.subplot(312)
        #plt.hist(map(lambda x: np.log(x),topple_data), bins=len(log_bins), range=None, normed=True, cumulative=False, bottom=None, histtype='step', align='mid', orientation='vertical', rwidth=None, log=True)
        #plt.title('Histogram')

        plt.subplot(2, 3, 1)
        plt.loglog(log_binned_data[1][0:-1], log_binned_data[0], marker='o')
        plt.grid(True)
        plt.xlabel('Avalanche size')
        plt.ylabel('Probability')
        plt.title( ` sum(topple_data) ` + ' Topplings')

        plt.subplot(2, 3, 4)
        plt.title(
            'Degrees (max = ' + ` max(self.G.degree().values()) ` + ')'
        )  #+', ave = '+str(round(np.average(self.G.degree().values()),3))+')')
        plt.ylabel('degree')
        plt.xlabel('rank')
        plt.loglog(sorted(nx.degree(self.G).values(), reverse=True),
                   'b-',
                   marker='o')

        plt.subplot(2, 3, 3)
        plt.title('Sands over time')
        plt.ylabel('# sands')
        plt.xlabel('time')
        #plt.plot(xrange(time_steps), num_sands_data)

        plt.subplot(2, 3, 2)
        plt.title('Proximity to toppling')
        plt.ylabel('sands & capacity')
        plt.xlabel('degree rank')
        node_degrees = np.array([(i, self.G.degree(i))
                                 for i in self.G.nodes()],
                                dtype=[('label', int), ('degree', int)])
        nodes_sorted_by_degrees = map(lambda x: x[0],
                                      np.sort(node_degrees, order='degree'))
        sand_bars = [
            self.pile.get_sands_at_node(i) for i in nodes_sorted_by_degrees
        ]
        capacity_minus_sand_bars = [
            self.capacities[i] - self.pile.get_sands_at_node(i)
            for i in nodes_sorted_by_degrees
        ]
        plt.bar(nodes_sorted_by_degrees, sand_bars, width=1, color='r')
        plt.bar(nodes_sorted_by_degrees,
                capacity_minus_sand_bars,
                width=1,
                color='b',
                bottom=sand_bars)

        plt.subplot(2, 3, 5)
        plt.title('Capacities')  #(max:'+`max(self.capacities)`+')')
        plt.ylabel('capacity')
        plt.xlabel('rank')
        #plt.loglog(sorted(original_capacities, reverse=True),'b-',marker='o')
        plt.loglog(sorted(self.pile.get_capacities(), reverse=True),
                   'r-',
                   marker='^')

        plt.subplot(2, 3, 6)
        plt.title( ` sum(self.pile.get_capacity_changes()) ` + ' cap. changes')
        plt.ylabel('capacity change')
        plt.xlabel('which node')
        #plt.plot(xrange(self.G.number_of_nodes()), self.pile.get_capacity_changes())

        plt.subplots_adjust(hspace=.8, wspace=.8)
        plt.suptitle(
            ` self.G.number_of_nodes() ` + ' nodes, dissipation rate = ' +
            str(round(self.dissipation_rate, 3)) + ',  ' + ` time_steps ` +
            ' grains dropped',
            fontsize=12)
        #(after '+`transients`+' transients)'

        #total_time = time.time()-beginTime
        #print('{0:.3f} seconds, {1:.3f} minutes, {2:.3f} hours.'.format(total_time, total_time/60.0, total_time/3600.0))

        #plt.show()
        plt.savefig(file_name)
class AnalyzeSandpile:
	def __init__(self, G_input, cap, dr):
		self.G = G_input
		self.capacities = cap
		self.dissipation_rate = dr
		self.pile = Sandpile(self.G, self.capacities, self.dissipation_rate)

	def __repr__(self):
		return 'Sandpile({0}, dissipation {1})'.format(`self.G`, self.dissipation_rate)

	def run_transients(self, transients):
		# Transients
		for i in xrange(transients):
			self.pile.add_sand(False)
		
	def record_topplings(self, time_steps, file_name, plot_results = False):
		# Record # topplings
		topple_data = []
		num_sands_data = []
		for i in xrange(time_steps):
			topple_count = self.pile.add_sand(False)
			num_sands_data.append(self.pile.number_of_sands())
			if topple_count > 0:
				topple_data.append(topple_count)
		
		if self.G.number_of_nodes() <= 50:
			print('Sands: '+`self.pile.get_sands()`)
			print('Final capacities: '+`self.capacities`)
		else:
			random_50_indices = rnd.sample(range(self.G.number_of_nodes()),50)
			print('50 of the sands: '+`[self.pile.get_sands_at_node(i) for i in random_50_indices]`)
			print('50 of the capacities: '+`[self.capacities[i] for i in random_50_indices]`)
		if time_steps < 50:
			print('Topplings: '+`topple_data`)
		else:
			print('Last 50 topplings: '+`topple_data[-50:-1]`)
		
		log_bins = [10.0**(float(x)/5.0) for x in xrange(5*(1+int(np.log10(max(topple_data)))))]
		log_binned_data = np.histogram(topple_data, log_bins, normed = True)
		
		# Write the results to a file
		fw = open(file_name+'.txt', 'w')
		fw.write(`topple_data`)
		fw.close()
		
		# Convert the topple data to be readable by Mathematica
		fs = open(file_name+'.txt','r')
		fo = open(file_name+'_converted.txt','w')
		
		char = fs.read(1)
		while char != '':
			if char == '[':
				fo.write('{')
			elif char == ']':
				fo.write('}')
			elif char == '\'':
				fo.write('"')
			else:
				fo.write(char)
			char = fs.read(1)
			
		fs.close()
		fo.close()
		
		if plot_results == True:
			self.plot_topple_data(topple_data, log_binned_data, time_steps, file_name)
		
		return topple_data

	def plot_topple_data(self, topple_data, log_binned_data, time_steps, file_name):	
		# Clear the current figure
		plt.clf()
		
		# log y axis
		#plt.subplot(211)
		#plt.hist(topple_data, bins=10, range=None, normed=True, cumulative=False, bottom=None, histtype='step', align='mid', orientation='vertical', rwidth=None, log=True)
		#plt.title('Histogram')
		
		#plt.subplot(312)
		#plt.hist(map(lambda x: np.log(x),topple_data), bins=len(log_bins), range=None, normed=True, cumulative=False, bottom=None, histtype='step', align='mid', orientation='vertical', rwidth=None, log=True)
		#plt.title('Histogram')
		
		plt.subplot(2,3,1)
		plt.loglog(log_binned_data[1][0:-1], log_binned_data[0], marker = 'o')
		plt.grid(True)
		plt.xlabel('Avalanche size')
		plt.ylabel('Probability')
		plt.title(`sum(topple_data)`+' Topplings')
		
		plt.subplot(2,3,4)
		plt.title('Degrees (max = '+`max(self.G.degree().values())`+')')#+', ave = '+str(round(np.average(self.G.degree().values()),3))+')')
		plt.ylabel('degree')
		plt.xlabel('rank')
		plt.loglog(sorted(nx.degree(self.G).values(),reverse=True),'b-',marker='o')
		
		plt.subplot(2,3,3)
		plt.title('Sands over time')
		plt.ylabel('# sands')
		plt.xlabel('time')
		#plt.plot(xrange(time_steps), num_sands_data)
		
		plt.subplot(2,3,2)
		plt.title('Proximity to toppling')
		plt.ylabel('sands & capacity')
		plt.xlabel('degree rank')
		node_degrees = np.array([(i, self.G.degree(i)) for i in self.G.nodes()], dtype = [('label', int), ('degree', int)])
		nodes_sorted_by_degrees = map(lambda x: x[0], np.sort(node_degrees, order = 'degree'))
		sand_bars = [self.pile.get_sands_at_node(i) for i in nodes_sorted_by_degrees]
		capacity_minus_sand_bars = [self.capacities[i] - self.pile.get_sands_at_node(i) for i in nodes_sorted_by_degrees]
		plt.bar(nodes_sorted_by_degrees, sand_bars, width = 1, color ='r')
		plt.bar(nodes_sorted_by_degrees, capacity_minus_sand_bars, width = 1, color ='b', bottom=sand_bars)
		
		plt.subplot(2,3,5)
		plt.title('Capacities')#(max:'+`max(self.capacities)`+')')
		plt.ylabel('capacity')
		plt.xlabel('rank')
		#plt.loglog(sorted(original_capacities, reverse=True),'b-',marker='o')
		plt.loglog(sorted(self.pile.get_capacities(), reverse=True), 'r-', marker='^') 
		
		plt.subplot(2,3,6)
		plt.title(`sum(self.pile.get_capacity_changes())`+' cap. changes')
		plt.ylabel('capacity change')
		plt.xlabel('which node')
		#plt.plot(xrange(self.G.number_of_nodes()), self.pile.get_capacity_changes())
		
		plt.subplots_adjust(hspace=.8, wspace=.8)
		plt.suptitle(`self.G.number_of_nodes()`+' nodes, dissipation rate = '+str(round(self.dissipation_rate,3))+',  '+`time_steps`+' grains dropped',fontsize=12)
		#(after '+`transients`+' transients)'
		
		#total_time = time.time()-beginTime
		#print('{0:.3f} seconds, {1:.3f} minutes, {2:.3f} hours.'.format(total_time, total_time/60.0, total_time/3600.0))
	
		#plt.show()
		plt.savefig(file_name)