#!/usr/bin/env python
# coding: utf-8
#
#
#
#
# # Calc
#
# We show a tablet calculator: a program that sums up the numerical value of both sides of a tablet and compares them.
#
# We assume that you have worked through the [search](search.ipynb) notebook.
# In[1]:
get_ipython().run_line_magic('load_ext', 'autoreload')
get_ipython().run_line_magic('autoreload', '2')
# In[2]:
from IPython.display import display, Markdown
from tf.app import use
# In[3]:
A = use("Nino-cunei/uruk",hoist=globals())
# # Numerals
#
# We want to find all the ShinPP numerals.
# In[4]:
shinPP = dict(
N41=0.2,
N04=1,
N19=6,
N46=60,
N36=180,
N49=1800,
)
shinPPPat = "|".join(shinPP)
# We make use of the fact that we can construct a search template programmatically.
# In[5]:
query = f"""
tablet
sign grapheme={shinPPPat}
"""
print(query)
results = A.search(query)
A.table(results, end=20, showGraphics=True)
# Let's see a few tablets in more detail:
# In[6]:
A.show(results, end=5, queryFeatures=False)
# # A tablet calculator
#
# Rather than displaying search results, you can also *process* them in your program.
#
# Search results come as tuples of nodes that correspond directly to the elements
# of your search template.
#
# We query for shinPP numerals on the faces of tablets.
# The result of the query is a list of tuples `(t, f, s)` consisting of
# a tablet node, a face node and a node for a sign of a shinPP numeral.
#
# ## Rationale
# This task will require a higher level of programming skills and a deeper knowledge of how
# Python works.
# We include it in this tutorial to get the message across that Text-Fabric is not
# a black box that shields you from your data. Everything you handle in Text-Fabric is
# open to further programming and processing of your own design and choosing.
# ## Data collection
# In[7]:
query = f"""
tablet
face
sign type=numeral grapheme={shinPPPat}
"""
results = A.search(query)
# We are going to put all these numerals in buckets: for each face on each tablet a separate bucket.
# In[8]:
numerals = {}
pNums = {}
for (tablet, face, sign) in results:
pNums[F.catalogId.v(tablet)] = tablet
numerals.setdefault(tablet, {}).setdefault(face, []).append(sign)
print(f"{len(pNums)} tablets")
print("\n".join(list(pNums)[0:10]))
print("...")
# ## The calculator
# We define a function that given a tablet, adds the shinPP numerals by its faces.
# We also show the line art and a pretty transcription.
#
# The function is a bit involved.
# In[9]:
# we generate Markdown strings and send them to the notebook formatter
def dm(x):
display(Markdown(x))
def calcTablet(pNum): # pNum identifies the tablet in question
# show a horizontal line in Markdown
dm("---\n")
tablet = pNums.get(pNum, None) # look up the node for this p-number
if tablet is None:
dm(f"**no results for {pNum}**")
return # if not found the tablet has no ShinPP numerals: quit
A.lineart(tablet, withCaption="top", width="200") # show lineart
faces = numerals[tablet] # get the buckets for the faces
mySigns = []
for (face, signs) in faces.items(): # work per face
mySigns.extend(signs)
dm(f"### {F.type.v(face)}") # show the name of the face
distinctSigns = {} # collect the distinct numerals
for s in signs:
distinctSigns.setdefault(A.atfFromSign(s), []).append(s)
A.lineart(distinctSigns) # display the list of signs
total = 0 # start adding up
for (signAtf, signs) in distinctSigns.items():
value = 0
for s in signs:
value += F.repeat.v(s) * shinPP[F.grapheme.v(s)]
total += value
amount = len(signs) # we report our calculation
shinPPval = shinPP[F.grapheme.v(signs[0])]
repeat = F.repeat.v(signs[0])
print(f"{amount} x {signAtf} = {amount} x {repeat} x {shinPPval} = {value}")
dm(f"**total** = **{total}**")
A.prettyTuple(
[tablet] + mySigns, 1, queryFeatures=False
) # show pretty transcription
# ## Calculate once
# In[10]:
calcTablet("P006377")
# ## Calculate ad lib
# Now the first 5 tablets.
# In[13]:
for tablet in sorted(pNums)[0:5]:
calcTablet(tablet)
# ## More ...
#
# The capabilities of search are endless.
# Often it is the quickest way to focus on a phenomenon, quicker than hand coding all the logic
# to retrieve your patterns.
#
# That said, it is not a matter of either-or. You can use coding to craft your templates,
# and you can use coding to process your results.
#
# It's an explosive mix. A later chapter in this tutorial shows
# even more [cases](cases.ipynb).
#
# Have another look at
# [the manual](https://annotation.github.io/text-fabric/tf/about/searchusage.html).
# # Next
#
# [signs](signs.ipynb)
#
# *Back to the basics ...*
#
# All chapters:
# [start](start.ipynb)
# [imagery](imagery.ipynb)
# [steps](steps.ipynb)
# [search](search.ipynb)
# **calc**
# [signs](signs.ipynb)
# [quads](quads.ipynb)
# [jumps](jumps.ipynb)
# [cases](cases.ipynb)
#
# ---
#
# CC-BY Dirk Roorda