mdpnp / mdpnp

MD PnP OpenICE
https://mdpnp.mgh.harvard.edu/
114 stars 68 forks source link

Where are the instructions to send the output of OpenICE 2.0 to python #112

Closed rhepstein1 closed 1 month ago

rhepstein1 commented 2 months ago

Are the instructions to connect OpenICE to a python app listed somewhere?

Also, is it possible to output the data when running a simulation in the Ice Supervisor to a csv file? I don't see any options to do that on the GUI.

simonkelly1973 commented 2 months ago

Hello

By "simulation" do you mean when running a simulated device?

No devices (network, serial or simulated) send output to a CSV file. That is not a feature of device interface design.

If you are starting your device from inside the OpenICE GUI, you can use the Data Exporter app to export data to a CSV file.

simonkelly1973 commented 2 months ago

Also, sample Python code is in the

data-types/x73-idl/src/main/idl/ice/numeric_subscriber

Directory of your cloned repository.

That shows how to subscribe to the "numeric" data type. Numerics are single data points such as pump speed or a heart rate. Subscribing to other data types such as the waveform datatype is certainly possible as well.

rhepstein1 commented 1 month ago

Yes, I was referring to exporting from the OpenICE GUI. However, I don't see a Data Exporter app listed in the ICE Applications GUI. Do I need to compile from source? If so, can you point me to the directory?

Also, concerning the python code, how do I get the rti module referenced in numeric_subscriber.py Do I need to download Connext from https://www.rti.com/free-trial ?

Do you have a tutorial describing the steps to get the Python connection to OpenICE working?

simonkelly1973 commented 1 month ago

We don't have a tutorial for the Python code at the moment. In fact, we worked on a white paper with the DDS Vendor [RTI] (https://www.rti.com) about all this in detail, but that hasn't been released yet.

Anyway, to get access to the module, you can do

pip install rti.connext

and that should just download and install it.

You will need to define a source for an RTI license file. The OpenICE code base includes a suitable license file. You can only use this license file for development and research purposes. You are not allowed to use it for anything else. The file is in the source tree location

interop-lab/demo-apps/bin/main/OpenICE_license.dat

You can make a reference to it by setting the environment variable

RTI_LICENSE_FILE

to point to that license file. You should use a full path. For example

export RTI_LICENSE_FILE=/home/rhepstein1/mdpnp/interop-lab/demo-apps/bin/main/OpenICE_license.dat

Once that is done, you should be able to run the sample code.

simonkelly1973 commented 1 month ago

There seems to be a problem with the data exporter app at runtime at the moment, meaning it doesn't appear in the list of applications on the left hand side of the main window. We should be able to commit a workaround for this shortly.

rhepstein1 commented 1 month ago

After posting my question, I went to rti.com and got an evaluation license. I then downloaded their rti module into python and set the license location to their rti_license.dat file in the RTI Launcher GUI.

I set the environmental variable RTI_LICENSE_FILE to this and also copied the file to the directory from which I'm running my python code. Probably redundant, but just to be sure. That allowed the NumericSubscriber.py to run.

However, I think rti may have changed their license file or verification process.

I found the OpenICE_license_dat at C:{OpenICE install directory}\interop-lab\demo-apps\build\resources\main\OpenICE_license.dat I couldn't find it in the location you described. Do I have the correct file? It's structure is somewhat different from my evaluation license. In particular, there is not an expiration date.

setting the RTI_LICENSE_FILE to that location didn't work, neither did copying it to my python folder and renaming in rti_license.dat I get an error message related to the absence of a license file.

When I reverted to my personal evaluation license file, it worked.

However, how do I hook NumericSubscription to my running OpenICE GUI window, which is displaying simulated data? I'm getting a message "Numeric subscriber sleeping for 1 seconds..." which I think is because it's not connected.

I'm guessing that this is specified in USER_QOS_PROFILES.xml but I'm not sure what to put here. Here is my currently running window. Do I use the Unique Device Identifier?

data window from OpenICE GUI

simonkelly1973 commented 1 month ago

We have just commited acbc1ac that updates the data type definitions for the Python code. These were effectively out of date because of some changes recommended by RTI. You should now be able to run the numeric subscriber program and see the numerics data.

Let us know if that gets you going.

rhepstein1 commented 1 month ago

Yes, I'm now seeing all the numerics. Thanks for taking care of this so quickly!

Is there in issue with your license file, or did I perhaps do something wrong?

Here's an example for others:

Numeric subscriber sleeping for 1 seconds... Received: ice_Numeric(unique_device_identifier='8OUe2sc70dIu1UtjIer5dRwOkh03oIygwCGL', metric_id='MDC_CO2_RESP_RATE', vendor_metric_id='', instance_id=0, unit_id='MDC_DIM_DIMLESS', value=15.0, device_time=ice_Time_t(sec=1726500617, nanosec=0), presentation_time=ice_Time_t(sec=1726500617, nanosec=0)) Numeric subscriber sleeping for 1 seconds... Received: ice_Numeric(unique_device_identifier='8OUe2sc70dIu1UtjIer5dRwOkh03oIygwCGL', metric_id='MDC_AWAY_CO2_ET', vendor_metric_id='', instance_id=0, unit_id='MDC_DIM_DIMLESS', value=30.0, device_time=ice_Time_t(sec=1726500617, nanosec=0), presentation_time=ice_Time_t(sec=1726500617, nanosec=0)) Received: ice_Numeric(unique_device_identifier='q9ukAW091iu9it011PBQUcL1rStCHdrgpoR7', metric_id='MDC_PULS_OXIM_PULS_RATE', vendor_metric_id='', instance_id=0, unit_id='MDC_DIM_DIMLESS', value=60.0, device_time=ice_Time_t(sec=1726500617, nanosec=0), presentation_time=ice_Time_t(sec=1726500617, nanosec=0)) Received: ice_Numeric(unique_device_identifier='q9ukAW091iu9it011PBQUcL1rStCHdrgpoR7', metric_id='MDC_PULS_OXIM_SAT_O2', vendor_metric_id='', instance_id=0, unit_id='MDC_DIM_DIMLESS', value=98.0, device_time=ice_Time_t(sec=1726500617, nanosec=0), presentation_time=ice_Time_t(sec=1726500617, nanosec=0)) Received: ice_Numeric(unique_device_identifier='q9ukAW091iu9it011PBQUcL1rStCHdrgpoR7', metric_id='MDC_CO2_RESP_RATE', vendor_metric_id='', instance_id=0, unit_id='MDC_DIM_DIMLESS', value=15.0, device_time=ice_Time_t(sec=1726500617, nanosec=0), presentation_time=ice_Time_t(sec=1726500617, nanosec=0)) Received: ice_Numeric(unique_device_identifier='q9ukAW091iu9it011PBQUcL1rStCHdrgpoR7', metric_id='MDC_AWAY_CO2_ET', vendor_metric_id='', instance_id=0, unit_id='MDC_DIM_DIMLESS', value=30.0, device_time=ice_Time_t(sec=1726500617, nanosec=0), presentation_time=ice_Time_t(sec=1726500617, nanosec=0)) Received: ice_Numeric(unique_device_identifier='q9ukAW091iu9it011PBQUcL1rStCHdrgpoR7', metric_id='MDC_ECG_HEART_RATE', vendor_metric_id='', instance_id=0, unit_id='MDC_DIM_DIMLESS', value=60.0, device_time=ice_Time_t(sec=1726500617, nanosec=0), presentation_time=ice_Time_t(sec=1726500617, nanosec=0)) Received: ice_Numeric(unique_device_identifier='q9ukAW091iu9it011PBQUcL1rStCHdrgpoR7', metric_id='MDC_TTHOR_RESP_RATE', vendor_metric_id='', instance_id=0, unit_id='MDC_DIM_DIMLESS', value=15.0, device_time=ice_Time_t(sec=1726500617, nanosec=0), presentation_time=ice_Time_t(sec=1726500617, nanosec=0)) Received: ice_Numeric(unique_device_identifier='q9ukAW091iu9it011PBQUcL1rStCHdrgpoR7', metric_id='MDC_PRESS_BLD_ART_ABP_SYS', vendor_metric_id='', instance_id=0, unit_id='MDC_DIM_DIMLESS', value=120.0, device_time=ice_Time_t(sec=1726500617, nanosec=0), presentation_time=ice_Time_t(sec=1726500617, nanosec=0)) Received: ice_Numeric(unique_device_identifier='q9ukAW091iu9it011PBQUcL1rStCHdrgpoR7', metric_id='MDC_PRESS_BLD_ART_ABP_DIA', vendor_metric_id='', instance_id=0, unit_id='MDC_DIM_DIMLESS', value=80.0, device_time=ice_Time_t(sec=1726500617, nanosec=0), presentation_time=ice_Time_t(sec=1726500617, nanosec=0))

simonkelly1973 commented 1 month ago

There doesn't seem to be an issue with the license file for us. I've just tested using that one.

Sorry about the slightly incorrect location. When you just check out the code from GitHub, you will only have two copies of the license file

./interop-lab/demo-apps/src/main/resources/OpenICE_license.dat ./wis-docker/web_integration_service/OpenICE_license.dat

After you complete a gradle build, you will have

./interop-lab/demo-apps/build/resources/main/OpenICE_license.dat

as an additional copy.

When we are actually doing development on OpenICE, we use Eclipse, and Eclipse compiles resources into a directory called bin, instead of build as Gradle does (we don't use the gradle build process from inside Eclipse). That's where the extra copy comes from that was referred to incorrectly earlier. You won't have it in your gradle only environment.

If we have no value for RTI_LICENSE_FILE, then we get the following output

Running ice_NumericSubscriber on domain 0
RTI Connext DDS No source for License information
Please contact support@rti.com with any questions or comments.
Traceback (most recent call last):
  File "/openice/check-for-as50/mdpnp/data-types/x73-idl/src/main/idl/ice/numeric_subscriber/read_numerics.py", line 85, in <module>
    main()
  File "/openice/check-for-as50/mdpnp/data-types/x73-idl/src/main/idl/ice/numeric_subscriber/read_numerics.py", line 30, in main
    ice_NumericSubscriber.run_subscriber(
  File "/openice/check-for-as50/mdpnp/data-types/x73-idl/src/main/idl/ice/numeric_subscriber/numeric_subscriber.py", line 36, in run_subscriber
    participant = dds.DomainParticipant(domain_id)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
rti.connextdds.Error: Failed to create DomainParticipant

If we then do

export RTI_LICENSE_FILE=/openice/check-for-as50/mdpnp/interop-lab/demo-apps/src/main/resources/OpenICE_license.dat

then we can run the program again, and everything is fine.

Did you use a full path in your export statement?

Which operating system are you using (Linux, Mac, Windows)?

simonkelly1973 commented 1 month ago

We added a README.md based on this

https://github.com/mdpnp/mdpnp/tree/master/data-types/x73-idl/src/main/idl/ice/numeric_subscriber

rhepstein1 commented 1 month ago

Windows. That makes the syntax of many of the simple unix commands more complex. But i expect that developers would know how to translate. I don’t think the Julians of the world are going to be compiling from source code 🙄. (BTW, I’ve been friends with him for 30 years so i’m allowed to make fun of him.)

I’ll try again just using the environmental value to point to your license file. I may have misspelled something

The readme is helpful.

Another thing i noticed when trying to get gradlew to work the other day was that it wanted the microsoft C++ compiler cl.exe which wasn’t on machine. I ended up installing Visual Studio 2022 to get this and added the location to my path. There’s an easier way to do this just installing the c++ build tools. Is CL.EXE actually required?

Rich

Richard H. Epstein, MD Professor of Clinical Anesthesiology Miller School of Medicine University of Miami

Sent from my iPhone 11 Pro Please excuse my brevity/typos.

On Sep 16, 2024, at 12:14 PM, Simon Kelly @.***> wrote:

 CAUTION: This email originated from outside the organization. DO NOT CLICK ON LINKS or OPEN ATTACHMENTS unless you know and trust the sender.

There doesn't seem to be an issue with the license file for us. I've just tested using that one.

Sorry about the slightly incorrect location. When you just check out the code from GitHub, you will only have two copies of the license file

./interop-lab/demo-apps/src/main/resources/OpenICE_license.dat ./wis-docker/web_integration_service/OpenICE_license.dat

After you complete a gradle build, you will have

./interop-lab/demo-apps/build/resources/main/OpenICE_license.dat

as an additional copy.

When we are actually doing development on OpenICE, we use Eclipse, and Eclipse compiles resources into a directory called bin, instead of build as Gradle does (we don't use the gradle build process from inside Eclipse). That's where the extra copy comes from that was referred to incorrectly earlier. You won't have it in your gradle only environment.

If we have no value for RTI_LICENSE_FILE, then we get the following output

Running ice_NumericSubscriber on domain 0 RTI Connext DDS No source for License information Please contact @.*** with any questions or comments. Traceback (most recent call last): File "/openice/check-for-as50/mdpnp/data-types/x73-idl/src/main/idl/ice/numeric_subscriber/read_numerics.py", line 85, in main() File "/openice/check-for-as50/mdpnp/data-types/x73-idl/src/main/idl/ice/numeric_subscriber/read_numerics.py", line 30, in main ice_NumericSubscriber.run_subscriber( File "/openice/check-for-as50/mdpnp/data-types/x73-idl/src/main/idl/ice/numeric_subscriber/numeric_subscriber.py", line 36, in run_subscriber participant = dds.DomainParticipant(domain_id) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rti.connextdds.Error: Failed to create DomainParticipant

If we then do

export RTI_LICENSE_FILE=/openice/check-for-as50/mdpnp/interop-lab/demo-apps/src/main/resources/OpenICE_license.dat

then we can run the program again, and everything is fine.

Did you use a full path in your export statement?

Which operating system are you using (Linux, Mac, Windows)?

— Reply to this email directly, view it on GitHubhttps://urldefense.com/v3/__https://github.com/mdpnp/mdpnp/issues/112*issuecomment-2353353784__;Iw!!KVu0SnhVq1hAFvslES2Y!J7KdLM7ubqXn0nIt1ZT23tfZgsUunFg4Jmz4uWjYrHtJpinLXtsMct7nJAp1vCV9GDSfo3Ol4xeD23Dnpl0TlInVSSOx$, or unsubscribehttps://urldefense.com/v3/__https://github.com/notifications/unsubscribe-auth/AVEO7BGI7TYOGTQ65HB265DZW37UZAVCNFSM6AAAAABOHZTOBCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGNJTGM2TGNZYGQ__;!!KVu0SnhVq1hAFvslES2Y!J7KdLM7ubqXn0nIt1ZT23tfZgsUunFg4Jmz4uWjYrHtJpinLXtsMct7nJAp1vCV9GDSfo3Ol4xeD23Dnpl0TlM4Bs01k$. You are receiving this because you authored the thread.Message ID: @.***>

simonkelly1973 commented 1 month ago

You can install a smaller subset of Visual Studio called "Visual Studio Command Line Tools" that includes cl.exe

At the moment, that is still required to process the .idl files, as they currently use syntax like this

include ....

This is based on the C syntax and these "preprocessor macros" are resolved using cl.exe - which is a pre compiler.

We have investigated using a pure java implementation to do this instead of requiring the cl.exe, but that isn't complete yet.

That tends to be less of an issue on Linux because the compiler chain is usually installed on any machine a developer uses.

rhepstein1 commented 1 month ago

I have python integration now working with parsing the desired numerics from the full string. Thank you for your assistance.