Note that MANTO's API limits JSON requests to 1000 / 15 minutes from a given IP. This should be more than sufficient for use with DICES, since MANTO entities are cached locally after the first download. If, however, you do exceed the limit, then the call to MANTO will return an error and the DICES client will create a dummy MANTO entity with no data.
I've introduced the cache_empty=False
default for getMantoID()
and getMantoChar()
, which specifies that an entity returned with an empty data
attribute should not be cached, forcing an automatic re-download the next time it's used. If, however, you expect data
to be empty, you can set cache_empty=True
to prevent unnecessary calls to the MANTO server.
Import statements. Our MANTO tools are in the manto
module.
from dicesapi import DicesAPI, SpeechGroup
from dicesapi.jupyter import NotebookPBar
from dicesapi import manto
import pandas as pd
Create a connection to DICES
api=DicesAPI(progress_class=NotebookPBar, logfile='dices.log')
Instantiate a DICES character to get started
char = api.getCharacters(name='Telemachus')[0]
print(char)
Let’s create a new MANTO entity by retrieving Telemachus’ ID from MANTO.
manto_ent = manto.getMantoChar(char)
print(manto_ent)
This code is still in development and subject to change. But for now, this is how we search MANTO for Telemachus' parents. Under the hood, we're checking two different MANTO ties, 31764
, "son of", and 31765
, "daughter of."
This function currently returns MANTO Entity objects.
parents = manto_ent.getParents()
print(parents)
Let's look for grandparents. Note that when sources disagree about parentage, MANTO returns an inclusive list.
for p in parents:
print(f'Grandparents on {p.name}’s side:')
for gp in p.getParents():
print(' - ' + gp.name)
# a list of character pairs, by MANTO ID
pairs = [
('8182179', '8182084'), # Anchises and Aeneas
('8188282', '8190182'), # Eteocles and Oedipus
('8189802', '8182035'), # Menelaus and Agamemnon
]
for a, b in pairs:
ent_a = manto.getMantoID(a)
ent_b = manto.getMantoID(b)
print(f'Is {ent_a.name} the child of {ent_b.name}? ', ent_a.isChildOf(ent_b))
For convenience, there are also wrapper functions that perform the same checks on DICES Characters by resolving the characters to MANTO entities first, then calling the boolean methods above. If you pass a CharacterInstance instead of a Character, the function will try to determine the MANTO ID of the underlying Character.
If passed a Character with no MANTO ID, or an anonymous CharacterInstance with no Character, these functions return None
. You can use the optional err_val
parameter to set a different fallback value; for example, if you're using the function in a filter and want to ensure it always returns a Boolean, set this to False
.
For these next examples, let's start with a list of Telemachus' interlocutors.
# download all speeches by Telemachus
speeches = api.getSpeeches(spkr_id=char.id, progress=True)
print(f'{len(speeches)} speeches')
# extract the list of addressees
addressees = speeches.getAddrs(flatten=True)
print(f'{len(addressees)} unique addressees.')
In this block, we use call charIsChild()
on the speaker and his addressees to test parentage using MANTO's data. Where the function returns None
, we know data was missing.
for addr in addressees:
check = manto.charIsChild(char, addr)
if check is not None:
print(f'Is {char.name} the child of {addr.name}?', check)
Or we can use MANTO ties in a custom filter. In this case I'll silence the debugging messages and force charIsChild()
to return False
if no MANTO ID is found.
# filter a CharacterInstanceGroup based on MANTO ties:
parent_addrs = addressees.advancedFilter(lambda addr: manto.charIsChild(char, addr, debug=False, err_val=False))
print(f'Parent addressees of {char.name}:')
for p in parent_addrs:
print(p.name)
print()
# now use the filtered list of CharacterInstances to filter the original SpeechGroup
parent_speeches = speeches.filterAddrInstances(parent_addrs)
print(f'Speeches in which {char.name} addresses a parent:\n')
for s in parent_speeches:
print(f'{s.author.name} {s.work.title} {s.l_range}\t{s.getAddrString()}')