PyArchInit-Mini Python API - Complete Reference
- Date:
2025-10-28
- Version:
1.7.0+
- Status:
✅ Complete API Documentation
Introduction
PyArchInit-Mini provides a comprehensive Python API for archaeological data management. This guide shows you how to use all APIs and modules in your Python applications, with complete input/output examples and integration patterns for external projects.
Use Cases:
Custom archaeological data management systems
Automated data processing pipelines
Integration with existing Python applications
Batch operations and data migration
Custom visualization and analysis tools
Architecture Overview
Core Components
PyArchInit-Mini Architecture:
┌─────────────────────────────────────────┐
│ Your Application │
└─────────────────┬───────────────────────┘
│
┌─────────────────┴───────────────────────┐
│ Python API Layer │
│ ┌────────────┐ ┌─────────────────┐ │
│ │ Services │ │ Matrix Generator │ │
│ │ - Site │ │ - GraphML Export │ │
│ │ - US │ │ - DOT Export │ │
│ │ - Inv. │ └─────────────────┘ │
│ └────────────┘ │
└─────────────────┬───────────────────────┘
│
┌─────────────────┴───────────────────────┐
│ Database Manager (SQLAlchemy) │
│ - Connection pooling │
│ - Transaction management │
│ - ORM models │
└─────────────────┬───────────────────────┘
│
┌─────────────────┴───────────────────────┐
│ Database (SQLite/PostgreSQL) │
└──────────────────────────────────────────┘
Key Modules:
Database Layer:
DatabaseManager, ModelsService Layer:
SiteService,USService,InventarioService,ImportExportServiceVisualization Layer:
MatrixGenerator,GraphMLExporterUtility Layer: Configuration, Validation, Helpers
Quick Start
Installation
# Install with all features
pip install 'pyarchinit-mini[all]'
# Or install specific features
pip install 'pyarchinit-mini[harris]' # Harris Matrix features
pip install 'pyarchinit-mini[web]' # Web interface
pip install 'pyarchinit-mini[auth]' # Authentication
Basic Usage
from pyarchinit_mini.database.manager import DatabaseManager
from pyarchinit_mini.services.site_service import SiteService
from pyarchinit_mini.services.us_service import USService
# Initialize database
db = DatabaseManager('sqlite:///my_project.db')
# Initialize services
site_service = SiteService(db)
us_service = USService(db)
# Create a site
site = site_service.create({
'sito': 'Pompeii',
'nazione': 'Italy',
'regione': 'Campania',
'descrizione': 'Ancient Roman city'
})
# Create a stratigraphic unit
us = us_service.create({
'sito': 'Pompeii',
'area': 'Area A',
'us': 1001,
'unita_tipo': 'US',
'd_stratigrafica': 'Fill layer with pottery',
'd_interpretativa': 'Medieval fill'
})
print(f"Created site: {site['sito']}")
print(f"Created US: {us['us']}")
Expected Output:
Created site: Pompeii
Created US: 1001
Database Management
DatabaseManager Class
The DatabaseManager class handles all database operations.
Import:
from pyarchinit_mini.database.manager import DatabaseManager
Initialization:
# SQLite
db = DatabaseManager('sqlite:///path/to/database.db')
# PostgreSQL
db = DatabaseManager('postgresql://user:pass@localhost:5432/dbname')
# With connection options
db = DatabaseManager(
'sqlite:///database.db',
echo=True, # Log SQL queries
pool_size=10, # Connection pool size
max_overflow=20 # Max connections beyond pool_size
)
Methods:
Method |
Description |
|---|---|
|
Get a new database session |
|
Close all connections |
|
Create all database tables |
|
Drop all database tables |
Complete Example:
from pyarchinit_mini.database.manager import DatabaseManager
from contextlib import contextmanager
class ArchaeologicalDatabase:
"""
Wrapper for database operations with context management
"""
def __init__(self, db_url: str):
self.db = DatabaseManager(db_url)
self.db.create_all_tables()
@contextmanager
def session_scope(self):
"""
Provide a transactional scope for database operations
"""
session = self.db.get_session()
try:
yield session
session.commit()
except Exception as e:
session.rollback()
raise
finally:
session.close()
def execute_query(self, model, filters=None):
"""
Execute a database query with filters
Args:
model: SQLAlchemy model class
filters: Dictionary of filter conditions
Returns:
list: Query results
"""
with self.session_scope() as session:
query = session.query(model)
if filters:
for key, value in filters.items():
if hasattr(model, key):
query = query.filter(
getattr(model, key) == value
)
return query.all()
# Usage
arch_db = ArchaeologicalDatabase('sqlite:///project.db')
# Query sites
from pyarchinit_mini.database.models import Site
sites = arch_db.execute_query(Site, {'nazione': 'Italy'})
for site in sites:
print(f"Site: {site.sito}, Region: {site.regione}")
Site Service API
The SiteService class manages archaeological site data.
Create Site
from pyarchinit_mini.services.site_service import SiteService
site_service = SiteService(db)
site_data = {
'sito': 'Pompeii',
'nazione': 'Italy',
'regione': 'Campania',
'comune': 'Pompeii',
'descrizione': 'Ancient Roman city buried by Vesuvius eruption',
'definizione_sito': 'Urban archaeological site',
'provincia': 'Naples',
'latitudine': 40.7489,
'longitudine': 14.4864
}
result = site_service.create(site_data)
print(f"Created site: {result['sito']}")
print(f"Site ID: {result['id_sito']}")
Expected Output:
Created site: Pompeii
Site ID: 1
Read Site
# Get by ID
site = site_service.get_by_id(1)
print(f"Site: {site['sito']}")
# Get by name
site = site_service.get_by_name('Pompeii')
print(f"Description: {site['descrizione']}")
# Get all sites
all_sites = site_service.get_all()
print(f"Total sites: {len(all_sites)}")
for site in all_sites:
print(f" - {site['sito']} ({site['nazione']})")
Expected Output:
Site: Pompeii
Description: Ancient Roman city buried by Vesuvius eruption
Total sites: 3
- Pompeii (Italy)
- Rome (Italy)
- Athens (Greece)
Update Site
# Update site data
updates = {
'descrizione': 'Updated description with new findings',
'provincia': 'Metropolitan City of Naples'
}
result = site_service.update(site_id=1, updates=updates)
print(f"Updated: {result['sito']}")
Expected Output:
Updated: Pompeii
Delete Site
# Delete site
result = site_service.delete(site_id=1)
print(f"Deleted: {result['success']}")
Expected Output:
Deleted: True
US (Stratigraphic Unit) Service API
The USService class manages stratigraphic unit data.
Create US
from pyarchinit_mini.services.us_service import USService
us_service = USService(db)
us_data = {
'sito': 'Pompeii',
'area': 'Area A',
'us': 1001,
'unita_tipo': 'US',
'd_stratigrafica': 'Fill layer with ceramic fragments and charcoal',
'd_interpretativa': 'Medieval fill from abandonment phase',
'tipo_us': 'deposit',
'formazione': 'natural',
'stato_di_conservazione': 'good',
'colore': 'dark brown',
'consistenza': 'compact',
'struttura': 'homogeneous',
'periodo_iniziale': 'Medieval',
'fase_iniziale': 'Early Medieval',
'periodo_finale': 'Medieval',
'fase_finale': 'Late Medieval'
}
result = us_service.create(us_data)
print(f"Created US: {result['us']}")
print(f"Type: {result['unita_tipo']}")
print(f"Site: {result['sito']}, Area: {result['area']}")
Expected Output:
Created US: 1001
Type: US
Site: Pompeii, Area: Area A
Search US
# Search by site
us_list = us_service.search(sito='Pompeii')
print(f"US in Pompeii: {len(us_list)}")
# Search by area
us_list = us_service.search(sito='Pompeii', area='Area A')
print(f"US in Area A: {len(us_list)}")
# Search by type
usm_list = us_service.search(sito='Pompeii', unita_tipo='USM')
print(f"USM units: {len(usm_list)}")
# Search by period
medieval_us = us_service.search(
sito='Pompeii',
periodo_iniziale='Medieval'
)
print(f"Medieval US: {len(medieval_us)}")
Expected Output:
US in Pompeii: 125
US in Area A: 45
USM units: 12
Medieval US: 23
Add Relationships
# Add stratigraphic relationship
relationship = {
'sito': 'Pompeii',
'area': 'Area A',
'us': 1001,
'rapporti': 'Copre', # Covers
'nazione': '',
'us_rapporti': 1002
}
result = us_service.add_relationship(relationship)
print(f"Relationship created: US {relationship['us']} → US {relationship['us_rapporti']}")
# Add multiple relationships
relationships = [
{'us': 1001, 'rapporti': 'Copre', 'us_rapporti': 1002},
{'us': 1002, 'rapporti': 'Copre', 'us_rapporti': 1003},
{'us': 1003, 'rapporti': 'Si appoggia', 'us_rapporti': 2001},
]
for rel in relationships:
rel.update({'sito': 'Pompeii', 'area': 'Area A', 'nazione': ''})
us_service.add_relationship(rel)
print(f"Created {len(relationships)} relationships")
Expected Output:
Relationship created: US 1001 → US 1002
Created 3 relationships
Get Relationships
# Get all relationships for a site
relationships = us_service.get_relationships(sito='Pompeii')
print(f"Total relationships: {len(relationships)}")
for rel in relationships[:5]: # Show first 5
print(f" US {rel['us']} {rel['rapporti']} US {rel['us_rapporti']}")
# Get relationships for specific US
us_1001_rels = [r for r in relationships if r['us'] == 1001]
print(f"\nUS 1001 relationships: {len(us_1001_rels)}")
Expected Output:
Total relationships: 342
US 1001 Copre US 1002
US 1002 Copre US 1003
US 1003 Si appoggia US 2001
US 2001 Si lega a US 2002
US 1004 Taglia US 1005
US 1001 relationships: 3
Inventario (Material Inventory) Service API
The InventarioService class manages material finds data.
Create Inventario Entry
from pyarchinit_mini.services.inventario_service import InventarioService
inv_service = InventarioService(db)
inventario_data = {
'sito': 'Pompeii',
'area': 'Area A',
'us': 1001,
'numero_inventario': 'POM2024-001',
'tipo_reperto': 'Ceramic',
'definizione_reperto': 'Terra sigillata plate fragment',
'descrizione': 'Red-slip ware plate fragment with stamp',
'tecnologia': 'Wheel-thrown',
'forma': 'Plate',
'stato_conservazione': 'fragmentary',
'n_reperto': 1,
'quota': -2.35,
'osservazioni': 'Found in fill layer, possibly intrusive'
}
result = inv_service.create(inventario_data)
print(f"Created inventory: {result['numero_inventario']}")
print(f"Type: {result['tipo_reperto']}")
print(f"From: US {result['us']}")
Expected Output:
Created inventory: POM2024-001
Type: Ceramic
From: US 1001
Search Inventario
# Search by site
finds = inv_service.search(sito='Pompeii')
print(f"Total finds: {len(finds)}")
# Search by US
us_finds = inv_service.search(sito='Pompeii', us=1001)
print(f"Finds from US 1001: {len(us_finds)}")
# Search by material type
ceramics = inv_service.search(sito='Pompeii', tipo_reperto='Ceramic')
print(f"Ceramic finds: {len(ceramics)}")
# Complex search
results = inv_service.search(
sito='Pompeii',
area='Area A',
tipo_reperto='Ceramic',
stato_conservazione='fragmentary'
)
print(f"Filtered results: {len(results)}")
Expected Output:
Total finds: 1234
Finds from US 1001: 23
Ceramic finds: 456
Filtered results: 12
Import/Export Service API
The ImportExportService class handles data synchronization between PyArchInit and PyArchInit-Mini.
Initialize Import/Export
from pyarchinit_mini.services.import_export_service import ImportExportService
# Initialize with database connections
service = ImportExportService(
mini_db_connection='sqlite:///pyarchinit_mini.db',
source_db_connection='sqlite:///pyarchinit_source.db'
)
# Or with PostgreSQL
service = ImportExportService(
mini_db_connection='sqlite:///pyarchinit_mini.db',
source_db_connection='postgresql://user:pass@localhost/pyarchinit'
)
Import Sites
# Import all sites
stats = service.import_sites(
auto_migrate=True, # Add missing i18n columns
auto_backup=True # Create automatic backup
)
print(f"Sites imported: {stats['imported']}")
print(f"Sites updated: {stats['updated']}")
if stats.get('backup_path'):
print(f"Backup created: {stats['backup_path']}")
# Import specific sites
stats = service.import_sites(
sito_filter=['Pompeii', 'Herculaneum'],
auto_migrate=True,
auto_backup=True
)
print(f"Filtered import: {stats['imported']} sites")
Expected Output:
Sites imported: 5
Sites updated: 0
Backup created: /path/to/pyarchinit_source.db.backup_20251028_143025
Filtered import: 2 sites
Import US with Relationships
# Import US with relationships
stats = service.import_us(
sito_filter=['Pompeii'],
import_relationships=True,
auto_migrate=True,
auto_backup=True
)
print(f"US imported: {stats['imported']}")
print(f"US updated: {stats['updated']}")
print(f"Relationships created: {stats.get('relationships_created', 0)}")
Expected Output:
US imported: 758
US updated: 0
Relationships created: 2459
Complete Import Workflow
def import_complete_site(site_name: str, mini_db: str, source_db: str) -> dict:
"""
Import complete archaeological site data
Args:
site_name: Name of site to import
mini_db: Target database URL
source_db: Source database URL
Returns:
dict: Import statistics
"""
from pyarchinit_mini.services.import_export_service import ImportExportService
service = ImportExportService(mini_db, source_db)
results = {}
# Import site metadata
print(f"Importing site: {site_name}")
site_stats = service.import_sites(
sito_filter=[site_name],
auto_migrate=True,
auto_backup=True
)
results['sites'] = site_stats
print(f" ✓ Sites: {site_stats['imported']}")
# Import stratigraphic units
print("Importing stratigraphic units...")
us_stats = service.import_us(
sito_filter=[site_name],
import_relationships=True,
auto_migrate=True,
auto_backup=True
)
results['us'] = us_stats
print(f" ✓ US: {us_stats['imported']}")
print(f" ✓ Relationships: {us_stats.get('relationships_created', 0)}")
# Import material inventory
print("Importing material inventory...")
inv_stats = service.import_inventario(
sito_filter=[site_name],
auto_migrate=True,
auto_backup=True
)
results['inventario'] = inv_stats
print(f" ✓ Inventario: {inv_stats['imported']}")
# Import periodization
print("Importing periodization...")
per_stats = service.import_periodizzazione(
sito_filter=[site_name]
)
results['periodizzazione'] = per_stats
print(f" ✓ Periodizzazione: {per_stats['imported']}")
# Import thesaurus (once per database)
print("Importing thesaurus...")
thes_stats = service.import_thesaurus()
results['thesaurus'] = thes_stats
print(f" ✓ Thesaurus: {thes_stats['imported']}")
return results
# Usage
stats = import_complete_site(
'Pompeii',
'sqlite:///pyarchinit_mini.db',
'sqlite:///pyarchinit_source.db'
)
Expected Output:
Importing site: Pompeii
✓ Sites: 1
Importing stratigraphic units...
✓ US: 758
✓ Relationships: 2459
Importing material inventory...
✓ Inventario: 1234
Importing periodization...
✓ Periodizzazione: 42
Importing thesaurus...
✓ Thesaurus: 156
Harris Matrix Generation API
The MatrixGenerator class creates Harris Matrix visualizations.
Generate Matrix
from pyarchinit_mini.harris_matrix.matrix_generator import MatrixGenerator
# Initialize generator
matrix_gen = MatrixGenerator('sqlite:///pyarchinit_mini.db')
# Generate matrix
graph = matrix_gen.generate_matrix(
sito='Pompeii',
area='Area A'
)
print(f"Matrix generated:")
print(f" Nodes: {graph.number_of_nodes()}")
print(f" Edges: {graph.number_of_edges()}")
# Inspect graph
for node_id, data in list(graph.nodes(data=True))[:3]:
print(f"\nNode {node_id}:")
print(f" Type: {data.get('unita_tipo')}")
print(f" Label: {data.get('extended_label')}")
Expected Output:
Matrix generated:
Nodes: 125
Edges: 342
Node 1001:
Type: US
Label: US1001
Node 2001:
Type: USM
Label: USM2001
Node 8001:
Type: DOC
Label: DOC8001
Export to GraphML
# Export to GraphML for yEd
output_file = matrix_gen.export_to_graphml(
graph=graph,
output_path='pompeii_matrix.graphml',
site_name='Pompeii',
title='Pompeii Area A Harris Matrix',
include_periods=True,
reverse_epochs=False
)
print(f"GraphML exported: {output_file}")
Expected Output:
GraphML exported: pompeii_matrix.graphml
Export to DOT
# Export to Graphviz DOT format
dot_file = matrix_gen.export_to_dot(
graph=graph,
output_path='pompeii_matrix.dot',
site_name='Pompeii',
include_periods=True
)
print(f"DOT exported: {dot_file}")
# Generate PNG from DOT
import subprocess
subprocess.run([
'dot', '-Tpng',
'pompeii_matrix.dot',
'-o', 'pompeii_matrix.png'
])
Expected Output:
DOT exported: pompeii_matrix.dot
Integration Patterns
Pattern 1: Custom Data Pipeline
"""
Custom archaeological data processing pipeline
"""
from pyarchinit_mini.database.manager import DatabaseManager
from pyarchinit_mini.services.site_service import SiteService
from pyarchinit_mini.services.us_service import USService
from pyarchinit_mini.harris_matrix.matrix_generator import MatrixGenerator
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class ArchaeologicalDataPipeline:
"""
Complete data processing pipeline
"""
def __init__(self, db_url: str):
self.db = DatabaseManager(db_url)
self.site_service = SiteService(self.db)
self.us_service = USService(self.db)
self.matrix_gen = MatrixGenerator(db_url)
def process_excavation_data(self, site_name: str, data_file: str) -> dict:
"""
Process excavation data from file
Args:
site_name: Site name
data_file: Path to data file (CSV/Excel)
Returns:
dict: Processing statistics
"""
import pandas as pd
logger.info(f"Processing data for site: {site_name}")
# Read data
df = pd.read_excel(data_file)
logger.info(f"Loaded {len(df)} records")
stats = {
'sites': 0,
'us': 0,
'relationships': 0
}
# Create site if not exists
existing_site = self.site_service.get_by_name(site_name)
if not existing_site:
self.site_service.create({'sito': site_name})
stats['sites'] = 1
logger.info(f"Created site: {site_name}")
# Process US records
for _, row in df.iterrows():
try:
us_data = {
'sito': site_name,
'area': row.get('area', 'Main'),
'us': int(row['us']),
'unita_tipo': row.get('type', 'US'),
'd_stratigrafica': row.get('description', ''),
'd_interpretativa': row.get('interpretation', '')
}
self.us_service.create(us_data)
stats['us'] += 1
# Add relationships if present
if 'relationship_to' in row and pd.notna(row['relationship_to']):
rel = {
'sito': site_name,
'area': row.get('area', 'Main'),
'us': int(row['us']),
'rapporti': row.get('relationship_type', 'Copre'),
'nazione': '',
'us_rapporti': int(row['relationship_to'])
}
self.us_service.add_relationship(rel)
stats['relationships'] += 1
except Exception as e:
logger.error(f"Error processing row {row.get('us')}: {e}")
logger.info(f"Processing complete: {stats}")
return stats
def generate_outputs(self, site_name: str, output_dir: str) -> dict:
"""
Generate all outputs for site
Args:
site_name: Site name
output_dir: Output directory
Returns:
dict: Paths to generated files
"""
from pathlib import Path
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
outputs = {}
# Generate Harris Matrix
graph = self.matrix_gen.generate_matrix(site_name)
# Export GraphML
graphml_file = output_path / f'{site_name}_matrix.graphml'
self.matrix_gen.export_to_graphml(
graph=graph,
output_path=str(graphml_file),
site_name=site_name
)
outputs['graphml'] = str(graphml_file)
logger.info(f"GraphML exported: {graphml_file}")
# Export DOT
dot_file = output_path / f'{site_name}_matrix.dot'
self.matrix_gen.export_to_dot(
graph=graph,
output_path=str(dot_file),
site_name=site_name
)
outputs['dot'] = str(dot_file)
logger.info(f"DOT exported: {dot_file}")
return outputs
# Usage
pipeline = ArchaeologicalDataPipeline('sqlite:///project.db')
# Process excavation data
stats = pipeline.process_excavation_data(
'Pompeii',
'excavation_data.xlsx'
)
# Generate outputs
outputs = pipeline.generate_outputs('Pompeii', 'exports/')
print(f"\nProcessing complete:")
print(f" Sites created: {stats['sites']}")
print(f" US created: {stats['us']}")
print(f" Relationships: {stats['relationships']}")
print(f"\nOutputs:")
for name, path in outputs.items():
print(f" {name}: {path}")
Pattern 2: Web Application Integration
"""
Flask web application with PyArchInit-Mini integration
"""
from flask import Flask, request, jsonify
from pyarchinit_mini.database.manager import DatabaseManager
from pyarchinit_mini.services.site_service import SiteService
from pyarchinit_mini.services.us_service import USService
app = Flask(__name__)
# Initialize database and services
db = DatabaseManager('sqlite:///webapp.db')
site_service = SiteService(db)
us_service = USService(db)
@app.route('/api/sites', methods=['GET'])
def get_sites():
"""Get all sites"""
try:
sites = site_service.get_all()
return jsonify({
'success': True,
'data': sites,
'count': len(sites)
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/sites', methods=['POST'])
def create_site():
"""Create new site"""
try:
data = request.get_json()
site = site_service.create(data)
return jsonify({'success': True, 'data': site}), 201
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 400
@app.route('/api/sites/<site_name>/us', methods=['GET'])
def get_site_us(site_name):
"""Get all US for site"""
try:
us_list = us_service.search(sito=site_name)
return jsonify({
'success': True,
'site': site_name,
'data': us_list,
'count': len(us_list)
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/sites/<site_name>/matrix', methods=['GET'])
def get_harris_matrix(site_name):
"""Generate Harris Matrix for site"""
try:
from pyarchinit_mini.harris_matrix.matrix_generator import MatrixGenerator
matrix_gen = MatrixGenerator('sqlite:///webapp.db')
graph = matrix_gen.generate_matrix(site_name)
# Export to file
output_file = f'temp/{site_name}_matrix.graphml'
matrix_gen.export_to_graphml(
graph=graph,
output_path=output_file,
site_name=site_name
)
return jsonify({
'success': True,
'site': site_name,
'nodes': graph.number_of_nodes(),
'edges': graph.number_of_edges(),
'file': output_file
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
if __name__ == '__main__':
app.run(debug=True, port=5000)
Usage with curl:
# Get all sites
curl http://localhost:5000/api/sites
# Create site
curl -X POST http://localhost:5000/api/sites \
-H "Content-Type: application/json" \
-d '{"sito": "Pompeii", "nazione": "Italy"}'
# Get US for site
curl http://localhost:5000/api/sites/Pompeii/us
# Generate Harris Matrix
curl http://localhost:5000/api/sites/Pompeii/matrix
Pattern 3: Data Analysis Integration
"""
Jupyter notebook / data analysis integration
"""
import pandas as pd
import matplotlib.pyplot as plt
from pyarchinit_mini.database.manager import DatabaseManager
from pyarchinit_mini.services.us_service import USService
from pyarchinit_mini.services.inventario_service import InventarioService
class ArchaeologicalDataAnalysis:
"""
Archaeological data analysis toolkit
"""
def __init__(self, db_url: str):
self.db = DatabaseManager(db_url)
self.us_service = USService(self.db)
self.inv_service = InventarioService(self.db)
def get_us_dataframe(self, site: str) -> pd.DataFrame:
"""
Get US data as pandas DataFrame
Args:
site: Site name
Returns:
pd.DataFrame: US data
"""
us_list = self.us_service.search(sito=site)
return pd.DataFrame(us_list)
def get_inventario_dataframe(self, site: str) -> pd.DataFrame:
"""
Get inventory data as pandas DataFrame
Args:
site: Site name
Returns:
pd.DataFrame: Inventory data
"""
inv_list = self.inv_service.search(sito=site)
return pd.DataFrame(inv_list)
def analyze_chronology(self, site: str) -> dict:
"""
Analyze chronological distribution
Args:
site: Site name
Returns:
dict: Analysis results
"""
df = self.get_us_dataframe(site)
# Count by period
period_counts = df['periodo_iniziale'].value_counts()
# Count by type
type_counts = df['unita_tipo'].value_counts()
return {
'total_us': len(df),
'periods': period_counts.to_dict(),
'types': type_counts.to_dict()
}
def plot_chronology(self, site: str, output_file: str = None):
"""
Plot chronological distribution
Args:
site: Site name
output_file: Optional output file path
"""
df = self.get_us_dataframe(site)
# Create figure
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5))
# Plot periods
period_counts = df['periodo_iniziale'].value_counts()
period_counts.plot(kind='bar', ax=ax1)
ax1.set_title(f'{site} - Distribution by Period')
ax1.set_xlabel('Period')
ax1.set_ylabel('Count')
# Plot types
type_counts = df['unita_tipo'].value_counts()
type_counts.plot(kind='pie', ax=ax2, autopct='%1.1f%%')
ax2.set_title(f'{site} - Distribution by Unit Type')
plt.tight_layout()
if output_file:
plt.savefig(output_file, dpi=300, bbox_inches='tight')
plt.show()
def export_to_excel(self, site: str, output_file: str):
"""
Export all data to Excel with multiple sheets
Args:
site: Site name
output_file: Output Excel file path
"""
with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
# US data
us_df = self.get_us_dataframe(site)
us_df.to_excel(writer, sheet_name='US', index=False)
# Inventory data
inv_df = self.get_inventario_dataframe(site)
inv_df.to_excel(writer, sheet_name='Inventory', index=False)
# Relationships
rels = self.us_service.get_relationships(sito=site)
rel_df = pd.DataFrame(rels)
rel_df.to_excel(writer, sheet_name='Relationships', index=False)
# Usage in Jupyter notebook
analysis = ArchaeologicalDataAnalysis('sqlite:///project.db')
# Get data
df = analysis.get_us_dataframe('Pompeii')
print(df.head())
# Analyze
stats = analysis.analyze_chronology('Pompeii')
print(stats)
# Plot
analysis.plot_chronology('Pompeii', 'pompeii_analysis.png')
# Export
analysis.export_to_excel('Pompeii', 'pompeii_export.xlsx')
Complete Example: Multi-Site Analysis
"""
Complete example: Multi-site archaeological data analysis system
"""
from pyarchinit_mini.database.manager import DatabaseManager
from pyarchinit_mini.services.site_service import SiteService
from pyarchinit_mini.services.us_service import USService
from pyarchinit_mini.services.inventario_service import InventarioService
from pyarchinit_mini.harris_matrix.matrix_generator import MatrixGenerator
import logging
from pathlib import Path
import json
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class MultiSiteArchaeologicalSystem:
"""
Complete multi-site archaeological data management system
"""
def __init__(self, db_path: str, output_dir: str):
self.db_url = f'sqlite:///{db_path}'
self.db = DatabaseManager(self.db_url)
self.site_service = SiteService(self.db)
self.us_service = USService(self.db)
self.inv_service = InventarioService(self.db)
self.matrix_gen = MatrixGenerator(self.db_url)
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
def create_project(self, project_data: dict) -> dict:
"""
Create complete archaeological project
Args:
project_data: Dictionary with project data
Returns:
dict: Creation statistics
"""
logger.info("Creating archaeological project")
stats = {
'sites': 0,
'us': 0,
'relationships': 0,
'inventario': 0
}
# Create sites
for site_data in project_data.get('sites', []):
self.site_service.create(site_data)
stats['sites'] += 1
logger.info(f"Created site: {site_data['sito']}")
# Create US
for us_data in project_data.get('us', []):
self.us_service.create(us_data)
stats['us'] += 1
# Create relationships
for rel in project_data.get('relationships', []):
self.us_service.add_relationship(rel)
stats['relationships'] += 1
# Create inventory
for inv in project_data.get('inventario', []):
self.inv_service.create(inv)
stats['inventario'] += 1
logger.info(f"Project creation complete: {stats}")
return stats
def analyze_all_sites(self) -> dict:
"""
Analyze all sites in database
Returns:
dict: Analysis results for all sites
"""
sites = self.site_service.get_all()
results = {}
for site in sites:
site_name = site['sito']
logger.info(f"Analyzing site: {site_name}")
# Get statistics
us_list = self.us_service.search(sito=site_name)
inv_list = self.inv_service.search(sito=site_name)
rels = self.us_service.get_relationships(sito=site_name)
results[site_name] = {
'us_count': len(us_list),
'inventario_count': len(inv_list),
'relationships_count': len(rels),
'us_by_type': {},
'periods': set()
}
# Count by type
for us in us_list:
us_type = us.get('unita_tipo', 'Unknown')
results[site_name]['us_by_type'][us_type] = \
results[site_name]['us_by_type'].get(us_type, 0) + 1
# Collect periods
if us.get('periodo_iniziale'):
results[site_name]['periods'].add(us['periodo_iniziale'])
# Convert set to list for JSON serialization
results[site_name]['periods'] = list(results[site_name]['periods'])
return results
def export_all_matrices(self) -> dict:
"""
Export Harris Matrices for all sites
Returns:
dict: Paths to exported files
"""
sites = self.site_service.get_all()
exported = {}
for site in sites:
site_name = site['sito']
logger.info(f"Exporting matrix for: {site_name}")
try:
# Generate matrix
graph = self.matrix_gen.generate_matrix(site_name)
if graph.number_of_nodes() == 0:
logger.warning(f"No nodes found for {site_name}")
continue
# Export GraphML
graphml_file = self.output_dir / f'{site_name}_matrix.graphml'
self.matrix_gen.export_to_graphml(
graph=graph,
output_path=str(graphml_file),
site_name=site_name
)
exported[site_name] = str(graphml_file)
logger.info(f"Exported: {graphml_file}")
except Exception as e:
logger.error(f"Export failed for {site_name}: {e}")
return exported
def generate_report(self) -> str:
"""
Generate comprehensive analysis report
Returns:
str: Path to report file
"""
logger.info("Generating comprehensive report")
# Analyze all sites
analysis = self.analyze_all_sites()
# Create report
report = {
'total_sites': len(analysis),
'sites': analysis,
'summary': {
'total_us': sum(s['us_count'] for s in analysis.values()),
'total_inventario': sum(s['inventario_count'] for s in analysis.values()),
'total_relationships': sum(s['relationships_count'] for s in analysis.values())
}
}
# Save report
report_file = self.output_dir / 'analysis_report.json'
with open(report_file, 'w') as f:
json.dump(report, f, indent=2)
logger.info(f"Report saved: {report_file}")
return str(report_file)
# Example usage
if __name__ == '__main__':
# Initialize system
system = MultiSiteArchaeologicalSystem(
db_path='multi_site_project.db',
output_dir='exports/'
)
# Create project with sample data
project_data = {
'sites': [
{
'sito': 'Pompeii',
'nazione': 'Italy',
'regione': 'Campania'
},
{
'sito': 'Herculaneum',
'nazione': 'Italy',
'regione': 'Campania'
}
],
'us': [
{
'sito': 'Pompeii',
'area': 'Area A',
'us': 1001,
'unita_tipo': 'US',
'd_stratigrafica': 'Fill layer',
'periodo_iniziale': 'Roman'
},
# ... more US
],
'relationships': [
{
'sito': 'Pompeii',
'area': 'Area A',
'us': 1001,
'rapporti': 'Copre',
'nazione': '',
'us_rapporti': 1002
},
# ... more relationships
],
'inventario': [
{
'sito': 'Pompeii',
'us': 1001,
'numero_inventario': 'POM-001',
'tipo_reperto': 'Ceramic'
},
# ... more inventory
]
}
# Create project
stats = system.create_project(project_data)
print(f"\nProject created: {stats}")
# Analyze all sites
analysis = system.analyze_all_sites()
print(f"\nAnalysis results:")
for site, data in analysis.items():
print(f"\n{site}:")
print(f" US: {data['us_count']}")
print(f" Inventory: {data['inventario_count']}")
print(f" Relationships: {data['relationships_count']}")
print(f" Periods: {', '.join(data['periods'])}")
# Export matrices
exported = system.export_all_matrices()
print(f"\nExported matrices:")
for site, path in exported.items():
print(f" {site}: {path}")
# Generate report
report_path = system.generate_report()
print(f"\nReport generated: {report_path}")
Expected Output:
2025-10-28 14:30:25 - INFO - Creating archaeological project
2025-10-28 14:30:25 - INFO - Created site: Pompeii
2025-10-28 14:30:25 - INFO - Created site: Herculaneum
2025-10-28 14:30:26 - INFO - Project creation complete: {'sites': 2, 'us': 125, 'relationships': 342, 'inventario': 234}
Project created: {'sites': 2, 'us': 125, 'relationships': 342, 'inventario': 234}
2025-10-28 14:30:26 - INFO - Analyzing site: Pompeii
2025-10-28 14:30:27 - INFO - Analyzing site: Herculaneum
Analysis results:
Pompeii:
US: 75
Inventory: 156
Relationships: 234
Periods: Roman, Medieval
Herculaneum:
US: 50
Inventory: 78
Relationships: 108
Periods: Roman
2025-10-28 14:30:27 - INFO - Exporting matrix for: Pompeii
2025-10-28 14:30:28 - INFO - Exported: exports/Pompeii_matrix.graphml
2025-10-28 14:30:28 - INFO - Exporting matrix for: Herculaneum
2025-10-28 14:30:29 - INFO - Exported: exports/Herculaneum_matrix.graphml
Exported matrices:
Pompeii: exports/Pompeii_matrix.graphml
Herculaneum: exports/Herculaneum_matrix.graphml
2025-10-28 14:30:29 - INFO - Generating comprehensive report
2025-10-28 14:30:29 - INFO - Report saved: exports/analysis_report.json
Report generated: exports/analysis_report.json
See Also
PyArchInit Import/Export - Complete Guide with Automatic Backup - Import/Export system guide
Extended Matrix Framework - Complete Guide - Extended Matrix framework
Extended Matrix GraphML Export - Technical Guide - GraphML export technical details
Python Module Usage Examples - Additional Python examples
The Python API is complete, documented, and production-ready! 🚀