Вызов Гнуплота в Свифте
Я пытаюсь вызвать ганфлот из Свифта, чтобы произвести несколько сюжетов в .png
, Тем не менее, программа ниже не работает --- в результате 1.png
файл пуст Если я оставляю "установить термин аква", он вызывает окно аква с сюжетом в нем. Однако, когда я пытаюсь установить вывод в файл (png или pdf), результатом всегда будет пустой файл.
Команды gnuplot в порядке - я могу правильно запустить их вручную.
import Foundation
let task = NSTask()
task.launchPath = "/opt/local/bin/gnuplot"
task.currentDirectoryPath = "~"
let pipeIn = NSPipe()
task.standardInput = pipeIn
task.launch()
let plotCommand: NSString =
"set term png\n" +
"set output \"1.png\"\n"
"plot sin(x)\n" +
"q\n"
pipeIn.fileHandleForWriting.writeData(plotCommand.dataUsingEncoding(NSUTF8StringEncoding)!)
Я новичок как в Swift, так и в конвейере, поэтому, пожалуйста, скажите мне, если что-то не так или не рекомендуется с кодом.
2 ответа
Часто легко пропустить простой знак, когда мы объединяем строки.
В этом случае вы можете исправить добавление \n
а также +
на линию с set output
:
"set output \"1.png\"\n" +
Идея состоит в том, чтобы создать строку, как если бы мы писали в gnuplot
оболочка, поэтому с каждой\n
мы моделируем новую линию и с каждым +
мы объединяем две или более строки...
это даже идея, лежащая в основе сценариев gnuplot...
Часто с gnuplot
удобно писать внешний скрипт и загружать его
load "myscript.gnuplot"
или запустить его с
gnuplot -persist myscript.gnuplot
Таким образом, у вас всегда будет возможность переделать ваш график или анализ в мгновение ока, и ваш результат будет всегда воспроизводимым.
Swift 5.4
let commandString: String =
"""
set terminal png
set output \"FIND_ME_01.png\"
plot sin(x)
quit\n
"""
func plotDirect() {
let argv: [String] = ["--persist"] // do not close interactive plot
let task = Process()
task.arguments = argv
// "/opt/homebrew/bin/gnuplot" // Big Sur, Apple Silicon
task.launchPath = "/usr/local/bin/gnuplot" // Big Sur, Intel
// where to find the output
let homeDir = FileManager.default.homeDirectoryForCurrentUser
task.currentDirectoryURL = homeDir.appendingPathComponent("Desktop")
let pipeIn = Pipe()
task.standardInput = pipeIn
let pipeOut = Pipe()
task.standardOutput = pipeOut
let pipeErr = Pipe()
task.standardError = pipeErr
do {
try task.run()
let commandData = commandString.data(using: .utf8)!
pipeIn.fileHandleForWriting.write(commandData)
let dataOut = pipeOut.fileHandleForReading.readDataToEndOfFile()
if let output = String(data: dataOut, encoding: .utf8) {
print("STANDARD OUTPUT\n" + output)
}
let dataErr = pipeErr.fileHandleForReading.readDataToEndOfFile()
if let outputErr = String(data: dataErr, encoding: .utf8) {
print("STANDARD ERROR \n" + outputErr)
}
} catch {
print("FAILED: \(error)")
}
task.waitUntilExit()
print("STATUS: \(task.terminationStatus)")
}
Текущий Свифт
"""
синтаксис позволяет использовать многострочную строку. Это позволяет избежать конкатенации строк.
Обратите внимание
commandString
должен заканчиваться новой строкой. Завершающая дополнительная пустая строка необходима, если
\n
не используется в конце.
quit\n
"""
quit
"""