Last active
May 31, 2019 15:35
-
-
Save arnobaer/c673a63924aec2d151525db026ae315a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
================================================================================ | |
Generated periods | |
================================================================================ | |
Period Range Diagram | |
================================================================================ | |
P01 40-360 .##########................................................ | |
P02 180-420 .....#######............................................... | |
P03 220-540 ......##########........................................... | |
P04 660-1000 ....................##########............................. | |
P05 960-1140 ..............................#####........................ | |
P06 1120-1280 ...................................#####................... | |
P07 1160-1640 ....................................###############........ | |
P08 1220-1660 ......................................#############........ | |
P09 1720-1840 .....................................................###... | |
================================================================================ | |
Generated contexts | |
================================================================================ | |
Ctx P01 P02 P03 P04 P05 P06 P07 P08 P09 Range | |
================================================================================ | |
C01 . . . . . . . 1 4] 1220-1840 P08-P09 | |
C02 . . . . . . . . 4] 1720-1840 P09 | |
C03 . . . . 1 . 4 . 1] 960-1840 P05-P09 | |
C04 1 . . 1 . . . .] . 40-1000 P01-P04 | |
C05 . . . . 5 . . .] . 960-1140 P05 | |
C06 . . . . . . 1 .] . 1160-1640 P07 | |
C07 . . . 1 2 . . 1] . 660-1660 P04-P08 | |
C08 . . . . 2 1 2] . . 960-1640 P05-P07 | |
C09 1 2 . .] . . . . . 40-420 P01-P02 | |
C10 3 . . .] . . . . . 40-360 P01 | |
C11 . . . 3] . . . . . 660-1000 P04 | |
C12 . . 3] . . . . . . 220-540 P03 | |
sum 5 2 3 5 10 1 7 2 9 | |
d/U d d U U d d U U d | |
================================================================================ | |
seed: 1559260424.6490061 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Simulating test-pit find matrices | |
# | |
# Requires: texttable | |
# | |
import argparse | |
import random | |
import time | |
import sys, os | |
from texttable import Texttable | |
class TestPit: | |
def __init__(self, name, number, contexts): | |
self.name = name | |
self.number = number | |
self.contexts = contexts | |
self.date_contexts() | |
def date_contexts(self): | |
prev_period = None | |
# Iterate from bottom to top of trench | |
for context in self.contexts[::-1]: | |
# If context contains datable finds | |
if context.finds: | |
period = context.finds[-1].period | |
if prev_period is None: | |
prev_period = period | |
elif period.end > prev_period.end: | |
prev_period = period | |
elif period.end == prev_period.end: | |
if period.begin >= prev_period.begin: | |
prev_period = period | |
context.period = prev_period | |
def get_periods(self): | |
periods = [] | |
for context in self.contexts: | |
period = context.period | |
if period and period not in periods: | |
periods.append(period) | |
for find in context.finds: | |
period = find.period | |
if period not in periods: | |
periods.append(period) | |
periods.sort(key=lambda period: period.sort_key) | |
return periods | |
def get_disturbed(self, periods): | |
used_periods = periods#self.get_periods() | |
states = [] | |
prev_period = None | |
for p in used_periods: | |
disturbed = None | |
# HACK latest is always disturbed | |
if p.end == used_periods[-1].end: | |
disturbed = True | |
for c in self.contexts[::-1]: | |
for f in c.finds: | |
if f.period is p: | |
if f.period is c.period: | |
if disturbed is None: | |
disturbed = False | |
else: | |
if f.period.end < c.period.end: | |
if disturbed is None: | |
disturbed = True | |
states.append(disturbed) | |
return states | |
class Period: | |
def __init__(self, name, begin, end): | |
assert(begin < end) | |
self.name = name | |
self.begin = begin | |
self.end = end | |
@property | |
def span(self): | |
return self.end - self.begin | |
@property | |
def sort_key(self): | |
return self.end, self.begin, self.name | |
class Context: | |
def __init__(self, index, finds): | |
self.index = index | |
self.finds = finds | |
self.period = None | |
self.sort_finds() | |
def sort_finds(self): | |
self.finds.sort(key=lambda find: (find.sort_key)) | |
@property | |
def name(self): | |
return 'C{:02}'.format(self.index) | |
@property | |
def finds_span(self): | |
if self.finds: | |
begin = self.finds[0].period.begin | |
end = self.finds[-1].period.end | |
return begin, end | |
return 0, 0 | |
def count_finds(self, period=None): | |
count = 0 | |
for find in self.finds: | |
if period is not None: | |
if period is not find.period: | |
continue | |
count += find.count | |
return count | |
class Find: | |
def __init__(self, type, period, count, weight): | |
self.type = type | |
self.period = period | |
self.count = count | |
self.weight = weight | |
@property | |
def sort_key(self): | |
return self.period.sort_key, self.type, self.count, self.weight | |
parser = argparse.ArgumentParser() | |
parser.add_argument('--seed', type=float, default=time.time()) | |
parser.add_argument('--begin', type=int, default=0) | |
parser.add_argument('--end', type=int, default=1900) | |
args = parser.parse_args() | |
random.seed(args.seed) | |
def create_periods(n): | |
periods = [] | |
for _ in range(n): | |
a, b = sorted((0, 0)) | |
while b-a < 100 or b-a > 500: | |
a, b = sorted((random.randint(args.begin//20, args.end//20)*20, random.randint(args.begin//20, args.end//20)*20)) | |
periods.append(Period(None, a, b)) | |
# sort by end, then begin | |
periods.sort(key=lambda period: period.sort_key) | |
for i, period in enumerate(periods): | |
name = 'P{:02}'.format(i + 1) | |
period.name = name | |
return periods | |
def create_finds(n, periods): | |
finds = [] | |
types = ('pottery','clay-pipe','CBM') | |
counts = (1,1,1,1,1,1,2,2,2,3,3,4) | |
weights = (1,1,2,2,3,3,4,5,6,7) | |
for _ in range(n): | |
count = random.choice(counts) | |
weight = 0 | |
for _ in range(count): | |
weight += random.choice(weights) | |
find = Find(random.choice(types), random.choice(periods), count, weight) | |
finds.append(find) | |
return finds | |
def create_contexts(n, periods): | |
contexts = [] | |
for index in range(n): | |
finds = create_finds(random.randint(0, 3), periods) | |
context = Context(index + 1, finds) | |
contexts.append(context) | |
return contexts | |
def draw_title(*args, width=80, separator=''): | |
bar = '=' * width | |
title = separator.join(args).center(80) | |
return os.linesep.join((bar, title, bar)) | |
periods = create_periods(9) | |
contexts = create_contexts(random.randint(8, 12), periods) | |
testpit = TestPit("TO/16/03", 3, contexts) | |
print(draw_title("Generated periods")) | |
table = Texttable() | |
table.set_deco(Texttable.HEADER) | |
table.set_cols_align(["l", "c", "l"]) | |
table.header(("Period", "Range", "Diagram")) | |
for period in periods: | |
scale = 32 | |
offset = '.'*(period.begin // scale) | |
bar = '#'*(period.span // scale) | |
frame = offset + bar + '.'*((1900 // scale)-(len(offset)+len(bar))) | |
table.add_row((period.name, "{:>4}-{:<4}".format(period.begin, period.end), frame)) | |
print(table.draw()) | |
print(draw_title("Generated contexts")) | |
used_periods = periods#testpit.get_periods() | |
table = Texttable() | |
table.set_deco(Texttable.HEADER) | |
align = ["l"] | |
header = ["Ctx"] | |
for period in used_periods: | |
align.append("r") | |
header.append(period.name) | |
align.append("c") | |
header.append("Range") | |
table.set_cols_align(align) | |
table.header(header) | |
for c in testpit.contexts: | |
row = [c.name] | |
for p in used_periods: | |
count = 0 | |
for f in c.finds: | |
if f.period is p: | |
count += f.count | |
gate = " " | |
if c.period: | |
if c.period.end is p.end: | |
gate = "]" | |
if count: | |
row.append('{:>2}{}'.format(count, gate)) | |
else: | |
row.append('{:>2}{}'.format('.', gate)) | |
span = c.finds_span | |
if span != (0, 0): | |
lhs, rhs = c.finds[0].period, c.finds[-1].period | |
if lhs is rhs and c.finds[0] is not c.finds[-1]: | |
row.append(' {:>4}-{:<4} {:>3} '.format(*c.finds_span, lhs.name)) | |
else: | |
row.append(' {:>4}-{:<4} {:>3}-{:<3} '.format(*c.finds_span, lhs.name, rhs.name)) | |
else: | |
row.append('') | |
table.add_row(row) | |
row = ["sum"] | |
for p in used_periods: | |
count = 0 | |
for c in testpit.contexts: | |
count += c.count_finds(p) | |
if count: | |
row.append("{:>2} ".format(count)) | |
else: | |
row.append("-") | |
table.add_row(row + [""]) | |
row = ["d/U"] | |
for disturbed in testpit.get_disturbed(periods): | |
row.append({None: "-", False: "U", True: "d"}[disturbed]) | |
table.add_row(row + [""]) | |
data = table.draw() | |
# Add colored output | |
if sys.stdout.isatty(): | |
data = data.replace("]", "\033[35m]\033[0m") | |
data = data.replace(" d ", "\033[31m d \033[0m") | |
data = data.replace(" U ", "\033[32m U \033[0m") | |
print(data) | |
print("=" * 80) | |
print("seed:", args.seed) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment