Tactool
TACtool is a desktop GUI tool for targeting and co-ordinating sampling points for microanalysis, using spatially resolved imagery, enabling their import directly into sampling systems such as a laser ablation system. The use of this tool dramatically improves analytical traceability and workflow efficiency in the lab.
Install / Use
/learn @BritishGeologicalSurvey/TactoolREADME
TACtool
TACtool: A targeting and co-ordination tool for spatial sampling and data traceability applied to scanning electron microscopy and laser ablation ICP-MS
TACtool (Targeting And Coordination tool) is a desktop GUI tool designed to allow users to annotate laser ablation analysis locations onto high resolution SEM images. TACtool automatically calculates coordinates of annotations and provides the tools to export them into a CSV file format, which can then be uploaded to laser ablation systems. This ensures efficient and accurate re-coordination of target locations relative to the spatial context resolved in the SEM image. This automatic process saves time and resources, whilst improving reproducibility and traceability throughout a lab's workflow.
Getting started
You can download the TACtool application here:
On Windows, save it somewhere you'll remember, then just double-click the icon to run it (no installation necessary).
Instructions for using the application can be found here.
TACtool outputs a CSV file which contains your analysis points and their metadata. This can then be used to setup an analysis run on your micro-analysis system.
A guide for importing the resulting CSV into ESI laser control software can be found here.

Original Contributors
TACTool was initially developed within the British Geological Survey by:
- Connor Newstead
- Dan Sutton
- Declan Valters
- Leo Rudczenko
- John A Stevenson
The original idea was by Connor Newstead and Matt Horstwood.
Development
Community Contributions
If you would like to give feedback, ask questions, submit a bug report, or make a contribution to TACtool, you are welcome to submit an issue to the repository here.
Installation
Note: this is only if you want to run the tool from the source code. If you just want to use the app, see "Getting started" above.
Check out the repository and install dependencies using Anaconda.
Windows
conda env create -f environments/windows-environment.yml
conda activate tactool-windows
MacOS
conda env create -f environments/macos-environment.yml
conda activate tactool-macos
Note: Both environments have been generated using environments/unversioned-environment.yml.
Running the Program
To run the program, first you need to setup your Python path.
Windows
$env:PYTHONPATH="."
MacOS
export PYTHONPATH=.
Then you can run the program with:
python tactool/main.py --dev
The --dev flag starts the application in developer mode, with a test image
pre-loaded into the GraphicsView.
Class Relationship Diagram
classDiagram
direction LR
class TACtool{
QApplication
Manages preloaded modes of the application
---
+testing_mode: bool
+window: Window
+graphics_view: GraphicsView
+graphics_scene: GraphicsScene
+table_model: TableModel
+table_view: TableView
+set_scale_dialog: Optional[SetScaleDialog]
+recoordinate_dialog: Optional[RecoordinateDialog]
developer_mode()
}
class Window {
QMainWindow
Main User Interface with data flow
---
+testing_mode: bool
+default_settings: dict[str, Any]
+image_filepath: Optional[str]
+csv_filepath: Optional[str]
+point_colour: str
+graphics_view: GraphicsView
+graphics_scene: GraphicsScene
+table_model: TableModel
+table_view: TableView
+set_scale_dialog: Optional[SetScaleDialog]
+recoordinate_dialog: Optional[RecoordinateDialog]
+menu_bar: QMenuBar
+menu_bar_file: QMenu
+import_image_button: QAction
+export_image_button: QAction
+import_tactool_csv_button: QAction
+export_tactool_csv_button: QAction
+recoordinate_sem_csv_button: QAction
+menu_bar_tools: QMenu
+ghost_point_button: QAction
+status_bar: QStatusBar
+sample_name_input: QLineEdit
+mount_name_input: QLineEdit
+material_input: QLineEdit
+label_input: QComboBox
+colour_button: QPushButton
+diameter_input: QSpinBox
+scale_value_input: QLineEdit
+set_scale_button: QPushButton
+clear_points_button: QPushButton
+reset_ids_button: QPushButton
+reset_settings_button: QPushButton
+status_bar_messages: dict[str, dict[str, Any]]
+main_input_widgets: list[QWidget]
+dialogs: list[QDialog]
+setup_ui_elements()
+connect_signals_and_slots()
+set_colour_button_style()
+create_status_bar_messages()
+toggle_status_bar_messages()
+import_image_get_path()
+export_image_get_path()
+import_tactool_csv_get_path()
+load_tactool_csv_data(filepath)
+export_tactool_csv_get_path()
+validate_current_data(validate_image)
+add_analysis_point(x, y, apid, label, diameter, scale, colour, sample_name, mount_name, material, notes, use_windows_inputs, ghost)
+add_ghost_point(x, y)
+remove_analysis_point(x, y, apid)
+reload_analysis_points(index, transform)
+clear_analysis_points()
+get_point_colour()
+set_point_colour(colour)
+get_point_settings(analysis_point, clicked_column_index)
+reset_settings()
+update_point_settings(label, diameter, scale, colour, sample_name, mount_name, material)
+toggle_main_input_widgets(enable)
+set_scale(scale)
+toggle_scaling_mode()
+toggle_recoordinate_dialog()
+qmessagebox_error(error)
+closeEvent(event)
}
class TableView{
QTableView
Manage the display of TableModel data
---
+format_columns()
+mousePressEvent(event)
+signal: selected_analysis_point(analysis_point, column)
}
class TableModel{
QAbstractTableModel
Manage AnalysisPoint data
---
+headers: list[str]
+_data: list[list[Any]]
+editable_columns: list[int]
+public_headers: list[str]
+analysis_points: list[AnalysisPoint]
+reference_points: list[AnalysisPoint]
+next_point_id: int
+headerData(section, orientation, role)
+columnCount(*args)
+rowCount(*args)
+data(index, role)
+setData(index, value, role)
+flags(index)
+add_point(analysis_point)
+remove_point(target_id)
+get_point_by_ellipse(target_ellipse)
+get_point_by_apid(target_id)
signal: updated_analysis_point(index)
}
class AnalysisPoint{
Create AnalysisPoint data
---
+id: int
+label: str
+x: int
+y: int
+diameter: int
+scale: float
+colour: str
+sample_name: str
+mount_name: str
+material: str
+notes: str
+_outer_ellipse: QGraphicsEllipseItem
+_inner_ellipse: QGraphicsEllipseItem
+_label_text_item: QGraphicsTextItem
+field_names()
+aslist()
}
class GraphicsView{
QGraphicsView
Manage user interaction and visual display of GraphicsScene
---
+_zoom: int
+_empty: bool
+_image: QGraphicsPixmapItem
+disable_analysis_points: bool
+navigation_mode: bool
+scaling_mode: bool
+scale_start_point: QPointF
+scale_end_point: QPointF
+graphics_scene: GraphicsScene
+mousePressEvent(event)
+mouseMoveEvent(event)
+wheelEvent(event)
+keyPressEvent(event)
+keyReleaseEvent(event)
+configure_frame()
+load_image(filepath)
+save_image(filepath)
+show_entire_image()
+toggle_scaling_mode()
+reset_scaling_elements()
+remove_ghost_point()
+signal: left_click(x, y)
+signal: right_click(x, y)
+signal: scale_move_event(pixel_distance)
+signal: move_ghost_point(x, y)
}
class GraphicsScene{
QGraphicsScene
Manage items painted on image
---
+scaling_group: QGraphicsItemGroup
+scaling_line: QGraphicsLineItem
+transparent_window: QGraphicsRectItem
+add_analysis_point(x, y, apid, label, diameter, colour, scale, ghost)
+remove_analysis_point(ap)
+move_analysis_point(ap, x_change, y_change)
+get_ellipse_at(x, y)
+toggle_transparent_window(graphics_view_image)
+draw_scale_line(start_point, end_point)
+draw_scale_point(x, y)
+remove_scale_items()
}
class SetScaleDialog{
Related Skills
node-connect
339.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
339.5kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.9kCommit, push, and open a PR
