Initial Release
Learn the foundamentals to implement an Smart Data Fabric architect using InterSystems IRIS.
👉 We will combine different features of InterSystems IRIS such as multi-model database, interoperability and analytics.
If you are not too familiar with InterSystems IRIS technology, you can get a hands-on overview with these resources:
Clone the GitHub repository to your local computer. This will allow you to acces the code and build the samples:
git clone https://github.com/intersystems-ib/workshop-smart-data-fabric
Build the image we will use during the workshop:
docker-compose build
Run the container:
docker-compose up -d
You should be able to access InterSystems IRIS Management Portal and login using superuser
/ SYS
.
We are going to use an environment using Docker containers.
https://github.com/intersystems-ib/workshop-smart-data-fabric/blob/main/iris.script
to run whatever we need within IRIS.After running the environment, you can access to an interactive sesion on IRIS container using:
docker-compose exec -it iris bash
You can also have a look at the container logs using:
docker logs iris
Have a look at the main classes of our data model:
Our classes are persistent. That means that they can store data, and in InterSystems IRIS we will be able to work with them using objects as well as SQL automatically.
These classes also use Relationships and some Indexes. They can also contain methods and logic.
Go to System Explorer > SQL (SDF), locate the tables corresponding to our persistent classes and display them. They should be empty.
We manipulate data using SQL or Objects. Let’s create some simple data using objects through the WebTerminal
First, create a patient object:
set patientObj = ##class(sdf.data.Patient).%New()
set patientObj.Identifier = "12345"
set patientObj.FirstName = "John"
set patientObj.LastName = "Doe"
Then, create an observation for the patient:
set obxObj = ##class(sdf.data.Observation).%New()
set obxObj.Code = "BodyTemp"
set obxObj.ValueNM = "36"
set obxObj.Units = "C"
Finally, insert the observation into the patient record and save it
do patientObj.Observations.Insert(obxObj)
set sc = patientObj.%Save(1)
write !,"statusCode=",sc
After that, try to run SQL queries again. You can also take advantage of Implicit Joins (Arrow Syntax):
SELECT
Patient->FirstName, Patient->LastName,Code, Units, ValueNM
FROM sdf_data.Observation
After your tests, delete all the data you have just created:
write ##class(sdf.data.Observation).%KillExtent()
write ##class(sdf.data.Patient).%KillExtent()
cd data
tar -zxvf hl7files.tar.gz
git clone https://github.com/intersystems-ib/iris-datapipeUI
cd iris-datapipeUI
docker-compose up -d
You can also copy all files using:
cd data
cp hl7files/*.hl7 hl7in
DataPipe allows you to define an interoperability model with the properties that you need, and then decide how are you going to normalize and validate it. You have to implement a few methods.
In this case, we are using R01Model.cls:
Serialize
and Deserialize
methods to serialize and deserialize using JSON format.Normalize
, it calls R01Normalize data transformation.Validate
, implements some checks on the incoming data.RunOperation
implements what are we going to do with the ingested data. In this example it is storing data in sdf.data.*
classes.HL7 In
- built-in HL7 file Business Service that reads HL7 files from a directory.HL7 Staging
is a DataPipe business process (DataPipe.Staging.BP.StagingManager
) that handles the normalization and validation of your DataPipe model.HL7 Oper
is another DataPipe business process (DataPipe.Oper.BP.OperManager
) that handles running your DataPipe model operation.Let’s create a REST service to interact with your sdf.data.*
classes. But first, we can start by working with JSON.
Your sdf.data.*
classes already extends from %JSON.Adaptor. It provides some nice features for importing and exporting your objects to and from JSON.
Open a WebTerminal session and try the following:
Open an object and export to JSON:
// open an object from a persistent class
set patient = ##class(sdf.data.Patient).%OpenId(1)
// directly, export to json to current device
do patient.%JSONExport()
Now, let’s try to format the JSON for our object:
// export patient object to a json string
do patient.%JSONExportToString(.json)
// instantiate a json formatter
set formatter = ##class(%JSON.Formatter).%New()
do formatter.FormatToString(json, .formattedJson)
// print formatted json
write formattedJson
In your sdf.data.Patient class, change the %JSONREFERENCE
attribute from ID
to OBJECT
or viceversa and try again the following:
// delete previous in-memory object definition
kill patient
// re-open object (so it can load your change on %JSONREFERENCE)
set patient = ##class(sdf.data.Patient).%OpenId(1)
// export to a formatted json string
do patient.%JSONExportToString(.json)
do formatter.FormatToString(json, .formattedJson)
// print your json string
write formattedJson
Can you tell the difference between using ID
or OBJECT
?
⚠️ Important! Before going on, be sure your sdf.data.Patient class has (%JSONREFERENCE = "ID")
defined.
%JSON.Adaptor has a lot of nice features that allows you to export and import and customize those behaviours. We’ll use them in the REST service we will implement.
%JSON.Adaptor
is a nice approach if you have already defined classes that you want to serialize or deserialize to JSON format.
%DynamicObjects allows you to work with JSON structures without having a previous definition (dynamically).
In your WebTerminal session try the following:
set dynamicObject = {"prop1":"a string value"} write dynamicObject.prop1
set dynamicArray = [[1,2,3],{"A":33,"a":"lower case"},1.23456789012345678901234,true,false,null,0,1,""] write dynamicArray.%ToJSON()
Have a look at the documentation section Using JSON in ObjectScript to have an overview of all the options you have available with %JSON.Adaptor
or %DynamicObjects
.
There are different ways of implement REST services in InterSystems IRIS. We will implement a %CSP.REST
service. Don’t forget to check the documentation section Introduction to Creating REST Services to have a full view.
Open https://github.com/intersystems-ib/workshop-smart-data-fabric/blob/main/sdf.connectors.api.DataEndpoint. This will be our service for accesing some of our sdf.data.*
classes.
Review the different methods that are implemeted and try to figure out what are they doing.
REST services needs a web application that forwards HTTP requests to them, in this case we have the /sdf/api web application.
Also, in https://github.com/intersystems-ib/workshop-smart-data-fabric/blob/main/iris.script you will find how this web application is imported during the container image build for the environment.
Finally, try your service using Postman. Import the https://github.com/intersystems-ib/workshop-smart-data-fabric/blob/main/workshop-smart-data-fabric.postman_collection.json included in the repository and try the different requests:
Embedded Python allows you to use Python to program InterSystems IRIS applications. You can even mix ObjectScript methods and Python methods and refer to objects created in either language! And of course you could use any Python libraries on your implementation. Check the documentation section Using Embedded Python to have a full view on this topic.
We will use some Python libraries we must install. First, you need to connect to container bash:
docker compose exec iris bash
Then install the libraries we will use:
pip3 install --target /usr/irissys/mgr/python/ pandas openpyxl
We are going to use Embedded Python to implement in our REST service an operation that will return an Excel file with the observations for an specific patient. We will take advantage of openpyxl Python library to create Excel files:
/patient/:id/observations/xls
requests to return an Excel file.GetPatientObservationsExcel
method will run a SQL query, create a result set and convert it to Excel.ResultSetToXls
which is an Embedded Python classmethod that takes advantage of openpyxl](https://openpyxl.readthedocs.io/en/stable/) library.You can test it accessing to http://localhost:52773/sdf/api/patient/2/observations/xls in your browser.
We are going to create a Telegram bot and use it to send some notifications about our Smart Data Fabric.
/newbot
Write down your Telegram Bot token.
...
"chat":{"id":<your_chatId>
...
TelegramBotToken
Credentials with your token as password.TelegramSendMessage
operation and set the following:
TelegramBotToken
your chatId
You can now test your Telegram Business Operation:
You can call your Telegram business operation from the ingestion layer using your Data Pipe model, try to add the following in R01Model:
$$$AddLog(log, "Transaction Commited")
// you can send messages to other production components (while you are not on an open transaction) if $isobject(bOperation) { set req = ##class(sdf.connectors.interop.msg.TelegramMsgReq).%New() set req.text = "Patient ("_..PatientId_") ingested! 🌡️ "_$number(..ObxValues.GetAt("BodyTemp"),2)_" "_..ObxUnits.GetAt("BodyTemp") $$$ThrowOnError(bOperation.SendRequestAsync("TelegramSendMessage", req)) }
You can also call interoperability components from your REST service context.
Let’s call the Telegram business operation from the REST service:
/summary
to send a summary of the sdf.GetSummary
.HL7 FHIR (Fast Healthcare Interoperability Resources) has become the top standard for the exchange of patient data across healthcare systems.
However, not all applications can be completely re-written to exchange data using the FHIR standard, and facilities may not be able to deploy a full FHIR repository.
You can use InterSystems IRIS For Health to to create an architecture that acts as a façade for a FHIR repository, allowing you to avoid complete rework while reaping the benefits of using FHIR data in your existing applications.
You can find more information in FHIR Façade Architecture Overview.
Let’s say that you want to implement an architecture that enables FHIR for our classes in sdf.data.*
package.
You will now implement a FHIR Façade.
You will now create a FHIR Server and use your own InteractionsStrategy that implements a FHIR Façade on top of your sdf.data.*
package:
Create a FHIR server in Health > SDF > FHIR Configuration > Server Configuration > Add Endpoint
hl7.fhir.r4.core@4.0.1
/csp/healthshare/sdf/fhir/r4
sdf.fhirserver.InteractionsStrategy
Now, edit the FHIR endpoint you have just created:
In this case these are the main involved classes:
Using the included Postman collection, try some requests that are already prepared:
metadata
: retrieve your FHIR Façade Capability StatementGet Patient
: retrieve a particular patient as a FHIR resourceGet Patients. Female. Paginated
: search female patients and retrieve a paginated bundle.You can also find more information about IRIS and OAuth2 in workshop-iris-oauth2.
IRIS will act as your OAuth Authorization server. You can create a it in System Administration > Security > OAuth 2.0 > Server
Or you can simply type this command that will create the OAuth Authorization server for you:
zn "SDF"
do ##class(sdf.Utils).CreateOAuth2Server()
Next, create the OAuth2 Resource server that will be used in your FHIR Server.
Go to System Administration > Security > OAuth 2.0 > Client > Create Server Description
https://webserver/iris/oauth2
ssl
Go to System Administration > Security > OAuth 2.0 > Client > Client Configurations > Create Client Configuration:
fhirserver-resserver
fhirserver oauth resource server
Resource server
ssl
Next, add a new client (with a ClientId and a Secret) that will be used while testing your FHIR Server + OAuth from Postman.
Now, go back and edit your FHIR Server endpoint in Health > SDF > FHIR Configuration > Server Configuration > Edit Endpoint
Update the following:
fhirserver-resserver
oauth-clientid
and oauth-clientsecret
Postman variables to use your ClientID and Secret.There multiple ways in which you can leverage analytics & data science using InterSystems IRIS:
We will focus on IRIS BI on our first example.
Open Management Portal > Analytics > SDF > Architect > Open Observations Cube and go through the different dimensions and measures defined for a cube based on the observations persistent class.
These dimensions and measures define what kind of analysis can be done using this cube.
Click on Build to build the cube based on the data you have loaded previously.
Then, open Management Portal > Analytics > SDF > Analyzer > Open Observations Cube and try different combinations for rows & columns on your analysis pivot table.
You can also open a pre-defined pivot. In your VS Code Import & Compile AvgObservationsByAge.pivot.dfi.
Finally, you can create dashboards and build widgets based on your analysis pivot tables. In your VS code Import & Compile AvgObservationsByCode.dashboard.dfi.
Then, open Management Portal > Analytics > SDF > User Portal > Open Avg Values by Sex, Age Dashboard
In Open Exchange you can find awesome applicatiosn like DSW that enables a whole new great looking UI for your IRIS BI.
You can checkout in your example accessing http://localhost:52773/dsw/index.html#/SDF
Again, there are different ways you can add Machine Learning features on your InterSystems IRIS Applications:
pandas
, scikit-learn
, tensorflow
, etc directly with your IRIS data to implement your ML models.We will focus on a simple example of IntegratedML.
We are still using a dataset inspired on Maternal Health Risk Data dataset from Kaggle.
“Inspired” in this particular case means that we won’t have all the data available, so the accuracy of our ML model could be better.
In any case, if you are interested on using the whole dataset check out workshop-integratedml-intro.
Now, in our example check the following:
Go to Management Portal > Explorer > SQL > SDF and run the following:
Create a model for predicting the RiskLevel
column based on your training data:
CREATE MODEL MaternalModel PREDICTING (RiskLevel) FROM sdf_data.MaternalRiskTrain
Train your model using your training data:
TRAIN MODEL MaternalModel
Now, validate your model using your test data:
VALIDATE MODEL MaternalModel FROM sdf_data.MaternalRiskTest
You can check the validation metrics for your model:
SELECT * FROM INFORMATION_SCHEMA.ML_VALIDATION_METRICS
And finally, you can use your model to get predictions:
SELECT *, PREDICT(MaternalModel) AS PredictedRisk FROM sdf_data.MaternalRiskTest
In https://github.com/intersystems-ib/workshop-smart-data-fabric/blob/main/docker-compose.yml has been added a jupyter notebook service so we can connect to IRIS using IRIS Native SDK for Python.
Try the following:
Try it! Think about all the available Python ML libraries you could use to analyze your IRIS data from a pure Python context. You can run queries or directly call your IRIS objects methods.
During the workshop you have been working with already created HL7 files inspired on Maternal Health Risk Data dataset from Kaggle.
Here is how these HL7 files have been created:
Load train data into a temporary table in IRIS:
do ##class(community.csvgen).Generate("/app/data/maternalRisk/maternal_health_risk.csv",",","temp.MaternalHealthRisk")
Then use a simple tool to generate HL7 files:
do ##class(sdf.tools.HL7Generator).GenerateFilesHL7()
Your files will be generated in data/maternalRisk/hl7gen
.