0 Followers · 117 Posts

Git is a version control system for tracking changes in computer files and coordinating work on those files among multiple people.

Official site.

Article Pietro Di Leo · Sep 24, 2025 23m read

Table of Contents

  1. Purpose of the article
  2. What containers are and why they make sense with IRIS
     2.1 Containers and images in a nutshell
     2.2 Why containers are useful for developers
     2.3 Why IRIS works well with Docker
  3. Prerequisites
  4. Installing the InterSystems IRIS image
     4.1 Using Docker Hub
     4.2 Pulling the image
  5. Running the InterSystems IRIS image
     5.1 Starting an IRIS container
     5.2 Checking container status
     5.3 Executing code in the container terminal
     5.4 Accessing the IRIS Management Portal
     5.5 Connecting the container to VS Code
     5.6 Stopping or removing the container
     5.7 Setting a specific password with a bind mount
     5.8 Using durable %SYS volumes
      5.8.1 What gets stored with durable %SYS
      5.8.2 How to enable durable %SYS
  6. Using Docker Compose
     6.1 Docker Compose example
     6.2 Running Docker Compose
  7. Using a Dockerfile to run custom source code
     7.1 Dockerfile example
     7.2 Docker Compose example
     7.3 Understanding layers, image tagging and build vs. run time
     7.4 Source code and init script
     7.5 Building the image with Dockerfile
     7.6 Running instructions in the containerized IRIS terminal
  8. Conclusion and what’s next
6
6 217
Article Andrew Sklyarov · Nov 2, 2025 7m read

Over time, while I was working with Interoperability on the IRIS Data Platform, I developed rules for organizing a project code into packages and classes. That is what is called a Naming Convention, usually. In this topic, I want to organize and share these rules. I hope it can be helpful for somebody.

 

4
2 82
Discussion Andrew Sklyarov · Oct 8, 2025

I know the next ones:

1. Place all different settings in environment variables. You have a different .env file for each environment, and you must add some code to Production for reading and setting these values. It's good for deploying into containers, but challenging for management when we have a large production. I mean, we have many settings that can vary depending on the environment: active flag, pool size, timeouts, and so on. Not only endpoints.

10
0 135
Article Jordan Simpson · Sep 26, 2025 2m read

Hi,

Just thought I'd share quite a handy hook that has helped me out when developing on Health Connect Cloud with VS Code and GitBash. When developing on Health Connect Cloud, if changes are made directly on the server such as routing rules or component deployments, they aren't automatically included in source control, therefore you must export from the server into your local files and push to your remote repo. I'm sure there are easier methods to deal with that which I'm in the process of testing, but as a quick solution I thought it would be handy have a pre-commit hook which triggers a reminder in GitBash - see below.

1
1 123
Question Jochen Roese · Sep 15, 2025

Hi,

so we introduced GIT in our workflow and we exported all files with $SYSTEM.OBJ.ExportUDL

Everything fine so far. But for some reason the export adds an extra line for classes (Routines are OK as far as I can see):

On Serverside it isn't there

The Problem is now that when we checkout a branch and a class changed we automatically compile it from the repository to a namespace that is made for the developer. E.g. DEV_001, DEV_002 and so on. 

2
0 48
Question PaulSomebody · Aug 19, 2025

Hello All,

  I have used github (outside of IRIS) for many many years and have no problem with it.  Also used SVN and other source control systems.

  I have a conceptual problem understanding the ISC github links and how they work via VSCode.

https://github.com/intersystems/git-source-control

 Our server is on Linux.

What I've done:

1. On Linux Server - d ##class(SourceControl.Git.API).Configure()

2. Create a local repo (we have a local git), say https://repo/myrepo

3. VSCode installed Object script addons, github Pull requests extension

4. VSCode Connect to namespace on server, all good

3
0 110
Question JESUS (COGNOSANTE) BRAVO · Jun 24, 2025

I installed and configure CodeTidy in my local development environment, without InterSystems source-control (git-source-control) and only git for source control.

I would like to use only CodeTidy to stablish an automated  Linting and Code Style Validation for InterSystems ObjectScript code triggered by GitHub Actions.

Could you shed some light on how to accomplish that?

4
0 100
Question André-Claude Gendron · Jul 31, 2025

Hi everyone,

I’m working with an existing InterSystems IRIS server that hosts several web applications and namespace-specific code and data. I’d like to reverse-engineer the current environment into a %Installer.Manifest file so I can store it in Git and manage its changes.

My goal is to:

  • Track the application setup and configuration in version control
  • Rebuild environments consistently (namespaces, CSP apps, security roles, etc.)
  • Possibly automate deployments later on
1
2 59
Article Guillaume Rongier · Jul 17, 2025 5m read

img

This will be an introduction to Python programming in the context of IRIS.

Before anything I will cover an important topic: How python works, this will help you understand some issues and limitations you may encounter when working with Python in IRIS.

All the articles and examples can be found in this git repository: iris-python-article

How Python works

Interpreted Language

Python is an interpreted language, which means that the code is executed line by line at runtime even when you import a script.

What does this mean ? Let's take a look at the following code:

# introduction.py

def my_function():
    print("Hello, World!")

my_function()

When you run this script, the Python interpreter reads the code line by line. It first defines the function my_function, and then it calls that function, which prints "Hello, World!" to the console.

Example of running the script directly:

python3 /irisdev/app/src/python/article/introduction.py 

This will output:

Hello, World!

In an IRIS context, what will happen if we import this script ?

Class Article.Introduction Extends %RegisteredObject
{
    ClassMethod Run()
    {
        Set sys = ##class(%SYS.Python).Import("sys")
        do sys.path.append("/irisdev/app/src/python/article")

        do ##class(%SYS.Python).Import("introduction")
    }
}

Let's run it:

iris session iris -U IRISAPP '##class(Article.Introduction).Run()'

You will see the output:

Hello, World!

This is because the Python interpreter imports the code by interpreting it, first it defines the function and then calls it, just like it would if you ran the script directly but you are not running you are importing it.

⚠️ Important Note: If you import the script without calling the function, nothing will happen. The function is defined, but it won't execute until you explicitly call it.

Did you get it? The Python interpreter executes the code in the file, and if you don't call the function, it won't run.

Example of importing without calling:

# introduction1.py
def my_function():
    print("Hello, World!")

Let's run it in an python interpreter:

python3 /irisdev/app/src/python/article/introduction1.py 

Output:

# No output, because the function is defined but not called

In an IRIS context, if you import this script:

Class Article.Introduction1 Extends %RegisteredObject
{
    ClassMethod Run()
    {
        Set sys = ##class(%SYS.Python).Import("sys")
        do sys.path.append("/irisdev/app/src/python/article")
        do ##class(%SYS.Python).Import("introduction1")
    }
}

Let's run it:

iris session iris -U IRISAPP '##class(Article.Introduction1).Run()'

You will see no output, because the function is defined but not called.

🤯 Why this subtlety is important ?

  • When you import a Python script, it executes the code in that script.
    • You may don't want this to happen
  • You can be confused by guessing importing a script it's like running it, but it's not.

Import caching

When you import a Python script, the Python interpreter caches the imported script. This means that if you import the same script again, it will not re-execute the code in that script, but will use the cached version.

Demonstration by example:

Let's reuse the introduction.py script:

# introduction.py
def my_function():
    print("Hello, World!")

my_function()

Now, same thing let's reuse the Article.Introduction class:

Class Article.Introduction Extends %RegisteredObject
{
    ClassMethod Run()
    {
        Set sys = ##class(%SYS.Python).Import("sys")
        do sys.path.append("/irisdev/app/src/python/article")
        do ##class(%SYS.Python).Import("introduction")
    }
}

But now, we will be running it twice in a row in the same IRIS session:

iris session iris -U IRISAPP 

IRISAPP>do ##class(Article.Introduction).Run()
Hello, World!

IRISAPP>do ##class(Article.Introduction).Run()

IRISAPP>

🤯 What the heck ?

Yes, Hello, World! is printed only once !

⚠️ Your imported script is cached. This means if you change the script after importing it, the changes will not be reflected until you change the IRIS session.

This is even true if you use the language tag python in IRIS:

Class Article.Introduction2 Extends %RegisteredObject
{

ClassMethod Run() [ Language = python ]
{
    import os

    if not hasattr(os, 'foo'):
        os.foo = "bar"
    else:
        print("os.foo already exists:", os.foo)
}

}

Let's run it:

iris session iris -U IRISAPP

IRISAPP>do ##class(Article.Introduction2).Run()

IRISAPP>do ##class(Article.Introduction2).Run()
os.foo already exists: bar

OMG, the os module is cached, and the foo attribute is not redefined to non existing.

Conclusion

I hope this introduction helped you understand why when you work with Python in IRIS, you may encounter some unexpected behaviors, especially when it comes to importing scripts and caching.

Takeway, when working with Python in IRIS:

  • Change everytime the IRIS session to see changes in your Python scripts.
    • This is not a bug, it's how Python works.
  • Be aware that importing a script executes its code.

Bonus

Wait ! It doesn't make sense, if you say that when you import a script, it's cached. Why when I work with the language tag = python, when I change the script, it works without changing the IRIS session?

Good question, this is because the language tag is built in a way that everytime you run it, it will read the script again and execute it line by line as it was new lines in an native Python interpreter, language tag doesn't import the script, it just executes it as if you were running it directly in a Python interpreter without restarting it.

Example:

Class Article.Introduction2 Extends %RegisteredObject
{
ClassMethod Run() [ Language = python ]
{
    import os

    if not hasattr(os, 'foo'):
        os.foo = "bar"
    else:
        print("os.foo already exists:", os.foo)
}
}

Let's run it:

iris session iris -U IRISAPP
IRISAPP>do ##class(Article.Introduction2).Run()

IRISAPP>do ##class(Article.Introduction2).Run()
os.foo already exists: bar  

In a python interpreter it will look like this:

import os

if not hasattr(os, 'foo'):
    os.foo = "bar"
else:
    print("os.foo already exists:", os.foo)

import os
if not hasattr(os, 'foo'):
    os.foo = "bar"
else:
    print("os.foo already exists:", os.foo)

Output:

os.foo already exists: bar # only printed once

Make sense now?

Next :

  • Pep8
  • Modules
  • Dunder methods
  • Working with Python in IRIS
  • ...
0
3 184
Article Guillaume Rongier · Jul 8, 2024 6m read

Flask_logo

Description

This is a template for a Flask application that can be deployed in IRIS as an native Web Application.

Installation

  1. Clone the repository
  2. Create a virtual environment
  3. Install the requirements
  4. Run the docker-compose file
git clone
cd iris-flask-template
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
docker-compose up

Usage

The base URL is http://localhost:53795/flask/.

Endpoints

  • /iris - Returns a JSON object with the top 10 classes present in the IRISAPP namespace.
  • /interop - A ping endpoint to test the interoperability framework of IRIS.
  • /posts - A simple CRUD endpoint for a Post object.
  • /comments - A simple CRUD endpoint for a Comment object.

How to develop from this template

See WSGI introduction article: wsgi-introduction.

TL;DR : You can toggle the DEBUG flag in the Security portal to make changes to be reflected in the application as you develop.

Code presentation

app.py

This is the main file of the application. It contains the Flask application and the endpoints.

from flask import Flask, jsonify, request
from models import Comment, Post, init_db

from grongier.pex import Director

import iris

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'iris+emb://IRISAPP'

db = init_db(app)
  • from flask import Flask, jsonify, request: Import the Flask library.
  • from models import Comment, Post, init_db: Import the models and the database initialization function.
  • from grongier.pex import Director: Import the Director class to bind the flask app to the IRIS interoperability framework.
  • import iris: Import the IRIS library.
  • app = Flask(__name__): Create a Flask application.
  • app.config['SQLALCHEMY_DATABASE_URI'] = 'iris+emb://IRISAPP': Set the database URI to the IRISAPP namespace.
    • The iris+emb URI scheme is used to connect to IRIS as an embedded connection (no need for a separate IRIS instance).
  • db = init_db(app): Initialize the database with the Flask application.

models.py

This file contains the SQLAlchemy models for the application.

from dataclasses import dataclass
from typing import List
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

@dataclass
class Comment(db.Model):
    id:int = db.Column(db.Integer, primary_key=True)
    content:str = db.Column(db.Text)
    post_id:int = db.Column(db.Integer, db.ForeignKey('post.id'))

@dataclass
class Post(db.Model):
    __allow_unmapped__ = True
    id:int = db.Column(db.Integer, primary_key=True)
    title:str = db.Column(db.String(100))
    content:str = db.Column(db.Text)
    comments:List[Comment] = db.relationship('Comment', backref='post')

Not much to say here, the models are defined as dataclasses and are subclasses of the db.Model class.

The use of the __allow_unmapped__ attribute is necessary to allow the creation of the Post object without the comments attribute.

dataclasses are used to help with the serialization of the objects to JSON.

The init_db function initializes the database with the Flask application.

def init_db(app):
    db.init_app(app)

    with app.app_context():
        db.drop_all()
        db.create_all()
        # Create fake data
        post1 = Post(title='Post The First', content='Content for the first post')
        ...
        db.session.add(post1)
        ...
        db.session.commit()
    return db
  • db.init_app(app): Initialize the database with the Flask application.
  • with app.app_context(): Create a context for the application.
  • db.drop_all(): Drop all the tables in the database.
  • db.create_all(): Create all the tables in the database.
  • Create fake data for the application.
  • return the database object.

/iris endpoint

######################
# IRIS Query example #
######################

@app.route('/iris', methods=['GET'])
def iris_query():
    query = "SELECT top 10 * FROM %Dictionary.ClassDefinition"
    rs = iris.sql.exec(query)
    # Convert the result to a list of dictionaries
    result = []
    for row in rs:
        result.append(row)
    return jsonify(result)

This endpoint executes a query on the IRIS database and returns the top 10 classes present in the IRISAPP namespace.

/interop endpoint

########################
# IRIS interop example #
########################
bs = Director.create_python_business_service('BS')

@app.route('/interop', methods=['GET', 'POST', 'PUT', 'DELETE'])
def interop():
    
    rsp = bs.on_process_input(request)

    return jsonify(rsp)

This endpoint is used to test the interoperability framework of IRIS. It creates a Business Service object and binds it to the Flask application.

NB : The bs object must be outside of the scope of the request to keep it alive.

  • bs = Director.create_python_business_service('BS'): Create a Business Service object named 'BS'.
  • rsp = bs.on_process_input(request): Call the on_process_input method of the Business Service object with the request object as an argument.

/posts endpoint

############################
# CRUD operations posts    #
############################

@app.route('/posts', methods=['GET'])
def get_posts():
    posts = Post.query.all()
    return jsonify(posts)

@app.route('/posts', methods=['POST'])
def create_post():
    data = request.get_json()
    post = Post(title=data['title'], content=data['content'])
    db.session.add(post)
    db.session.commit()
    return jsonify(post)

@app.route('/posts/<int:id>', methods=['GET'])
def get_post(id):
    ...

This endpoint is used to perform CRUD operations on the Post object.

Thanks to the dataclasses module, the Post object can be easily serialized to JSON.

Here we use the sqlalchemy query method to get all the posts, and the add and commit methods to create a new post.

/comments endpoint

############################
# CRUD operations comments #
############################

@app.route('/comments', methods=['GET'])
def get_comments():
    comments = Comment.query.all()
    return jsonify(comments)

@app.route('/comments', methods=['POST'])
def create_comment():
    data = request.get_json()
    comment = Comment(content=data['content'], post_id=data['post_id'])
    db.session.add(comment)
    db.session.commit()
    return jsonify(comment)

@app.route('/comments/<int:id>', methods=['GET'])
def get_comment(id):
    ...

This endpoint is used to perform CRUD operations on the Comment object.

The Comment object is linked to the Post object by a foreign key.

Troubleshooting

How to run the Flask application in a standalone mode

You can always run a standalone Flask application with the following command:

python3 /irisdev/app/community/app.py

NB : You must be inside of the container to run this command.

docker exec -it iris-flask-template-iris-1 bash

Restart the application in IRIS

Be in DEBUG mode make multiple calls to the application, and the changes will be reflected in the application.

How to access the IRIS Management Portal

You can access the IRIS Management Portal by going to http://localhost:53795/csp/sys/UtilHome.csp.

Run this template locally

For this you need to have IRIS installed on your machine.

Next you need to create a namespace named IRISAPP.

Install the requirements.

Install IoP :

#init iop
iop --init

# load production
iop -m /irisdev/app/community/interop/settings.py

# start production
iop --start Python.Production

Configure the application in the Security portal.

4
1 491
InterSystems Official Henry Wojnicki · Jul 9, 2024

The Application Services team is pleased to announce the release of git-source-control version 2.4.0, introducing several new features to the open-source project.

For those unfamiliar, git-source-control is an embedded (or "server-side") source control tool for InterSystems products, installed through the InterSystems Package Manager.

Here are the key additions to the 2.4.0 release:

  1. Basic Mode
1
2 324
Question Patrik Spisak · Apr 19, 2025

After upgrading from 2024 to 2025 Im not able to compile any class.

I was using ZPM and git-source-control.

Now Im getting 

Compilation started on 04/19/202520:53:00 with qualifiers 'cuk /checkuptodate=expandedonly'

ERROR #5002: ObjectScript error: <CLASS DOES NOT EXIST>OnAfterSave+4^SourceControl.Git.Extension.1 *SourceControl.Git.Utils
Detected 1 errors during compilation in 0.209s. class '%Studio.SourceControl.Interface', method 'OnBeforeTimestamp': <CLASS DOES NOT EXIST> 150 

I disabled SourceControl in Management portal and nothing happen.

2
0 99
Article Patrick Jamieson · Apr 15, 2025 6m read

I know that people who are completely new to VS Code, Git, Docker, FHIR, and other tools can sometimes struggle with setting up the environment. So I decided to write an article that walks through the entire setup process step by step to make it easier to get started.

I’d really appreciate it if you could leave a comment at the end - let me know if the instructions were clear, if anything was missing, or if there’s anything else you'd find helpful.

The setup includes:

✅ VS Code – Code editor
✅ Git – Version control system
✅ Docker – Runs an instance of IRIS for Health Community
✅ VS Code REST Client Extension – For running FHIR API queries
✅ Python – For writing FHIR-based scripts
✅ Jupyter Notebooks – For AI and FHIR assignments

Before you begin: Ensure you have administrator privileges on your system.

In addition to reading the guide, you can also follow the steps in the videos:

For Windows

2
2 335
Question Alex Efa · Apr 8, 2025

Greetings,

Our team is transitioning to Git in the foreseeable future, and I'm trying to figure out how to design the best development workflow. Being new to IRIS, I am having trouble wraping my head around a few concepts.

Current Setup:

  • All code is hosted on a remote server
  • Each developer works in their own dedicated Namespace, on that server
  • Classes are locked to avoid conflicts
  • Committed code is imported into the Development NS, then redestributed to developers

Challenge:

2
0 198
Question Dmitrii Baranov · Mar 31, 2025

I'd like to ask you for recommendations on how to properly use repository dependencies when using VSCode and Client-side editing. Suppose I have projects A, B and C, with A being independent, B depending on A, and C depending on A and B. I am currently working with the main project C, and I want to be able to contribute to all the other projects in a single VSCode window (instead of opening three instances). How do you solve this problem? Git submodules? ZPM? Something else?

1
0 81
Question Colin Brough · Mar 3, 2025

The compile step in VS Code when using the InterSystems VS Code extensions appears to modify line endings in our class files when newly pulled from remote repo.

What steps can we take to stop this happening? / What settings can we modify?

We are doing local development with client side source control using git (BitBucket Cloud repository). We were previously using GitLab (locally hosted) and didn't have this issue. Developers are all on Windows machines, as are all the Ensemble instances. We believe we have autocrlf = true in all our local git configurations.

Steps to reproduce:

1
0 117
Question Armin Gayl · Jan 28, 2025

Hi,

We are currently switching from Studio to VSCode and central GIT with Serverside Development and have a few start problems.
I have set up a system with Git.

The baseline commit including remote push works. 

But now I have a problem with the VSCode. When I create and compile a new class, it saves it correctly. But if I want to make further changes to the class, it saves the class and loads it again with the previous status.  So the changes I made are gone again.   

I have deactivated CompileOnSave without success.
The log shows the following

4
1 103
InterSystems Official Timothy Leavitt · Dec 4, 2024

It's been a while since I've posted about Embedded Git on the Developer Community, and I'd like to provide an update on the massive amount of work we've done this year and where we're going next.

Context

If you're building solutions on IRIS and want to use Git, that's great! Just use VSCode with a local git repo and push your changes out to the server - it's that easy.

But what if:

6
0 436
Question Sean Brady · Jan 17, 2025

Hello everyone! This is my first post into the developer community and one that I hope is fairly simple to answer. In our environment we currently have 3 different Test environments for testing before migrating code to our Prod environment. Currently we are working on establishing a source control method using Git in house which has been a bit of a struggle. We have also had developers that had used different test and migration methods in the past which has caused some issues with keeping the different test environment in sync.

7
0 162
Question Shanwen Liu · Dec 10, 2024

Hey everyone, I am implementing version control with git-source-control on our codebase and I ran into a pretty strange issue. I believe I have the set up (mostly) correct as the behavior with .cls files is exactly as expected. However, I noticed that git is not keeping track of any changes to CSP files.

Specifically, if a new CSP file is created and saved, I will get the following output:

exporting new version of /csp/testdb/wrc.csp to C:\InterSystems\IRIS\mgr\repo\TESTDB\csp\testdb\wrc.csp

Added /csp/testdb/wrc.csp to source control.

8
1 201
Question Gautam Rishi · Jun 21, 2023

Hi everyone, 
I am new to "git-source-control", what i am doing so far will explain you in few steps.
1. installed git-source-control into a namsapace TEST using ZPM "install git-source-control"
2. configure the git settings and created a new mapping for as such 

3. Now when I am trying to ADD a new file which is created for eg - NewFolder/impl.cls , getting an error like this

exporting new version of NewFolder.impl.cls to /Users/abc/workspace/NewFolder/impl.cls

No mapping with a matching path found for file NewFolder/impl.cls

5
2 578
Question Scott Roth · Nov 6, 2024

There are a select few in the group that have been using Github as a Local Client push to a Repository setup in GitHub. Questions were brought up today about the security, and possible issues when it comes to data being pushed in this method.

Looking over code we have noticed that there is Histogram data within some of the class files that could be considered a security issue. Does anyone else have concerns with the Histogram data being within the class files pushed up to github?

1
0 108
Article Guillaume Rongier · Jul 8, 2024 6m read

fastapi_logo

Description

This is a template for a FastApi application that can be deployed in IRIS as an native Web Application.

Installation

  1. Clone the repository
  2. Create a virtual environment
  3. Install the requirements
  4. Run the docker-compose file
git clone
cd iris-fastapi-template
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
docker-compose up

Usage

The base URL is http://localhost:53795/fastapi/.

Endpoints

  • /iris - Returns a JSON object with the top 10 classes present in the IRISAPP namespace.
  • /interop - A ping endpoint to test the interoperability framework of IRIS.
  • /posts - A simple CRUD endpoint for a Post object.
  • /comments - A simple CRUD endpoint for a Comment object.

How to develop from this template

See WSGI introduction article: wsgi-introduction.

TL;DR : You can toggle the DEBUG flag in the Security portal to make changes to be reflected in the application as you develop.

Code presentation

app.py

This is the main file of the FastAPI application. It contains the FastAPI application and the routes.

from fastapi import FastAPI, Request

import iris

from grongier.pex import Director

# import models
from models import Post, Comment, init_db
from sqlmodel import Session,select

app = FastAPI()

# create a database engine
url = "iris+emb://IRISAPP"
engine = init_db(url)
  • from fastapi import FastAPI, Request - Import the FastAPI class and the Request class.
  • import iris - Import the IRIS module.
  • from grongier.pex import Director: Import the Director class to bind the flask app to the IRIS interoperability framework.
  • from models import Post, Comment, init_db - Import the models and the init_db function.
  • from sqlmodel import Session,select - Import the Session class and the select function from the sqlmodel module.
  • app = FastAPI() - Create a FastAPI application.
  • url = "iris+emb://IRISAPP" - Define the URL of the IRIS namespace.
  • engine = init_db(url) - Create a database engine for the sqlmodel ORM.

models.py

This file contains the models for the application.

from sqlmodel import Field, SQLModel, Relationship, create_engine

class Comment(SQLModel, table=True):
    id: int = Field(default=None, primary_key=True)
    post_id: int = Field(foreign_key="post.id")
    content: str
    post: "Post" = Relationship(back_populates="comments")

class Post(SQLModel, table=True):
    id: int = Field(default=None, primary_key=True)
    title: str
    content: str
    comments: list["Comment"] = Relationship(back_populates="post")

Not much to say here, just the definition of the models with foreign keys and relationships.

The init_db function is used to create the database engine.

def init_db(url):

    engine = create_engine(url)

    # create the tables
    SQLModel.metadata.drop_all(engine)
    SQLModel.metadata.create_all(engine)

    # initialize database with fake data
    from sqlmodel import Session

    with Session(engine) as session:
        # Create fake data
        post1 = Post(title='Post The First', content='Content for the first post')
        ...
        session.add(post1)
        ...
        session.commit()

    return engine
  • engine = create_engine(url) - Create a database engine.
  • SQLModel.metadata.drop_all(engine) - Drop all the tables.
  • SQLModel.metadata.create_all(engine) - Create all the tables.
  • with Session(engine) as session: - Create a session to interact with the database.
  • post1 = Post(title='Post The First', content='Content for the first post') - Create a Post object.
  • session.add(post1) - Add the Post object to the session.
  • session.commit() - Commit the changes to the database.
  • return engine - Return the database engine.

/iris endpoint

######################
# IRIS Query example #
######################

@app.get("/iris")
def iris_query():
    query = "SELECT top 10 * FROM %Dictionary.ClassDefinition"
    rs = iris.sql.exec(query)
    # Convert the result to a list of dictionaries
    result = []
    for row in rs:
        result.append(row)
    return result
  • @app.get("/iris") - Define a GET route for the /iris endpoint.
  • query = "SELECT top 10 * FROM %Dictionary.ClassDefinition" - Define the query to get the top 10 classes in the IRIS namespace.
  • rs = iris.sql.exec(query) - Execute the query.
  • result = [] - Create an empty list to store the results.
  • for row in rs: - Iterate over the result set.
  • result.append(row) - Append the row to the result list.
  • return result - Return the result list.

/interop endpoint

########################
# IRIS interop example #
########################
bs = Director.create_python_business_service('BS')

@app.get("/interop")
@app.post("/interop")
@app.put("/interop")
@app.delete("/interop")
def interop(request: Request):
    
    rsp = bs.on_process_input(request)

    return rsp

  • bs = Director.create_python_business_service('BS') - Create a Python business service.
    • Must be created outside the route definition to prevent multiple instances of the business service.
  • @app.get("/interop") - Define a GET route for the /interop endpoint.
  • @app.post("/interop") - Define a POST route for the /interop endpoint.
  • ...
  • def interop(request: Request): - Define the route handler.
  • rsp = bs.on_process_input(request) - Call the on_process_input method of the business service.
  • return rsp - Return the response.

/posts endpoint

############################
# CRUD operations posts    #
############################

@app.get("/posts")
def get_posts():
    with Session(engine) as session:
        posts = session.exec(select(Post)).all()
        return posts
    
@app.get("/posts/{post_id}")
def get_post(post_id: int):
    with Session(engine) as session:
        post = session.get(Post, post_id)
        return post
    
@app.post("/posts")
def create_post(post: Post):
    with Session(engine) as session:
        session.add(post)
        session.commit()
        return post

This endpoint is used to perform CRUD operations on the Post object.

Note much to say here, just the definition of the routes to get all posts, get a post by id, and create a post.

Everything is done using the sqlmodel ORM.

/comments endpoint

############################
# CRUD operations comments #
############################


@app.get("/comments")
def get_comments():
    with Session(engine) as session:
        comments = session.exec(select(Comment)).all()
        return comments
    
@app.get("/comments/{comment_id}")
def get_comment(comment_id: int):
    with Session(engine) as session:
        comment = session.get(Comment, comment_id)
        return comment
    
@app.post("/comments")
def create_comment(comment: Comment):
    with Session(engine) as session:
        session.add(comment)
        session.commit()
        return comment

This endpoint is used to perform CRUD operations on the Comment object.

Note much to say here, just the definition of the routes to get all comments, get a comment by id, and create a comment.

Everything is done using the sqlmodel ORM.

Troubleshooting

How to run the FastAPI application in a standalone mode

You can always run a standalone Flask application with the following command:

python3 /irisdev/app/community/app.py

NB : You must be inside of the container to run this command.

docker exec -it iris-fastapi-template-iris-1 bash

Restart the application in IRIS

Be in DEBUG mode make multiple calls to the application, and the changes will be reflected in the application.

How to access the IRIS Management Portal

You can access the IRIS Management Portal by going to http://localhost:53795/csp/sys/UtilHome.csp.

Run this template locally

For this you need to have IRIS installed on your machine.

Next you need to create a namespace named IRISAPP.

Install the requirements.

Install IoP :

#init iop
iop --init

# load production
iop -m /irisdev/app/community/interop/settings.py

# start production
iop --start Python.Production

Configure the application in the Security portal.

3
0 528
Question Oliver Wilms · Oct 12, 2024

What is the reason for

RUN apt-get update && apt-get install -y \
    git \
    nano \
    python3-opencv \
    sudo && \
    /bin/echo -e ${ISC_PACKAGE_MGRUSER}\\tALL=\(ALL\)\\tNOPASSWD: ALL >> /etc/sudoers && \
    sudo -u ${ISC_PACKAGE_MGRUSER} sudo echo enabled passwordless sudo-ing for ${ISC_PACKAGE_MGRUSER}
 

I think I get error because I do not have sudo privilege in the environment where I use podman to build the image

podman build --tag oliver3 .

I cloned iris-pero-ocr repo, added two large files into misc location, and I tried to build image. I see this:

0
0 176
Article Nicky Zhu · Oct 10, 2024 9m read

This demo program is used to show how a custom FHIR profile can be employed to validate data compliance. The custom FHIR implementation guide was developed based on FHIR Version R4, and in this example implements the Organization resource extension to validating data compliance.

Installation

  1. Download the project via Git clone.
  2. Execute docker-compose up -d to build and start the container, the initial execution will download required container images and executing the script will take another 5 to 10 minutes (depending on the machine). InterSystems IRIS for Health image will be built, then FHIR server will be installed, and the custom FHIR specification will be imported so that it can be used to validate the data.
  3. Import the test case files from TestCases in Postman to see how the various FHIR constraints are validated
  4. After the container is started, you can view the contents of the Custom IG.

Code Structure

FHIRValidation
├─ ExampleIG                        
│  ├─ ig.ini
│  ├─ input
│  │  ├─ fsh
│  │  │  ├─ alias.fsh
│  │  │  ├─ codesystems.fsh
│  │  │  ├─ organization.fsh
│  │  │  └─ valuesets.fsh
│  │  └─ pagecontent
│  │     └─ index.md
│  └─ sushi-config.yaml
├─ README.md
├─ README_zh.md
├─ TestCases
│  └─ FHIR Profile-based Validation  testcases.postman_collection.json
├─ docker-compose.yml
└─ image-iris
   ├─ Dockerfile
   └─ src
      ├─ FullIG
      ├─ IGPackages
      │  ├─ hl7.fhir.uv.extensions.r4#5.1.0.tgz
      │  ├─ hl7.terminology.r4#6.0.2.tgz
      │  └─ package.tgz
      └─ init
         └─ init.sh

ExampleIG

All files in this subdirectory are SUSHI source codes of the customized FHIR specification.

TestCases

This subdirectory holds test case scripts based on the FHIR REST API, which need to be imported into Postman.

image-iris

This subdirectory holds the files required for InterSystems IRIS for Health image: └─ src ├─ FullIG This directory stores the custom FHIR IG generated by SUSHI ├─ IGPackages This directory holds the package files for custom FHIR IGs └─ init This directory holds the IRIS Docker image initialization scripts

FHIR package introduction

The HL7 organization recommends the use of implementation guides (Implementation Guild) to explain how to use the FHIR specification. In addition to instructions for developers to read (e.g., html), implementation guides typically include artifacts that are directly machine-readable and applicable and can be used to drive tasks such as code generation and data validation.
The FHIR Implementation Guide uses the NPM Package specification to manage dependencies. All StructureDefinition, ValueSet, and other resources covered by the guide are packaged together in a single package that can be used by FHIR Server to read the specification, generate client code, or perform data quality checks.
The implementation guide generated by the SUSHI tool contains several package files. In this example, image-iris/src/IGPackages/package.tgz is the generated package, which can be directly imported by IRIS FHIR Server. It should be noted that in addition to the core resource packages (e.g., hl7.fhir.r4.core), the complete FHIR specification needs to refer to additional resource packages such as terminology, extensions, and so on.
The current documentation of the FHIR specification referencing mechanism is not yet complete. For example, based on the R4 version of the FHIR specification in addition to referencing hl7.fhir.r4.core, it also needs to reference [hl7.fhir.uv.extensions.r4#5.1.0](https://simplifier.net/packages/hl7.fhir.uv.extensions.r4/ 5.1.0) and hl7.terminology.r4#6.0.2, these references are documented in the R5 versionbut not declared in the R4 version, so the developer needs to add them during the development process.
In this case these packages have been downloaded in the image-iris/src/IGPackages folder and will be loaded as dependencies before customizing the FHIR implementation guide.

FHIR validation introduction

See the Validating Resources section of the FHIR specification. The FHIR specification has been designed with data quality checking mechanisms for a range of mechanisms including data structures, attribute bases, value fields, code bindings, and constraints, etc. The HL7 organization in the FHIR specification does not mandate what intensity of quality control to follow, but recommends that the principle of leniency be applied to FHIR data.
For FHIR repositories that hold FHIR resources, guaranteeing the data quality of FHIR resources is a prerequisite for making the healthcare industry valuable and guaranteeing the safety of healthcare practices. Therefore, when building a data sharing and exchange scheme based on FHIR repositories, even if data that does not meet data quality requirements has to be saved, it should be calibrated to mark non-conformities and promote data governance activities to safeguard healthcare security and the interests of data consumers.
Of the multiple data validation methods indicated by the FHIR specification, FHIR Validator and FHIR Operations provide the most comprehensive coverage of data quality validation.
This example will use the $validate operation provided by InterSystems IRIS for Health to validate FHIR data that has not yet been saved via the profile parameter. Users can also modify the test case to construct an HTTP POST parameter to validate the stock FHIR resource.
It should also be noted that the $validate operation, if called correctly, will return the validation result via Http 200, and if there are any non-conformities, an error message will be wrapped in the returned OperationOutcome resource instead of identifying the error via the Http code.

Extensions to FHIR R4

The following extensions were made to the Organization resource based on FHIR R4:

1. Modify the binding strength of language

Change the binding strength of the organization's primary language to required

2. Active field cardinality changed from 0...1 to 1...1

This makes the status of active field a required field, with one and only one element

3. Name field cardinality changed from 0..1 to 1..1

The name of the organization becomes a required field with one and only one element. For reference, hospitals in China may have more than one name in addition to the hospital name if they have licenses as an Emergency Center, an Chest Pain Center, and so on. However, it is noted that these licenses usually identify the capacity of the services provided by the healthcare institution rather than the legal name it has in the organization registration system, and the life cycle of such licenses does not coincide with the life cycle of the healthcare institution itself. Therefore, the name obtained from the license is appropriately considered to be the service capability of the healthcare organization rather than the unique name of the organization. In FHIR, the name derived from the service capability can be provided through the resource HealthcareService, which can be more appropriately used to express the above concept by establishing a many-to-one referencing relationship with the Organization resource.

4. Increase in the type of organization of medical institutions

According to the Chinese national standard GB/T 20091-2021 organization types, CodeSystem organizationtype-code-system and ValueSet organizationtype-vs are added respectively, and the extension mdm-organizationTypeExtension is added to the Organization resource through Extension. Extension mdm-organizationTypeExtension is added to the Organization resource so that the resource can be used to represent the organization type that identifies Chinese organization types.
The extension is implemented by slicing the Extension with a cardinality of 1..1 so that the Healthcare Organization resource must have an organization type element.

5. Constraints on healthcare organization identification numbers

The FHIR base standard does not include the type of the unified social credit code for Chinese organizations, for this reason the CodeSystem cs-identifierType-code-system is added and the Identifier is sliced according to its type, so that it must be able to express the social credit code. And the format of the social credit code follows the following constraints:

  1. identifier.use must take the value official, i.e. official/official use
  2. identifier.type MUST follow cs-identifierType-code-system, system MUST be the uri of the codesystem, and code MUST be “USCC”.
  3. identifier.value must follow the custom constraint uscc-length-18, the field must be 18 digits long, of which the first 17 digits must be numeric and the last 1 digit must be numeric or alpha

Test Case List

1. Without profile - All OK

The resource's corresponding profile is not declared, so FHIR Server will not validate the values of the attributes in the resource and will only return All OK.

2. Unknow field

An undefined attribute isNational was added to the resource, so the validation engine returned an Unrecognized element error.

3. Wrong cardinality - less

In this IG, the cardinality of the Organization resource name attribute was modified to 1..1, which means that there should be and only one organization name. The name is not filled in this test case and hence the data validation fails. In addition, it can be observed that Identifier.type has been extended to include the Uniform Social Credit Code as an identifier type, which is not included in the FHIR R4 specification, but the strength of the code binding for this field is only EXAMPLE, which does not force constraints. Therefore, the validation engine returns the information level value field code non-conformance information without reporting an error.

4. Binding strength

In this IG, the code binding strength of the organization's language attribute is changed to required, then the field value field must conform to http://hl7.org/fhir/ValueSet/languages, therefore, when the field takes the value of 'wrong language', it is not in the required value value, which will result in an error level error

5. Wrong value

In this IG, the value field for the organization type comes from organizationtype-code-system, so when the value of code in the extension element of type mdm-organizationTypeExtension, which has a value of “999 ”, which is not in the value field, will result in an error-level error

6. Failing invariant

In this IG, the social credit code of an organization must follow the custom constraint uscc-length-18 (the field must be 18 digits long, where the first 17 digits must be numeric, and the last 1 digit must be numeric or alphabetic), and therefore violating this constraint when the last digit is the character “%” will result in an error

7. Failing profile

A single profile for a resource definition contains multiple constraints, so all issues that do not satisfy the profile will be detected during validation, such as the following issues in this example:

  1. wrong language code
  2. wrong organization type
  3. missing name field
0
1 325
Question Reuben Formosa · Jul 15, 2024

We have installed IRIS on a separate server that we access remotely and copied all code and data to it so we can test IRIS before we do the move.We develop directly on the server.We Use VsCode to code but sometimes we might need to go to cache studio for some tasks.

We were interested in git for Shared Development Environments, we have installed it on a server with IRIS 2021 and configured it by following the instructions and videos of InterSystems summits we found online. We initialised a local repository on the server, added some files to start testing branches.

4
0 304