Temat: Nowy interfejs R -> .NET

Dobre wieści dla programistów .NET, którzy chcą wykorzystać w swoich projektach analitycznych potencjał eRa.

Dotychczas mieliśmy do dyspozycji jedynie StatConnector. Niestety, było przy nim nieco zachodu z rejestrowaniem serwera OLECOM (uprawnienia, sam proces instalacji) i ta uciążliwa winietka (która może zniknąć po przekonaniu autorów, że to w słusznej sprawie $ ;) ) wkurzająca podczas testów.

Bolesne były także restrykcje licencyjne, na mocy których StatConnectora nie wolno redystrybuować, lecz za każdym razem trzeba go pobrać ze strony autorów. Czasem to poważne ograniczenie. Za to narzędzie było (i jest) za darmo, pewne, stabilne i za to chwała Autorom.

Od niedawna jednakże istnieje R.NET.

Z tego, co widzę, nie opiera się (nareszcie) o (D)COM, ale o interop regularnej DLLki. Niestety, jest jeszcze trochę bugów, a to głównie z uwagi na fakt, że pracujemy z kodem niezarządzanym (R.DLL). Ale, jak widać na stronie, testerzy mają "oko i ucho na pulsie".

Co ważne, można wprost wskazać wersję, z której chcemy korzystać, a to poprzez podanie ścieżki do katalogu R.

StanConnector oferował "nazwane sesje", gdzie każdy użytkownik mógł mieć własne środowisko (była też metoda na dostęp wielu userów do jednej sesji przez prefiksowanie nazw zmiennych i kolejkowanie żądań). Tutaj są "nazwane instancje" i jest to na 99% to samo. W każdym razie będę to testował w najbliższych dniach.

Wystawienie eRa jako webservice nie będzie stanowić żadnego problemu. Dodatkowo, dzięki CLR możemy się do eRa odwoływać wprost z Excela bądź zapytań SQLowych (oczywiście tylko SQL Server).

A teraz kilka linków.
Strona projektu (CodePlex):
1. Strona główna projektu
2. Krótkie HowTo
3. Dyskusje - bardzo ważna strona dotycząca bugów, np. 1

i seria artykułów o wykorzystaniu potencjału R.NET:
4. Making GUIs using C# and R with the help of R.NET - prosty kalkulator w oparciu o R
5. Importing and displaying a Data frame with C# and R.NET
6. Yet another way to use R in Excel for .NET programmer

I jeszcze prezentacja R with COM the dark side of .NET

Jak się na coś ciekawego natknę, to się podzielę.Adrian Olszewski edytował(a) ten post dnia 09.07.11 o godzinie 04:31

Temat: Nowy interfejs R -> .NET

No i za wcześnie te peany...
Na grupie dla programistów .NET jest wątek poświęcony R.NET i tam będę zamieszczał uwagi.

W skrócie: działa rewelacyjnie szybko (1-kilka ms per wywołanie, czyli minimalny narzut, czego nie można było powiedzieć o DCOM), ale wysypuje się po kilku uruchomieniach tego samego kodu.

Jak tego jakoś nie obejdę, to do zastosowań produkcyjnych się nie nadaje. Ale zawsze to jakiś początek, projekt jest uaktualniany.

http://www.goldenline.pl/forum/2478264/nowy-interfejs-...

Temat: Nowy interfejs R -> .NET

Już wszystko gra :)

Problem został rozwiązany w najnowszych źródłach, ale binarka nie została jeszcze opublikowana. Pobrałem więc najnowsze źródła, zbudowałem DLLkę i działa jak marzenie.

Szybka jest bestia (jak to wywołanie regularnej DLLki), dobrze, że ktoś wreszcie wziął się za "wystawienie" R.DLL bez opakowywania tego w ileś tam warstw pośrednich, instalacji, rejestracji, etc.

Zabieram się do testowania w poważniejszych, niż test Studenta na 6-elem. próbie, zastosowaniach :]

----------------

Jeśli chodzi o osadzanie wykresów, zgodnie z tym wątkiem, to działa, ale "tylko raz" :) Potem leci exception. Sprawdzone na świeżo skompilowanej DLLce.

Obrazek

Tak, że albo trzeba wyświetlać wykresy w oknie eRa, albo zastosować to podejście, a konkretnie - użyć EagerEvaluate do wygenerowania wykresu, zapisania go do pliku na dysku do wskazanego katalogu, a potem wczytania go do PictureBoxa:

     engine.EagerEvaluate("library(Cairo)");
engine.EagerEvaluate(@"CairoPNG('c:\\tmp\\R.png')");
engine.EagerEvaluate("plot(1:100,col=\"red\")");
engine.EagerEvaluate ("dev.off()");

this.pictureBox1.Image = new Bitmap("c:\\tmp\\R.png");
this.pictureBox1.Invalidate();


Ładnie działa :)

Obrazek
Adrian Olszewski edytował(a) ten post dnia 09.07.11 o godzinie 17:15

Temat: Nowy interfejs R -> .NET

"Rozpoznałem teren" w zakresie skalowania obrazków. Zainteresowanych zapraszam do tematu: http://www.goldenline.pl/forum/2478264/nowy-interfejs-...

Tutaj tylko w skrócie:

1. Filmik z działania (trzeba oglądać na fullscreen). Prezentowane jest generowanie przezroczystych wykresów (zmieniający się kolor kontrolki wyświetlającej wykresy) i zmiana ich rozmiarów. Informacje techniczne - pod powyższym linkiem do tematu na grupie "Programiści .NET".
http://www.youtube.com/watch?v=K2h-wfR5txY

2. Generowanie PDF i osadzanie w kontrolce przeglądarki:

Obrazek


---------------------------------------

EDIT:
Dodałem przechwytywanie wielu wykresów (na przykładzie plot(lm(...)) ). Szczegóły - jak wcześniej, na grupie dla programistów .NET.
http://www.youtube.com/watch?v=HIaojtiQXroAdrian Olszewski edytował(a) ten post dnia 24.07.11 o godzinie 02:20

Temat: Nowy interfejs R -> .NET

Gdyby ktoś potrzebował przechwycić konsolę R w swoim programie, przedstawiam dwa rozwiązania.

Wątek na stronie projektu w CodePlex: http://rdotnet.codeplex.com/discussions/261917
Wątek wraz z przykładami kodu w C# na grupie dla programistów .NET

1. Można napisać klasę implementującą interfejs ICharacterDevice, a następnie przekazać w konstruktorze tej klasy referencję do jakiegoś TexBoxa, RTF boxa czy czegoś podobnego. Niestety, jest tutaj pewien problem - wyświetlone zostaną jedynie komendy "opatrzone" funkcją "print()". Jeśli się o tym zapomni - nic nie zostanie wyświetlone.

Wyniki przechwycone przez VS2010 i wyświetlone w oknie "Output":
Obrazek


2. Jest jednak lepszy IMHO sposób, który świetnie się sprawdza. Należy wykorzystać "sink()" i "source()". Efekt jak poniżej.
Wyniki:
Obrazek


Zainteresowanych zapraszam do wskazanego wyżej wątku na GL.

Temat: Nowy interfejs R -> .NET

Przy okazji - warto przypomnieć kilka słów a propos wykorzystania oprogramowania na licencji (L)GPL w komercyjnych aplikacjach.

W tym poście zawarłem większość przemyśleń z długiego wątku na grupie programistów .NET, Zaczyna się mniej więcej w połowie, od "grubej kreski" :)
http://www.goldenline.pl/forum/2709060/zarzadzanie-zlo...

Niestety, jest mały update. Bardzo trudno ominąć "licencyjnie" kwestię generowanego kodu R, który korzysta z GPLowych komponentów - czyli czy muszą być udostępniana bezpłatnie czy nie. Ale da się i to ominąć :)

Temat: Nowy interfejs R -> .NET

Nieco po czasie, ale lepiej późno niż wcale :]

Interfejs .NETowy do eRowego serwera TCP/IP znanego jako Rserve. Początkowo klienci byli napisani jedynie w C++ i Javie, teraz doszedł .NET.

Projekt nazywa się RserveCLI. Jest o tyle wygodny, że nie trzeba, jak w przypadku bibliotek korzystających z COM, niczego (poza RServe) instalować ani rejestrować.

Krótka prezentacja: http://www.rinfinance.com/agenda/2011/OliverHaynold.pdf

Obowiązkowa lektura dotycząca RServe:
1. Dokumentacja: http://www.rforge.net/Rserve/doc.html
2. FAQ: http://www.rforge.net/Rserve/faq.html
3. Newsy: http://www.rforge.net/Rserve/news.html
4. dla ciekawych - protokół: http://www.rforge.net/Rserve/dev.html

--------------------
Features of Rserve

* fast - no initialization of R is necessary
* binary transport - the transport protocol sends R objects as binary data, not just R text output.
* automatic type conversion - most R data types are converted into native data types, e.g. the result of rnorm(10) will be double[10] in C/Java. Java client also provides classes for new R types such as RBool, RList etc.
* persistent - each connection has its own namespace and working directory. Every object you create is persistent until the connection is closed. The client doesn't have to fetch or store intermediate results.
* client independence - since the client is not linked to R there are no threading issues like in RSJava etc.
* security - Rserve provides some basic security by supporting encrypted user/password authentication with server challenge. Rserve can be also configured to accept local connections only.
* file transfer - the Rserve protocol allows to transfer files between the client and the server. This way Rserve can be used as a remote server even for task such as generating plot images etc.
* configurable - one configuration file is used to control settings and to enable/disable features such as authorization, remote access or file transfer.

What Rserve is NOT

* Rserve provides no callback functionality. Your application could implement callbacks via TCP/IP and the R sockets but it is not a part of Rserve.
* Rserve is not a telnet frontend to R. The printed output is not transported (except via capture.output). Rserve uses binary protocol for transport of objects for better speed.
* Rserve is thread safe across connections, but eval methods are not thread safe within one connection. This means that multiple threads should not use the same connection unless they guarantee that no eval calls are run in parallel.
--------------------

Mamy zatem już następujące metody połączenia się z R:
1. TCP/IP (RServe, RserveCLI)
2. OLE COM (StatConnector, RCOM). Niestety, StatConnector nie jest już darmowy do komercyjnych zastosowań, a i niemało kosztuje.
3. DDE (NDDE + Tcl/Tk
4. Bezpośrednie wywołania biblioteki R.DLL (R.NET)

Zalety
1. Nareszcie zaimplementowana wielosesyjność bez potrzeby uruchamiania biblioteki w osobnych przestrzeniach adresowych (procesy potomne). Na poniższej ilustracji dwa okna aplikacji, każda z innym GUIDem użytkownika. GUID potrzebny był mi tylko do rysowania wykresu (plik wykresu trzeba "pobrać" z serwera, więc żeby się nie nadpisywał, dodawałem mu GUID do nazwy). Każda nowa instancja aplikacji dostaje swoje środowisko, podobnie, jak w COM (np. StatConnector), ale bez problemów z tym związanych.

2. Szybkość działania. Od momentu wystartowania serwera (Rserve() albo jako exeka) połączenie trwa dosłownie chwilę, zauważalnie szybciej niż w przypadku StatConnectora. Trzeba uważać na wyjątki, które mogą zamknąć serwer, dobrze mieć watchdoga. Inaczej dostaniemy znane zabawne komunikaty o "gwałtownym zakończeniu" i "aktywnej odmowie serwera" :D

EDIT: wystarczy ustawić: option(error=function() NULL)
Więcej w FAQ

3. Możliwość współpracy z serwerem po localhoście i po sieci. Podobnie, jak w DCOM, ale bez problemu z rejestracją komponentów i uprawnieniami. Trzeba tylko uważać na firewall.

4. Łatwa integracja z kodem w C#

5. Także same "eRy" mogą ze sobą rozmawiać dzięki klientowi "RSclient".

Wady
1. Brak urządzenia graficznego, brak konsoli tekstowej. Można zapomnieć o przechwytywaniu komunikatów konsoli (błędy, ostrzeżenia) czy sformatowanych wynikach (np. summary()). Ale tak jest ze wszystkimi tego rodzaju bibliotekami (R.NET, StatConnector). Rozwiązaniem jest sink().

EDIT: Nie jest tak źle, da się to obejść:
string s=c.eval("paste(capture.output(print(summary(mymodel))),collapse='\\n')").asString();

Więcej w FAQ

2. W zwiazku z p1. - wykresy trzeba zapisywać do pliku (png, CairoPNG, PDF) i wyświetlać w kontrolce wyświetlającej obrazki albo osadzonej przeglądarce PDF (np. MSIE, Acrobat). Tak właśnie robię w aplikacji testowej.

3. Trzeba pamiętać o podnoszeniu "upadłego serwera". Problemu tego nie było w przypadku COM ani R.DLL (R był zawsze podnoszony od zera).

EDIT: co prawda można ustawić "option(error=function() NULL)" ale serwer może "paść" z różnych powodów, dlatego watchdog zawsze powinien być brany pod uwagę.

4. Brak informacji o błędzie zgłoszonym przez R. Dostajemy wyjątek, że R ma problem i to wszystko. Trzeba kombinować z własną procedurą, która wyświetli ostatni napotkany error/warning. Błędy R można olać (albo try/catch, albo ustawić R tak, by nie zamykał się przy wyjątku), ale błędy transmisji danych najpewniej wywalą serwer. Info o błędach można odczytać także przez sink() ale to wymaga dodatkowej pracy.

EDIT: metoda na odczytanie błędu:
Problem w tym, że RServeCLI rzuca różne wyjątki. Te pochodzące z R np. dla niezdef. obiektu, są typu (nie mam pojęcia dlaczego!) WebException. Pół biedy, jak mamy aplikację okienkową, ale jeśli sieciową, to ten wyjątek może dotyczyć tysiąca stu problemów. Rzucane są także inne wyjątki, np. InvalidOperationEx. (przy problemie konswersji danych). Trzeba więc sprawdzać nie tylko rodzaj wyjątku, ale także źródło jego wyrzucenia oraz zawartość tekstową.
try
{
var r = s.Eval("alamakota <- 0; 1/alaniemakota"); // niezdef. zmienna, dziel. przez 0
Console.WriteLine(r.AsDouble); // obsłuży nieskończoność, gdyby alaniemakota = 0
}
catch(WebException webEx) // dowolny wyjątek
{
// eRowe wyjątki mają odpowiednio ustawione Source i Message
if(webEx.Source.Equals("RserveCli"))
{
if(webEx.Message.Equals("R threw an error."))
{
Console.WriteLine(s.Eval("geterrmessage()").AsString);
}
}
else
{
// oho, to był jednak błąd "sieciowy", a nie eRa
}
}
catch(inne wyjątki) { obsługa }


Więcej w FAQ

5. Po zakończeniu pracy warto zamykać RServe, żeby nie zabierał pamięci.

6. Instancje mogą się wzajemnie blokować. Jeśli RServe czeka na odpowiedź od instancji A, a ona się powiesiła albo czeka na reakcję użytkownika, to pozostałe instancje też wiszą.

-----------------
Wielosesyjność:

Obrazek


Przykładowa struktura zwracanych danych:

Obrazek
Adrian Olszewski edytował(a) ten post dnia 31.08.12 o godzinie 01:25

Temat: Nowy interfejs R -> .NET

Z uwagi na gruntowne testy różnych form komunikacji z R pod Debianem (Squeeze) i mono 2.10.8 powstało kilka dodatkowych uwag w poprzednim poście.

Jeśli chodzi o R.NET, to coś mi w ostatniej wersji nie działa pod Debianem. Kompiluje się, co prawda, bez problemu, ale jest problem z załadowaniem libR.so. Muszę nad tym posiedzieć, dobrze że są źródła. Za to pod Windowsem działa OK i stabilnie.

Natomiast coraz bardziej mi się podoba RServe. Im więcej o nim czytam, tym bardziej skłaniam się ku przerzuceniu na ten właśnie mechanizm, ponieważ:
1. jest uniwersalny - można się podpiąć czymkolwiek, choćby telnetem,
2. ma potężne możliwości,
3. jest naprawdę szybki (StatConnector przy nim to żółw), porównywalny z R.NET
4. jest w pełni zarządzany (nie ma mieszania safe/unsafe),
5. działa po sieci (jak StatConnector),
6. dobrze obsługuje wielosesyjność,
7. licencja .NETowego klienta to BSD, co ma kolosalne znaczenie przy komercyjnych zastosowaniach (nawet, jeśli samo RServe jest na GPL2).

Kompiluje się i działa bez problemu na mono 2.10.8 pod Debianem.

Poniżej zrzut ekranu z monodevelopa i konsoli. Są na niej: przykład ze strony, łapanie wyjątku dla niezdefiniowanego obiektu, przechwycenie wyjścia z konsoli

Obrazek
Adrian Olszewski edytował(a) ten post dnia 31.08.12 o godzinie 02:10

Temat: Nowy interfejs R -> .NET

Hurra, udało się odpalić R.NET pod Mono (na Debianie). Był problem z wyrzucaniem SIGSEGVa podczas próby załadowania jakiejkolwiek biblioteki pod Mono (bug, który pojawia się i znika w różnych wersjach). Udało się znaleźć dość nietypowe rozwiązanie: http://rdotnet.codeplex.com/discussions/401882

Efekt:

Obrazek


Taka przestroga, żeby unikać odwołań do systemu operacyjnego i niezarządzanego kodu :]

Na chwilę obecną mamy takie możliwości "rozmawiania" z R:

Obrazek
Ten post został edytowany przez Autora dnia 26.08.14 o godzinie 23:11
Wojciech Sobala

Wojciech Sobala Redaktor
statystyczny,
biostatystyk,
Instytut Medycyny
Pr...

Temat: Nowy interfejs R -> .NET

Czy te strzałki na schemacie oznaczają, że komunikacja jest w jedną stronę?
Zastanawiam się również czy nie było by bardziej spójne z resztą opisu użycie Rterm/Rgui zamiast Konsola R.

Temat: Nowy interfejs R -> .NET

Nie, komunikacja jest dwustronna (choć czasem wymaga to nieco pracy) tylko taką formę (strzałka + bloczek) miałem na schemacie organizacyjnym w Wordzie ;)

To, co jest, przypomina mi UMLową zależność - "zależy od", "dostawca - klient".

Obrazek


Konsola to wyrażenie ogólne. Bardziej pasuje tutaj wyrażenie "proces ładujący bibliotekę DLL i uruchamiający dla niej pętlę komunikatów zapewniającą interakcję z użytkownikiem". Może to być RGui, RTerm lub po prostu R (w linuksie - skrypt powłoki, pod Win - exek), może być także odpowiednie okienko programu RStudio lub RCommandera.

EDIT: OK, podłubałem w Paintcie :D zrobiłem "ręcznie" dwustronne strzałki i uaktualniłem diagram w poprzednim poście.Adrian Olszewski edytował(a) ten post dnia 07.11.12 o godzinie 16:16

Temat: Nowy interfejs R -> .NET

Pojawił się .netowy odpowiednik pakietu rJava, czyli rClr. Pakiet umożliwia odwoływanie się do bibliotek .netowych / Mono z poziomu R.

Strona projektu (w trakcie przenoszenia pod nowy adres): https://r2clr.codeplex.com/
Opis instalacji: http://r2clr.codeplex.com/wikipage?title=Installing%20...

Co prawda repozytorium CRAN zawiera pakiety do zrealizowania praktycznie dowolnego zadania programistycznego (w tym dostęp do baz danych i plikowych źródeł danych w wielu formatach, komunikacja sieciowa od gniazd po webserwisy, tworzenie i odwoływanie się do obiektów COM, kilka bibliotek interfejsu graficznego, funkcje plikowe, dostęp do funkcji systemu operacyjnego, generowanie dokumentów w wielu formatach, itd), ale teraz wystarczy zainstalować jedynie "bridge" i skupić się na wygodnym wykonaniu zadania w .NET/Mono, udostępniając "na zewnątrz" jedynie fasadę kilku funkcji.



Wyślij zaproszenie do