Selaa lähdekoodia

automatic processing one step further

FRANCESCO CORADESCHI 2 kuukautta sitten
vanhempi
commit
c407b61d03

+ 1 - 0
Serious_attempt/data/.~lock.Struttura_NEW.xlsx#

@@ -0,0 +1 @@
+,AzureAD/FRANCESCOCORADESCHI,koras,20.09.2024 13:45,file:///C:/Users/FRANCESCOCORADESCHI/AppData/Roaming/LibreOffice/4;

+ 1 - 0
Serious_attempt/data/.~lock.man_draft_NEW_entities.csv#

@@ -0,0 +1 @@
+,AzureAD/FRANCESCOCORADESCHI,koras,20.09.2024 13:41,file:///C:/Users/FRANCESCOCORADESCHI/AppData/Roaming/LibreOffice/4;

BIN
Serious_attempt/data/Struttura_NEW.xlsx


+ 129 - 111
Serious_attempt/output/manoscritti_dariah_entities.csv

@@ -1,111 +1,129 @@
-Concetto,Contesto,Definizione,Esempi,Note,,

-"Manoscritto
-Codice",Descrizione Esterna,"LIBRO formato da FOGLI piegati in due (BIFOGLI)  e riuniti in uno o più FASCICOLI, cuciti mediante un filo lungo la linea di PIEGATURA
-Nota: Il termine MANOSCRITIO indica, più generalmente, qualunque testo scritto a mano",,,,

-Ttiolo del codice,Descrizione Esterna,,Codex Amiatinus,,,

-Supporto,Descrizione Esterna,Materiale sul quale è stata tracciata la scrittura o che è destinato a riceverl (MM),pergamena,,,

-"Consistenza
-Dimensioni",Descrizione Esterna,"Numero complessivo delle CARTE che costituiscono un VOLUME, indipendentemente dalla maniera in cui sono numerate  (MM)",I + 177 + II-III,,,

-Volume,Descrizione Esterna,"Unità costituita da una serie di BIFOGLI o di FOGLI ricoperti o destinati ad essere rico­ perti da una sola LEGATURA, a prescindere dal fatto che si tratti di un insieme costitu­to da una o più UNITÀ CODICOLOGICHE, indipendente o parte di un'opera in più volu­mi ",,,,

-Bifoglio,Descrizione Esterna,"Unità costitutiva del FASCICOLO, rappresentata da un pezzo rettangolare di PERGAME­NA, CARTA, … ,  piegato a metà per formare due CARTE",,,,

-Foglio,Descrizione Esterna,"a) Superficie rettangolare di PERGAMENA, CARTA ... (corrispondente ad un FOGLIO DI FORMA o ad una PELLE intera, o anche ad un loro sottomultiplo), come si presenta an­teriormente alle operazioni di PIEGATIJRA o di suddivisione eseguite per ottenere i BIFOGLI
-*b) Termine usato come sinonimo di BIFOGLIO 
-*c) Termine usato come sinonimo di CARTA",,,,

-Carta,Descrizione Esterna,"Ciascuna delle due metà di un BIFOGLIO [Nota:  Il  termine FOGLIO  viene da alcuni impiegato come sottomultiplo di BIFO­GLIO, per indicare la CARTA]",,,,

-Pagina,Descrizione Esterna,"Ciascuna delle due superfici opposte di una CARTA [Nota:  Impropriamente, nella terminologia del libro moderno, il termine ""pagi­na""  è adoperato talvolta per indicare la CARTA] ",,,,

-Unità codicologica,Descrizione Esterna,"VOLUME, parte di volume o insieme di volumi la cui esecuzione può essere conside­ rata come un'operazione unica, realizzata nelle stesse condizioni di tecnica, di luo­go e di tempo ",,,,

-Formato,Descrizione Esterna,a) Dimensioni (altezza e larghezza) del FOGLIO  o della CARTA,528 x 375 mm,,,

-Numerazione,Descrizione Esterna,"Apporre un numero d'ordine ai FASCICOLI,  ai BIFOGLI,  alle CARTE  o  alle PAGINE  di un VOLUME",,,,

-"Cartulazione
-Cartolazione
-Cartulatura
-Cartolatura 
-Foliotazione
-Foliazione ",Descrizione Esterna,"Cartulazione. Numerazione di tutte le CARTE  che compongono un VOLUME,  normalmente apposta sul RECTO di ciascuna",,,,

-Fascicolo,Descrizione Esterna,"Serie di BIFOGLI inseriti l'uno dentro l'altro ed uniti o  pronti per essere uniti da uno stesso  passaggio  del  FILO  DI  CUCITURA.  Il fascicolo  può essere eventualmente composto da un un unico bifoglio, o  anche da una singola CARTA,  cucita autonoma­ mente agli altri fascicoli",,,,

-Fascicolazione,Descrizione Esterna,"a) Numero dei FASCICOLI  che compongono un VOLUME  o un'UNITÀ  CODICOLOGICA e loro TIPO 
-b)  Studio  del  TIPO  e  della  STRUTTURA  dei  fascicoli  che  compongono  un  volume o un'unità codicologica ",(IV-1)8 + IV16 + (IV-2)24 + 12 IV120 + V130 + IV138 + (IV-1)145 + (IV-1)154 + 3 IV178 + I180 + (II-2)182,,,

-Legatura,Descrizione Esterna,"a)  Operazione che consiste nel confezionare un LIBRO cucendo l'uno all'altro i FASCICOLI  e aggiungendo eventualmente altri elementi (COPERTA, CAPITELLI, CARTE DI GUARDIA ... ) 
-b)  Risultato di tale operazione ",,,,

-"Architettura della pagina
-Organizzazione della pagina
-Disposizione della pagina
-Utilizzazione della pagina
-Impaginazione",Descrizione Interna,"Disposizione generale dei diversi elementi che figurano su una PAGINA,  nel rispetto di determinati canoni ed equilibri [M 331.01] ",,,,

-Tipo di scrittura,Descrizione Interna,,scrittura gotica corale,,,

-Mani,Descrizione Interna,,,,,

-Notazione musicale,Descrizione Interna,,Notazione musicale quadrata a inchiostro nero su tetragramma a inchiostro rosso,,,

-Decorazione,Descrizione Interna,"Disposizione generale dei diversi elementi che figurano su una PAGINA,  nel rispetto di determinati canoni ed equilibri","iniziali ritoccate in giallo
-rubriche ed indicazioni liturgiche in rosso. Ovunque sono visibili, a penna marrone e di modulo molto piccolo, le indicazioni per il rubricatore e per i miniatori
-iniziali filigranate:
-piccole alternate rosse e blu all’inizio dei versetti
-medie all’inizio delle messe delle domeniche comuni e dei giorni feriali
-Queste iniziali filigranate sarebbero opera di un ""Miniatore calligrafo"" attivo anche nel codice III e IV (v. Hudig-Frey 1971 p. 302, 318; Gilardoni 1972, p. 228: „calligrafo delle filigrane“; Speroni 2000, 42 che però dice attivo nell’I, II e IV)",,,

-Miniatura,Descrizione Interna,"Dipinto eseguito in un MANOSCRITTO,  in particolare se si  tratta di un'ILLUSTRAZIONE",,,,

-Illustrazione,Descrizione Interna,"Rappresentazione  di  oggetti,  personaggi,  scene  ...  in  rapporto  con  il  testo",,,,

-Contenuto,Descrizione Interna,,"Contiene i canti antifonali e responsoriali delle messe dall’Avvento alla domenica XXIII dopo la Pentecoste.
-2r-178v Proprium de Tempore
-[Dominica prima de adventu. L’inizio manca] 2r … misericordiam tuam et salutare tuum da nobis. Offertorium. Ad te domine levavi animam meam
->Dominica secunda de adventu. Introitus.< Populus Syon …–… 178v Dominica XXIIII post pentecosten officium resumitur de dominica preterita. Dicit dominus ego cogito et cetera.
-[mancano le cc. 20-21 con una parte dell’Ufficio per S. Stefano e l’intero ufficio per S. Giovanni Battista]
-Il testo segue l'Ordo Breviarii di Aimone da Faversham, ed. S. P. J. Van Dijk, Sources of the modern liturgy, The Ordinals by Haymo of Faversham and Related Documents, Leiden, II (1963), 207-270.
-123v-128r Litanie, da notare Francesco Antonio, Domenico, Clara. A c. 125v nel margine superiore aggiunti in un secondo momento i nomi di S. Abbondio e di S. Ludovico.",,,

-"Aggiunta
-Inserzione 
-Integrazione
-Addizione",Descrizione Interna,"Menzione iscritta al di fuori del CORPO  DELLA PAGINA, destinata ad esservi introdotta durante la lettura o al  momento di una COPIA ulteriore","c. 152r margine esterno: hic introitus dicitur etiam in solemnitate corporis Christi.
-c. 156v margine esterno: Introitus pro sanctissma trinitate quere in fine huius libri fo. 168.
-c. 163r margine esterno: Require clxxv cui fa seguito, di altra mano più tarda: in libro sanctorum in die purificacionis S. Marie virginis.",,,

-"Annotazione
-Chiosa
-Nota",Descrizione Interna,"Breve testo di contenuto informativo, esplicativo o critico",,,,

-Marginalia,Descrizione Interna,Insieme delle ANNOTAZIONI e dei segni iscritti in margine al testo,,,,

-Datazione,Storia,,XIV sec (1401-1500),,,

-"Stato di conservazione
-Condizione",Storia,"Conservazione del supporto 
-Conservazione del tracciato e dei colori 
-Conservazione del volume","Alcune carte, o parti di esse, sono state da tempo ritagliate ed asportate:
-c. 1 (asportato l'intero foglio, ancora visibili traccie della iniziale nel margine superiore), cc. 20 e 21 (asportato tutto questo bifoglio centrale del fascicolo), c. 51 (margine inferiore), c. 85 (margine inferiore), c. 128r (margine inferiore), c. 147 (asportata l’intera carta).
-Presenza di cuciture originali su alcuni fogli (per es. c. 31, c. 145).
-Il codice è stato restaurato nel 1992-3 nel laboratorio di restauro di Andrea Giovannini a Lumino (v. Rapporto di restauro).",,,

-Origine,Storia,Luogo in cui un LIBRO è stato approntato,"Si tratta probabilmente del primo di due volumi: il secondo avrebbe dovuto contenere il Proprium de sanctis, come fa pensare la presenza del richiamo a c. 180v In vigilia Santi Andree apostoli, ed il Commune sanctorum. Il testo segue lo schema del Libro ordinario di Aimone di Faversham (ed. S. P. J. Van Dijk, Sources of the modern liturgy, The Ordinals by Haymo of Faversham and Related Documents (1243-1307), Leiden, vol. II (1963).
-Gli elementi utili per la datazione del manoscritto ai primi decenni del XIV secolo sono:
-l'aggiunta nelle litanie, non molto dopo la stesura del testo, del nome di S. Ludovico, canonizzato nel 1297 (c. 125v).
-la Messa festiva ""De sancta Trinitate"" trascritta alla fine del Proprium de Tempore, autorizzata per l’ordine dal capitolo generale di Parigi del 1266 e nel 1316 estesa da papa Giovannni XXII a tutta la chiesa
-la annotazione tarda (XIX sec.) nel margine inferiore di c. 130v: Librum hunc accurate scripserunt Anno 1315 Fr. Jacobus domini Rostelli de Orello lector et beneficus alumnus cenobii et ecclesie S. Francisci de Locarno et fr. Joannes de Raimondis.
-lo stile delle iniziali miniate, i cui esempi più vicini si trovano nella miniatura padovana della fine del sec. XIII e della prima metà del sec. XIV, quali per es. il Ms. 328 di probabile origine padovana con iniziali miniate che presentano il motivo dei draghetti, databile agli inizi del XIV sec. (v. G. Abate - G. Luisetto, Codici e manoscritti della Biblioteca Antoniana, Vicenza 1975, vol. 2, 607, fig. 46).",,,

-Provenienza,Storia,"a)  Indicazione degli antichi POSSESSORI  O  dei LUOGHI  DI  CONSERVAZIONE  di un LIBRO
-b) [in particolare:] Ultimo possessore prima di quello attuale ","Il graduale è sicuramente stato eseguito per un convento francescano e destinato poi al convento di S. Francesco di Locarno, come attesterebbe l'aggiunta nelle litanie del nome di S. Abbondio vescovo di Como, diocesi cui apparteneva all'epoca Locarno e cui il manoscritto era destinato, e l'annotazione del sec. XIX nel margine inferiore di c. 181r: Iste liber choralis iuris est conventus Sancti Francisci fratrum minorum conventualium de Locarno in tanta rerum vicissitudine aduc superstitis. Anno 1817.
-Non ha invece nessun valore l’ipotesi, più volte formulata dagli studiosi sulla base dello Statutum pro libris choralibus scribendis trascritto a c. 181, che il graduale sia stato prodotto in uno scriptorium di Locarno (Hudig-Frey, 300-301, Gilardoni 228; Speroni 2000/3, 18). Si tratta infatti di prescrizioni databili intorno alla metà del XIII sec. che i copisti avrebbero dovuto anteporre all'inizio del testo vero e proprio del graduale. L’editore van Dijk (vol. I, p. 120) ha reperito nove manoscritti, tutti di area italiana, che presentano questo testo all'inizio.
-Potrebbe invece essere verosimile l'ipotesi secondo la quale, come si legge a c. 182v, frate Giacomo di Rastelli Orelli, lettore del convento, e frate Giovanni Raimondi, si siano procurati il graduale - e probabilmente anche gli antifonari (codici II, III, IV) - per il convento nel 1315, in occasione di una nuova consacrazione della chiesa di S. Francesco, avvenuta nel 1316: … Et mihi fratri Jacobo domini Rastelli de Orello lectori conventus minorum in Locarno … tradidit personaliter fideliter ad perpetuam rei transcripsi. Et in hoc conventuali libro quem mo ccco xvo una cum fratre Johanne de Raymondis cum multa solicitudinem fieri procuravimus notavi diligenter atque conscripsi.
-Suffragherebbero questa ipotesi anche le trascrizioni (c. 182v) alla fine del codice della memoria concernente la costruzione di un armadio per la biblioteca del convento, della lettera di consacrazione del cimitero e di due altari avvenuta nel 1316, e della memoria di una donazione del 1315 per la costruzione di un pulpito e l'acquisto di un messale e di vari paramenti.",,,

-Possessore,Storia,Persona o istituzione cui un LIBRO appartiene,,,,

-Luogo di conservazione,Storia,Luogo in cui un LIBRO è attualmente conservato,,,,

-"Acquisizione del manoscritto
-Circolazione del manoscritto",Storia,,"A seguito della soppressione del convento di S. Francesco di Locarno, avvenuta nel 1848, il graduale (unitamente agli antifonari II, III e IV) fu probabilmente trasportato presso il convento della Madonna del Sasso di Orselina - affidato ai cappuccini - dove ricevette la segnatura „25-235 I“ (etichetta cartacea moderna originariamente applicata sull’asse anteriore, dopo il restauro conservata separatamente). Qui è presente sicuramente nel 1903, quando il Monti (Monti, 17) lo vide già privato di alcune miniature. A detta del Respini (Respini, 87) le prime manomissioni risalirebbero a prima del 1876, subito dopo la soppressione del convento. Successive asportazioni di miniature avvennero dopo il 1943 e dopo il 1967.
-Attualmente il graduale e gli antifonari II, III, IV appartiene allo Stato del Canton Ticino e si trovano in deposito presso il convento dei cappuccini della Madonna del Sasso di Orselina.",,,

-Bibliografia,Storia,,"Monti S., L’esposizione di arte sacra in Bellinzona (settembre, 1903), in „Bollettino Storico della Svizzera italiana“ 26 (1904), 17-18;
-[Respini G.], Il Ticino liberale-conservatore giudicato dalle sue opere, in „Bollettino Storico della Svizzera italiana“, 11 (1936), 87;",,,

-,,,,,,

-,,,,,,

-,,,,,,

-Testo,Descrizione Interna (2),,,,,

-Autore,Descrizione Interna (2),,,,,

-Rubrica,Descrizione Interna (2),Didascalia talvolta apposta ai testi contenente ad es. il nome dell'autore o informazioni sul testo,,,,

-Titolo,Descrizione Interna (2),Con tutti i caveat del caso!,,,,

-Incipit,Descrizione Interna (2),,,,,

-Explicit,Descrizione Interna (2),,,,,

-Lingua,Descrizione Interna (2),,,,,

-Attribuzione in Rubrica,Descrizione Interna (2),,,,,

-Genere in Rubrica,Descrizione Interna (2),,,,,

-Edizioni di riferimento ,Descrizione Interna (2),,,,,

-"Versificazione
-Metro",Descrizione Interna (2),,,,,

-Numero versi ,Descrizione Interna (2),,,,,

-Numero strofe ,Descrizione Interna (2),,,,,

-Versi per strofa  ,Descrizione Interna (2),,,,,

-Schema rimico ,Descrizione Interna (2),,,,,

-Schema metrico,Descrizione Interna (2),,,,,

-Partizione,Descrizione Interna (2),Per testi in prosa,,,,

-Tipologia,Descrizione Interna (2),"Prosa, Poesia, Prosimetro (nome temporaneo)",,,,

-Genere testuale,Descrizione Interna (2),,"Testo morale, Testo religioso...",,,

+ENTITÀ,ATTRIBUTO (LITERAL),SAME AS
+Aggiunta,,"Inserzione, Integrazione, Addizione"
+Aggiunta,Descrizione,
+Annotazione,,"Chiosa, Nota"
+Architettura Della Pagina,,"Organizzazione Della Pagina, Disposizione Della Pagina, Utilizzazione Della Pagina, Impaginazione"
+Architettura Della Pagina,Descrizione,
+Architettura Della Pagina,Tipo Di Scrittura,
+Attività,,
+Attribuzione In Rubrica,,
+Bibliografia,,
+Bifoglio,,Foglio
+Carta,,Foglio
+Carta,Cartulazione,
+Cartulazione,,"Cartolazione, Cartulatura, Cartolatura, Foliotazione, Foliazione"
+Codice,,"Libro, Volume"
+Codice,Fascicolazione,
+Codice,Legatura,
+Consistenza,,Dimensioni
+Contenuto,,
+Decorazione,,
+Dimensioni,,Formato
+Dimensioni,Larghezza,
+Dimensioni,Lunghezza,
+Dimensioni,Unità Di Misura,
+Edizione,,
+Ente,,
+Ente,Attività,
+Ente,Descrizione,
+Ente,Vide,
+Evento,,
+Evento,Descrizione,
+Explicit,,
+Fascicolazione,,
+Fascicolo,,
+Fascicolo,Cartulazione,
+Fascicolo,Consistenza,
+Fascicolo,Numerazione,
+Foglio,,
+Foglio,Numerazione,
+Foglio Intero,,
+Fondo,,
+Genere In Rubrica,,
+Genere Testuale,,
+Illustrazione,,
+Illustrazione,Oggetto,
+Incipit,,
+Legatura,,
+Lingua,,
+Luogo,,
+Luogo,Coordinate,
+Luogo,Descrizione,
+Luogo,Estensione,
+Mano,,
+Mano,Collocazione Nel Manoscritto,
+Mano,Data,
+Mano,Tipo Di Scrittura,
+Manoscritto,,
+Manoscritto,Consistenza,
+Manoscritto,Contenuto,
+Manoscritto,Data,
+Manoscritto,Nome Vulgato,
+Manoscritto,Stato Di Conservazione,
+Manoscritto,Titolo Del Codice,
+Manoscritto,Bibliografia,
+Marginalia,,
+Marginalia,Annotazione,
+Marginalia,Descrizione,
+Miniatura,,
+Notazione Musicale,,
+Numerazione,,
+Numero Strofe,,
+Numero Versi,,
+Origine,,
+Pagina,,
+Pagina,Annotazione,
+Pagina,Cartulazione,
+Pagina,Decorazione,
+Pagina,Numerazione,
+Pagina,Notazione Musicale,
+Partizione,,
+Periodo,,
+Periodo,Data,
+Periodo,Data,
+Persona,,
+Persona,Attività,
+Persona,Morte,
+Persona,Nascita,
+Persona,Nome,
+Persona,Ruolo,
+Persona,Sesso,
+Provenienza,,
+Provenienza,Data,
+Rubrica,,
+Rubrica,Attribuzione In Rubrica,
+Rubrica,Attribuzione In Rubrica,
+Rubrica,Genere In Rubrica,
+Rubrica,Genere In Rubrica,
+Schema Metrico,,
+Schema Rimico,,
+Segnatura,,
+Segnatura,Segnatura Numerica,
+Stato Di Conservazione,,Condizione
+Supporto,,
+Supporto,Materiale,
+Supporto,Stato Di Conservazione,
+Testo,,
+Testo,Edizione,
+Testo,Explicit,
+Testo,Genere Testuale,
+Testo,Incipit,
+Testo,Lingua,
+Testo,Partizione,
+Testo,Tipologia,
+Testo,Titolo,
+Tipo Di Scrittura,,
+Tipologia,,
+Titolo,,
+Titolo Del Codice,,
+Unità Codicologica,,
+Unità Codicologica,Consistenza,
+Unità Codicologica,Fascicolazione,
+Unità Codicologica,Legatura,
+Versi Per Strofa,,
+Versificazione,,Metro
+Versificazione,Numero Strofe,
+Versificazione,Numero Versi,
+Versificazione,Schema Metrico,
+Versificazione,Schema Rimico,
+Versificazione,Versi Per Strofa,

+ 81 - 15
Serious_attempt/the_one_that_does_it.py

@@ -29,10 +29,17 @@ entities_sheet = input_data[ENTITIES_SHEETNAME]
 relations_sheet = input_data[RELATIONS_SHEETNAME]
 
 # Parse sheet data into a dict (assuming the xlsx has headers)
+
+# Get non-empty headers for entities sheet
 entities_keys = [cell for cell in next(entities_sheet.values) if cell]
+
+# Get entity rows as list of dicts
 raw_entities = [{key: row[ind] for ind, key in enumerate(entities_keys)} for row in entities_sheet.values][1:]
-#
+
+# Get non-empty headers for relations sheet
 relations_keys = [cell for cell in next(relations_sheet.values) if cell]
+
+# Get relation rows as list of dicts
 raw_relations = [{key: row[ind] for ind, key in enumerate(relations_keys)} for row in relations_sheet.values][1:]
 # %%
 # NOTE:
@@ -53,30 +60,47 @@ raw_relations = [{key: row[ind] for ind, key in enumerate(relations_keys)} for r
 
 # Process entities:
 
+def normalize_ent_name(name: str) -> str:
+    return re.sub(r'\s+', ' ', name.strip().title())
+
 # 1. Filter out unnamed entities, normalize entity names, collect aliases, discover duplicates
 clean_entities = {}
 for ent in raw_entities:
     entity_names = ent['Concetto']
     if not isinstance(entity_names, str):
         continue
-    aliases = [re.sub(r'\s+', ' ', al.strip().title()) for al in entity_names.split('\n') if al.strip()]
+    aliases = [normalize_ent_name(al) for al in re.split(r'\r\n|\r|\n', entity_names) if al.strip()]
     if not aliases:
         continue
     entity_name = aliases[0]
     entity_same_as = aliases[1:]
     if clean_entities.get(entity_name):
         # DUPLICATE!
-        clean_entities[entity_name].append({'Alias': aliases, 'Raw': ent})
+        clean_entities[entity_name].append({'Alias': entity_same_as, 'Raw': ent})
     else:
-        clean_entities[entity_name] = [{'Alias': aliases, 'Raw': ent}]
+        clean_entities[entity_name] = [{'Alias': entity_same_as, 'Raw': ent}]
+
+# TEMP - filter out a few of the entities manually
+clean_entities.pop(normalize_ent_name('Circolazione Del Manoscritto'), None)
+clean_entities.pop(normalize_ent_name('Luogo Di Conservazione'), None)
+clean_entities.pop(normalize_ent_name('Possessore'), None)
+clean_entities.pop(normalize_ent_name('Volume'), None)
 
 all_entities = clean_entities.keys()
 
 duplicated_entities = [ent_name for ent_name, ent_val in clean_entities.items() if len(ent_val)>1]
+
+if duplicated_entities:
+    print('WARNING! DUPLICATED ENTITIES:')
+    for ent in duplicated_entities:
+        print(ent)
 # %%
 # Process relations:
 
 # 1. Filter ill-formed relations and normalize entity names
+def normalize_rel_name(name: str) -> str:
+    return re.sub(r'\s+', '_', name.strip().lower()).replace('__', '_')
+
 clean_relations = []
 for rel in raw_relations:
     subj = rel['Soggetto']
@@ -94,29 +118,71 @@ for rel in raw_relations:
     clean_rel = {'Soggetto': subj, 'Relazione': rel_name, 'Oggetto': obj}
     clean_relations.append(clean_rel)
 
-all_rels = set((rel['Soggetto'], rel['Relazione'], rel['Oggetto']) for rel in clean_relations)
-
+# TEMP - filter out a few of the relations manually
+def manual_remove(rel: dict) -> bool:
+    if rel['Soggetto']==normalize_ent_name('Circolazione del manoscritto'):
+        return True
+    if rel['Soggetto']==normalize_ent_name('Fascicolo') and rel['Oggetto']==normalize_ent_name('Data'):
+        return True
+    #
+    return False
+clean_relations = [rel for rel in clean_relations if not manual_remove(rel)]
+# In this case, I don't really care if a relation appears twice
+
+# Get all Entities that appear as Subjects
 all_subjects = set(rel['Soggetto'] for rel in clean_relations)
+
+# Get all Entities that appear either as Subjects or Objects
 all_cited_entities = set(sum([[rel['Soggetto'], rel['Oggetto']] for rel in clean_relations], []))
 
+# Get entities that appear in the relations sheet but NOT in the entities sheet
 undefined_entities = all_cited_entities - all_entities
-unused_entities = all_entities - all_cited_entities
+
+# Get all entities that appear purely as Subjects; it is (mostly) OK if they are not defined in the Entity sheet.
 atomic_entities = all_cited_entities - all_subjects
+
+# Entities which are not 'atomic' and are undefined are a problem
 problematic_entities = undefined_entities - atomic_entities
+
+# Get entities which do not appear in any relation, and are NOT classified as Subclasses.
+unused_entities = all_entities - all_cited_entities
+unused_entities = [ un for un in unused_entities if (not clean_entities.get(un) or not clean_entities[un][0]['Raw']['Sottoclasse di']) ]
 # %%
 ####
 # MANUS ONLINE (MOL) API: https://api.iccu.sbn.it/devportal/apis
 ####
 # %%
-for ent in sorted(list(problematic_entities)):
-    print(ent)
+if problematic_entities:
+    print('ERROR: some non-atomic entities are undefined')
+    print()
+    for ent in sorted(list(problematic_entities)):
+        print(ent)
 # %%
-for ent in sorted(list(atomic_entities)):
-    print(ent)
+if unused_entities:
+    print('Unused entities:')
+    print()
+    for ent in sorted(list(unused_entities)):
+        print(ent)
 # %%
-for ent in sorted(list(unused_entities)):
-    print(ent)
+if undefined_entities:
+    print("Undefined 'atomic' entities:")
+    print()
+    for ent in sorted(list(undefined_entities)):
+        print(ent)
 # %%
-for ent in sorted(list(undefined_entities)):
-    print(ent)
+# Export results
+if not problematic_entities and not duplicated_entities:
+    entities_to_export = [{'ENTITÀ': ent, 'ATTRIBUTO (LITERAL)': None, 'SAME AS': ', '.join(ent_val[0]['Alias'])} for ent, ent_val in clean_entities.items()]
+    #
+    atomic_rels = [rel for rel in clean_relations if rel['Oggetto'] in atomic_entities]
+    entities_to_export += [{'ENTITÀ': rel['Soggetto'], 'ATTRIBUTO (LITERAL)': rel['Oggetto'], 'SAME AS': None} for rel in atomic_rels]
+
+    entities_to_export = sorted(entities_to_export, key=lambda x: x['ENTITÀ'])
+
+    with open(OUTPUT_FOLDER + ent_filename, 'w', encoding='utf-8', newline='\n') as ent_csv:
+        headers = ['ENTITÀ', 'ATTRIBUTO (LITERAL)', 'SAME AS']
+        writer = csv.DictWriter(ent_csv, fieldnames=headers)
+        writer.writeheader()
+        writer.writerows(entities_to_export)
+
 # %%