diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..570f03f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +oldimages/ +.spyproject/ diff --git a/model.py b/model.py index b1d7851..aa00799 100644 --- a/model.py +++ b/model.py @@ -13,7 +13,8 @@ import random import xml.etree.ElementTree as ET import collections -import uuid # used for tracking experiments +import logging +import uuid try: import Image @@ -22,6 +23,10 @@ hackstring = "" hackcount = 0 + +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + class Model: def __init__(self, width, height): @@ -48,6 +53,8 @@ def __init__(self, width, height): self.observe_count = 0 self.count_prop_passes = 0 + + self.SAVE_IN_PROGRESS = False def Observe(self): self.observe_count += 1 @@ -142,7 +149,8 @@ def Run(self, seed, limit): while(presult): presult = self.Propagate() - self.Graphics().save("in_progress_{0}_{1}.png".format(hackstring, hackcount), format="PNG") + if self.SAVE_IN_PROGRESS: + self.Graphics().save("in_progress_{0}_{1}.png".format(hackstring, hackcount), format="PNG") hackcount += 1 #print("Propagate: {0}".format(pcount)) @@ -169,7 +177,7 @@ def Graphics(self): class OverlappingModel(Model): - def __init__(self, width, height, name, N_value = 2, periodic_input_value = True, periodic_output_value = False, symmetry_value = 8, ground_value = 0): + def __init__(self, width, height, name, N_value = 2, periodic_input_value = True, periodic_output_value = False, symmetry_value = 8, ground_value = 0, additional_samples=[], additional_periodic="", antipatterns=""): """ Initializes the model. """ @@ -177,29 +185,53 @@ def __init__(self, width, height, name, N_value = 2, periodic_input_value = True self.propagator = [[[[]]]] self.N = N_value self.periodic = periodic_output_value - self.bitmap = Image.open("samples/{0}.png".format(name)) - self.SMX = self.bitmap.size[0] - self.SMY = self.bitmap.size[1] - - # .sample is an array of arrays that holds the index values for colors - # as found in the source image - self.sample = [[0 for _ in range(self.SMY)] for _ in range(self.SMX)] - # .colors is the list of colors that are found in the source image - self.colors = [] + self.bitmaps = [Image.open("samples/{0}.png".format(name)).convert("RGBA")] + self.SMXs = [self.bitmaps[0].size[0]] + self.SMYs = [self.bitmaps[0].size[1]] + self.samples = [[[0 for _ in range(self.SMYs[0])] for _ in range(self.SMXs[0])]] + + self.antipattern_flags = [int(x) for x in list(antipatterns.ljust(len(additional_samples) + 1, '0'))] + print(self.antipattern_flags) + + add_periodic = 0 + if periodic_input_value: + add_periodic = 1 + self.periodic_flags = [add_periodic] + [int(x) for x in list(additional_periodic.ljust(len(additional_samples), str(add_periodic)))] + print(self.periodic_flags) + + for additional in additional_samples: + self.bitmaps.append(Image.open("samples/{0}.png".format(additional)).convert("RGBA")) + add_index = len(self.bitmaps)-1 + self.SMXs.append(self.bitmaps[add_index].size[0]) + self.SMYs.append(self.bitmaps[add_index].size[1]) + self.samples.append([[0 for _ in range(self.SMYs[add_index])] for _ in range(self.SMXs[add_index])]) - # This initializes the .sample array with the color index values. - # It loops over the pixels in the source bitmap, adds the color to the - # list of colors if it is new, and sets the .sample x,y value to the - # index of the color in the list of colors. - for y in range(0, self.SMY): - for x in range(0, self.SMX): - a_color = self.bitmap.getpixel((x, y)) - color_exists = [c for c in self.colors if c == a_color] - if len(color_exists) < 1: - self.colors.append(a_color) - samp_result = [i for i,v in enumerate(self.colors) if v == a_color] - self.sample[x][y] = samp_result +# self.antibitmaps = [] +# self.aSMXs = [] +# self.aSMYs = [] +# self.antisamples = [] +# for anti in antipatterns: +# self.antibitmaps.append(Image.open("samples/{0}.png".format(anti))) +# add_index = len(self.antibitmaps)-1 +# self.SMXs.append(self.antibitmaps[add_index].size[0]) +# self.SMYs.append(self.antibitmaps[add_index].size[1]) +# self.antisamples.append([[0 for _ in range(self.aSMYs[add_index])] for _ in range(self.aSMXs[add_index])]) + + + + self.colors = [] + for samp_n in range(len(self.bitmaps)): + for y in range(0, self.SMYs[samp_n]): + for x in range(0, self.SMXs[samp_n]): + a_color = self.bitmaps[samp_n].getpixel((x, y)) + color_exists = [c for c in self.colors if c == a_color] + if len(color_exists) < 1: + self.colors.append(a_color) + samp_result = [i for i,v in enumerate(self.colors) if v == a_color] + self.samples[samp_n][x][y] = samp_result + for c in self.colors: + print(c) self.color_count = len(self.colors) self.W = StuffPower(self.color_count, self.N * self.N) @@ -208,9 +240,14 @@ def __init__(self, width, height, name, N_value = 2, periodic_input_value = True self.patterns= [[]] #self.ground = 0 - # A helper function to extract the neighboring cells from the sample - # matrix. Takes a function that translates (dx,dy) into a reference to - # a cell in the matrix. + # Additional samples can individually be marked as periodic/non-periodic + #periodic_input_values = [periodic_input_value] + #for _ in range(len(self.bitmaps)): + # periodic_input_values.append(periodic_input_value) + #for idx_peri, peri in enumerate(additional_periodic): + # periodic_input_values[idx_peri + 1] = ((1 == peri) or ('T' == peri) or ('True' == peri)) + + def FuncPattern(passed_func): result = [0 for _ in range(self.N * self.N)] for y in range(0, self.N): @@ -220,12 +257,9 @@ def FuncPattern(passed_func): pattern_func = FuncPattern - def PatternFromSample(x, y): - ''' - Takes the sample and returns the pattern for that (x,y) location. - ''' + def PatternFromSample(x, y, n=0): def innerPattern(dx, dy): - return self.sample[(x + dx) % self.SMX][(y + dy) % self.SMY] + return self.samples[n][(x + dx) % self.SMXs[n]][(y + dy) % self.SMYs[n]] return pattern_func(innerPattern) def Rotate(p): ''' @@ -254,7 +288,7 @@ def Index(p): def PatternFromIndex(ind): ''' - Takes a pattern index and returns the pattern byte power index. + Takes a pattern index and returns the pattern byte array. ''' residue = ind power = self.W @@ -270,50 +304,96 @@ def PatternFromIndex(ind): self.weights = collections.Counter() ordering = [] + antiordering = [] + self.anti_adjacency = [] - # This chunk converts the sample to patterns. - # SMX and SMY are the sample size x and y. - # if periodic_input_value is true, the source image wraps around - ylimit = self.SMY - self.N + 1 - xlimit = self.SMX - self.N + 1 - if True == periodic_input_value: - ylimit = self.SMY - xlimit = self.SMX - for y in range (0, ylimit): - for x in range(0, xlimit): - ps = [0 for _ in range(8)] - ps[0] = PatternFromSample(x,y) - ps[1] = Reflect(ps[0]) - ps[2] = Rotate(ps[0]) - ps[3] = Reflect(ps[2]) - ps[4] = Rotate(ps[2]) - ps[5] = Reflect(ps[4]) - ps[6] = Rotate(ps[4]) - ps[7] = Reflect(ps[6]) - for k in range(0,symmetry_value): - ind = Index(ps[k]) - indexed_weight = collections.Counter({ind : 1}) - self.weights = self.weights + indexed_weight - if not ind in ordering: - ordering.append(ind) - + for samp_n in range(len(self.bitmaps)): + ylimit = self.SMYs[samp_n] - self.N + 1 + xlimit = self.SMXs[samp_n] - self.N + 1 + if 1 == self.periodic_flags[samp_n]: + ylimit = self.SMYs[samp_n] + xlimit = self.SMXs[samp_n] + for y in range (0, ylimit): + for x in range(0, xlimit): + ps = [0 for _ in range(8)] + ps[0] = PatternFromSample(x,y,samp_n) + ps[1] = Reflect(ps[0]) + ps[2] = Rotate(ps[0]) + ps[3] = Reflect(ps[2]) + ps[4] = Rotate(ps[2]) + ps[5] = Reflect(ps[4]) + ps[6] = Rotate(ps[4]) + ps[7] = Reflect(ps[6]) + for k in range(0,symmetry_value): + ind = Index(ps[k]) + logger.info('pattern: ' + str(ps[k]) + ' index ' + str(ind)) + if 1 == self.antipattern_flags[samp_n]: + if not ind in antiordering: + antiordering.append(ind) + indexed_weight = collections.Counter({ind : 1}) + self.weights = self.weights + indexed_weight + if not ind in ordering: + ordering.append(ind) + + for indo, o in enumerate(ordering): + print(indo, o, PatternFromIndex(o)) self.T = len(self.weights) - self.ground = int((ground_value + self.T) % self.T) + self.ground = (102,106)# int((ground_value + self.T) % self.T) + print('self.ground',self.ground) self.patterns = [[None] for _ in range(self.T)] self.stationary = [None for _ in range(self.T)] self.propagator = [[[[0]]] for _ in range(2 * self.N - 1)] + self.antipatterns = [[None] for _ in antiordering] + + for w in antiordering: + self.antipatterns.append(PatternFromIndex(w)) + counter = 0 for w in ordering: self.patterns[counter] = PatternFromIndex(w) self.stationary[counter] = self.weights[w] counter += 1 + for samp_n in range(len(self.bitmaps)): + if 1 == self.antipattern_flags[samp_n]: + #print('sample #',samp_n) + ylimit = self.SMYs[samp_n] - self.N + 1 + xlimit = self.SMXs[samp_n] - self.N + 1 + if 1 == self.periodic_flags[samp_n]: + ylimit = self.SMYs[samp_n] + xlimit = self.SMXs[samp_n] + #print('limits',xlimit, ylimit, self.periodic_flags[samp_n]) + for py in range (0, ylimit): + for px in range(0, xlimit): + pattern_one = PatternFromIndex(Index(PatternFromSample(px,py,samp_n))) + print('pattern_one', pattern_one) + for tx in range(1 - self.N, self.N): + for ty in range(1 - self.N,self.N): + #print(tx,ty) + if not (tx == 0 and ty == 0): + if (1 == self.periodic_flags[samp_n]) or ((px + tx >= 0) and (py + ty >= 0) and (px + tx < xlimit) and (py + ty < ylimit)): + pattern_two = PatternFromIndex(Index(PatternFromSample(px+tx,py+ty,samp_n))) + #print('pattern_two', pattern_two, px + tx, py + ty, tx, ty) + self.anti_adjacency.append((pattern_one, pattern_two, (tx, ty))) + #print('create antipattern', (pattern_one, pattern_two, (tx, ty))) + for x in range(0, self.FMX): for y in range(0, self.FMY): self.wave[x][y] = [False for _ in range(self.T)] + + def Disallowed(p1, p2, dx, dy): + #print(p1,p2,'\n---\n') + for anti_adj in self.anti_adjacency: + #print(anti_adj) + if (anti_adj[0] == p1 and anti_adj[1] == p2): + if dx == anti_adj[2][0] and dy == anti_adj[2][1]: + print('antipattern:',p1,p2,dx,dy,'\n',anti_adj,'\n') + return True + return False + def Agrees(p1, p2, dx, dy): ifany = True xmin = dx @@ -329,25 +409,39 @@ def Agrees(p1, p2, dx, dy): for y in range(ymin, ymax): for x in range(xmin, xmax): if p1[x + self.N * y] != p2[x - dx + self.N * (y - dy)]: - print(p1[x + self.N * y] != p2[x - dx + self.N * (y - dy)]) + logger.debug(p1[x + self.N * y] != p2[x - dx + self.N * (y - dy)]) ifany = False #return False return ifany #return True for x in range(0, 2 * self.N - 1): + #print('x',x) self.propagator[x] = [[[0]] for _ in range(2 * self.N - 1)] for y in range(0, 2 * self.N - 1): + #print('y',y) self.propagator[x][y] = [[0] for _ in range(self.T)] for t in range(0, self.T): + #print('t',t) a_list = [] + #print('pattern',self.patterns[t]) for t2 in range(0, self.T): - if Agrees(self.patterns[t], self.patterns[t2], x - self.N + 1, y - self.N + 1): - a_list.append(t2) + #if not (((2 in self.patterns[t]) and (3 in self.patterns[t2])) or ((3 in self.patterns[t]) and (2 in self.patterns[t2]))): + if not Disallowed(self.patterns[t], self.patterns[t2], x - self.N + 1, y - self.N + 1): + if Agrees(self.patterns[t], self.patterns[t2], x - self.N + 1, y - self.N + 1): + a_list.append(t2) self.propagator[x][y][t] = [0 for _ in range(len(a_list))] for c in range(0, len(a_list)): self.propagator[x][y][t][c] = a_list[c] + + for x in self.propagator: + for y in x: + for t in y: + #print('-----') + for c in t: + #print(c) + pass return def OnBoundary(self, x, y): @@ -409,7 +503,7 @@ def Propagate(self): return change - def Graphics(self): + def Graphics(self, monochrome=False): result = Image.new("RGB",(self.FMX, self.FMY),(0,0,0)) bitmap_data = list(result.getdata()) if(self.observed != None): @@ -425,8 +519,11 @@ def Graphics(self): local_patt = self.patterns[local_obsv][dx + dy * self.N] c = self.colors[local_patt] #bitmap_data[x + y * self.FMX] = (0xff000000 | (c.R << 16) | (c.G << 8) | c.B) - if isinstance(c, (int, float)): - bitmap_data[x + y * self.FMX] = (c, c, c) + if monochrome: + if isinstance(c, (int, float)): + bitmap_data[x + y * self.FMX] = (c, c, c) + else: + bitmap_data[x + y * self.FMX] = (c[0], c[1], c[2]) else: bitmap_data[x + y * self.FMX] = (c[0], c[1], c[2]) @@ -464,7 +561,7 @@ def Graphics(self): if contributors > 0: bitmap_data[x + y * self.FMX] = (int(r / contributors), int(g / contributors), int(b / contributors)) else: - print("WARNING: No contributors") + logger.info("INFO: No contributors") bitmap_data[x + y * self.FMX] = (int(r), int(g), int(b)) result.putdata(bitmap_data) return result @@ -475,12 +572,14 @@ def Clear(self): for x in range(0, self.FMX): for t in range(0, self.T): - if t != self.ground: + #print('clear?',x,t,(t != self.ground),self.wave[x][self.FMY - 1][t],self.changes[x][self.FMY - 1], self.FMY - 1) + if not (t in self.ground): self.wave[x][self.FMY - 1][t] = False self.changes[x][self.FMY - 1] = True for y in range(0, self.FMY - 1): - self.wave[x][y][self.ground] = False + for g in range(self.ground[0], self.ground[1]): + self.wave[x][y][g] = False self.changes[x][y] = True while self.Propagate(): pass @@ -563,7 +662,15 @@ def Main(self): print("< {0} ".format(name), end='') if "overlapping" == xnode.tag: #print(xnode.attrib) - a_model = OverlappingModel(int(xnode.get('width', 48)), int(xnode.get('height', 48)), xnode.get('name', "NAME"), int(xnode.get('N', 2)), string2bool(xnode.get('periodicInput', True)), string2bool(xnode.get('periodic', False)), int(xnode.get('symmetry', 8)), int(xnode.get('ground',0))) + add_samp_string = xnode.get('additional', "NONE") + + add_samp = [] + if "NONE" != add_samp_string: + add_samp = add_samp_string.split(':') + + add_peri = xnode.get('additional_periodic', "") + + a_model = OverlappingModel(int(xnode.get('width', 48)), int(xnode.get('height', 48)), xnode.get('name', "NAME"), int(xnode.get('N', 2)), string2bool(xnode.get('periodicInput', True)), string2bool(xnode.get('periodic', False)), int(xnode.get('symmetry', 8)), int(xnode.get('ground',0)), additional_samples=add_samp, additional_periodic=add_peri, antipatterns=xnode.get('antipatterns', '0')) pass elif "simpletiled" == xnode.tag: print("> ", end="\n") @@ -598,4 +705,4 @@ def Main(self): #test_img = a_model.Graphics() #else: # print("CONTRADICTION") -#test_img \ No newline at end of file +#test_img diff --git a/samples.xml b/samples.xml index c280657..685e008 100644 --- a/samples.xml +++ b/samples.xml @@ -1,77 +1,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/samples/Yellow Maze.png b/samples/Yellow Maze.png new file mode 100644 index 0000000..f7e4799 Binary files /dev/null and b/samples/Yellow Maze.png differ diff --git a/samples/anti_flower_ground.png b/samples/anti_flower_ground.png new file mode 100644 index 0000000..335e538 Binary files /dev/null and b/samples/anti_flower_ground.png differ diff --git a/samples/blue_flowers.png b/samples/blue_flowers.png new file mode 100644 index 0000000..3371495 Binary files /dev/null and b/samples/blue_flowers.png differ diff --git a/samples/blue_flowers2.png b/samples/blue_flowers2.png new file mode 100644 index 0000000..0b02dfd Binary files /dev/null and b/samples/blue_flowers2.png differ diff --git a/samples/blue_flowers3.png b/samples/blue_flowers3.png new file mode 100644 index 0000000..5d17408 Binary files /dev/null and b/samples/blue_flowers3.png differ diff --git a/samples/blue_flowers4.png b/samples/blue_flowers4.png new file mode 100644 index 0000000..a3ff563 Binary files /dev/null and b/samples/blue_flowers4.png differ diff --git a/samples/blue_flowers5.png b/samples/blue_flowers5.png new file mode 100644 index 0000000..fb42aa7 Binary files /dev/null and b/samples/blue_flowers5.png differ diff --git a/samples/blue_flowers6.png b/samples/blue_flowers6.png new file mode 100644 index 0000000..e2cf067 Binary files /dev/null and b/samples/blue_flowers6.png differ diff --git a/samples/blue_flowers8.psd b/samples/blue_flowers8.psd new file mode 100644 index 0000000..7dc836d Binary files /dev/null and b/samples/blue_flowers8.psd differ diff --git a/samples/blue_flowers8_anti1.png b/samples/blue_flowers8_anti1.png new file mode 100644 index 0000000..f8101ad Binary files /dev/null and b/samples/blue_flowers8_anti1.png differ diff --git a/samples/blue_flowers8_anti2.png b/samples/blue_flowers8_anti2.png new file mode 100644 index 0000000..b5af3a8 Binary files /dev/null and b/samples/blue_flowers8_anti2.png differ diff --git a/samples/blue_flowers9.png b/samples/blue_flowers9.png new file mode 100644 index 0000000..4ca2d7e Binary files /dev/null and b/samples/blue_flowers9.png differ diff --git a/samples/blue_flowers9_anti1.png b/samples/blue_flowers9_anti1.png new file mode 100644 index 0000000..51acbbb Binary files /dev/null and b/samples/blue_flowers9_anti1.png differ diff --git a/samples/red_flowers.png b/samples/red_flowers.png new file mode 100644 index 0000000..a3ead9f Binary files /dev/null and b/samples/red_flowers.png differ diff --git a/samples/test_antipattern.png b/samples/test_antipattern.png new file mode 100644 index 0000000..4bf1c61 Binary files /dev/null and b/samples/test_antipattern.png differ diff --git a/samples/test_antipattern10.png b/samples/test_antipattern10.png new file mode 100644 index 0000000..5d830ab Binary files /dev/null and b/samples/test_antipattern10.png differ diff --git a/samples/test_antipattern2.png b/samples/test_antipattern2.png new file mode 100644 index 0000000..bcec0dc Binary files /dev/null and b/samples/test_antipattern2.png differ diff --git a/samples/test_antipattern3.png b/samples/test_antipattern3.png new file mode 100644 index 0000000..264e43d Binary files /dev/null and b/samples/test_antipattern3.png differ diff --git a/samples/test_antipattern4.png b/samples/test_antipattern4.png new file mode 100644 index 0000000..1541aa4 Binary files /dev/null and b/samples/test_antipattern4.png differ diff --git a/samples/test_antipattern5.png b/samples/test_antipattern5.png new file mode 100644 index 0000000..8d5ad1c Binary files /dev/null and b/samples/test_antipattern5.png differ diff --git a/samples/test_antipattern6.png b/samples/test_antipattern6.png new file mode 100644 index 0000000..41cddc9 Binary files /dev/null and b/samples/test_antipattern6.png differ diff --git a/samples/test_antipattern7.png b/samples/test_antipattern7.png new file mode 100644 index 0000000..735b666 Binary files /dev/null and b/samples/test_antipattern7.png differ diff --git a/samples/test_antipattern8.png b/samples/test_antipattern8.png new file mode 100644 index 0000000..3656bbd Binary files /dev/null and b/samples/test_antipattern8.png differ diff --git a/samples/test_antipattern9.png b/samples/test_antipattern9.png new file mode 100644 index 0000000..ddfaca3 Binary files /dev/null and b/samples/test_antipattern9.png differ