|
|
Archæologist, Bremen, GermanyContact: andy[at]postantiquarian.de Web: Postantiquarian European Association of Archaeologists, Deutsche Gesellschaft für Ur- und Frühgeschichte, Verband für Grabungstechnik und Feldarchäologie |
Since graduating I have worked on over 30 different archaeological projects, the vast majority of them in Germany, and have held a variety of positions up to and including Site Supervisor/Project Leader. I am familiar with excavation techniques and the legal requirements for archaeological work in both Bremen and Niedersachsen.
I am experienced with various digital archaeological practices including GIS (QGIS), R, and Python. I have previously used Python to develop an application that automates a variety of tasks such as the creation of project folder structures, importing data from a Total Station or GNSS device, as well as creating geopackages containing vector layers created with the imported data. I use R for data processing and visualisation.
The above map was digitised from a scanned and georeferenced copy of a 1978 excavation report published in the Proceedings of the Prehistoric Society. Digitisation was carried out in QGIS and the map was rendered using in Leaflet with additional HTML and Javascript. Christie, P. M. L. (1978). “The Excavation of an Iron Age Souterrain and Settlement at Carn Euny, Sancreed, Cornwall”, Proceedings of the Prehistoric Society, 44, pp.309-433.
The above excavation plan was converted from an old AutoCAD drawing into QGIS and saved as a geopackage. The data within the geopackage was then visualised with Leaflet. The actual coordinates of the excavation site were also obfuscated with QGIS. The points show areas where calcified bone was found.
Below is a screenshot of a simple web application displaying all of
the archaeological sites in the Scottish parish of Farr. Click the
screenshot to be taken to the interactive map which allows the user to
filter the displayed sites by with period of site type.
I have used Python to automate many of the repetitive desk based jobs that I am required to do. Everything from quickly creating an appropriate folder structure for an archaeological project to error checking measurement data taken in the field and then automatically generating vector layers in QGIS and saving them to an appropriately named Geopackage.
Folder Structure Creation
The code below is part of a larger plugin for QGIS and allows the user to set up their working project folders appropriately. This saves time and ensures a persistent structure across all projects.
import os
from PyQt5.QtWidgets import QFileDialog
class OrdnerStruktur:
def __init__(self, dlg):
# dlg is the dialog instance that contains the GUI elements
self.dlg = dlg
self.target_folder = None
# Connects buttons to their respective methods
self.dlg.ord_wahl.clicked.connect(self.ordner_auswaehlen)
self.dlg.ord_go_b.clicked.connect(self.ordner_erstellen)
def ordner_auswaehlen(self):
# Method to select a target directory for creating folder structure.
folder_path = QFileDialog.getExistingDirectory(self.dlg, "Wählen Sie den Ordner")
if folder_path:
self.target_folder = folder_path
print("Ziel Ordner:", self.target_folder)
def ordner_erstellen(self):
# Method to create folder structure based on user input.
# Get user inputs from the text fields
gm_in = self.dlg.gm_in.toPlainText().strip()
ms_in = self.dlg.ms_in.toPlainText().strip()
fst_in = self.dlg.fst_in.toPlainText().strip()
# Check if the mandatory fields are filled
if not gm_in or not ms_in:
print("Please provide both Gemarkung and Massnahmen values.")
return
# Construct the root folder name
root_folder_name = f"{gm_in}_{ms_in}"
if fst_in: # If the optional field is filled
root_folder_name += f"_{fst_in}"
# Check if a target folder is selected
if not self.target_folder:
print("No target folder selected.")
return
# Create the root directory
root_dir_path = os.path.join(self.target_folder, root_folder_name)
try:
os.makedirs(root_dir_path, exist_ok=True)
print(f"Root Directory '{root_folder_name}' Created")
except FileExistsError:
print(f"Root Directory '{root_folder_name}' already exists")
# Define the folder structure with subdirectories
folder_structure = {
'00_Hintergrund_Daten': [],
'10_Bericht': [],
'20_Fotos': ['21_Unsortiert', '22_Sortiert'],
'30_Zeichnenblätter': [],
'40_GIS': ['00_Arbeits_Ordner', '41_Layout', '42_Messdaten', '43_Anderer_Daten'],
'50_Datenbank': [],
'60_Tagebuch': []
}
# Iterate through the folder structure and create directories
for main_folder, subfolders in folder_structure.items():
main_folder_path = os.path.join(root_dir_path, main_folder)
# Create the main folder
try:
os.makedirs(main_folder_path, exist_ok=True)
print(f"Main Directory '{main_folder_path}' Created")
except FileExistsError:
print(f"Main Directory '{main_folder_path}' already exists")
# Create subfolders
for subfolder in subfolders:
subfolder_path = os.path.join(main_folder_path, subfolder)
try:
os.makedirs(subfolder_path, exist_ok=True)
print(f"Subdirectory '{subfolder_path}' Created")
except FileExistsError:
print(f"Subdirectory '{subfolder_path}' already exists")
Layer Renaming The script below is a QGIS plugin that allows the user to quickly append text to the beginning of each layer name within QGIS, a requirement with some, though not all, regional authorities.
from qgis.core import QgsProject
from qgis.PyQt.QtWidgets import QAction, QMessageBox, QDialog
from .suedlink_layers_dialog import Ui_SuedlinkLayerRenamerDialogBase # Import the generated UI class
class RenameLayersPlugin:
def __init__(self, iface):
self.iface = iface
self.action = None
self.dialog = None
self.dialog_ui = None
def initGui(self):
# Create action that will start the renaming process
self.action = QAction("Rename Layers with Prefix", self.iface.mainWindow())
self.action.triggered.connect(self.show_dialog)
# Add action to the QGIS interface
self.iface.addPluginToMenu("&Layer Tools", self.action)
# Set up the dialog
self.dialog = QDialog()
self.dialog_ui = Ui_SuedlinkLayerRenamerDialogBase()
self.dialog_ui.setupUi(self.dialog)
# Connect the button to the renaming function
self.dialog_ui.go_b.clicked.connect(self.run)
def unload(self):
# Remove the plugin menu item
if self.action:
self.iface.removePluginMenu("&Layer Tools", self.action)
def show_dialog(self):
# Show the dialog
self.dialog.show()
def run(self):
# Get the prefix from the text entry field in the dialog
prefix = self.dialog_ui.ms_in.toPlainText().strip()
if not prefix:
QMessageBox.information(None, "Rename Layers", "No prefix provided. Operation cancelled.")
return
# Access QGIS project instance
project = QgsProject.instance()
# Iterate over layers in project, update names
for layer in project.mapLayers().values():
# Update layer name with prefix
new_name = f"{prefix}_{layer.name()}"
layer.setName(new_name)
QMessageBox.information(None, "Rename Layers", "Layers have been renamed successfully.")
Since graduation I have continued to expand upon my skillset with both self directed learning and structured courses.
-M.Litt in Archaeological Studies, distance learning, graduation in 2027.