Skip to content

Instantly share code, notes, and snippets.

@numpde
Created February 12, 2025 15:55
Show Gist options
  • Save numpde/7010d35fbcec5c440272770e9b61bc56 to your computer and use it in GitHub Desktop.
Save numpde/7010d35fbcec5c440272770e9b61bc56 to your computer and use it in GitHub Desktop.
MestReNova script to batch-reexport NMR spectra from .mnova files
/**
* Batch Export Script for LOGS Data Bundle (.zip)
*
* This script processes all `.mnova` files in the specified directory,
* extracts 1D NMR spectra, and exports each file as a LOGS Data Bundle (.zip).
*
* It's partially based on the `LOGSDataBundle.qs` script by MestReNova.
*
* - Uses `saveAsLOGSDataBundle()` to perform the export.
* - Opens each `.mnova` file using `serialization.open()`.
* - Generates a `.zip` file for each dataset in the output directory.
* - Ensures proper error handling and document cleanup.
*
* Notes:
* - The script closes each file after processing to free memory.
* - Skips any `.mnova` files that fail to open.
* - Logs success and failure messages to the console.
*/
// Define input/output directories
var inputDir = "/home/ra/Datasets/2023-VanBramer-Bastin/c_reexport";
var outputDir = "/home/ra/Datasets/2023-VanBramer-Bastin/c_reexport";
/**
* saveAsLOGSDataBundle - Exports the active Mnova document as a LOGS Data Bundle (.zip).
*
* This function extracts 1D NMR spectrum data from the active document,
* saves each spectrum as a JSON file, and optionally includes the full .mnova file.
* The exported files are compressed into a timestamped ZIP archive.
*
* Usage:
* - `saveAsLOGSDataBundle("/path/to/output.zip");` // Default, Mnova file NOT saved
* - `saveAsLOGSDataBundle("/path/to/output.zip", true);` // Mnova file INCLUDED
*
* @param {string} outputPath - Full path where the LOGS Data Bundle (.zip) will be saved.
* @param {boolean} saveMnovaFile - Whether to include the full .mnova file in the ZIP.
*
* @returns {boolean} - Returns `true` if export was successful, `false` otherwise.
*
* Notes:
* - If no active document is found, the function exits with a warning.
* - The ZIP file contains JSON representations of valid 1D NMR spectra.
* - A timestamped directory is created for temporary storage and cleaned up after export.
*/
function saveAsLOGSDataBundle(outputPath, saveMnovaFile) {
"use strict";
// Ensure an active document is loaded
var doc = mainWindow.activeDocument;
if (!doc) {
print("⚠️ No active document found.");
return false;
}
// Extract filename and path components
function extractPathAndName(filePath) {
filePath = filePath.replace(/[\\\/]+$/, ''); // Remove trailing slashes
var parts = filePath.split(/[\\\/]/);
var lastElement = parts[parts.length - 1];
var isFile = /\.\w+$/.test(lastElement);
var name = isFile ? lastElement.replace(/\.[^/.]+$/, '') : lastElement;
var path = isFile ? parts.slice(0, -1).join(parts[0].indexOf("\\") !== -1 ? "\\" : "/") : filePath;
return { path: path, name: name };
}
var result = extractPathAndName(outputPath);
var path = result.path;
var name = result.name;
// Create timestamped output directory
var startDate = date2ISOString(new Date()).replace(/\:/g, ".") + "_LOGS";
var resultDir = new Dir(path);
resultDir.mkdir(startDate);
resultDir.cd(startDate);
var tempResultName = path + "/" + startDate;
// Collect NMR spectrum data
var nmrItems = doc.itemsByName('NMR Spectrum');
var jsonArray = [];
var pageArray = [];
for (var i = 0; i < nmrItems.length; i++) {
var spec = new NMRSpectrum(nmrItems[i]);
if (spec.isValid() && spec.dimCount === 1) {
var jsonFile = tempResultName + "/" + spec.uuid + ".json";
jsonArray.push(jsonFile);
pageArray.push(nmrItems[i].page);
}
}
// Initialize ZIP file for export
var zip = new Zip(outputPath);
var flag = zip.open() === 0;
if (flag) {
for (var i = 0; i < jsonArray.length; i++) {
doc.setCurPage(pageArray[i]);
serialization.save(jsonArray[i], "JSON NMR (*.json)");
if (!File.exists(jsonArray[i])) {
print("❌ Failed to save JSON: " + jsonArray[i]);
flag = false;
} else {
zip.addFile(jsonArray[i], "", Zip.SkipPaths);
}
}
// Save Mnova file (only if enabled)
if (saveMnovaFile) {
var mnovaFile = tempResultName + "/" + name + ".mnova";
serialization.save(mnovaFile, "mnova");
if (!File.exists(mnovaFile)) {
print("❌ Failed to save Mnova file: " + mnovaFile);
flag = false;
} else {
zip.addFile(mnovaFile, "", Zip.SkipPaths);
}
}
} else {
print("❌ Failed to open ZIP file for writing.");
flag = false;
}
zip.close();
// Clean up temporary directory
var tempResultDir = new Dir(tempResultName);
tempResultDir.removeRecursively();
if (flag) {
print("✅ Successfully exported: " + outputPath);
} else {
print("⚠️ Export process completed with errors.");
}
return flag;
}
// Ensure output directory exists
if (!File.exists(outputDir)) {
new Dir(outputDir).mkdir();
}
// Get list of .mnova files in the input folder
var dir = new Dir(inputDir);
var files = dir.entryList("*.mnova", Dir.Files);
if (files.length === 0) {
print("No .mnova files found in " + inputDir);
return;
}
print("Starting batch export of " + files.length + " files...");
for (var i = 0; i < files.length; i++) {
var filePath = inputDir + "/" + files[i];
print("Opening: " + filePath);
// Open file using serialization.open()
var success = serialization.open(filePath);
if (!success) {
print("❌ Failed to open: " + filePath);
continue; // Skip to the next file
}
// Construct output path for the LOGS Data Bundle
var fileName = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.lastIndexOf("."));
var exportPath = outputDir + "/" + fileName + ".zip";
// Call the function to export
var saveMnovaFile = false;
var exportSuccess = saveAsLOGSDataBundle(exportPath, saveMnovaFile);
if (!exportSuccess) {
print("❌ Export failed: " + filePath);
}
// Close document to free memory
mainWindow.activeDocument.close();
}
print("Batch export completed.");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment