I am trying to take multiple linear measurements from a bone using the markups tool, then export the lengths (distances) as a table. This has proven to be incredibly complicated, with posts discussing creating a database in excel from json files, or using python scripts. I can export a single measurement, but I don’t know how to export a table of measurements. I would be content with copy/paste if I could get the lengths in a single table. Again, I don’t need coordinates, points, or anything else, just the measurement name and the length value. Am I missing something really obvious?
Thanks!
Measurements are saved in the json file. I am not sure if there is a readily available way to export a bunch of measurements from different line Markups. You can use chatGPT or other LLMs to help you create a simple script to do it.
1 Like
As Murat noted, you can try something along the following line:
# === Markups → CSV: Node name + numeric value + units ===
# Paste into Slicer's Python console.
import os, csv, datetime
import slicer
# --- Choose output file ---
def pick_save_path(default_name):
try:
import qt
dlg = qt.QFileDialog()
dlg.setAcceptMode(qt.QFileDialog.AcceptSave)
dlg.setNameFilter("CSV (*.csv)")
dlg.selectFile(default_name)
if dlg.exec():
return dlg.selectedFiles()[0]
except:
pass
return os.path.join(slicer.app.temporaryPath, default_name)
ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
out_path = pick_save_path(f"markups_values_units_{ts}.csv")
# --- Collect Markups nodes ---
markups_nodes = slicer.util.getNodesByClass("vtkMRMLMarkupsNode")
# --- CSV output ---
header = ["NodeName", "Value", "Units"]
rows = []
for node in markups_nodes:
name = node.GetName() or ""
mcount = node.GetNumberOfMeasurements()
if mcount == 0:
rows.append([name, "", ""])
continue
for i in range(mcount):
m = node.GetNthMeasurement(i)
try:
value = m.GetValue()
except:
value = ""
units = m.GetUnits() or ""
rows.append([name, value, units])
# --- Write CSV ---
os.makedirs(os.path.dirname(out_path), exist_ok=True)
with open(out_path, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(header)
writer.writerows(rows)
print(f"[Markups → CSV] {len(rows)} rows written to:\n{out_path}")
slicer.util.delayDisplay(f"Export complete:\n{out_path}", 1500)
2 Likes
This works beautifully, thanks for the help!
