Teil 3: Eigene Funktionen¶
KI-gestützte Übersetzung - mehr erfahren & Verbesserungen vorschlagen
Am Ende dieses Abschnitts hast du eigene Funktionen in deinem Plugin, die lokal gebaut und installiert sind und in einem echten Workflow laufen.
Hier eingestiegen?
Wenn du erst ab diesem Teil mitmachst, kopiere die Lösung aus Teil 2 als Ausgangspunkt:
1. Sieh dir an, was das Template generiert hat¶
Bevor du eigene Funktionen schreibst, schau dir die Beispielfunktion an, die das Template erstellt hat, um das Muster zu verstehen.
Wechsle in das Plugin-Verzeichnis:
Das Template hat eine Datei namens GreetingExtension.groovy erstellt, in der Plugin-Funktionen definiert werden.
Öffne sie, um den Ausgangspunkt zu sehen:
/*
* Copyright 2025, Seqera Labs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package training.plugin
import groovy.transform.CompileStatic
import nextflow.Session
import nextflow.plugin.extension.Function
import nextflow.plugin.extension.PluginExtensionPoint
/**
* Implementiert eine eigene Funktion, die von
* Nextflow-Skripten importiert werden kann.
*/
@CompileStatic
class GreetingExtension extends PluginExtensionPoint { // (1)!
@Override
protected void init(Session session) { // (2)!
}
/**
* Begrüßt das angegebene Ziel.
*
* @param target
*/
@Function // (3)!
void sayHello(String target) {
println "Hello, ${target}!"
}
}
- Die Klasse, auf der deine Extension aufbaut. Nextflow benötigt sie, um deine Funktionen zu erkennen.
- Wird beim Laden des Plugins aufgerufen; hier kannst du Initialisierungen vornehmen
- Macht diese Methode über
includeaus Workflows heraus aufrufbar
Das Template enthält eine Beispielfunktion sayHello.
Die Annotation @Function macht eine Methode aus Nextflow-Workflows heraus aufrufbar.
Ohne sie existiert die Methode nur innerhalb des Plugin-Codes.
In Groovy (und Java) deklarieren Methoden, welchen Typ sie zurückgeben und welche Typen ihre Parameter haben.
Zum Beispiel deklariert String reverseGreeting(String greeting) eine Methode, die einen String-Parameter entgegennimmt und einen String zurückgibt.
Das Schlüsselwort void bedeutet, dass die Methode nichts zurückgibt, wie bei sayHello oben.
Das unterscheidet sich von Python oder R, wo Typen nicht explizit deklariert werden müssen.
2. sayHello durch reverseGreeting ersetzen¶
Die sayHello-Funktion des Templates ist ein Platzhalter.
Ersetze sie durch deine eigene Funktion, um den vollständigen Zyklus aus Schreiben, Bauen und Verwenden einer Plugin-Funktion zu durchlaufen.
Bearbeite src/main/groovy/training/plugin/GreetingExtension.groovy, um die sayHello-Methode zu ersetzen:
| GreetingExtension.groovy | |
|---|---|
- Macht die Methode aus Nextflow-Workflows heraus aufrufbar
- Nimmt einen String entgegen, gibt einen String zurück
- Grooovys eingebaute Methode zur String-Umkehrung
Die wichtigsten Teile dieser Funktion:
@Function: Macht die Methode aus Nextflow-Workflows heraus aufrufbarString reverseGreeting(String greeting): Nimmt einen String entgegen, gibt einen String zurückgreeting.reverse(): Grooovys eingebaute Methode zur String-Umkehrung
Öffentliche und private Methoden
Methoden ohne @Function werden Nextflow-Workflows nicht zugänglich gemacht.
Du kannst deiner Klasse Hilfsmethoden hinzufügen, ohne dir Sorgen zu machen, dass sie in den Workflow-Namespace gelangen.
3. Dein Plugin bauen und installieren¶
Baue und installiere das Plugin:
Falls der Build fehlschlägt
Lies die Fehlermeldung sorgfältig; sie enthält meist eine Zeilennummer und beschreibt das Problem. Häufige Ursachen sind Syntaxfehler (fehlende Klammer oder Anführungszeichen), falsch geschriebene Klassennamen und Typkonflikte. Wenn du nicht weiterkommst, vergleiche deinen Code Zeichen für Zeichen mit den Beispielen.
4. Deine Funktion in einem Workflow verwenden¶
Das Plugin ist gebaut und installiert.
Der nächste Schritt ist, reverseGreeting in einem Workflow zu verwenden, um zu überprüfen, ob es von Anfang bis Ende funktioniert.
Wechsle zurück in das Pipeline-Verzeichnis:
Bearbeite greet.nf, um reverseGreeting zu importieren und zu verwenden:
Führe die Pipeline aus:
Ausgabe
N E X T F L O W ~ version 25.10.2
Launching `greet.nf` [elated_marconi] DSL2 - revision: cd8d52c97c
Pipeline is starting! 🚀
executor > local (5)
[fe/109754] process > SAY_HELLO (5) [100%] 5 of 5 ✔
Reversed: olleH
Reversed: ruojnoB
Reversed: àloH
Reversed: oaiC
Reversed: ollaH
Output: Hello
Output: Bonjour
Output: Holà
Output: Ciao
Output: Hallo
Pipeline complete! 👋
Deine erste eigene Plugin-Funktion funktioniert in einem echten Workflow.
Das gleiche include { ... } from 'plugin/...'-Muster, das du in Teil 1 mit nf-hello und nf-schema verwendet hast, funktioniert auch mit deinem eigenen Plugin.
5. decorateGreeting hinzufügen¶
Ein Plugin kann mehrere Funktionen bereitstellen. Füge eine zweite hinzu, die eine Begrüßung mit dekorativen Markierungen umschließt; in Teil 6 wirst du sie konfigurierbar machen.
Bearbeite GreetingExtension.groovy, um decorateGreeting nach reverseGreeting und vor der schließenden Klammer der Klasse hinzuzufügen:
- Groovy-String-Interpolation:
${...}fügt den Wert der Variable in den String ein
| GreetingExtension.groovy | |
|---|---|
Diese Funktion verwendet Groovy-String-Interpolation ("*** ${greeting} ***"), um die Begrüßungsvariable in einen String einzubetten.
Baue und installiere das Plugin und aktualisiere den Workflow:
Aktualisiere greet.nf, um auch decorateGreeting zu importieren und zu verwenden:
- Mehrere Funktionen aus demselben Plugin benötigen separate
include-Anweisungen - Plugin-Funktionen funktionieren auch innerhalb von
script:-Blöcken eines Prozesses
Ausgabe
N E X T F L O W ~ version 25.10.2
Launching `greet.nf` [elated_marconi] DSL2 - revision: cd8d52c97c
Pipeline is starting! 🚀
executor > local (5)
[fe/109754] process > SAY_HELLO (5) [100%] 5 of 5 ✔
Reversed: olleH
Reversed: ruojnoB
Reversed: àloH
Reversed: oaiC
Reversed: ollaH
Decorated: *** Hello ***
Decorated: *** Bonjour ***
Decorated: *** Holà ***
Decorated: *** Ciao ***
Decorated: *** Hallo ***
Pipeline complete! 👋
Plugin-Funktionen funktionieren sowohl in Prozess-Skripten (wie decorateGreeting innerhalb von SAY_HELLO) als auch in Workflow-Operationen (wie reverseGreeting in einem map).
Fazit¶
Du hast gelernt, dass:
- Funktionen mit der Annotation
@FunctioninPluginExtensionPoint-Unterklassen definiert werden - Mit
includeimportierte Plugin-Funktionen identisch funktionieren, egal ob sie aus deinem eigenen Plugin oder einem bestehenden stammen - Plugin-Funktionen sowohl in Prozess-Skripten als auch in Workflow-Operationen funktionieren
Wie geht es weiter?¶
Deine Funktionen funktionieren, aber bisher hast du das nur überprüft, indem du die vollständige Pipeline ausgeführt und die Ausgabe manuell kontrolliert hast. Dieser Ansatz skaliert nicht: Wenn du mehr Funktionen hinzufügst, brauchst du eine schnellere Möglichkeit zu prüfen, dass jede einzelne korrekt funktioniert – besonders nach Änderungen. Der nächste Abschnitt stellt Unit-Tests vor, mit denen du einzelne Funktionen automatisch überprüfen kannst, ohne eine Pipeline auszuführen.