Python und C# – Das Beste aus zwei Welten

(Gast) Hinrich Rahlfs

25/10/2019

Ziel dieses Artikels ist es zu zeigen, wie sich das .Net Framework und die Python Bibliotheken scipy und numpy sinnvoll verbinden lassen.

Wer sich mit digitaler Signalverarbeitung (DSV) beschäftigt, wird zwangsläufig mit Python oder MatLab in Berührung kommen. Ich persönlich beschäftige mich seit Längerem mit DSV in Python und fühle mich vor allem wegen des Open Source Ansatzes sehr wohl damit.
Bei Medtech Ingenieur habe ich angefangen mich näher mit dem .Net Framework (C#) auseinanderzusetzen und bin von Visual Studio und den nahezu unendlichen Möglichkeiten begeistert.
Mein Projekt war und ist es diese beiden Welten zu verbinden: professionelles Design von Grafischen Benutzeroberflächen (GUI); umfassendes Filterdesign.

Ich werde in diesem Beitrag ein von uns entwickeltes Programm vorstellen, welches das Beste aus diesen beiden Welten verwendet. Außerdem werde ich eine kurze Anleitung bereitstellen, die es Ihnen ermöglicht in Ihrer .Net Anwendung Python zu verwenden.

Robustes, intuitives Filterdesign

Mit numpy und scipy Filter zu erzeugen und zu verwenden ist einfach. Den „perfekten“ Filter für die Anwendung zu finden ist eine deutlich schwierigere Aufgabe. Das von uns entwickelte Programm ermöglicht es verschiedene Filterdesignmethoden auszuprobieren, ohne dabei Programmcode zu schreiben. Dabei liefert es zusätzlich nützliche Informationen zu den einzelnen Designmethoden, die es Ihnen ermöglichen Ihr Verständnis für Filterdesign und DSV zu vertiefen.

Abbildung 1: EKG Signal überlagert mit 50 Hz Rausch(SNR -10 dB)

In Abbildung 1 wurde ein stark verrauschtes EKG Signal in den Filterdesigner geladen.

Abbildung 2: Mithilfe des Filterdesigners wird ein Bandstoppfilter Implementiert

Im Filterdesigner erzeugt man daher einen Bandstoppfilter. Während des Designen kann man sich den Betrag und Phasengang des Filters anschauen. Außerdem wird das Pol-Nullstellen Diagramm gezeigt. (Abbildung 2)
(Wussten Sie z. B., dass die Polstellen von Linearphase Filtern immer im Ursprung liegen; die Nullstellen direkt auf dem Einheitskreis für den „Notch“ verantwortlich sind?)

Abbildung 3: Gefiltertes Signal

In Abbildung 3 kann jetzt das EKG Signal eindeutig erkannt werden. Nun könnte man weitere Filter hinzufügen, um z. B. den Gleichanteil herauszufiltern.

Wo stehen wir und wo wird es hingehen?

Aktuell ist nur das Design von Filtern mit linearer Phase möglich. Diese haben eine konstante Gruppenlaufzeit. Deshalb ist das EKG Signal auch noch als solches zu erkennen und ist nicht frequenzspezifisch verzerrt. Mittelfristig werden erweiterte Möglichkeiten zum Design von rekursiven Filtern hinzugefügt.
In Zukunft wird es außerdem möglich sein automatisch C Code zu generieren, der die erstellten Filter auf einem Mikrocontroller implementiert.

Bei Interesse und Anregungen, welche Funktionen für Sie von Bedeutung sein könnten melden Sie sich gerne bei mir.

Anleitung für Ihren Python Code im .Net Framework

Zu Beginn: Es könnte so einfach sein. Man könnte einfach Ironpython Code verwenden (für eine Erkläung hier klicken). Da für DSV die beiden cPython Bibliotheken numpy und scipy unabdinglich sind, kann der Code jedoch nicht einfach in C# ausgeführt werden.

Um cPython zu verwenden wird eine backend.py Datei entwickelt. Daraus wird dann eine backend.exe gebaut. Diese übernimmt alle DSV Aufgaben und wird von dem C# Code ausgeführt. Das Gute an dieser Lösung ist, dass man automatisch dazu gezwungen wird,  zwischen Frontend(C#) und Backend(Python) zu trennen.

Der Python Teil

Da der Visual Studio Debugger keine Möglichkeit hat, die main.exe zu debuggen, sollte hier darauf geachtet werden, dass man den Pythoncode unabhängig von der Hauptanwendung testen kann. Dafür empfiehlt es sich in der backend.py zu Beginn abzufragen, ob C# Code oder eine Person die Anwendung ausführt. Dadurch kann während der Entwicklung im Python IDE der Wahl gedebugged werden.

Dabei gilt es darauf zu achten, dass die backend.exe in einem anderen Verzeichnis liegen wird, als backend.py. Daher sollte zu Beginn alles behandelt werden, was sich durch die verschiedenen Aufrufvarianten verändert. Am Ende von backend.py kann dann das ausgeführt werden, was für alle Aufrufvarianten gleich abläuft.
Ein entsprechendes Codebeispiel ist unten zu finden. Eine Python Datei, die noch ein wenig mehr übernimmt, ist hier zu finden.

if __name__ == "__main__":
 
    # Ohne Argumente vom Python IDE ausgeführt 
    # (oder aus der cmd mit: python backend.py)
    if len(sys.argv) == 1:
        output_file = open(".\\data_transfer\\outputsignal.txt", "w")
        a = "no arguments"
 
    #aufgerufen mit .\dist\backend\backend.exe "write this text"
    elif sys.argv[1] == "write this text": 
        output_file = open(".\\..\\..\\data_transfer\\outputsignal.txt", "w")
        a = sys.argv[1]
 
    #aufgerufen mit .\dist\backend\backend.exe "write 1"
    elif sys.argv[1] == "write 1":
        output_file = open(".\\..\\..\\data_transfer\\outputsignal.txt", "w")
        a = "1"
 
    #mit fehlerhaften Argumenten aufgerufen
    else: 
        exit()
		
    #der Programmcode der für alle Zweige gleich verläuft
    output_file.write(a)
    output_file.close()

Nach erfolgreicher Implementierung des Backends kann pyinstaller aus der .py Datei eine .exe bauen, welche wir dann aus unserem C# Code ausführen können.

Der C# Teil

Die aus backend.py erstellte backend.exe lässt sich nun mit folgender C# Funktion aufrufen. Dabei übergibt man die Argumente und erhält als Rückgabewert die stdout des Programms.

 
/* @brief runs the command and returns the stdout as string
   @param cmd name of the programm(backend.exe)
   @param args all args that are given to the backend
*/
protected string run_cmd(string cmd, string[] args)
        {
            ProcessStartInfo start = new ProcessStartInfo();
            start.FileName = string.Format("{0}{1}", "..\\..\\..\\Python_Backend\\dist\\", cmd);

            string arguments = "";

            //args need to be given in a single string (as you would type it to the cmd)
            foreach (string arg in args)
            {
                arguments += "\"" + arg + "\" ";
            }
            start.Arguments = arguments;
            // Any output, generated by application 
            //will be redirected back
            start.RedirectStandardOutput = true;
            // Any error in standard error stream will 
            //be redirected back (for example exceptions)
            start.RedirectStandardError = true; 
            using (Process process = Process.Start(start))
            {
                using (StreamReader reader = process.StandardOutput)
                {
                    string stderr = process.StandardError.ReadToEnd(); 
                    string result = reader.ReadToEnd(); 
                    return result;
                }
            }
        }

Die Datenübertragung

Bleibt ein letztes Problem zu lösen. Das Übertragen von Informationen zwischen Python und C#.
Was genau backend.exe tun soll, kann mithilfe der argv übergeben werden. Statusupdates und Fehler der backend.exe können mithilfe des out und error Kanals zurückgemeldet werden. Die Datenübertragung muss jedoch aufgrund der limitierten Länge der argv auf einem anderen Weg erfolgen. Dafür können Signale in Form von .csv Dateien gespeichert oder mithilfe von .txt oder .json Dateien serialisiert werden.

Sollten Sie Fragen zu den Code Beispielen haben, kontaktieren Sie mich gerne. Auch wenn Sie ein umfangreiches C# Programm haben, das eine Erweiterung um ein Python Backend vertragen könnte, kommen Sie gerne auf uns zu.


Geschrieben von (Gast) Hinrich Rahlfs

Hinrich Rahlfs arbeitete als Werkstudent bei MEDtech Ingenieur. Seine Aufgabengebiete umfassten das Programmieren grafischer Benutzeroberflächen und das Entwickeln eines intuitiven Filterdesign-Tools.


Weitere Beiträge

  • 12/11/2024
  • Allgemein, Software, Testen, Tools

In sicherheitskritischen Softwareprojekten steht die Qualität der Software an erster Stelle. Besonders bei Klasse-C-Software, die nach strengen Normen wie IEC 62304 (Medizintechnik) zertifiziert werden muss, ist es essenziell, dass ...

Weiterlesen
  • 08/08/2024
  • Allgemein, Elektrostimulation, Software, Testen

Heutzutage sind Apps im Gesundheitsbereich sehr wichtig. Besonders Apps, die Daten von medizinischen Sensoren lesen und verarbeiten können, sind nützlich. Flutter ist ein Open-Source-Framework von Google, das sich hervorragend ...

Weiterlesen
  • 30/06/2024
  • Allgemein, Hardware, Software, Technik, Tools, Usability

KI – Was ist das denn überhaupt? Künstliche Intelligenz ist zurzeit in aller Munde, doch die wenigsten Menschen beschäftigen sich mit der Funktionsweise von künstlicher Intelligenz oder damit, was ...

Weiterlesen
Cookie-Übersicht

Die Internetseiten der MEDtech Ingenieur GmbH verwenden Cookies. Cookies sind Textdateien, welche über einen Internetbrowser auf einem Computersystem abgelegt und gespeichert werden.

Zahlreiche Internetseiten und Server verwenden Cookies. Viele Cookies enthalten eine sogenannte Cookie-ID. Eine Cookie-ID ist eine eindeutige Kennung des Cookies. Sie besteht aus einer Zeichenfolge, durch welche Internetseiten und Server dem konkreten Internetbrowser zugeordnet werden können, in dem das Cookie gespeichert wurde. Dies ermöglicht es den besuchten Internetseiten und Servern, den individuellen Browser der betroffenen Person von anderen Internetbrowsern, die andere Cookies enthalten, zu unterscheiden. Ein bestimmter Internetbrowser kann über die eindeutige Cookie-ID wiedererkannt und identifiziert werden.

Durch den Einsatz von Cookies kann die MEDtech Ingenieur GmbH den Nutzern dieser Internetseite nutzerfreundlichere Services bereitstellen, die ohne die Cookie-Setzung nicht möglich wären.

Mittels eines Cookies können die Informationen und Angebote auf unserer Internetseite im Sinne des Benutzers optimiert werden. Cookies ermöglichen uns, wie bereits erwähnt, die Benutzer unserer Internetseite wiederzuerkennen. Zweck dieser Wiedererkennung ist es, den Nutzern die Verwendung unserer Internetseite zu erleichtern. Der Benutzer einer Internetseite, die Cookies verwendet, muss beispielsweise nicht bei jedem Besuch der Internetseite erneut seine Zugangsdaten eingeben, weil dies von der Internetseite und dem auf dem Computersystem des Benutzers abgelegten Cookie übernommen wird.

Die betroffene Person kann die Setzung von Cookies durch unsere Internetseite jederzeit mittels einer entsprechenden Einstellung des genutzten Internetbrowsers verhindern und damit der Setzung von Cookies dauerhaft widersprechen. Ferner können bereits gesetzte Cookies jederzeit über einen Internetbrowser oder andere Softwareprogramme gelöscht werden. Dies ist in allen gängigen Internetbrowsern möglich. Deaktiviert die betroffene Person die Setzung von Cookies in dem genutzten Internetbrowser, sind unter Umständen nicht alle Funktionen unserer Internetseite vollumfänglich nutzbar.

Weitere Informationen erhalten Sie in unserer Datenschutzerklärung.

Unbedingt notwendige Cookies

Dieses Cookie wird benötigt, um Ihre Cookie-Einstellungen zu merken und weitere Hauptfunktionen zur Verfügung zu stellen

Um Ihnen eine Auskunft über Ihre gespeicherten personenbezogenen Daten hier (https://medtech-ingenieur.de/gespeicherte-daten-2/) geben zu können, benötigen wir einen Cookie, um Sie bei der Datenabfrage identifizieren zu können. Dieser Cookie muss aus Sicherheitsgründen deshalb aktiviert sein. Ein weiterer Cookie wird gesetzt, um diesen Banner nicht erneut anzeigen zu müssen.

Cookie-Name Beschreibung
PHPSESSID Name: PHP session
Anbieter:
Eigentümer der Webseite (MEDtech Ingenieur)
Zweck:
Wir benötigt, um Sie bei der Anfrage von personenbezogenen Daten identifizieren zu können. Das Cookie wird nur gesetzt, wenn Sie eine Anfrage hier (https://medtech-ingenieur.de/gespeicherte-daten-2/) stellen.
Laufzeit: Sitzungsende
Kategorie: Unbedingt notwendige Cookies
moove_gdpr_popup Name: Cookie-Box Einstellungen
Anbieter:
Eigentümer der Webseite (MEDtech Ingenieur)
Zweck:
Wird benötigt, um Ihre Cookie-Einstellungen zu speichern, um den Cookie-Banner nicht erneut anzeigen zu müssen.
Laufzeit: 1 Jahr
Kategorie: Unbedingt notwendige Cookies
comment_author_9c90e388e3e1be4a6c594fa6ac8a3eec
comment_author_email_9c90e388e3e1be4a6c594fa6ac8a3eec
comment_author_url_9c90e388e3e1be4a6c594fa6ac8a3eec
Name: Kommentar Einstellungen
Anbieter:
Eigentümer der Webseite (MEDtech Ingenieur)
Zweck:
Cookie wird angelegt, wenn Sie ein Kommentar auf MEDtech Ingenieur veröffentlichen wollen, um Sie als Autor identifizieren und den aktuellen Status Ihres Kommentars anzeigen zu können. Das Cookie enthält den angegebenen Namen. Das Cookie wird erst gesetzt, wenn Sie der Speicherung Ihrer personenbezogenen Daten zustimmen.
Laufzeit: 1 Jahr
Kategorie: Unbedingt notwendige Cookies
rmp-rate Name: RMP Rate
Anbieter: Eigentümer der Webseite (MEDtech Ingenieur)
Zweck: Cookie wird angelegt, wenn Sie eine Bewertung eines Blogbeitrags mithilfe des Sternebewertungssystems abgeben. Ihnen wird eine anonymisierte ID zugewiesen, um zu erkennen, ob Sie einen Artikel bereits bewertet haben oder nicht. Das Cookie wird nur verwendet, um zu verhindern, dass mehrfache Bewertung abgegeben werden und erst gesetzt, wenn Sie auf einen Stern klicken.
Laufzeit: 1 Jahr
Kategorie: Unbedingt notwendige Cookies
medtech-download-page Name: Download Page
Anbieter: Eigentümer der Webseite (MEDtech Ingenieur)
Zweck: Cookie wird angelegt, wenn Sie den Landing-Page Prozess erfolgreich durchlaufen haben. Dies geschieht nur, wenn Sie einen Content-Download von unserer Website anstreben.
Laufzeit: 1/2 Jahr
Kategorie: Unbedingt notwendige Cookies