0

to Gribouillis or someone else who wants to take a look:

my rotated function only works with square grids and not with grids with different height and width. I'm really stuck on this because everything else just works fine.

I think it has something to do with the initializing of my grid class or the __getitem__ method.

import os, glob
import csv
import sys

sys.path.append('G:\Afstuderen\Library')
from data_structure_6 import *

class Grid(object):
	def __init__(self, width, height):
		self.grid = []
		self.width = width
		self.height = height
		self.length = width * height
		for x in range(self.width):
			col = []
			for y in range(self.height):
				col.append(Cell(x, y, self.grid))
			self.grid.append(col)

	def __getitem__(self, (x, y)):
		return self.grid[x][y]

	def getCellValue(self, (x, y)):
		return self.grid[x][y].value

	def fillBlock(self, left, right, top, bottom, value):
		for x in range(left, right):
			for y in range(top, bottom):
				self[x, y].value = value

	def firstFreeCell(self):
		for y in range(self.height):
			for x in range(self.width):
				if self.grid[x][y].clusterId == -1:
					return self.grid[x][y]
		return None

	def floodFill(self, x, y, clusterId, landUse):
		if (x < 0 or y < 0 or x >= self.width or y >= self.height):
			return
		
		cell = self.grid[x][y]
		cluster = Cluster()
		if (cell.clusterId != -1 or cell.value != landUse):
			return
		
		cell.setClusterId(clusterId)
		cluster.add(cell)
		
		self.floodFill(x-1, y, clusterId, landUse)
		self.floodFill(x+1, y, clusterId, landUse)
		self.floodFill(x, y-1, clusterId, landUse)
		self.floodFill(x, y+1, clusterId, landUse)

	def analyze(self):
		freeCell = self.firstFreeCell()
		clusterId = 0
		
		while freeCell != None:
			self.floodFill(freeCell.x, freeCell.y, clusterId, freeCell.value)
			freeCell = self.firstFreeCell()
			clusterId += 1

	def printClusterId(self, clusterId):
		for y in range(self.height):
			for x in range(self.width):
				if self.grid[x][y].clusterId == clusterId:
					print 'ClusterId:', clusterId, '=>', 'Cell-coordinates:', 
					'(', self.grid[x][y].x, ',', self.grid[x][y].y, ')', 
					'with a landUse value of:', self.grid[x][y].value
		print "No cells with such clusterId left or the clusterId is not defined yet..."

	def load(cls, filename):
		loadGrid = []
		reader = csv.reader(open(filename), delimiter=';')
		for line in reader:
			loadGrid.append(line)
		width = len(loadGrid[0])
		height = len(loadGrid)
		grid = Grid(width, height)
		for x in range(width):
			for y in range(height):
				grid[x, y].value = loadGrid[y][x]
		return grid
	load = classmethod(load)

	def printGrid(self):
		for y in range(len(self.grid[0])):
			for x in range(len(self.grid)):
				print self.grid[x][y].value,
			print

	def clusterBoundingBoxCentroid(self, clusterId):
		x_values = []
		y_values = []
		for x in range(self.width):
			for y in range(self.height):
				if self.grid[x][y].clusterId == clusterId:
					x_values.append(self.grid[x][y].x)
					y_values.append(self.grid[x][y].y)
		print float(max(x_values)-min(x_values))/2 + min(x_values), float(max(y_values)-min(y_values))/2 + min(y_values)

	def clusterCentroid(self, clusterId):
		cluster = Cluster()
		for y in range(len(self.grid[0])):
			for x in range(len(self.grid)):
				if self.grid[x][y].clusterId == clusterId:
					cluster.add(self.grid[x][y])
		cluster_x = []
		cluster_y = []
		for i in range(len(cluster.cells)):
			cluster_x.append(cluster.cells[i].x)
		for i in range(len(cluster.cells)):
			cluster_y.append(cluster.cells[i].y)
		cx = float(sum(cluster_x))/len(cluster.cells)
		cy = float(sum(cluster_y))/len(cluster.cells)
		print cx, cy

	def clusterCentroidX(self, clusterId):
		cluster = Cluster()
		for y in range(len(self.grid[0])):
			for x in range(len(self.grid)):
				if self.grid[x][y].clusterId == clusterId:
					cluster.add(self.grid[x][y])
		cluster_x = []
		for i in range(len(cluster.cells)):
			cluster_x.append(cluster.cells[i].x)
		cx = float(sum(cluster_x))/len(cluster.cells)
		return cx

	def clusterCentroidY(self, clusterId):
		cluster = Cluster()
		for y in range(len(self.grid[0])):
			for x in range(len(self.grid)):
				if self.grid[x][y].clusterId == clusterId:
					cluster.add(self.grid[x][y])
		cluster_y = []
		for i in range(len(cluster.cells)):
			cluster_y.append(cluster.cells[i].y)
		cy = float(sum(cluster_y))/len(cluster.cells)
		return cy

	def rotated(self, n):
		L = self.toList()
		n %=4 
		if n ==0 :
			pass 
		elif n ==1 :
			L =[list (x )for x in zip (*reversed (L))]
		elif n ==2 :
			L =[list (reversed (x ))for x in reversed (L)]
		else :
			L =[list (x )for x in reversed (zip (*L))]
		return Grid.fromList(L)

	def toList(self):
		return [tuple(cell.value for cell in row) for row in self.grid]

	@staticmethod
	def fromList(L):
		height, width = len(L), len(L[0])
		self = Grid(width, height)
		for x in range(height):
			for y in range(width):
				self[(x, y)].value = L[x][y]
		return self

	def cutbb(self, left, right, top, bottom):
		# cut_grid heeft x, y coordinaten van 0 tot width, en 0 tot height
		cut_grid = Grid(right - left, bottom - top)
		for x in range(left, right):
			for y in range(top, bottom):
				if x < 0 or x >= self.width or y < 0 or y >= self.height:
					value = -1
				else:
					value = self[x, y].value
				cut_grid[x-left, y-top].value = value
		return cut_grid

	def cut(self, x, y, width, height):
		left = x - width // 2
		top = y - height // 2
		return self.cutbb(left, left + width, top, top + height)

	def cutFromTemplate(self, template):
		width = template.width
		height = template.height
		x = int(round(self.clusterCentroidX(1)))
		y = int(round(self.clusterCentroidY(1)))
		return self.cut(x, y, width, height)

	def compare(self, temp):
		score = 0
		cut = self.cutFromTemplate(temp)
		for x in range(cut.width):
			for y in range(cut.height):
				if cut[x, y].value == temp[x, y].value:
					if cut[x, y].value == '0':
						score += 1
					if cut[x, y].value == '1':
						score += 3
				if self[x, y].value != temp[x, y].value:
					score -= 1
		return score

	def assignTemplates(self):
		pass
		# Load templates for living_type = 1
		#templates_1 = []
		#for i in csv_list_1:
		#	i = Grid.load(i)
		#	templates_1.append(i)
		#print templates_1
		# Create a list of comparison scores to eventually get the maximum score
		#comparison_scores = []
		# Create comparison scores for 4 rotations
		#for template in templates_1:
		#	for rotation in range(4):
		#		score = self.compare(template.rotated(rotation))
		#		comparison_scores.append(score)
		#print comparison_scores
		# Print the comparison scores
		#print comparison_scores
		# Get the maximum value
		#m = max(comparison_scores)
		# Get the position (rotation index)
		#p = comparison_scores.index(m)
		# Print the maximum score, and the template belonging to the maximum score
		#print 'The comparison score is: ', m
		#print 'The cut out cluster:'
		#cut = self.cutFromTemplate(temp).printGrid()
		#print 'The best matching template:'
		#temp.rotated(p).printGrid()

class Cell(object):
	def __init__(self, x, y, grid):
		self.x = x
		self.y = y
		self.grid = grid
		self.value = 0
		self.clusterId = -1

	def setClusterId(self, clusterId):
		self.clusterId = clusterId

	def getClusterId(self):
		return self.clusterId

class Cluster(object):
	def __init__(self):
		self.cells = []

	def __getitem__(self):
		return self.cells[x][y]

	def add(self, i):
		self.cells.append(i)

target = Grid.load('target.csv')
target.printGrid()
print ('-'*20)

target.analyze()

# load a template (1.csv)

# Make a cut out of the original grid with center based on 
# the centroid of a given cluster, and a width and height
# defined through the width and height of the loaded template
#target.cutFromTemplate(template1)

# Compare the template and the cut out

my_grid = Grid(5, 3)
my_grid.printGrid()
my_grid.rotated(1)

Gives a list index out of range IndexError:

Traceback (most recent call last):
File "<string>", line 11, in ?
File "grid_cell_clusterc.py", line 276, in ?
my_grid.rotated(1)
File "grid_cell_clusterc.py", line 154, in rotated
return Grid.fromList(L)
File "grid_cell_clusterc.py", line 165, in fromList
self[(x, y)].value = L[x][y]
File "grid_cell_clusterc.py", line 21, in __getitem__
return self.grid[x][y]
IndexError: list index out of range

Hmm I'm kinda stuck with that part, the rest all works fine as long as I use square grids. If I could only get this rotated method to work on rectangular grids I would be much helped.

0

Ithink you should change

for x in range(height):
    for y in range(width):

to

for x in range(width):
    for y in range(height)

in the method fromList .

0

Yes, I tried this but it won't work still.

Somewhere in all my code there's something wrong with how i define columns and rows, and as for someone with my coding experience this piece of code is allready kind of big, I can't figure out where...I tried all kinds of stuff but I don't seem to get it working.

I'm now going to ask my tutor here maybe he can spot it... :S

0

I rewritten my rotation function and it works fine now...

I'm still working on this and I have a new question about my load method.

Say I have 2 different forms of csv files I want to load. Some are just representations of grids like before but there can also be a csv file which contains a first line where I want to give the x and y coordinate of a point (the centroid of all cells being 1).

So the old csv file can be this

0;0;0;0;0;0;0;0
0;0;0;0;0;0;0;0
0;0;0;0;0;0;0;0
0;0;0;0;0;0;0;0
0;0;0;1;1;1;0;0
0;0;0;1;1;1;0;0
0;0;0;1;1;1;0;0
0;0;0;0;0;0;0;0

And I also want to be able to load this csv file:

centroid;2;3
0;0;0;0;0;0;0;0
0;0;0;0;0;0;0;0
0;1;1;1;0;0;0;0
0;1;1;1;0;0;0;0
0;1;1;1;0;0;0;0
0;0;0;0;0;0;0;0
0;0;0;0;0;0;0;0
0;0;0;0;0;0;0;0

When loading the latter file I want something that notices the first line starts with 'centroid' or in some other way detect the difference this csv file is build and keep the x centroid = 2 and the y centroid = 3, and after that take all the following lines to make the grid:

0;0;0;0;0;0;0;0
0;0;0;0;0;0;0;0
0;1;1;1;0;0;0;0
0;1;1;1;0;0;0;0
0;1;1;1;0;0;0;0
0;0;0;0;0;0;0;0
0;0;0;0;0;0;0;0
0;0;0;0;0;0;0;0

just like it did before...

I've tried playing around a bit to get this but I'm not succeeding :P

import math
import csv

class Grid(object):
	def __init__(self, width, height):
		self.grid = []
		self.array = []
		self.width = width
		self.height = height
		self.length = width * height
		for x in range(self.width):
			col = []
			for y in range(self.height):
				cell = Cell(x, y, self)
				col.append(cell)
				self.array.append(cell)
			self.grid.append(col)

	def __getitem__(self, key):
		if hasattr(key, '__len__'):
			return self.grid[key[0]][key[1]]
		else:
			return self.array[key]

	def __len__(self):
		return len(self.array)

	def load(cls, filename):
		loadGrid = []
		fileObj = open(filename)
		text = fileObj.read(256)
		fileObj.seek(0)
		if text.count(',') > text.count(';'):
			foundDelimiter = ','
		else:
			foundDelimiter = ';'
		reader = csv.reader(fileObj, delimiter=foundDelimiter)
		for line in reader:
			loadGrid.append(line)
		width = len(loadGrid[0])
		height = len(loadGrid)
		grid = Grid(width, height)
		for x in range(width):
			for y in range(height):
				grid[x, y].value = loadGrid[y][x]
		return grid
	load = classmethod(load)

#def lookForOrigins(filename):
#	templateReader = csv.reader(open(filename), delimiter=';')
#	for row in templateReader:
#		if row[0] == 'centroid':
#			x_origin = row[1]
#			y_origin = row[2]
#	return int(x_origin), -int(y_origin)

	def rotated(self, n):
		source = self
		width = source.width
		height = source.height
		n %= 4
		if n == 0:
			return source
		if n == 1:
			destination = Grid(height, width)
			for x in range(destination.width):
				for y in range(destination.height):
					destination[x, y].value = source[y, destination.width-1-x].value
			return destination
		else:
			destination = self
			for i in range(n % 4):
				destination = destination.rotated(1)
			return destination

	def cutbb(self, left, right, top, bottom):
		# cut_grid heeft x, y, coordinaten van 0 tot width, en 0 tot height)
		cut_grid = Grid(right - left, bottom - top)
		for x in range(left, right):
			for y in range(top, bottom):
				if x < 0 or x >= self.width or y < 0 or y >= self.height:
					value = 0
				else:
					value = self[x, y].value
				cut_grid[x - left, y - top].value = value
		return cut_grid

	def cut(self, x, y, width, height):
		left = x - width // 2
		top = y - height // 2
		return self.cutbb(left, left+width, top, top + height)

	def printGrid(self):
		for y in range(len(self.grid[0])):
			for x in range(len(self.grid)):
				print self.grid[x][y].value,
			print

class Cell(object):
	def __init__(self, x, y, grid):
		self.x = x
		self.y = y
		self.grid = grid
		self.value = 0
		self.clusterId = -1

	def setClusterId(self, clusterId):
		self.clusterId = clusterId

	def getClusterId(self):
		return self.clusterId

my_grid = Grid.load('cut_test_grid.csv')
my_grid.printGrid()


#
#def rotateMatrix(x, y, n):
#	width = 8
#	n %= 4
#	if n == 0:
#		return x, -y
#	if n == 1:
#		new_x = x * math.cos(-90 * math.pi/180) -y * math.sin(-90 * math.pi/180) + width
#		new_y = x * math.sin(-90 * math.pi/180) + y * math.cos(-90 * math.pi/180)
#		return int(new_x), int(-new_y)
#	else:
#		newer_x = rotateMatrix(x, y, 1)[0]
#		newer_y = rotateMatrix(x, y, 1)[1]
#		for i in range(n % 4):
#			new_x = rotateMatrix(newer_x, -newer_y, i)[0]
#			new_y = rotateMatrix(newer_x, -newer_y, i)[1]
#		return new_x, new_y

Later I want to combine the rotate and rotateMatrix function to 1 function where I use the x and y centroid values to be rotated as well so I can keep track of the centroid after rotation.

But first things first, how do I detect if a csv file has a first line containing these coordinates, save them, and take all the other lines to generate a grid like I did before.

EDIT: this is just the short version of the whole program containing only the functionality I need to figure out this question...

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.