#InterSystems IRIS for Health

0 Abonnés · 382 Publications

InterSystems IRIS for Health™ est la première et la seule plateforme de données au monde conçue spécifiquement pour le développement rapide d'applications de santé afin de gérer les données les plus critiques du monde. Elle comprend de puissantes fonctionnalités prêtes à l'emploi : traitement et analyse des transactions, modèle de données de santé extensible, développement de solutions basé sur FHIR, prise en charge des normes d'interopérabilité de santé, etc. Toutes ces fonctionnalités permettent aux développeurs de créer rapidement de la valeur et des applications révolutionnaires. En savoir plus.

Question Cyril Grosjean · Déc 12, 2023

Bonjour,

Nous avons voulu mettre en pré-production un flux 100% python, cependant lorsqu'on a lancé la commande iop pour tester avec l'utilisateur qui va déployer via une CI/CD le code, voici ce qu'on obtient:

ssh.gitlab est notre utilisateur, nous sommes sur un serveur Windows 10 et ssh.gitlab est admin.

Y a-t-il des modifications à faire sur le portail d'IRIS ? (Un utilisateur est créé pour la CI/CD suite à ce post)

Merci d'avance !

Cordialement,

Cyril

2
0 65
Question Cyril Grosjean · Déc 12, 2023

Cette question est apparue à l'origine dans les commentaires du post : Problème avec le FTP OutboundAdapter sur IRIS PEX
 

Parfait ça marche je te remercie, est-ce que c'est normal de devoir écrire chunk par chunk pour le stream ? J'avais essayé mais avec un StreamContainer et en écrivant normalement, donc pas par chunk ça ne me marchait pas.

1
0 80
Question Cyril Grosjean · Déc 11, 2023

Bonjour,

En souhaitant créer une production qui récupère un fichier provenant d'une API et qui envoie ce fichier sur un serveur SFTP, j'ai rencontré un problème avec la librairie de Guillaume Rongier.

Je reçois des bytes depuis une opération jusque là aucun problème, j'ai lié un SFTP à mon opération, les credentials sont les bons, l'adresse ip, le port, le dossier dans lequel déposer le fichier également. Cependant j'ai cette erreur:

ERROR <Ens>ErrException: <METHOD DOES NOT EXIST>PutStream+11^EnsLib.FTP.OutboundAdapter.1 *Rewind,%SYS.Python -- logged as '-'
number - @''

Voici mon code:

1
0 76
InterSystems officiel Sylvain Guilbaud · Déc 5, 2023

Nous sommes ravis d'annoncer une nouvelle partie de la documentation InterSystems qui facilite la mise à niveau de la plateforme de données InterSystems IRIS®, InterSystems IRIS® for Health™ ou HealthShare® Health Connect. La liste de contrôle de l'impact de la mise à niveau sur https://docs.intersystems.com/upgrade vous montre tous les éléments que vous devez prendre en compte – et uniquement les éléments que vous devez prendre en compte – lors d'une mise à niveau entre deux versions. Cela reprend tout le contenu de notre « Historique d'incompatibilité » et ajoute des filtres pratiques, des

0
0 62
Question Cyril Grosjean · Déc 4, 2023

Bonjour,

Je suis toujours en train de préparer le terrain pour inclure la librairie de Guillaume Rongier pour utiliser InterSystems entièrement via Python. Cependant notre environnement local tourne sur Docker avec l'OS linux, jusque là nous n'avons aucun problème avec la librairie. Le problème arrive lorsque l'on passe sur la pré-production où iris est installé directement sur Windows. J'installe les librairies requises avec le package pip et un fichier requirements.txt contenant ceci:
 

5
0 92
Question Jean-Charles Cano · Nov 23, 2023

Bonjour,

Je souhaite accéder à la Web Gateway. N'ayant pas fait l'installation d'Iris sur la machine je ne connais pas le compte autorisé à y accéder.

J'ai donc ajouté les propriétés username et password dans le fichier CSP.ini dans la section [SYSTEM] comme indiqué dans cette doc : 

https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cl…

Puis j'ai relancé le server web à l'aide de la commande : do ##class(Config.Startup).RestartWebServer()

Je me suis ensuite rendu sur la page 

http://localhost:52773/csp/bin/Systems/Module.cxw
2
0 106
Article Niels Genne · Nov 24, 2023 4m read

Comment déployer les productions IRIS sereinement et plus rapidement ?

L'objectif des productions d'interopérabilité est de vous permettre de connecter des systèmes afin de transformer et d'acheminer des messages entre eux. Pour connecter des systèmes, vous développez, configurez, déployez et gérez des productions qui intègrent plusieurs solutions.

C’est ce que nous dit la documentation InterSystems sur son site de référence, mais que faut-il réellement faire pour déployer une production ?

On peut composer les productions, selon les usages, pour connecter des systèmes externes à IRIS Data Platform. Il est pour cela nécessaire de créer un environnement propre à chaque production à savoir les composants suivants :

  • un Business service 📨
  • un Business processus (facultatif) 📘
  • une Business opération 💉
  • des schémas de définition de table (.cls; classes) 📅
  • un fichier d’initialisation d’espace de noms (.cpf) 📋

Bien sûr l’importance d’employer les productions pour traiter les messages réside dans le fait de pouvoir tracer chaque message et remonter ainsi la trace des accidents de parcours de chaque événement indésirable.

Et si je vous disais qu’il est possible de déployer vos productions à l’aide de notre framework d’interopérabilité IRIS d’un coup de baguette magique ?🪄

Explications

L’approche mainframe de laquelle provient notre framework permet de déployer à vitesse grand « V » des productions IRIS InterSystems® sans devoir recréer tous les composants à la main.

L’emploi du framework permet d’ajouter une fonctionnalité intéressante autorisant la lecture des données des tables à déployer avec la production : l’ajout d’une API sortante (RestForms2).

Sounds good :)

➡️Les données deviennent ainsi interrogeables et restituables dans un format JSON.

Le framework va générer tous les composants en se basant sur un fichier de spécifications fonctionnelles rempli en accord avec le métier et notre chef de projet (dont le rôle est de veiller à ce que chaque information nécessaire trouve sa place).

Le script agit en deux temps à savoir : la construction du flux ETL et du point de chute des données. 📦🪂

Une fois rempli conformément à ce qui est attendu, le fichier de spécifications fonctionnelles permet de générer dans un premier temps : le fichier de sérialisation des messages (classes de données ; obj.py), le fichier de structure des données dans chaque message (msg.py), le fichier de génération de messages (bs.py) et le fichier d’ingestion des messages dans la base de données correspondante (bo.py); dans un second temps : il sert à créer/supprimer les tables dans la base de données sous forme d’un script SQL comprenant des instructions DDL (Data Definition Language).

De quoi vous faire gagner beaucoup de temps ! ⌚ Le plus beau dans tout cela, c’est que le framework est déployable facilement depuis un container Docker ! 🐳

Intérêts

Toujours pas convaincu(e) ? En quoi utiliser ce framework vous ferait gagner 80% du temps ?⏱️

Et si je vous disais que le code déployé par le framework est validé par l’éditeur InterSystems®, qu’il permet à votre équipe de travailler sur du code uniformisé, que lors de campagnes de maintenance cette possibilité vous incite à être plus efficace en cas de mise à jour de code ou de recherche de bug, qu’il vous permet d’interagir avec vos données à l’aide d’un mécanisme de REST API (issu du dépôt des paquets compatibles InterSystems IRIS toutes versions confondues). Cela fait sens pour vous ? 👌

Qu’entend-on par « le code est validé par l’éditeur » ? ✅ Simplement qu’il respecte les standards Python et ceux de l’éditeur en matière d’architecture, d’appels aux mécanismes internes d’IRIS InterSystems® également qu’il sait s’interfacer avec le langage ObjectScript et vice versa.

La suite

Si cet article fait écho à vos besoins ou si vous êtes simplement curieux de voir comment ce framework pourrait révolutionner votre manière de travailler sous IRIS InterSystems® : rendez vous sur notre site web et/ou demander un accès à notre Discord Server pour discuter avec l’un de nos experts.

Suivez-nous aussi sur LinkedIn profile

Prochainement, nous vous ferons découvrir un cas d’usage du framework en environnement opérationnel 😉 !

0
0 105
Article Benjamin De Boe · Nov 22, 2023 3m read

Nous avons récemment publié un nouveau livre blanc sur l'utilisation de nœuds de reporting (« membres miroir de reporting asynchrone ») dans un environnement miroir. De plus en plus de clients considèrent ce mécanisme comme un moyen simple et rapide de configurer une copie de leurs données de production qui reste à jour, tout en pouvant être utilisée pour des requêtes analytiques ou des charges de travail de reporting lourdes sans impact sur le système source. Lisez le livre blanc ici.

Comme toujours, nous sommes curieux de connaître vos propres commentaires sur la manière dont vous avez utilisé cette option de mise en miroir dans votre organisation et si vous avez des idées sur la façon dont nous pouvons la rendre encore plus productive.

0
0 43
InterSystems officiel Sylvain Guilbaud · Nov 21, 2023

Lorsqu'AMD a publié la norme x86-64 en 1999, ils ne savaient pas qu'ils inventaient ce qui allait devenir de facto l'architecture des processeurs de serveur. Mais les processeurs d'aujourd'hui ne sont pas les mêmes que ceux produits il y a 20 ans : ils disposent d'extensions pour tout, depuis les Advanced Vector Extensions (AVX) jusqu'à la Hardware-Assisted Virtualization (VT-d).

InterSystems souhaite mieux profiter de ces nouvelles extensions dans les prochaines versions d'InterSystems IRIS. Bien que nos compilateurs soient suffisamment intelligents pour créer du code optimisé pour de nombreuses situations, certaines optimisations ne peuvent être activées qu'en supprimant explicitement la prise en charge des processeurs qui ne disposent pas de ce jeu d'instructions. De plus, nous avons de plus en plus de mal à conserver les anciens modèles de processeurs sur lesquels effectuer des tests.

0
0 45
Question Cyril Grosjean · Nov 15, 2023

Bonjour,

Dans le besoin de notre service infrastructure de notre entreprise, j'ai créé une petite API qui fait des requêtes SNMP sur InterSystems afin de visualiser les données intéressantes à récupérer lorsque l'infra mettra en place le monitoring.

Cependant, j'ai un timeout lorsque j'essaye de collecter des informations via un walk. Voici le code du service SNMP de mon API:

7
0 111
Article Guillaume Rongier · Nov 17, 2023 3m read

Rubrique Questions fréquentes (FAQ) d'InterSystems

Pour les routines (*.mac)

Vous pouvez masquer la source en exportant/important uniquement le fichier *.obj généré après la compilation du programme source.

L'exemple d'exécution de la commande spécifie EX1Sample.obj et EX2Sample.obj, qui sont générés par la compilation de EX1Sample.mac et EX2Sample.mac, comme cibles d'exportation et les exporte dans le deuxième fichier argument.

Après avoir changé d'espace de noms, j'utilise le fichier XML exporté pour effectuer l'importation.

0
0 73
Article Irène Mykhailova · Nov 16, 2023 3m read

Introduction

InterSystems souhaite optimiser IRIS pour tirer parti des extensions modernes du jeu d'instructions du processeur. C'est excellent pour les performances du produit, mais comment savoir si votre processeur sera toujours pris en charge pour les nouvelles versions d'IRIS ? Voici comment connaître la famille de microarchitecture de votre processeur ainsi que comment connaître les extensions de jeu d’instructions spécifiques à votre processeur.

0
0 131
Article Iryna Mykhailova · Nov 13, 2023 6m read

Dans l'article précédent, nous avons vu comment récupérer une ressource stockée dans la base de données de notre HIS particulier, nous allons donc voir aujourd'hui comment ajouter de nouveaux dossiers dans notre HIS dont l'origine est une ressource FHIR reçue dans notre système.

Les opérations CRUD avec FHIR

Une des fonctionnalités principales de FHIR est son support pour les opérations CRUD à travers l'API Rest, ce qui implique que tout système qui fonctionne avec FHIR soit capable de supporter les appels HTTP de type GET, POST, PUT et DELETE. Pour notre article d'aujourd'hui, nous allons voir comment nous pouvons gérer un appel POST vers notre endpoint configuré automatiquement lors de l'installation de FHIR Adapter.

Si nous examinons les spécifications FHIR pour les appels de stockage de ressources, nous verrons qu'elles nous informent que l'URL avec laquelle nous ferons l'appel doit suivre le format suivant :

http(s)://server_url/{endpoint}/{Resource}

Dans notre exemple, nous n'utiliserons pas d'appels sécurisés, nous aurons donc une URL comme la suivante :

http://localhost:52774/Adapter/r4/Patient

Pour enregistrer un nouveau patient, nous devons effectuer un appel POST avec les données de notre patient dans le corps de l'appel. Dans notre cas, le format d'appel sera application/fhir+json bien que nous puissions utiliser sans problème le format XML avec application/fhir+xml.

La sauvegarde de notre ressource "Patient"

Nous avons déjà eu l'occasion de voir dans l'article précédent la définition des ressources " Patient ", nous n'allons donc pas la répéter ici, ce que nous allons voir c'est à quoi ressemblerait notre patient test formaté. Voici notre patient :

{
    "resourceType": "Patient",
    "address": [
        {
            "city": "SALAMANCA",
            "line": [
                "CALLE LAMENTOS 2 1ºA"
            ],
            "postalCode": "45021"
        }
    ],
    "birthDate": "1988-01-23",
    "gender": "F",
    "identifier": [
        {
            "type": {
                "text": "NHC"
            },
            "value": "803987"
        },
        {
            "type": {
                "text": "DNI"
            },
            "value": "87654321F"
        }
    ],
    "name": [
        {
            "family": "SANZ LÓPEZ",
            "given": [
                "REBECA"
            ]
        }
    ],
    "telecom": [
        {
            "system": "phone",
            "value": "699850017"
        },
        {
            "system": "email",
            "value": "rebek1988@hotmail.com"
        }
    ]
}

Comme vous pouvez le voir, c'est une Ressource de type "Patient" que nous enverrons depuis notre Postman vers le point de terminaison de notre serveur :

Bien, nous avons reçu 200 et notre patient a été enregistré dans notre HIS, voyons à quoi ressemble notre tableau "Patient" :

Voici Rebeca qui parfaitement enregistrée dans notre HIS avec l'identifiant que nous avons reçu dans la réponse à notre requête POST. Passons maintenant à notre production pour voir le chemin parcouru par notre message FHIR dans IRIS.

Utilisation de la ressource " Patient " dans IRIS

Jusqu'à présent nous avons vu comment envoyer une ressource FHIR au point de terminaison de notre serveur, voyons comment traduire la ressource FHIR reçue et la transformer pour l'insérer dans notre SIH particulier.

Souvenons-nous de la façon dont nous avons configuré notre production :

Notre message parvient via InteropService et est transmis à ProcessFHIRBP, où FromAdapterToHIS est invoqué pour effectuer l'opération correspondante. Voyons maintenant la trace du message reçu.

Ici nous voyons les détails du message reçu, nous avons reçu la requête HTTP POST vers le point de terminaison Patient, nous voyons aussi que QuickStreamId a une valeur, ce qui indique que notre message est contenu dans un Stream.

Que fera notre BO avec ce message ?

elseif (requestData.Request.RequestPath [ "Patient")
  {
    if (requestData.Request.RequestMethod = "POST")
    {
      If requestData.QuickStreamId '= "" {
        Set quickStreamIn = ##class(HS.SDA3.QuickStream).%OpenId(requestData.QuickStreamId,, .tSC)
        
        set dynamicPatient = ##class(%DynamicAbstractObject).%FromJSON(quickStreamIn)

        set sc = ..InsertPatient(dynamicPatient, .response)
      }      
    }
    elseif (requestData.Request.RequestMethod = "GET")
    {
      set patientId = $Piece(requestData.Request.RequestPath,"/",2)
      set sc = ..GetPatient(patientId, .response)
    }

  }

C'est très simple, nous pouvons rediriger le message vers la méthode appropriée avec les informations disponibles sur la requête reçue, nous vérifions qu'il s'agit d'une requête spécifique de la ressource "Patient" et que la méthode a été POST, nous allons donc récupérer le Stream qui stocke le message et nous allons le transformer en un %DynamicObject, ci-après nous allons le traiter à partir de la méthode InsertPatient, voyons le code de cette méthode :

Method InsertPatient(dynamicPatient As%DynamicAbstractObject, Output patient As Adapter.Message.FHIRResponse) As%Status
{
  Set tSC = $$$OKkill pResp
  set pResp=$$$NULLOREFset sqlInsert="INSERT INTO his.patient (name, lastname, phone, address, city, email, nhc, postal_code, birth_date, dni, gender) values (?,?,?,?,?,?,?,?,?,?,?)"//perform the Insertset tSC = ..Adapter.ExecuteUpdate(.nrows, sqlInsert, dynamicPatient.%Get("name").%Get(0).%Get("given").%Get(0), dynamicPatient.%Get("name").%Get(0).%Get("family"), dynamicPatient.%Get("telecom").%Get(0).value, 
    dynamicPatient.%Get("address").%Get(0).%Get("line").%Get(0), dynamicPatient.%Get("address").%Get(0).%Get("city"), dynamicPatient.%Get("telecom").%Get(1).value, dynamicPatient.%Get("identifier").%Get(1).value, 
    dynamicPatient.%Get("address").%Get(0).%Get("postalCode"), dynamicPatient.%Get("birthDate"), dynamicPatient.%Get("identifier").%Get(2).value, dynamicPatient.%Get("gender"))

  set sql="SELECT id, name, lastname, phone, address, city, email, nhc, postal_code, birth_date, dni, gender FROM his.patient WHERE nhc = ?"//perform the Selectset tSC = ..Adapter.ExecuteQuery(.resultSet, sql, dynamicPatient.%Get("identifier").%Get(1).value)
  
  If resultSet.Next() {
    set personResult = {"id":(resultSet.GetData(1)), "name": (resultSet.GetData(2)), 
        "lastname": (resultSet.GetData(3)), "phone": (resultSet.GetData(4)), 
        "address": (resultSet.GetData(5)), "city": (resultSet.GetData(6)),
        "email": (resultSet.GetData(7)), "nhc": (resultSet.GetData(8)),
        "postalCode": (resultSet.GetData(9)), "birthDate": (resultSet.GetData(10)),
        "dni": (resultSet.GetData(11)), "gender": (resultSet.GetData(12)), "type": ("Patient")}
  } else {
    set personResult = {}
  }
  
  //create the response messagedo patient.Resource.Insert(personResult.%ToJSON())
	
	Return tSC
}

Comme vous pouvez le voir, la première chose que nous faisons est l'insertion dans le tableau "Patient" de notre HIS (nous supposons que quelqu'un s'est assuré au préalable que ce patient n'existe pas). Une fois l'insertion terminée, nous exécutons une commande SELECT sur le même tableau pour obtenir l'identifiant généré pour ce patient et pouvoir le renvoyer à l'application cliente ayant envoyé la requête. Pour compléter le message de réponse, nous pouvons récupérer les champs que nous considérons les plus pertinents.

Une fois les données du patient récupérées, nous retournerons à notre BP qui effectuera les transformations nécessaires pour générer une ressource de type Patient que nous pourrons renvoyer au client.

Vous pouvez consulter la transformation dans l'article précédent.

Une fois la Ressource générée, nous allons la transformer en un Stream à inclure dans notre réponse et à renvoyer à l'application cliente :

Comme vous pouvez le voir, c'est vraiment simple, il nous suffit de récupérer les données de la ressource "Patient" et de les insérer dans le tableau correspondant. Enfin, nous retournerons l'objet enregistré de la même manière que nous l'avons fait avec la requête GET.

Dans le prochain article, nous verrons comment traiter un paquet (Bundle) ou un ensemble de ressources. Nous vous remercions de votre attention !

0
0 51
Question Moussa SAMB · Nov 2, 2023

Bonjour, 

Je cherche à me connecter via OAuth2 sur un serveur outlook.office365.com et récupérer les messages avec IMAP.

J'ai un programme qui fonctionne avec la connexion plain, cependant je n'arrive pas à me connecter avec certains e-mails.

Raison pour la quelle je pense que la connexion plain est désactivé pour ces comptes.

Pour faire le client IMAP je me suis inspiré de ce Post : https://community.intersystems.com/post/implementing-imap-client-inters…

4
0 424
Article Iryna Mykhailova · Nov 6, 2023 11m read

Nous poursuivons notre série d'articles sur l'outil FHIR Adapter (adaptateur FHIR) disponible pour les utilisateurs de HealthShare HealthConnect et d'InterSystems IRIS.

Dans les articles précédents, nous avons présenté la petite application avec laquelle nous avons configuré notre atelier et montré l'architecture déployée dans notre instance IRIS après l'installation de l'adaptateur FHIR Adapter. Dans l'article d'aujourd'hui, nous allons voir un exemple de comment nous pouvons effectuer une des opérations CRUD (Créer - Lire - Mettre à jour - Supprimer) les plus courantes, l'opération de lecture, et nous allons le faire en récupérant une Ressource.

Qu'est-ce qu'une Ressource ?

Une Ressource dans FHIR correspond à un type d'information clinique pertinente, celle-ci peut être un patient (Patient), une demande à un laboratoire (ServiceRequest) ou un diagnostic (Condition), etc. Chaque ressource définit le type de données la composant, ainsi que les restrictions sur les données et les relations avec d'autres types de ressources. Chaque ressource permet l'extension des informations qu'elle contient, permettant ainsi de couvrir des besoins qui dépassent les 80% de FHIR (couvrir les besoins utilisés par plus des 80% des utilisateurs).

Pour l'exemple de cet article, nous allons utiliser la ressource la plus courante, le Patient. Examinons sa définition :

{
  "resourceType" : "Patient",
  // from Resource: id, meta, implicitRules, and language
  // from DomainResource: text, contained, extension, and modifierExtension
  "identifier" : [{ Identifier }], // An identifier for this patient
  "active" : <boolean>, // Whether this patient's record is in active use
  "name" : [{ HumanName }], // A name associated with the patient
  "telecom" : [{ ContactPoint }], // A contact detail for the individual
  "gender" : "<code>", // male | female | other | unknown
  "birthDate" : "<date>", // The date of birth for the individual
  // deceased[x]: Indicates if the individual is deceased or not. One of these 2:
  "deceasedBoolean" : <boolean>,
  "deceasedDateTime" : "<dateTime>",
  "address" : [{ Address }], // An address for the individual
  "maritalStatus" : { CodeableConcept }, // Marital (civil) status of a patient
  // multipleBirth[x]: Whether patient is part of a multiple birth. One of these 2:
  "multipleBirthBoolean" : <boolean>,
  "multipleBirthInteger" : <integer>,
  "photo" : [{ Attachment }], // Image of the patient
  "contact" : [{ // A contact party (e.g. guardian, partner, friend) for the patient
    "relationship" : [{ CodeableConcept }], // The kind of relationship
    "name" : { HumanName }, // I A name associated with the contact person
    "telecom" : [{ ContactPoint }], // I A contact detail for the person
    "address" : { Address }, // I Address for the contact person
    "gender" : "<code>", // male | female | other | unknown
    "organization" : { Reference(Organization) }, // I Organization that is associated with the contact
    "period" : { Period } // The period during which this contact person or organization is valid to be contacted relating to this patient
  }],
  "communication" : [{ // A language which may be used to communicate with the patient about his or her health
    "language" : { CodeableConcept }, // R!  The language which can be used to communicate with the patient about his or her health
    "preferred" : <boolean> // Language preference indicator
  }],
  "generalPractitioner" : [{ Reference(Organization|Practitioner|
   PractitionerRole) }], // Patient's nominated primary care provider
  "managingOrganization" : { Reference(Organization) }, // Organization that is the custodian of the patient record
  "link" : [{ // Link to a Patient or RelatedPerson resource that concerns the same actual individual
    "other" : { Reference(Patient|RelatedPerson) }, // R!  The other patient or related person resource that the link refers to
    "type" : "<code>" // R!  replaced-by | replaces | refer | seealso
  }]
}

Comme vous pouvez le constater,pratiquement tous les besoins d'information administrative d'un patient sont ainsi couverts.

Retrouver un patient de notre HIS

Si vous vous souvenez des articles précédents, nous avons déployé une base de données PostgreSQL reproduisant la base de données d'un système HIS. Jetons un coup d'œil aux exemples de tableaux que nous avons dans notre HIS particulier.

Il n'y en a pas beaucoup, mais cela suffira pour notre exemple. Examinons notre tableau patient de manière un peu plus détaillée.

Voici nos 3 exemples de patients, et comme vous voyez, chacun a un identifiant unique (ID) ainsi qu'une série de données administratives pertinentes pour l'organisme de santé. Notre premier objectif sera d'obtenir la ressource FHIR pour l'un de nos patients.

Consultation du patient

Comment pouvons-nous demander des données de patient à notre serveur ? Selon la spécification de mise en œuvre faite par FHIR, nous devons effectuer un GET via REST vers une URL avec l'adresse de notre serveur, le nom de la ressource et l'identifiant. Nous devons faire l'appel suivant :

http://SERVER_PATH/Patient/{id}

Dans notre exemple, nous allons effectuer une recherche de Juan López Hurtado, avec son identifiant = 1, et nous devons donc invoquer l'URL suivante :

http://localhost:52774/Adapter/r4/Patient/1

Pour les tests, nous utiliserons Postman comme client. Et voici la réponse du serveur :

{
    "resourceType": "Patient",
    "address": [
        {
            "city": "TERUEL",
            "line": [
                "CALLE SUSPIROS 39 2ºA"
            ],
            "postalCode": "98345"
        }
    ],
    "birthDate": "1966-11-23",
    "gender": "M",
    "id": "1",
    "identifier": [
        {
            "type": {
                "text": "ID"
            },
            "value": "1"
        },
        {
            "type": {
                "text": "NHC"
            },
            "value": "588392"
        },
        {
            "type": {
                "text": "DNI"
            },
            "value": "12345678X"
        }
    ],
    "name": [
        {
            "family": "LÓPEZ HURTADO",
            "given": [
                "JUAN"
            ]
        }
    ],
    "telecom": [
        {
            "system": "phone",
            "value": "844324239"
        },
        {
            "system": "email",
            "value": "juanitomaravilla@terra.es"
        }
    ]
}

Analysons ensuite le chemin parcouru par notre demande au sein de notre production :

Voici le chemin :

  1. Réception de la demande par notre service d'interopérabilité BS InteropService.
  2. Transmission de la demande à la BP que nous avons configuré comme destination de notre BS où l'identifiant du patient de l'appel reçu sera récupéré.
  3. Une requête de notre BO FromAdapterToHIS vers notre base de données HIS.
  4. Transmission des données du patient à notre BP et leur transformation en une ressource FHIR Patient.
  5. Transmission de la réponse à la BS.

Examinons le type de message que nous recevons dans notre BP ProcessFHIRBP :

Examinons trois attributs qui seront essentiels pour identifier le type d'opération demandé par le client :

  • Request.RequestMethod: cet attribut nous indique le type d'opération que nous allons effectuer. Dans cet exemple, pour rechercher un patient, nous utiliserons un GET.
  • Request.RequestPath: cet attribut contient le chemin de la demande qui est arrivée à notre serveur, cet attribut indiquera la ressource sur laquelle nous travaillerons et dans ce cas il inclura l'identifiant spécifique pour sa récupération.
  • Quick.StreamId: L'adaptateur FHIR Adapter transformera chaque message FHIR reçu en un flux et lui attribuera un identifiant qui sera sauvegardé dans cet attribut. Pour cet exemple, il n'est pas nécessaire puisque nous effectuons un GET et que nous n'envoyons pas d'objet FHIR.

Poursuivons le parcours de notre message en analysant en profondeur les GLP responsables du traitement.

ProcessFHIRBP:

Nous avons mis en place une BPL dans notre production qui gère la messagerie FHIR reçue depuis notre service métier (Business Service). Voici la manière dont elle est mise en œuvre :

Examinons les opérations que nous effectuerons à chaque étape :

Gestion de l'objet FHIR :

Nous invoquerons le BO FromAdapterToHIS responsable de la connexion à la base de données HIS et de l'interrogation de la base de données.

Method ManageFHIR(requestData As HS.FHIRServer.Interop.Request, response As Adapter.Message.FHIRResponse) As%Status
{
  set sc = $$$OKset response = ##class(Adapter.Message.FHIRResponse).%New()

  if (requestData.Request.RequestPath = "Bundle")
  {
    If requestData.QuickStreamId '= "" {
        Set quickStreamIn = ##class(HS.SDA3.QuickStream).%OpenId(requestData.QuickStreamId,, .tSC)
        
        set dynamicBundle = ##class(%DynamicAbstractObject).%FromJSON(quickStreamIn)

        set sc = ..GetBundle(dynamicBundle, .response)
      }
    
  }
  elseif (requestData.Request.RequestPath [ "Patient")
  {
    if (requestData.Request.RequestMethod = "POST")
    {
      If requestData.QuickStreamId '= "" {
        Set quickStreamIn = ##class(HS.SDA3.QuickStream).%OpenId(requestData.QuickStreamId,, .tSC)
        
        set dynamicPatient = ##class(%DynamicAbstractObject).%FromJSON(quickStreamIn)

        set sc = ..InsertPatient(dynamicPatient, .response)
      }      
    }
    elseif (requestData.Request.RequestMethod = "GET")
    {
      set patientId = $Piece(requestData.Request.RequestPath,"/",2)
      set sc = ..GetPatient(patientId, .response)
    }

  }
  Return sc
}

Notre BO va vérifier le message reçu de type HS.FHIRServer.Interop.Request, dans ce cas en mettant un GET et en indiquant le chemin qui correspond à la ressource Patient, la méthode GetPatient sera invoquée, ce que nous verrons plus bas :

Method GetPatient(patientId As%String, Output patient As Adapter.Message.FHIRResponse) As%Status
{
  Set tSC = $$$OKset sql="SELECT id, name, lastname, phone, address, city, email, nhc, postal_code, birth_date, dni, gender FROM his.patient WHERE id = ?"//perform the Selectset tSC = ..Adapter.ExecuteQuery(.resultSet, sql, patientId)
  
  If resultSet.Next() {
     set personResult = {"id":(resultSet.GetData(1)), "name": (resultSet.GetData(2)), 
        "lastname": (resultSet.GetData(3)), "phone": (resultSet.GetData(4)), 
        "address": (resultSet.GetData(5)), "city": (resultSet.GetData(6)),
        "email": (resultSet.GetData(7)), "nhc": (resultSet.GetData(8)),
        "postalCode": (resultSet.GetData(9)), "birthDate": (resultSet.GetData(10)),
        "dni": (resultSet.GetData(11)), "gender": (resultSet.GetData(12)), "type": ("Patient")}

   } else {
     set personResult = {}
   }
  
  //create the response messagedo patient.Resource.Insert(personResult.%ToJSON())
 
	Return tSC
}

Comme vous pouvez le voir, cette méthode ne fait que lancer une requête dans la base de données de notre HIS et récupérer toutes les informations du patient, puis générer un DynamicObject qui est par la suite transformé en une Chaîne et stocké dans une variable de type Adapter.Message.FHIRResponse. Nous avons défini la propriété Ressource comme une liste de chaînes pour pouvoir afficher la réponse plus tard dans la trace. Vous pourriez la définir directement en tant que DynamicObjects, en évitant les transformations ultérieures.

Vérifiction d'un Bundle:

Suite à la réponse de notre BO, nous vérifions s'il s'agit d'un type de Bundle (nous l'expliquerons dans un prochain article) ou s'il s'agit simplement d'une Ressource.

Création d'un objet dynamique:

Nous transformons la réponse de BO en objet dynamique DynamicObject et l'assignons à une variable de contexte temporaire (context.temporalDO). La fonction utilisée pour la transformation est la suivante :

##class(%DynamicAbstractObject).%FromJSON(context.FHIRObject.Resource.GetAt(1))

Transformation FHIR:

Nous lançons une transformation de notre variable temporaire de type DynamicObject vers un objet de classe HS.FHIR.DTL.vR4.Model.Ressource.Patient. Si nous voulons rechercher d'autres types de ressources, il nous faudrait définir des transformations particulières pour chaque type. Voici notre transformation :

Cette transformation nous permet d'avoir un objet interprétable par notre InteropService BS. Le résultat sera stocké dans la variable context.PatientResponse.

Affectation d'une ressource à un flux (Stream):

Nous convertissons la variable context.PatientResponse obtenue dans la transformation FHIR en flux (Stream).

Transformation en QuickStream :

Nous assignons toutes les données que nous devons renvoyer à notre client à la variable response :

set qs=##class(HS.SDA3.QuickStream).%New()
 set response.QuickStreamId = qs.%Id()
 set copyStatus = qs.CopyFrom(context.JSONPayloadStream)
 set response.Response.ResponseFormatCode="JSON"set response.Response.Status=200set response.ContentType="application/fhir+json"set response.CharSet = "utf8"

Dans ce cas, nous renvoyons toujours une réponse 200. Dans un environnement de production, il faudrait vérifier si nous avons correctement récupéré la ressource recherchée, et si ce n'est pas le cas, modifier l'état de la réponse de 200 à 404 correspondant à "Not found". Comme vous pouvez le voir dans ce fragment de code, l'objet HS.FHIR.DTL.vR4.Model.Ressource.Patient
est transformé en un flux (Stream) et stocké en tant que HS.SDA3.QuickStream, en ajoutant l'identifiant dudit objet à l'attribut QuickStreamID, par la suite notre service InteropService retournera correctement le résultat sous la forme d'un JSON.

Conclusion:

Résumons ce qui a été fait :

  1. Nous avons envoyé une requête de type GET pour rechercher une ressource Patient avec un ID défini.
  2. Le service BS InteropService a transmis la requête à la BP configurée.
  3. Cette dernière a invoqué la BO responsable de l'interaction avec la base de données HIS.
  4. La BO configurée a récupéré les données du patient dans la base de données HIS.
  5. La BP a transformé le résultat en un objet compréhensible par la BS créée par le service InteropService par défaut.
  6. La BS a reçu la réponse et l'a transmise au client.

Comme vous pouvez le constater, l'opération est relativement simple, si nous voulons ajouter d'autres types de ressources à notre serveur nous n'aurons qu'à ajouter dans notre BO la requête aux tableaux de notre base de données qui correspondent à la nouvelle ressource à récupérer et à inclure dans notre BP la transformation du résultat de notre BO en un objet de type HS.FHIR.DTL.vR4.Model.Ressource.* qui lui corresponde.

In our next article we will review how we can add new FHIR resources of the Patient type to our HIS database.

Je vous remercie de votre attention !

0
1 71
Article Iryna Mykhailova · Nov 3, 2023 4m read

Nous reprenons notre exemple d'utilisation de l'adaptateur FHIR, dans cet article nous allons voir comment le configurer dans nos instances IRIS et quel est le résultat de l'installation.

Les étapes de configuration du projet sont les mêmes que celles présentées dans la documentation officielle, que vous pouvez consulter directement ici. Bon, au travail !

Installation

Comme vous pouvez le voir dans le projet associé à l'article, nous avons déployé notre instance IRIS dans Docker, de sorte que la majeure partie de la configuration initiale sera effectuée dans le fichier Docker. Rassurez-vous, nous n'entrerons pas dans les détails de la configuration de Docker.

Pour installer notre adaptateur FHIR, nous n'avons que :

  1. Créer un espace de noms (Namespace) appelé ADAPTER dans notre instance IRIS avec la fonctionnalité d'interopérabilité.
  2. Depuis le terminal IRIS, accéder à notre espace de noms et exécuter la commande suivante.
set status = ##class(HS.FHIRServer.Installer).InteropAdapterConfig("/Adapter/r4")

Dans notre cas, nous avons défini que l'URL du point de terminaison IRIS recevant les requêtes REST sera l'adaptateur /Adapter/r4.

Résultat de l'installation

Une fois l'installation de l'adaptateur FHIR terminée, nous pouvons examiner ce qui se passe dans notre instance IRIS. Pour ce faire, nous allons d'abord passer en revue le menu des applications web (Administration du système -> Sécurité -> Applications -> Applications Web).

Comme nous le voyons, une nouvelle application web a été ajoutée à la liste, ce qui indique qu'elle correspond à notre espace de noms adaptateur (ADAPTER Namespace). Accédons-y pour examiner sa configuration plus en détail.

Comme nous le voyons, l'application web créée permet la réception d'appels REST et la classe responsable de la gestion de ces appels est HS.FHIRServer.HC.FHIRInteropAdapter. Un autre détail que nous voyons est l'activation de l'authentification par mot de passe et des appels non authentifiés. Pour notre exemple, nous n'allons rien modifier, mais il serait intéressant que l'authentification JWT soit activée dans un environnement de production.

Passons en revue ce qui se passe dans la production de notre espace de noms.

Dans le cadre de cette installation, deux nouveaux composants ont été créés et déployés, le service métier InteropService et l'opération métier InteropOperation. Pour notre exemple, nous allons utiliser uniquement InteropService qui sera chargé de transmettre le message FHIR reçu, celui-ci sera de la classe HS.FHIRServer.Interop.Request et c'est sur celui-ci que nous travaillerons pour extraire l'information reçue. La réponse reçue par InteropService pour retourner la réponse JSON sera de type HS.FHIRServer.Interop.Response.

Configuration de notre "HIS"

Nous avons mentionné dans l'article précédent que notre but était de simuler l'interopérabilité avec un SIH théorique, pour cela nous avons déployé une instance PostgreSQL dans notre Docker avec une série de tableaux de test. Pour lancer des requêtes sur cette base de données externe, nous avons inclus et configuré la passerelle Java Gateway, de manière à ce que nous puissions effectuer les connexions nécessaires via JDBC. Nous avons également inclus la bibliothèque JAVA que nous utiliserons pour nous connecter à PostgreSQL.

Examinons donc les éléments de production responsables de cette connexion.

Nous avons configuré notre JavaGateway pour qu'elle pointe vers la machine virtuelle Java déployée dans notre Docker :

L'opération métier FromAdapterToHIS sera en charge des requêtes vers notre PostgreSQL, passons à sa configuration :

Comme nous pouvons le voir, elle utilise EnsLib.SQL.OutboundAdapter comme classe d'adaptateur, ce qui nous permettra de nous connecter directement à la base de données de notre "HIS". La valeur DSN sera la chaîne de connexion à l'instance PostgreSQL déployée dans notre Docker.

Pour résumer...

Reprenons ce que nous avons fait dans cet article :

  1. Installation du FHIRAdapter dans notre espace de noms et vérification de la présence d'un point de terminaison vers lequel les messages FHIR peuvent être envoyés.
  2. Vérification des composants créés par des défauts dans la production de notre espace de noms (InteropService et InteropOperation).
  3. Création des composants nécessaires pour communiquer avec notre base de données "HIS".

En suivant ces étapes, nous disposons de tous les éléments nécessaires pour commencer à recevoir des messages FHIR au format JSON. Dans le prochain article, nous créerons le processus métier responsable du traitement des messages reçus et nous implémenterons les différentes fonctionnalités que nous devrons consulter et écrire sur notre base de données PostgreSQL.

Je vous remercie de votre attention !

0
0 64
InterSystems officiel Adeline Icard · Nov 1, 2023

InterSystems mettra fin à la prise en charge de l'utilisation du système de fichiers VxFS avec InterSystems IRIS et le qualifiera de obsolète à compter de la sortie d'InterSystems IRIS 2023.3. InterSystems continuera à prendre en charge tous les clients existants utilisant la technologie, mais elle n'est plus recommandée pour les nouveaux déploiements.

VxFS n'était pris en charge que sur SUSE Linux. Les clients concernés sont encouragés à migrer vers XFS ou un autre système de fichiers pris en charge.

0
0 53
Annonce Sylvain Guilbaud · Oct 26, 2023

Nous sommes ravis d'annoncer le dernier ajout à notre programme d'accès anticipé (EAP - Early Access Program) : l'outil - the Health Data De-ID.

L'outil désidentifiera les données cliniques structurées conformément au HIPAA Safe Harbor et permettra une réidentification si nécessaire. Il utilise le format canonique SDA d'InterSystems qui est utilisé pour toutes nos transformations standards d'un format à un autre, telles que HL7 en CDA, HL7 en FHIR, etc. Cet outil utilise des transformations XSLT pour de meilleures performances. De fait, il fournit des méthodes d'assistance qui permettent un ajustement plus facile des règles de désidentification prêtes à l'emploi pour lesquelles vous n'avez pas besoin d'être un expert XSLT.

image

Health Data De-ID fonctionne sur n'importe quel produit InterSystems, d'InterSystems IRIS for Health à Health Connect en passant par Unified Care Record.

Vous pouvez rejoindre le programme d'accès anticipé ici - Inscription au programme d'accès anticipé au désidentification des données de santé. Nous avons besoin de vos commentaires, alors n'hésitez pas à nous contacter tout au long du processus ou si vous avez des questions.

0
0 83
Article Adeline Icard · Oct 20, 2023 8m read

Bonjour à toutes et à tous !

 

InterSystems a sponsorisé le FHIR User Day qui a eu lieu lors de la semaine européenne de la e-santé. Et je voudrais partager avec vous mes notes de cet événement. Mais avant ça, j'ai le plaisir à vous infirmer que la journée a été entièrement filmée. Les vidéos des différentes interventions seront transmises dans les semaines à venir. Restez à l'écoute!

Sans perte de temps, voici toute l'info.

0
0 158
Article Sylvain Guilbaud · Oct 19, 2023 6m read

Cet article a été écrit en réponse à un message de la communauté qui demandait si Python pouvait créer des messages HL7 de manière dynamique.

Conditions préalables et configuration

Utilisez un espace de noms compatible avec l'intégration.
Remarque : l'espace de noms USER n'est pas activé pour l'interopérabilité par défaut.
Si nécessaire, créez un nouvel espace de noms interopérable afin d'explorer les fonctionnalités.

# Passage à
ZN "[Espace de nom pour l'interopérabilité]"

# Lancement d'un shell interactif Python :
Exécuter $SYSTEM.Python.Shell()

Début du script

#Chargement des dépendances

import datetime as dt
import uuid

# L'heure actuelle du cache est exprimée au format AAAAMMJJHHMMss.
hl7_datetime_now=dt.datetime.now().strftime('%Y%m%d%H%M%S')

# Création d'un message HL7
hl7=iris.cls("EnsLib.HL7.Message")._New()

# Définition du type de document
# 2.5.1:ORU_R01 - Envoi non sollicité d'un message d'observation
hl7.PokeDocType("2.5.1:ORU_R01")

Les structures de ces messages sont accessibles à partir du portail de gestion

 

Création du MSH (segment d'en-tête de message)

// Segment MSH
hl7.SetValueAt('OutApp','MSH:SendingApplication')
hl7.SetValueAt('OutFac','MSH:SendingFacility')
hl7.SetValueAt('InApp','MSH:ReceivingApplication')
hl7.SetValueAt('InFac','MSH:ReceivingFacility')
hl7.SetValueAt(hl7_datetime_now,'MSH:DateTimeOfMessage')
hl7.SetValueAt('ORU','MSH:MessageType.MessageCode')
hl7.SetValueAt('R01','MSH:MessageType.TriggerEvent')
hl7.SetValueAt('ORU_R01','MSH:MessageType.MessageStructure')
hl7.SetValueAt(str(uuid.uuid4()),'MSH:MessageControlID')
hl7.SetValueAt('2.5.1','MSH:ProcessingID')

Fonction d'échappement et d'annulation ("Escape" ou "Unescape")

Les documents HL7 sont structurés en segments
Chaque segment est divisé en Éléments par un délimiteur ("|") et en Éléments répétitifs ("~").
Un élément comporte un délimiteur "^" et un sous-délimiteur "&".
Lorsque le délimiteur apparaît en tant que contenu textuel, il est échappé par "" et d'autres caractères qui remplacent les délimiteurs.
Le caractère "&" est souvent problématique, car il peut apparaître fréquemment dans les messages et entraîner une troncature lors de la lecture par le système de réception.
Un segment HL7 dispose d'une méthode intégrée pour échapper le contenu en fonction des délimiteurs choisis pour un message.
Un modèle commun est d'obtenir une référence au premier segment

# Exécution de cette ligne; la variable "msh" sera utilisée ultérieurement.
> msh=hl7.GetSegmentAt(1)

Ensuite, on peut appeler Escape (échappement) par exemple avec la chaîne brute de Python :

> msh.Escape(r"a&b~c^d")
'a\\T\\b\\R\\c\\S\\d'

Le segment peut également être utilisé pour annuler la fonction Unescape, par exemple :

> msh.Unescape('a\\T\\b\\R\\c\\S\\d')
'a&b~c^d'

Ainsi, lors de la définition d'un contenu qui devrait comporter des caractères de délimitation, ces caractères peuvent être échappés pour le message

hl7.SetValueAt(msh.Escape(r"a&b~c^d"),'MSH:ReceivingFacility')

Lors de la récupération du contenu, il est possible d'annuler l'echappement

msh.Unescape(hl7.GetValueAt('MSH:ReceivingFacility'))

Pour cet exemple, il suffit de rétablir la valeur précédente de msh.

hl7.SetValueAt('InFac','MSH:ReceivingFacility')

Pour la revérification du segment existant :

> hl7.GetValueAt('MSH')
'MSH|^~\\&|OutApp|OutFac|InApp|InFac|20230610100040||ORU^R01^ORU_R01|2dfab415-51aa-4c75-a7e7-a63aedfb53cc|2.5.1'

Segment démographique (PID)

# Préfixe du chemin virtuel pour l'identifiant PID
seg='PIDgrpgrp(1).PIDgrp.PID:'
hl7.SetValueAt('1',seg+'SetIDPID')
hl7.SetValueAt('12345',seg+'PatientIdentifierList(1).IDNumber')
hl7.SetValueAt('MRN',seg+'PatientIdentifierList(1).AssigningAuthority')
hl7.SetValueAt('MR',seg+'PatientIdentifierList(1).IdentifierTypeCode')
hl7.SetValueAt(msh.Escape('Redfield'), seg+'PatientName(1).FamilyName')
hl7.SetValueAt(msh.Escape('Claire') ,seg+'PatientName(1).GivenName')
hl7.SetValueAt('19640101',seg+'DateTimeofBirth')
hl7.SetValueAt('F',seg+'AdministrativeSex')
hl7.SetValueAt(msh.Escape('Umbrella Corporation') ,seg+'PatientAddress.StreetAddress')
hl7.SetValueAt(msh.Escape('Umbrella Drive') ,seg+'PatientAddress.OtherDesignation')
hl7.SetValueAt(msh.Escape('Raccoon City') ,seg+'PatientAddress.City')
hl7.SetValueAt(msh.Escape('MO') ,seg+'PatientAddress.StateorProvince')
hl7.SetValueAt(msh.Escape('63117') ,seg+'PatientAddress.ZiporPostalCode')

Revérification du contenu du segment PID

> hl7.GetValueAt(seg[0:-1])
'PID|1||12345^^^MRN^MR||Redfield^Claire||19640101|F|||Umbrella Corporation^Umbrella Drive^Raccoon City^MO^63117'

Segment de contrôle d'ordre

seg='PIDgrpgrp(1).ORCgrp(1).ORC:'
hl7.SetValueAt('RE',seg+'OrderControl')
hl7.SetValueAt('10003681',seg+'PlacerOrderNumber')
hl7.SetValueAt('99001725',seg+'FillerOrderNumber')
hl7.SetValueAt('AG104',seg+'OrderingProvider')
hl7.SetValueAt('L43',seg+'EnterersLocation')

Revérification du contenu des segments ORC (segments de contrôle d'ordre)

> hl7.GetValueAt(seg[0:-1])
'ORC|RE|10003681|99001725|||||||||AG104|L43'

 

Demande d'observation

seg='PIDgrpgrp(1).ORCgrp(1).OBR:'
hl7.SetValueAt('1',seg+'SetIDOBR')
hl7.SetValueAt('10003681',seg+'PlacerOrderNumber')
hl7.SetValueAt('99001725',seg+'FillerOrderNumber')
hl7.SetValueAt('20210428100729',seg+'ResultsRptStatusChngDateTime')
hl7.SetValueAt('F',seg+'ResultStatus')
hl7.SetValueAt('U',seg+'QuantityTiming.Priority')

 

Observation OBX/Résultat

seg='PIDgrpgrp(1).ORCgrp(1).OBXgrp(1).OBX:'
hl7.SetValueAt('1',seg+'SetIDOBX')
hl7.SetValueAt('TX',seg+'ValueType')
hl7.SetValueAt('V8132',seg+'ObservationIdentifier.Identifier')
hl7.SetValueAt(msh.Escape('G-Virus') , seg+'ObservationIdentifier.Identifier')
hl7.SetValueAt(msh.Escape('17.8 log10') ,seg+'ObservationValue')
hl7.SetValueAt(msh.Escape('RNA copies/mL') ,seg+'Units')
hl7.SetValueAt('F',seg+'ObservationResultStatus')
hl7.SetValueAt('20210428100729',seg+'DateTimeoftheObservation')
hl7.SetValueAt('AG001',seg+'ResponsibleObserver.IDNumber')
hl7.SetValueAt('Birkin',seg+'ResponsibleObserver.FamilyName')
hl7.SetValueAt('William',seg+'ResponsibleObserver.GivenName')
hl7.SetValueAt('AG001',seg+'ResponsibleObserver.IDNumber')
hl7.SetValueAt('UXL43',seg+'EquipmentInstanceIdentifier')

 

NTE - Remarques et commentaires

seg='PIDgrpgrp(1).ORCgrp(1).OBXgrp(1).NTE(1):'
hl7.SetValueAt('1',seg+'SetIDNTE')
hl7.SetValueAt(msh.Escape('Expected late onset Hyphema. Contain but do not approach.') ,seg+'Comment')

 

Affichage du message complet sur le terminal

> print(hl7.OutputToString())

MSH|^~\&|OutApp|OutFac|InApp|InFac|20230610141201||ORU^R01^ORU_R01|2dfab415-51aa-4c75-a7e7-a63aedfb53cc|2.5.1
PID|1||12345^^^MRN^MR||Redfield^Claire||19640101|F|||Umbrella Corporation^Umbrella Drive^Raccoon City^MO^63117
ORC|RE|10003681|99001725|||||||||AG104|L43
OBR|1|10003681|99001725|||||||||||||||||||20210428100729|||F||^^^^^U
OBX|1|TX|G-Virus||17.8 log10|RNA copies/mL|||||F|||20210428100729||AG001^Birkin^William||UXL43
NTE|1||Expected late onset Hyphema. Contain but do not approach.

Pièges

Si le contenu d'un élément comporte une valeur telle que "8@%SYS.Python", il est probable que la valeur "string" ou la propriété "string" ait été demandée à la place.

Par exemple, uuid a été enveloppé par "str" dans la structure de MSH.

0
1 122
Annonce Irène Mykhailova · Oct 18, 2023

Salut la Communauté!

Profitez de regarder la nouvelle vidéo sur l’importance de bâtir un système de santé connectée et apprendre les clés de réussite pour faciliter l'échange sécurisé d'informations médicales dans le but d’assurer une meilleure coordination des soins.

📺 Coordination Ville Hôpital : Comment créer un pont entre la Ville et l'Hôpital ?

0
0 63
Question Moussa SAMB · Oct 17, 2023

Bonjour,

Je cherche à  dézipper un fichier zip que je récupère  via HTTP avec ObjectScript.

Je récupère  de ma requête HTTP un  %Stream.GlobalBinary, et via mon BusinessOperation, je crée le fichier Zip.

J'aimerais savoir s'il y a une méthode pour dézipper directement le  %Stream.GlobalBinary et avoir le dossier dézipper  en sortie ?

Ou sinon quelle méthode permet de dézipper un fichier Zip en ObjectScript ?

Merci d'avance pour votre aide

3
0 81
InterSystems officiel Adeline Icard · Oct 17, 2023

InterSystems a pris la décision d'arrêter le développement d'InterSystems Cloud Manager et de le qualifier de obsolète à partir de la version InterSystems IRIS 2023.3. InterSystems continuera à prendre en charge les clients existants utilisant cette technologie, mais elle n'est plus recommandée pour les nouveaux déploiements.

Les clients du cloud qui souhaitent déployer et gérer un déploiement IRIS avec de nombreux systèmes sont encouragés à envisager Kubernetes et InterSystems Kubernetes Operator, qui possède des fonctionnalités très similaires à ICM.

0
0 36
Question Cyril Grosjean · Oct 11, 2023

Bonjour,

J'ai un soucis depuis quelques jours que je n'arrive pas à régler après pas mal de recherche sur le forum communautaire français et anglais, ainsi que la documentation InterSystems. J'ai deux namespaces : "TEST" et "SUPPLY_CHAIN" ainsi qu'une fonction en python identique compilée dans les deux namespaces :

ClassMethod testPython() As%Status [ Language = python ]

{

    print("Ok")

}

Lorsque j'appelle depuis le terminal iris cette fonction comme ceci:

do##class(TEST.maclasse).testPython()


Cela me retourne bien "ok"

7
0 168
Question Jean-Charles Cano · Oct 4, 2023

Bonjour,

Nous voulons créer une CD pour InterSystems. Nous avons créé un script IRIS qui permet de compiler automatiquement les fichiers .cls dans les bons namespaces et pour exécuter ce script, nous faisons la commande: iristerm /console=cn_ap:IRIS .\import.scr'

Cependant, cela va nous ouvrir un terminal IRIS dans une nouvelle fenêtre (GUI). Le problème, c'est que nous passons par un user SSH, en exécutant la commande : 

ssh user@hostname 'E: && iristerm /console=cn_ap:IRIS .\import.scr'
5
0 166