0 Abonnés · 123 Publications

Python est un langage de programmation interprété de haut niveau pour la programmation à usage général. Créé par Guido van Rossum et publié pour la première fois en 1991, Python a une philosophie de conception qui met l'accent sur la lisibilité du code, notamment en utilisant des espaces blancs importants

Site officiel.

Documentation InterSystems sur les liaisons Python.

Article Sylvain Guilbaud · Juil 10, 2023 13m read

Découvrir Django

Django est un framework web conçu pour développer des serveurs et des API, et pour traiter des bases de données de manière rapide, évolutive et sécurisée. Pour ce faire, Django fournit des outils permettant non seulement de créer le squelette du code, mais aussi de le mettre à jour sans souci. Il permet aux développeurs de voir les changements presque en direct, de corriger les erreurs avec l'outil de débogage et de traiter la sécurité avec facilité.

Pour comprendre le fonctionnement de Django, examinons l'image :

0
0 164
Article Guillaume Rongier · Juin 26, 2023 3m read

Introduction

Dans certains des derniers articles, j'ai parlé des types entre IRIS et Python, et il est clair qu'il n'est pas facile d'accéder aux objets d'un côté à l'autre.  

Heureusement, un travail a déjà été fait pour créer SQLAlchemy-iris (suivez le lien pour le voir sur Open Exchange), qui rend tout beaucoup plus facile pour Python d'accéder aux objets d'IRIS, et je vais montrer les starters pour cela.

Merci à @Dmitry Maslennikov !

Installation

Pour l'installer, il suffit d'ouvrir votre terminal avec un accès administrateur et de taper

pip install sqlalchemy-iris

et les pré-requis seront également installés pour vous, si nécessaire.

Utilisation

Maintenant, sur un fichier python, vous pouvez importer le module, vous connecter à la base de données et jouer avec sqlalchemy comme vous le souhaitez. Si vous vous sentez à l'aise, vous pouvez suivre les étapes suivantes :

  • Importez "create_engine" de sqlalchemy et créez le moteur avec la chaîne "iris://username:password@IP:port/namespace". Bien sûr, vous pouvez importer tout le module, mais "create_engine" crée une instance de Engine (sqlalchemy.engine, pour plus d'informations cliquez ici) qui a toutes les sous-classes nécessaires pour ce que je présente ici..
from sqlalchemy import create_engine

engine = create_engine("iris://_SYSTEM:SYS@localhost:1972/SAMPLE")
  • Créez la connexion (sqlalchemy.engine.connection, pour plus d'informations cliquez ici) ainsi vous pourrez travailler avec des transactions, des exécutions simples, etc.
conn = engine.connect()

C'est très bien ! Vous avez maintenant configuré l'accès à votre base de données.

Pour une simple requête SELECT, et pour itérer à travers l'ensemble des résultats, faites ce qui suit (comme d'habitude, en utilisant comme exemple le tableau créé dans cet article):

query = 'SELECT Name, Age  from Sample.PersistentData WHERE Age >=21'
result = conn.exec_driver_sql(query)

Maintenant, le résultat est un CursorResult (sqlalchemy.engine.CursorResult). Vous pouvez vérifier tout ce que vous pouvez faire avec un CursorResult ici, dans la documentation officielle. C'est tout ce que vous avez à faire pour une simple itération :

print("Name, Age")
for row in result:
    print(row[0], ", ", row[1])

 et avec un peu de formatage, vous pouvez avoir un résultat du type suivant :

Maintenant comme vous savez par où commencer, vous pouvez également consulter la documentation officielle pour plus de détails et de possibilités.

PS : vous pouvez également importer "text" de sqlalchemy et exécuter la requête comme suit

result = conn.execute(text(query))

ce qui produira exactement les mêmes résultats.

Conclusion

Vous pouvez également exécuter des DDL et toute autre instruction DML, et il y a un support encore plus important pour travailler avec un un mapping objet-relationnel ORM (_Object Relational Mapping), _mais comme ceci n'est qu'un "démarrage", je n'irai pas plus loin.

Souhaitez-vous plus de tutoriels avec SQLAlchemy ? Peut-être la prochaine fois en utilisant ORM ?
N'hésitez pas à me contacter si vous avez des doutes !

0
1 618
Article Sylvain Guilbaud · Mai 19, 2023 3m read

Apache Superset est une plate-forme moderne d'exploration et de visualisation des données. Superset peut remplacer ou augmenter les outils de business intelligence propriétaires pour de nombreuses équipes. Superset s'intègre bien à une variété de sources de données.

Désormais, il est également possible de l'utiliser avec InterSystems IRIS.

Une démo en ligne est disponible et elle utilise SQL d'IRIS Cloud comme source de données.

Apache Superset fournit un certain nombre d'exemples, qui ont été chargés avec succès dans IRIS sans aucun problème, et affichés sur des tableaux de bord d'exemple.

Le support d'IRIS est implémenté avec un paquetage Python nommé superset-iris, qui peut être installé manuellement dans Superset.

Superset utilise SQLAlchemy comme moteur de base de données, tandis que le paquet superset-iris utilise sqlalchemy-iris.

Lorsque le paquet est installé dans l'environnement Superset, il devient possible de sélectionner InterSystems IRIS dans la liste des bases de données prises en charge.

Pour se connecter à la base de données IRIS, il faut un URI SQLAlchemy sous la forme suivante: iris://{login}:{password}@{hostname}:{port}/{namespace}

La connexion de test doit vérifier la disponibilité du serveur. Cliquez ensuite sur Connecter pour terminer l'ajout de la base de données.

Dans le même formulaire d'édition de base de données, dans l'onglet avancé Advanced Tab, et dans le bloc de sécurité Security, l'option nommée Autoriser le téléchargement de fichiers vers la base de données, qui permettra de télécharger des fichiers CSV et de construire des tableaux avec des données dans IRIS en se basant sur ces derniers.

Le Labo SQL, qui permet d'effectuer des requêtes SQL

Il permet également de collecter et d'afficher des renseignements sur les schémas et les tableaux existants, de prévisualiser ces tableaux et de proposer la construction d'une simple requête SQL avec toutes les colonnes.

Pour l'essayer localement, clonez le dépôt

git clone https://github.com/caretdev/superset-iris.git superset-iris
cd superset-iris

Lancez Superset avec Docker-Compose

docker-compose pull
docker-compose up -d

Lancez Superset avec Docker-Compose Pendant le démarrage, il importe les données d'exemple dans la base de données IRIS, cela prendra un certain temps, pour attendre que ce soit fait, exécutez la commande suivante

docker-compose logs -f superset-init

Lorsque la commande ci-dessus a fini de fonctionner, allez à http://localhost:8088/dashboard/list/. Les panneaux de bord sont disponibles sans autorisation. Pour accéder au Labo SQL, utilisez admin/admin comme login et mot de passe.

Veuillez voter sur le concours

0
0 210
Article Sylvain Guilbaud · Mai 15, 2023 5m read

Aperçu général

En passant d'IRIS objectScript à Python, on s'aperçoit qu'il existe des différences syntaxiques fascinantes.

L'une d'entre elles concerne la manière dont Python renvoie des tuples à partir d'une méthode à décompression automatique.

En fait, il s'agit d'une méthode qui renvoie plusieurs valeurs. Quelle invention géniale :)

out1, out2 = some_function(in1, in2)

ObjectScript a une autre approche avec les paramètres ByRef et Output.

Do ##class(some_class).SomeMethod(.inAndOut1, in2, .out2)

Où:

  • inAndOut1 représente ByRef
  • out2 représente Output

Le point initiale (".") devant le nom de la variable passe ByRef et pour Output.

Le but de cet article est de décrire comment l'utilitaire communautaire PyHelper a été amélioré pour donner une façon pythonique de tirer parti des paramètres ByRef et Output. Il donne accès à %objlasterror et a une approche pour la gestion des types Python None.
 

Exemple ByRef

L'invocation normale pour python intégré serait :

oHL7=iris.cls("EnsLib.HL7.Message")._OpenId('er12345')

Lorsque cette méthode ne parvient pas à s'ouvrir, la variable "oHL7" est une chaîne vide.
Dans la signature de cette méthode, il y a un paramètre d'état qui est disponible pour le script de l'objet qui donne une explication du problème exact.
Par exemple :

  • L'enregistrement peut ne pas exister
  • L'enregistrement ne peut être ouvert dans le mode d'accès simultané exclusif par défaut ("1"), pendant un timeout.
ClassMethod %OpenId(id As %String = "", concurrency As %Integer = -1, ByRef sc As %Status = {$$$OK}) As %ObjectHandle

La méthode TupleOut peut aider à renvoyer la valeur de l'argument sc dans un contexte python.
 

> oHL7,tsc=iris.cls("alwo.PyHelper").TupleOut("EnsLib.HL7.Message","%OpenId",['sc'],1,'er145999', 0)
> oHL7
''
> iris.cls("%SYSTEM.Status").DisplayError(tsc)
ERROR #5809: Objet à charger introuvable, classe 'EnsLib.HL7.Message', ID 'er145999'1
```

La liste ['sc'] contient un seul élément dans ce cas. Elle peut retourner plusieurs valeurs ByRef, et dans l'ordre spécifié. Ce qui est utile pour décompresser automatiquement vers les variables python prévues.

La gestion des paramètres de sortie (Output) en cas d'exemple

Code Python :

> oHL7=iris.cls("EnsLib.HL7.Message")._OpenId('145')
> oHL7.GetValueAt('<%MSH:9.1')
''

La chaîne renvoyée est vide, mais est-ce parce que l'élément est effectivement vide OU parce que quelque chose s'est mal passé ?
Dans le script objet, il existe également un paramètre de sortie d'état (pStatus) auquel il est possible d'accéder pour déterminer cette condition.

Code script objet :

> write oHL7.GetValueAt("<%MSH:9.1",,.pStatus)
''
> Do $System.Status.DisplayError(pStatus)
ERROR <Ens>ErrGeneral: Aucun segment n'a été trouvé lors du trajet '<%MSH'

Avec TupleOut, la fonctionnalité équivalente peut être atteinte en renvoyant et en décompressant à la fois la valeur de retour de la méthode ET le paramètre de sortie d'état.

Code Python :

> hl7=iris.cls("EnsLib.HL7.Message")._OpenId(145,0)
> val, status = iris.cls("alwo.PyHelper").TupleOut(hl7,"GetValueAt",['pStatus'],1,"<&$BadMSH:9.1")
> val==''
True
> iris.cls("%SYSTEM.Status").IsError(status)
1
> iris.cls("%SYSTEM.Status").DisplayError(status)
ERROR <Ens>ErrGeneral: Aucun segment n'a été trouvé lors du trajet '<&$BadMSH'1

Variable spéciale %objlasterror

Dans ObjectScript, il est possible d'accéder à des variables de pourcentage dans le cadre d'une méthode.
Dans certains cas, il est utile de détecter la variable spéciale %objlasterror ou d'y accéder après avoir appelé une API CORE ou une API de tiers.
La méthode TupleOut permet d'accéder à %objlasterror, comme si elle avait été définie en tant que paramètre de sortie, lors de l'invocation de méthodes à partir de Python.

> del _objlasterror

> out,_objlasterror=iris.cls("alwo.PyHelper").TupleOut("EnsLib.HL7.Message","%OpenId",['%objlasterror'],1,'er145999', 0)

> iris.cls("%SYSTEM.Status").DisplayError(_objlasterror)
ERROR #5809: Objet à charger introuvable, classe 'EnsLib.HL7.Message', ID 'er145999'1

Quand "None" n'est pas une chaîne

TupleOut traite les références python "None" comme objectscript "undefined". Cela permet aux paramètres d'être définis par défaut et aux méthodes de se comporter de manière cohérente.
C'est important, par exemple, dans le cas de %Persistent::%OnNew, où la méthode %OnNew n'est pas déclenchée lorsque "None" est fourni comme valeur initiale "initvalue", alors qu'elle serait déclenchée si une chaîne vide était fournie.

En objectscript, l'implémentation pourrait être la suivante :

do oHL7.myMethod("val1",,,"val2")

Notez l'absence de variables entre les virgules.

TupleOut facilite le même comportement avec :

Python:

iris.cls("alwo.PyHelper").TupleOut(oHL7,"myMethod",[],0,"val1",None,None,"val2")

Une autre façon d'envisager la question est d'avoir une implémentation du code d'invocation en une seule ligne, qui se comporte de manière flexible en fonction de la configuration préalable des variables :

Object Script:

set arg1="val1"
kill arg2
kill arg3
set arg4="val2"
do oHL7.myMethod(.arg1, .arg2, .arg3, .arg4)

TupleOut facilite le même comportement avec :

Python:

arg1="val1"
arg2=None
arg3=None
arg4="val2"
iris.cls("alwo.PyHelper").TupleOut(oHL7,"myMethod",[],0,arg1,arg2,arg3,arg4)

Liste et dictionnaires

Lors de la gestion des paramètres d'entrée, de ByRef et Output, TupleOut utilise la correspondance automatique de PyHelper entre: l les listes IRIS et les listes Python
les tableaux IRIS et les tableaux Python
Il prend soin de toujours utiliser des chaînes pour représenter les clés du dictionnaire lorsqu'il passe des tableaux IRIS aux types Dict de Python.

Conclusion

J'espère que cet article contribuera à inspirer de nouvelles idées et discussions sur les idées et suggestions relatives à Python intégré.

J'espère aussi qu'il encouragera à explorer la flexibilité d'IRIS, qui peut facilement s'adapter à de nouveaux défis.

0
0 80
Article Iryna Mykhailova · Mai 10, 2023 6m read

De nombreux facteurs influencent la qualité de vie des gens, et l'un des plus importants est le sommeil. La qualité de notre sommeil détermine notre capacité à fonctionner pendant la journée et affecte notre santé mentale et physique. Un sommeil de bonne qualité est essentiel à notre santé et à notre bien-être général. Par conséquent, en analysant les indicateurs précédant le sommeil, nous pouvons déterminer la qualité de notre sommeil. C'est précisément la fonctionnalité de l'application Sheep's Galaxy.

Sheep's Galaxy est un exemple d'application qui fonctionne avec les technologies IntegratedML et IRIS Cloud SQL d'InterSystems et qui fournit à l'utilisateur un outil d'analyse et d'amélioration de la qualité du sommeil. L'analyse du sommeil prend en compte des facteurs tels que les niveaux de bruit, l'éclairage de la pièce, la durée du sommeil, la consommation de caféine, etc., ce qui permet à l'utilisateur de reconsidérer ses habitudes en matière de sommeil et de créer des conditions optimales pour le sommeil à l'avenir.

Présentation vidéo :

https://www.youtube.com/watch?v=eZ9Wak831x4&ab_channel=MariaGladkova

L'application est basée sur les technologies suivantes :

Partie Frontend :

Pour construire cette application, nous avons utilisé la structure Angular. Il nous a aidé à créer une application simple à page unique. Nous avons utilisé Angular v15, et tous les composants Angular ont été implémentés en tant que standalones pour rationaliser l'expérience de création. Nous n'avons pas utilisé de modules Angular et c'est une bonne pratique pour faire évoluer une application dans le futur si nécessaire. Nous avons également utilisé l'architecture des composants intelligents (Smart Component Architecture) - tous les composants de notre application frontale sont divisés en composants "intelligents" et "muets". Ce concept nous aide à séparer le code de logique métier et le code de présentation entre ces composants. Toute la Logique métier et les demandes adressées au serveur sont conservées dans les services isolés. Pour traiter les données de notre backend, nous utilisons RxJS - une bibliothèque pour composer des programmes asynchrones et basés sur des événements en utilisant des séquences observables. Pour styliser notre application, nous avons utilisé Angular Material - il s'agit d'une bibliothèque de composants d'interface utilisateur que les développeurs peuvent utiliser dans leurs projets Angular pour accélérer le développement d'interfaces utilisateur élégantes et cohérentes. Cette bibliothèque offre un grand nombre de composants d'interface utilisateur réutilisables et magnifiques - nous en avons ajouté quelques-uns comme les cartes, les entrées, les tableaux de données, les sélecteurs de date, et bien d'autres encore. Nous présentons ci-dessous une vue d'ensemble du flux de travail typique d'un utilisateur. Tout d'abord, l'utilisateur passe par le processus d'enregistrement, s'il l'utilise pour la première fois, ou par l'écran d'autorisation.

image

À l'aide de cette application, l'utilisateur entre des renseignements sur son sommeil, tels que son niveau d'activité pendant la journée, le nombre de tasses de café, son confort de sommeil, son niveau de stress et la quantité d'émotions positives, ainsi que la lumière de la pièce et l'heure du coucher.

image

Après chaque saisie de données, l'utilisateur reçoit une notification sur la qualité de son sommeil. Ces données sont ensuite analysées à l'aide d'algorithmes d'apprentissage automatique afin de fournir aux utilisateurs des informations sur leurs habitudes de sommeil.

image

Partie Backend :

Fastapi est un framework python basé sur deux technologies : Pydantic et Starlette. Il a les fonctionnalités suivantes :

  • Il est basé sur des standards ouverts : OpenAPI, schéma JSON, OAuth2 ;
  • Documentation automatique de l'API en swagger ;
  • Implémentation des dépendances ;
  • Il utilise les fonctionnalités de python moderne : annotation de type, asyncio ;
  • Il supporte le code synchrone et asynchrone ;

La structure du projet consiste en des routeurs avec des points d'extrémité, des modèles pour chaque entité et des services de traitement.

Chaque point d'extrémité apparaît dans la documentation atomique à /docs et les champs des points d'extrémité ont une relation avec les modèles de données dans la base de données.

image

Les modèles pydantiques valident automatiquement les données entrantes et sortantes.

image

Le processus de traitement des données des utilisateurs repose sur le protocole, qui vous permet de traiter les données en toute sécurité.

image

Le processus d'interaction avec la base de données est mis en œuvre par la connexion SQL d'IRIS à l'aide de DB API.

image

IRIS Cloud SQL avec IntegratedML :

Tout d'abord, vous devez vous connecter au portail InterSystems Cloud Services. Vous devez ensuite créer un nouveau déploiement IRIS Cloud SQL. Veillez à inclure IntegratedML lorsque vous créez un nouveau déploiement. Lorsqu'il est prêt, vous pouvez obtenir les paramètres de connexion à utiliser dans docker-compose.yml :

image

En ouvrant le menu "IntegratedML Tools", vous avez accès à la création, à l'entraînement et à la validation de votre modèle, ainsi qu'à la possibilité de générer des prédictions sur un champ sélectionné dans le tableau de votre modèle.

image

Dans notre application, nous prédisons la qualité du sommeil sur la base des données de l'utilisateur. Pour ce faire, nous remplissons les champs de la section Prédiction comme suit :

image

Dans la requête générée, le champ prediction contient une prédiction de la qualité du sommeil, le champ probability_quality (probabilité de qualité) contient la probabilité que le sommeil soit " de bonne qualité ".

Liens :

Pour en savoir plus sur notre projet ou l'utiliser comme modèle pour vos futurs travaux : https://openexchange.intersystems.com/package/Sheep%E2%80%99s-Galaxy

Remerciements :

Notre équipe tient à remercier InterSystems et Banksia Global de nous avoir donné l'occasion de travailler avec une technologie de pointe sur des questions importantes.

Développeurs du projet :

0
0 53
Article Guillaume Rongier · Mai 8, 2023 9m read

Bonjour à la communauté,
Dans cet article, je vais présenter mon application iris-mlm-explainer

Cette application web se connecte au service SQL d'InterSystems Cloud pour créer, entraîner, valider et prédire des modèles d'apprentissage automatique, faire des Prédictions et afficher un tableau de bord de tous les modèles entraînés avec une explication du fonctionnement d'un modèle d'apprentissage automatique ajusté. Le tableau de bord fournit des graphiques interactifs sur les performances du modèle, les importances des caractéristiques, les contributions des caractéristiques aux prédictions individuelles, les graphiques de dépendance partielle, les valeurs SHAP (interaction), la visualisation des arbres de décision individuels, etc.

Conditions préalables

  • Vous devez avoir un compte à SQL d'InterSystems Cloud
  • Vous devez avoir <a book="" fr="" getting-started-installing-git="" git-scm.com="" https:="" v2="">Git</a> installé localement.
  • Vous devez avoir <a downloads="" https:="" www.python.org="">Python3</a> installé localement.  

Démarrage

Nous allons suivre les étapes suivantes pour créer et afficher le tableau de bord explicatif d'un modèle :

  • Etape 1 : Fermeture/git pull du référentiel

  • Étape 2 : Connexion au portail de service SQL d'InterSystems Cloud

    • Étape 2.1 : Ajout et gestion de fichiers
    • Étape 2.2 : Importation des fichiers DDL et des fichiers de données
    • Étape 2.3 : Création du modèle
    • Étape 2.4 : Entraînement du modèle
    • Étape 2.5 : Validation du modèle
    • Étape 3 : Activation de l'environnement virtuel Python
  • Étape 4 : Exécution de l'application Web pour la prédiction

  • Étape 5 : Exploration du tableau de bord explicatif

Etape 1 : Fermeture/git Extraction du référentiel

Commençons donc par la première étape

Créer un dossier et Cloner/utiliser le git pull pour le référentiel dans n'importe quel répertoire local.

git clone https://github.com/mwaseem75/iris-mlm-explainer.git

 

Étape 2 : Connexion au portail de service SQL d'InterSystems Cloud

Connectez-vous au portail InterSystems Cloud Service Portal
image

 

 

Sélectionner le déploiement en cours

image

 

Étape 2.1 : Ajout et gestion des fichiers

Cliquez sur Ajout et gestion de fichiers (Add and Manage Files)

image

Le référentiel contient les fichiers USA_Housing_tables_DDL.sql(DDL pour créer les tables), USA_Housing_train.csv(données d'entraînement), et USA_Housing_validate.csv(pour la validation) dans le dossier datasets. Sélectionnez le bouton de téléchargement pour ajouter ces fichiers.

AddFiles

Étape 2.2 : Importation des fichiers DDL et des fichiers de données

Cliquez sur Importation de fichiers, puis sur le bouton radio Instruction(s) DDL ou DML, puis sur le bouton suivant.

ImportDDL

Cliquez sur le bouton radio Intersystems IRIS et cliquez ensuite sur le bouton suivant

IsIRIS

Sélectionnez le fichier USA_Housing_tables_DDL.sql et appuyez sur le bouton d'importation de fichiers.

ImportFileDDL

Cliquez sur le bouton d'importation "Import" dans la boîte de dialogue de confirmation pour créer le tableau.

importconfirm

###importDone

Cliquez sur le bouton des outils de requête SQL (SQL Query tools) pour vérifier que les tableaux sont créés.

###checkTblCreated

Importez des fichiers de données

Cliquez sur Importation de fichiers (Import files), puis sur le bouton radio Données CSV (CSV data), et enfin sur le bouton suivant.

csv1

Selectionnez le fichier USA_Housing_train.csv et cliquez sur le bouton suivant

###csv2

 

Sélectionnez le fichier USA_Housing_train.csv dans la liste déroulante, cochez les cases d'importation de lignes en tant que ligne d'en-tête et de noms de champs dans la ligne d'en-tête correspondant aux noms de colonnes dans le tableau sélectionné, puis cliquez sur Importation de fichiers.

csv3

cliquer sur "importation" dans la boîte de dialogue de confirmation

csv4

Assurez-vous que 4000 lignes sont mises à jour

csv5

Procédez de la même manière pour importer le fichier USA_Housing_validate.csv qui contient 1500 enregistrements.

csv6

Étape 2.3 : Création du modèle

Cliquez sur les outils IntegratedM et sélectionnez Créer un panneau (Create Panel).

Saisissez USAHousingPriceModel dans le champ de nom du modèle (Model Name), sélectionnez le tableau usa_housing_train et Prix dans la liste déroulante des champs à prédire (Field to predict). Cliquez sur le bouton "Création du modèle" pour créer le modèle.

createModel

 

Étape 2.4 : Entraînement du modèle

sélectionnez le panneau d'entraînement (Train Panel), sélectionnez USAHousingPriceModel dans la liste déroulante du modèle à entraîner et saisissez USAHousingPriceModel_t1 dans le champ du nom du modèle d'entraînement (Train Model Name)

###TRAIN1

Le modèle sera entraîné une fois l'état de fonctionnement (Run Status) achevé

###TRAIN2

 

Étape 2.5 : Validation du modèle

Sélectionnez le panneau de validation (Validate Panel), sélectionnez USAHousingPriceModel_t1 dans le modèle entraîné pour valider la liste déroulante, sélectionnez usa_houseing_validate dans le tableau pour valider le modèle à partir de la liste déroulante et cliquez sur le bouton de validation du modèle.

###image

Cliquez sur affichage des mesures de validation pour visualiser les mesures.

showValidation

Cliquez sur l'icône graphique pour afficher le graphique Prédiction VS Réalité.

validationChart

 

Étape 3 : Activation de l'environnement virtuel Python

Le référentiel contient déjà un dossier d'environnement virtuel python (venv) avec toutes les bibliothèques nécessaires.

Il suffit d'activer l'environnement
Pour Unix ou MacOS :

&lt;span class="hljs-meta">$&lt;/span>&lt;span class="bash"> &lt;span class="hljs-built_in">source&lt;/span> venv/bin/activate&lt;/span>

Pour Windows:

venv\scripts\activate

Étape 4 : Définir les paramètres de connexion à InterSystems SQL Cloud

Le référentiel contient le fichier config.py. Il suffit de l'ouvrir et de le paramétrer
image
Mettez les mêmes valeurs que celles utilisées dans InterSystems SQL Cloud
image

 

Étape 4 : Exécution de l'application Web pour la prédiction

Exécutez la commande suivante dans l'environnement virtuel pour démarrer notre application principale

python app.py

###image

Pour démarrer l'application, naviguez jusqu'à http://127.0.0.1:5000/

image

Entrez l'âge de la maison, le nombre de pièces, le nombre de chambres et la population de la région pour obtenir la prédiction

image

Étape 5 : Exploration du tableau de bord explicatif

Enfin, exécutez la commande suivante dans l'environnement virtuel pour démarrer notre application principale

python expdash.py

imageimage
image

Pour démarrer l'application, naviguez jusqu'à http://localhost:8050/image

L'application répertorie tous les modèles entraînés ainsi que notre modèle USAHousingPriceModel. Cliquez sur "aller au panneau de bord" ("go to dashboard") pour voir l'explication du modèle.

Importance des fonctionnalités. Quelles sont les fonctionnalités ayant eu l'impact le plus important ?
image

Mesures quantitatives de la performance des modèles : dans quelle mesure la valeur prédite est-elle proche de la valeur observée ?
image

Prédiction et Comment chaque fonctionnalité a-t-elle contribué à la prédiction ?
image

Ajustez les valeurs des fonctionnalités pour modifier la prédiction
image

Sommaire des SHAPs, Classement des caractéristiques par valeurs de SHAPs
image

Sommaire des interactions, classement des fonctionnalités par valeur d'interaction de SHAP
image

Arbres de décision, affichage des arbres de décision individuels dans la forêt aléatoire
image

Merci

0
0 47
Article Lorenzo Scalese · Avr 21, 2023 5m read

picture

Créer un Chatbot avec IRIS et Python

Dans cet article, je vais montrer comment intégrer la base de données IRIS d'InterSystems avec Python pour servir un Modèle d'apprentissage automatique du traitement du langage naturel (NLP).

Pourquoi Python ?

Avec une large adoption et utilisation dans le monde, Python a une grande communauté et un grand nombre d'accélérateurs et de bibliothèques pour déployer n'importe quel type d'application. Vous pouvez également consulter : https://www.python.org/about/apps/ pour en savoir plus.

Globales Iris

Lorsque j'ai commencé à me familiariser avec les globales (^globals), leur utilisation m'est devenue familière en tant que moyen rapide d'ingérer des données dans un modèle de données prêt à l'emploi. Dans un premier temps, je vais donc utiliser les globales (^globals) pour stocker les données d'entraînement et les conversations pour enregistrer le comportement du chatbot.

Traitement du langage naturel

Le traitement du langage naturel ou NLP (Natural Language Processing) est un domaine de l'IA qui crée la capacité de lire et de comprendre le sens de nos langues pour les machines. Comme vous pouvez l'imaginer, ce n'est pas très simple, mais je vais vous montrer comment faire vos premiers pas dans ce vaste et beau domaine.

Démo - Essayez-le vous-même

J'ai déployé l'application Chatbot en tant que démonstration ici : http://iris-python-suite.eastus.cloudapp.azure.com:8080

Comment ça marche?

Apprentissage automatique

Il est tout d'abord bon de savoir que l'apprentissage automatique a un paradigme différent de celui du développement de logiciels courants. Le point principal qui est difficile à comprendre est le cycle de développement des modèles d'apprentissage automatique.

Alerte aux explications superficielles

Le cycle de développement d'une application standard est le suivant :

Développer le code->Tester (avec des données de développement)->Déployer (en utilisant des données réelles)

L'apprentissage automatique du code en lui-même n'a pas la même valeur. La responsabilité est partagée avec les données ! Et pas n'importe quelles données, mais de vraies données ! Car le code final à exécuter est généré par une fusion entre les concepts de développement et les données utilisées. Un cycle d'application de l'apprentissage automatique devrait donc se dérouler de la manière suivante :

Développer (Former) Modèle+Données réelles->Valider->Déployer le résultat de ceci (un Modèle)

Comment former le modèle?

Il existe de nombreuses techniques pour entraîner les modèles et chaque cas et objectif nécessite une courbe d'apprentissage importante. Dans ce cas, j'utilise la bibliothèque ChatterBot qui encapsule certaines techniques et fournit des méthodes d'entraînement et des données d'entraînement prétraitées pour nous aider à nous concentrer sur les résultats.

Langages de modèles pré-entraînés et modèles personnalisés

Vous pouvez commencer par cela pour avoir un chatbot conversationnel de base. Vous pouvez également créer toutes les données nécessaires à l'entraînement de votre chatbot, et cela peut être parfait pour vos besoins, mais terriblement difficile à réaliser en un temps limité. Dans ce projet, j'utilise en_core_web_sm comme base de conversation et je la fusionne avec des données d'entraînement personnalisées que vous pouvez créer à l'aide d'un formulaire

Architecture de base

image

Qu'ai-je utilisé en Python ?

Dans cet environnement d'application, j'utilise Python 3.7 avec les modules suivants :

  • PyYAML<=5.0.0
  • dash==1.12.0
  • dash-bootstrap-components==0.10.1
  • dash-core-components==1.10.0
  • dash-html-components==1.0.3
  • dash-renderer==1.4.1
  • dash-table==4.7.0
  • plotly==4.7.1
  • numpy==1.18.4
  • networkx==2.4
  • Flask>=1.0.0
  • chatterbot>=1.0.0
  • chatterbot-corpus>=1.2.0
  • SQLAlchemy>=1.2
  • ./nativeAPI_wheel/irisnative-1.0.0-cp34-abi3-linux_x86_64.whl

Structure de projet

Ce projet a une structure simple et facile à comprendre. Dans le dossier principal, nous avons trois sous-dossiers importants :

  • ./app: avec tout le code d'application et la configuration d'installation.
  • ./iris: avec InterSystems IRIS dockerfile préparant à servir l'application.
  • ./data: Pour relier l'hôte à l'environnement du conteneur par un volume

Structure de l'application

À l'intérieur du répertoire ./app, nous trouvons quelques fichiers :

  • chatbot.py : avec la mise en œuvre de l'application web
  • iris_python_suite.py : une classe avec quelques accélérateurs à utiliser avec IRIS Database et Python par l'API native d'IRIS.

Structure de la base de données

Cette application utilise Intersystems IRIS comme référentiel, les globales utilisées sont :

  • ^chatbot.training.data : stocke toutes les données d'entraînement personnalisées sous forme de questions et de réponses.
  • ^chatbot.conversation : stocke toutes les données de conversation.
  • ^chatbot.training.isupdated : contrôle le pipeline de formation.

Produits de mon autre solution

Je n'ai pas créé de rapport pour toutes les conversations mais ce n'est pas un problème, grâce à mon visualiseur de graphes globaux je peux suivre les conversations. image

Exécution de l'application par vous-même

Conditions préalables

  • git
  • docker et docker-compose (et plus de paramètres de mémoire dans docker au moins 4 Go)
  • accès à un terminal dans votre environnement

Étapes

Avec docker-compose, vous pouvez facilement mettre en place un environnement avec toutes les pièces et configurations. Allez dans le dossier iris-python-covid19 et tapez ce texte :

$ docker compose build
$ docker compose up

Durée estimée de mise en place des conteneurs

La première exécution dépendra de votre lien internet pour télécharger les images et les dépendances. Si la durée est supérieure à 15 minutes, il est probable que quelque chose ne fonctionne pas, n'hésitez pas à nous en faire part ici. Après la première exécution, les exécutions suivantes seront plus performantes et prendront moins de 2 minutes.

Si tout est correct

Après un certain temps, vous pouvez ouvrir votre navigateur et aller à l'adresse :

La forme des données d'apprentissage

http://localhost:8050/chatbot-training-data

Le chatbot

http://localhost:8080

Vous devriez consulter le portail d'administration d'IRIS

Pour le moment, j'utilise l'espace de noms USER.

http://localhost:9092
user: _SYSTEM
pass: theansweris42

Si cet article vous est utile ou si vous en aimez le contenu, votez :

Cette application est au concours actuel sur open exchange, vous pouvez voter pour mon application iris-python-suite ici (https://openexchange.intersystems.com/contest/current)

0
0 330
Article Irène Mykhailova · Avr 14, 2023 7m read

This is the third post of a series explaining how to create an end-to-end Machine Learning system.Cet article est le troisième article d'une série expliquant comment créer un système d'apprentissage automatique de bout en bout.

Formation d'un modèle d'apprentissage automatique

Lorsque vous travaillez avec l'apprentissage automatique, il est fréquent d'entendre ce terme : formation. Que signifie la formation dans un pipeline ML ? La formation peut désigner l'ensemble du processus de développement d'un modèle d'apprentissage automatique OU le point spécifique du processus de développement qui utilise les données de formation et aboutit à un modèle d'apprentissage automatique.

imageSource

Les modèles d'apprentissage automatique ne sont donc pas équivalents aux applications communes ?

Le dernier point ressemble à une application normale. Mais le concept est très différent, car dans une application courante, nous n'utilisons pas les données de la même manière. Tout d'abord, pour créer des modèles de ML, vous aurez besoin de données réelles (de production) dans tout le processus de développement. Une autre différence est que si vous utilisez des données différentes, vous aurez un modèle différent... toujours...

Pouvez-vous donner quelques exemples ?

Bien sûr ! Imaginez que vous êtes un développeur de systèmes et que vous créez un système qui contrôle les services dans un PetShop. La façon la plus simple de ce type de système est de créer une base de données pour stocker les données et de créer une application pour interagir avec l'utilisateur. Lorsque vous développez, vous n'avez pas besoin de données réelles. Vous pouvez créer tout le système avec de fausses données. C'est impossible avec les modèles d'apprentissage automatique Ils ont besoin de données réelles au début du développement et elles seront utilisées jusqu'à la fin du développement.
Lorsque vous créez un modèle d'apprentissage automatique, vous fournissez des données à un algorithme et l'algorithme produit une application adaptée à ces données. Si vous utilisez de fausses données, vous obtiendrez un faux modèle.

Qu'en est-il de l'initiative d'organisation de la communauté avec le ML ?

Revenons au sujet principal. Avec tous les articles que je possède, j'ai commencé à explorer un échantillon et j'ai trouvé le suivant :

  1. La plupart des articles n'ont pas été balisés.
  2. Certains articles étaient mal balisés
  3. Certains articles (de l'échantillon) avec des balises étaient balisés correctement.

Comment utiliser ces données ?

J'ai décidé de créer un sac de mots (BoW) à partir des données et d'utiliser les algorithmes de classification les plus courants.
Comment puis-je caractériser ces données ? Ma brève tentative ici :

1ère tentative - Formation avec uniquement des données de publication

Prenez toutes les données avec les balises, séparez 80 % pour la formation et 20 % pour la validation du modèle. Le modèle obtenu n'est pas très performant. La plupart du temps, il prédisait que tous les textes étaient à propos de Caché... (le BoW comportait environ 15000 caractéristiques).

2ème tentative - Formation avec les données de publication uniquement, en supprimant les mots vides.

La plupart des messages contiennent les mêmes mots : hi, for, to, why, in, on, the, do, don't... Le modèle a probablement pris une mauvaise direction pour prédire les balises. J'ai donc supprimé tous les mots vides et vectorisé les données, ce qui a permis d'obtenir environ 9000 caractéristiques. Mais le modèle n'est toujours pas performant.

image

3ème tentative - Entraînement à la description des balises

En regardant le tableau des balises, je vois une courte description de chaque balise. J'ai donc donné la chance à ces petites phrases d'être mon guide sur la bonne façon de baliser comme dans la vie réelle. J'ai obtenu environ 1500 caractéristiques et en les utilisant, le modèle commence à être suffisamment performant pour être montré à d'autres personnes =)

4ème tentative - Entraînement avec description des balises

Après toutes ces recherches, j'ai décidé de tester si IntegratedML pouvait être plus performant que mon modèle. J'ai donc converti le dernier sac de mots en tableau, mais j'ai été confronté à un problème : un sac de mots avec 1500 caractéristiques signifie que j'ai besoin d'un tableau avec 1500 colonnes.
Et en lisant la documentation d'IRIS, la limite de colonnes était de 1000. J'ai donc modifié mon vectoriseur pour n'utiliser que 900 caractéristiques. C'est moins, mais c'est la seule solution que j'ai trouvée.

Les algorithmes de classification

J'ai essayé 3 algorithmes avec des paramètres différents :

  1. SVM
  2. Forêt aléatoire
  3. Régression logistique

La meilleure performance (du moins ces derniers jours) a été la régression logistique dans une stratégie Un contre le Reste (One vs Rest).
One vs Rest considère que vous avez 1 classe à prédire contre plus ou moins 1 classe restante.

Article suivant : Application de bout en bout

J'espère que vous appréciez. Si vous aimez le texte et mon application, votez sur https://openexchange.intersystems.com/contest/current dans mon application iris-ml-suite

Training a Machine Learning Model

When you work with machine learning is common to hear this work: training. Do you what training mean in a ML Pipeline? Training could mean all the development process of a machine learning model OR the specific point in all development process that uses training data and results in a machine learning model.

pictureSource

So Machine Learning Models are not equal Common Applications?

In the very last point it looks like a normal application. But the concept is pretty different, because in a common application we don't use data in the same way. First of all, to create ML Models you will need real (production) data at all development process another difference is if you use different data you will have a different model..always...

Can you give some examples?

Sure! Imagine you are a system developer and create a system that controls services in a PetShop. The most simple way to do this kind of system is create a DataBase do store data and create an application to interact with the user. When you start develop it you don't need real data. You can create all system with fake data. This is impossible with machine learning models they need real data at the starting point of development and it will be used until the last point of development. When you create a machine learning model you provide data to an algorithm and the algorithm results in an application fitted to those data, so if you use fake data, you will have a fake model.

What about Organize the Community with ML?

Getting back to the main subject. With all posts that I have I started exploring a sample and realize:

  1. Most post were without any tag
  2. Some posts were with wrong tags
  3. Some posts (from sample) with tags were right tagged

How use this data?

I take the option of create a BoW (Bag of Words) of the data and use the most popular classification algorithms with. How do I featurize those data? My brief of attempts here:

1st Attempt - Training with only post data

Take all the data with tags, separate 80% for training and 20% to validate the model. The resulting model didn't perform well. Most of time it was predicting all text were about Caché... (the BoW was with aroun 15000 features)

2nd Attempt - Training with only post data removing stop words

Thinking of most posts has the same words like: hi, for, to, why, in, on, the, do, don't... the model probably was taking the wrong way to predict the tags. So I removed all stop words and vectorized the data, resulting in around 9000 features. But the model continues to not perform well.

picture

3rd Attempt - Training with Tags Description

Looking at tags table, I see a short description of each tag. So I give the chance to that small phrases be my guide to the right way to tagging like in real life. It resulted in about 1500 features and using it the model starts performing well enough to show to other people =)

4th Attempt - Training with Tags Description

After all this quest I decide to test if IntegratedML could perform better than my model. So I converted the last Bag of Words into a Table but I faced a problem: a bag of words with 1500 features means that I need a table with 1500 columns. And reading the IRIS docs the limit of columns was 1000. So I changed my vectorizer to use only 900 features. It would less but was the only way that I could think.

Classification Algorithms

I tried 3 algorithms with different params:

  1. SVM
  2. Random Forest
  3. Logistic Regression

The best performer (at least in last days) was Logistic Regression in a strategy One vs Rest. One vs Rest consider that you have 1 class to predict versus a more than 1 other classes.

Next article: End-to-End Application

I hope you are enjoying. If you like the text and my application, please vote on https://openexchange.intersystems.com/contest/current in my application iris-ml-suite

0
0 50
Article Irène Mykhailova · Avr 12, 2023 4m read

Cet article est le deuxième d'une série expliquant comment créer un système d'apprentissage automatique de bout en bout.

Exploration des données

L'Intersystème IRIS dispose déjà de ce dont nous avons besoin pour explorer les données : un moteur SQL ! Pour les personnes qui ont l'habitude d'explorer des données dans des fichiers
csv ou des fichiers texte, cela pourrait aider à accélérer cette étape. Fondamentalement, nous explorons toutes les données pour comprendre l'intersection (jointures), ce qui devrait permettre de créer un jeu de données préparé pour être utilisé par un algorithme d'apprentissage automatique.

Tableau d'articles ( Fourni par l'équipe Intersystems )

image

Tableaude balises ( Fourni par l'équipe Intersystems )

image

Notre défi consiste à classer un article avec les bonnes balises. Et nous avons un tas d'articles et toutes les balises avec description. Il existe plusieurs techniques de classification, mais les cas les plus courants de classification utilisent des données structurées ! Un article, un long texte n'est pas exactement structuré de ce point de vue.

L'apprentissage automatique fonctionne la plupart du temps avec des NOMBRES - Faites avec !

Oui ! Même le modèle de données le plus normalisé contient du texte, mais lorsque nous devons utiliser des algorithmes de ML, nous devons trouver une solution pour convertir tous les textes en nombres. Mais n'oubliez pas que les *données non structurées ne prendront pas les nombres prêts à être utilisés dans un modèle de classification. Il est temps de...

Ingénierie des caractéristiques

Dans cette étape, nous convertissons le texte, les nombres, les éléments non structurés et le chaos dans une matrice (la plupart du temps)... oui, cet élément de vos cours d'algèbre d'autrefois. Si nous avons un tableau qui ressemble déjà à une matrice, vous aurez probablement moins de travail que nous ! Nous avons un grand texte avec des tailles, des formes et des mots différents...

Sac de mots

L'une des façons de transformer un texte long en une matrice est le sac de mots :

expression
Nicole devrait acheter une voiture
Jack devrait vendre son bateau
 [Nicole, Jack, devrait, acheter, vendre, une, son, voiture, bateau]
 [1     ,    0,      1,   1,    0, 1,   0,   1,    0]
 [0     ,    1,      1,   0,    1, 0,   1,   0,    1]

Ce n'est qu'un petit exemple. Mais vous pouvez constater que plus il y a de mots, plus la matrice est grande. Heureusement, nous disposons de nombreux composants pour vous aider à créer des sacs de mots. Dans ce cas, j'ai utilisé les composants de Sklearn pour le faire.

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.preprocessing import MultiLabelBinarizer

ml_bin = MultiLabelBinarizer(classes=all_tags)
matrix_y = ml_bin.fit_transform(a_dataframe)

count_vec = CountVectorizer(ngram_range=(1,1), tokenizer=tokenize, strip_accents='unicode', stop_words=stop_words)
matrix_x = count_vec.fit_transform(a_dataframe)

Après avoir exécuté les méthodes ci-dessus, nous disposons d'un vectoriseur que nous devrons conserver tout le temps que nous voulons prédire. Si nous changeons le vectoriseur, nous risquons de perturber les matrices et rien ne devrait fonctionner par la suite.

Est-ce que je vous ai déjà dit que nous ne devions utiliser que des chiffres ?

Il y a un autre problème ! Pour certains algorithmes, la taille du nombre peut perturber vos intentions. En bref, si un élément de la matrice a une valeur de 1 et qu'un autre élément a une valeur de 987, certains algorithmes pourraient interpréter cela comme l'importance de l'élément et prendre la mauvaise direction.

Algorithmes de classification ML

Il existe de nombreux documents à lire sur les algorithmes de classification, vous pouvez commencer par cet article : https://machinelearningmastery.com/types-of-classification-in-machine-learning/

Article suivant : stratégie de formation (pour les données, oubliez les GIMS)

J'espère que vous appréciez. Si vous aimez le texte et mon application, votez sur https://openexchange.intersystems.com/contest/current dans mon application iris-ml-suite

0
0 55
Article Irène Mykhailova · Avr 10, 2023 6m read

Voici mon introduction à une série d'articles expliquant comment créer un système d'apprentissage automatique de bout en bout.

Un seul problème pour commencer

Notre communauté de développement d'IRIS a plusieurs messages sans balise ou mal balisés. Au fur et à mesure que le nombre de messages augmente, l'organisation de chaque balise et l'expérience d'un membre de la communauté qui parcourt les sujets tendent à diminuer.

Les premières solutions envisagées

Nous pouvons envisager quelques solutions habituelles pour ce scénario, comme par exemple :

  • Prendre un volontaire pour lire tous les messages et corriger les erreurs.
  • Payer un entrepreneur pour corriger toutes les erreurs.
  • Envoyez un courriel à chaque auteur de message pour qu'il revoie les textes du passé.

Ma solution

image

Et si nous pouvions apprendre à une machine à faire ce travail ?

image Nous avons beaucoup d'exemples de dessins animés, d'anime ou de films pour nous rappeler ce qui peut se passer lorsqu'on enseigne à une machine...

Apprentissage automatique

L'apprentissage automatique est un sujet très vaste et je vais faire de mon mieux pour expliquer ma vision du sujet. Revenons au problème que nous devons encore résoudre : Si l'on examine les solutions habituelles, elles prennent toutes en compte l'interprétation d'un texte. Comment apprendre à une machine à lire un texte, à comprendre la corrélation entre un texte et une balise ? Tout d'abord, nous devons explorer les données et en tirer des conclusions.

Classification ? Régression ?

Lorsque vous commencez à étudier l'apprentissage automatique, les deux termes ci-dessus sont toujours utilisés. Mais comment savoir ce qu'il faut approfondir ? -Classification : Un algorithme d'apprentissage automatique de classification prédit des valeurs discrètes.
-Régression : Un algorithme d'apprentissage automatique de régression prédit des valeurs continues. Si l'on considère notre problème, nous devons prédire des valeurs discrètes (toutes les baises existent).

C'est une question de données !

Toutes les données relatives aux articles ont été fournies ici.

Article

SELECT
 id, Name, Tags, Text
FROM Community.Post
Where  
not text is null              
order by id
idNomBalisesTexte
1946Introduction aux services webWeb Development,Web ServicesCette vidéo est une introduction aux services web. Elle explique ce que sont les services web, leur utilisation et comment les administrer. Les services web sont également connus sous le nom de "SOAP". Cette session comprend des informations sur la sécurité et la politique de sécurité.
1951Les outils pour CachéCachéCette astuce technique (Tech Tip) passe en revue les différents outils disponibles à partir du Caché dans la barre d'état système de Windows. Vous verrez comment accéder à Studio IDE, au terminal, au portail de gestion du système, à SQL, aux globales, à la documentation, à la référence de classe et à l'accès au système à distance.
1956Démarrage avec CachéCachéDémarrage avec Caché présentera Caché et son architecture. Nous examinerons également les outils de développement, la documentation et les exemples disponibles.

Balises

IDDescription
.NETNET Framework (prononcé dot net) est un cadre logiciel développé par Microsoft qui fonctionne principalement sur Microsoft Windows. Site officiel. Support .NET dans InterSystems Data Platform.
.NET ExperienceInterSystems .NET Experience révèle les possibilités d'interopérabilité entre .NET et InterSystems IRIS Data Platform. Pour plus de détails, cliquez ici. Site officiel de .NET
IAL'intelligence artificielle (IA) est la simulation des processus de l'intelligence humaine par des machines, en particulier par des systèmes informatiques. Ces processus comprennent l'apprentissage (l'acquisition d'informations et de règles d'utilisation de ces informations), le raisonnement (l'utilisation de règles pour parvenir à des conclusions approximatives ou définitives) et l'autocorrection. Apprenez-en plus.
APIL'interface de programmation d'applications (API) est un ensemble de définitions de sous-programmes, de protocoles et d'outils permettant de créer des logiciels d'application. En termes généraux, il s'agit d'un ensemble de méthodes de communication clairement définies entre divers composants logiciels. Apprenez-en plus.

Nous savons maintenant à quoi ressemblent les données. Mais il ne suffit pas de connaître la conception des données pour créer un modèle d'apprentissage automatique.

Qu'est-ce qu'un modèle d'apprentissage automatique ?

Un modèle d'apprentissage automatique est une combinaison d'un algorithme d'apprentissage automatique et de données. Après avoir combiné une technique avec des données un modèle peut commencer à prédire.

Exactitude

Si vous pensez que les modèles ML ne font jamais d'erreurs, vous devriez mieux comprendre la précision du modèle. En quelques mots, la précision correspond aux performances du modèle en matière de prédiction. En général, la précision est exprimée en pourcentage, sous forme de chiffres. Ainsi, quelqu'un dira : "J'ai créé un modèle dont la précision est de 70 %". Cela signifie que pour 70 % des prédictions, le modèle prédit correctement. Les 30 % restants seront des prédictions erronées.

NLP - Traitement du langage naturel

Le NLP est un domaine de l'apprentissage automatique qui travaille sur la capacité d'un ordinateur à comprendre et à analyser le langage humain. Et oui, notre problème peut être résolu grâce au NLP.

Utilisation d'algorithmes d'apprentissage automatique

La plupart des algorithmes d'apprentissage automatique ont une chose en commun : ils utilisent en entrée des NOMBRES. Oui, je sais... c'est le point le plus difficile à comprendre pour créer des modèles d'apprentissage automatique.

Si tous les messages et les balises sont du texte, comment le modèle peut-il fonctionner ?

Une bonne partie du travail dans une solution de ML consiste à transformer les données en quelque chose qui peut être utilisé dans un algorithme. Ce travail est appelé "ingénierie des fonctionnalités" (Feature Engineering). Dans ce cas, c'est plus compliqué car les données ne sont pas structurées. Mais voici une brève explication*: J'ai transformé chaque mot du texte en un identifiant unique représenté par un nombre. SKLearn et d'autres librairies python devraient vous aider
de le faire facilement.

Démonstration

J'ai déployé le modèle formé en tant que démonstration ici : http://iris-ml-suite.eastus.cloudapp.azure.com/

Quelle est la suite ?

Dans mon prochain article, je montrerai le code et les moyens de faire toute la modélisation. A ne pas manquer !

Si cet article vous a aidé ou si vous avez aimé son contenu, votez :

Cette application est au concours actuel sur l'échange ouvert, vous pouvez voter ici: https://openexchange.intersystems.com/contest/current ou dans mon application iris-ml-suite

0
0 65
Article Lucas Enard · Avr 3, 2023 10m read

Sur GitHub, vous trouverez toutes les informations sur l'utilisation d'un modèle d'apprentissage automatique "HuggingFace" / modèle d'IA sur le cadre IRIS à l'aide de Python.

1. iris-huggingface

Utilisation de modèles d'apprentissage automatique dans IRIS à l'aide de Python ; pour les modèles texte-texte, texte-image ou image-image.

Les modèles suivants servent d'exemple :

2. Installation

2.1. Lancement de la production

Dans le dossier iris-local-ml, ouvrez un terminal et saisisse :

docker-compose up

La première fois, cela peut prendre quelques minutes pour construire l'image de manière correcte et installer tous les modules nécessaires à Python.

2.2. Accès à la production

En suivant ce lien, vous accédez à la production : Access the Production

2.3. Clôture de la production

docker-compose down

Comment ça marche

Pour l'instant, certains modèles peuvent ne pas fonctionner avec cette implémentation car tout est fait automatiquement, ce qui veut dire que, quel que soit le modèle que vous saisissez, nous essaierons de le faire fonctionner grâce à la bibliothèque transformerspipeline.

Pipeline est un outil puissant de l'équipe HuggingFace qui va scanner le dossier dans lequel nous avons téléchargé le modèle, puis il va déterminer quelle bibliothèque il doit utiliser entre PyTorch, Keras, Tensorflow ou JAX pour ensuite charger ce modèle en utilisant AutoModel.
À partir de ce point, en saisissant la tâche, le pipeline sait ce qu'il doit faire avec le modèle, l'analyseur lexical ou même l'extracteur de caractéristiques dans ce dossier, et gère automatiquement votre entrée, l'analyse et la traite, la transmet au modèle, puis restitue la sortie sous une forme décodée directement utilisable par nous.

3. API HuggingFace

Vous devez d'abord démarrer la démo, en utilisant le bouton vert Start ou Stop et Start à nouveau pour appliquer vos changements de configuration.

Ensuite, en cliquant sur l'opération Python.HFOperation de votre choix, et en sélectionnant dans l'onglet de droite action, vous pouvez tester la démo.

Dans cette fenêtre test, sélectionnez :

Type de demande : Grongier.PEX.Message

Pour le classname vous devez saisir :

msg.HFRequest

Et pour le json, voici un exemple d'appel à GPT2 :

{
    "api_url":"https://api-inference.huggingface.co/models/gpt2",
    "payload":"Veuillez nous donner plus de détails sur votre ",
    "api_key":"----------------------"
}

Vous pouvez maintenant cliquer sur le bouton Visual Trace (Trace visuelle) pour voir en détail ce qui s'est passé et consulter les journaux.

REMARQUE : vous devez avoir une clé API de HuggingFace avant d'utiliser cette opération (les clés API sont gratuites, il suffit de s'enregistrer auprès de HF).

REMARQUE : vous pouvez changer l'url pour essayer n'importe quel autre modèle de HuggingFace, mais vous devrez peut-être changer le payload.

Par exemple :
sending hf reqhf reqhf resp

4. Utilisation de n'importe quel modèle sur le web

Dans cette section, nous vous apprendrons à utiliser presque tous les modèles disponibles sur l'internet, qu'il s'agisse de HuggingFace ou non.

4.1. PREMIER CAS : VOUS AVEZ VOTRE PROPRE MODÈLE

Dans ce cas, vous devez copier-coller votre modèle, avec la configuration, l'outil tokenizer.json etc. dans un dossier à l'intérieur du dossier model.
Chemin d'accès : src/model/yourmodelname/

A partir de là, vous devez aller dans les paramètres de Python.MLOperation.
Cliquez sur Python.MLOperation puis rendez-vous dans settings dans l'onglet de droite, puis dans la partie Python, puis dans la partie %settings. Ici, vous pouvez saisir ou modifier n'importe quel paramètre (n'oubliez pas d'appuyer sur apply une fois que vous avez terminé).
Voici la configuration par défaut pour ce cas :
%settings

name=yourmodelname
task=text-generation

REMARQUE : tous les paramètres qui ne sont pas name ou model_url sont placés dans les paramètres de PIPELINE.

NMaintenant vous pouvez double-cliquer sur l'opération Python.MLOperation et la démarrer. Vous devez voir dans la partie Log le démarrage de votre modèle.

A partir de là, nous créons une PIPELINE en utilisant des transformateurs qui utilisent votre fichier de configuration situé dans le dossier comme nous l'avons vu précédemment.

Pour appeler ce pipeline, cliquez sur l'opération Python.MLOperation , et sélectionnez dans l'onglet de droite action, vous pouvez tester la démo.

Dans cette fenêtre test, sélectionnez :

Type de demande : Grongier.PEX.Message

Pour le classname (nom de classe), vous devez saisir :

msg.MLRequest

Et pour le json, vous devez saisissez tous les arguments nécessaires à votre modèle. Voici un exemple d'appel à GPT2 :

{
    "text_inputs":"Malheureusement, le résultat",
    "max_length":100,
    "num_return_sequences":3
}

Cliquez sur Invoke Testing Service (Invoquer le service de test) et attendez que le modèle fonctionne.

Voir par exemple :
sending ml req

Vous pouvez maintenant cliquer sur Visual Trace (Trace visuelle) pour voir en détail ce qui s'est passé et consulter les journaux.

Voir par exemple :
ml req

ml resp

4.2. DEUXIÈME CAS : VOUS VOULEZ TÉLÉCHARGER UN MODÈLE À PARTIR DE HUGGINGFACE

Dans ce cas, vous devez trouver l'URL du modèle sur HuggingFace ;

4.2.1. Paramètres

À partir de là, vous devez accéder aux paramètres de la Python.MLOperation.
Cliquez sur Python.MLOperation puis allez dans des paramètres settings dans l'onglet de droite, puis dans la partie Python, puis dans la partie %settings. Ici, vous pouvez saisir ou modifier n'importe quel paramètre (n'oubliez pas d'appuyer sur apply (appliquer) une fois que vous avez terminé).
Voici quelques exemples de configuration pour certains modèles que nous avons trouvés sur HuggingFace :

%settings pour gpt2

model_url=https://huggingface.co/gpt2
name=gpt2
task=text-generation

%settings pour camembert-ner

name=camembert-ner
model_url=https://huggingface.co/Jean-Baptiste/camembert-ner
task=ner
aggregation_strategy=simple

%settings pour bert-base-uncased

name=bert-base-uncased
model_url=https://huggingface.co/bert-base-uncased
task=fill-mask

%settings pour detr-resnet-50

name=detr-resnet-50
model_url=https://huggingface.co/facebook/detr-resnet-50
task=object-detection

%settings pour detr-resnet-50-protnic

name=detr-resnet-50-panoptic
model_url=https://huggingface.co/facebook/detr-resnet-50-panoptic
task=image-segmentation

REMARQUE : tous les paramètres qui ne sont pas name ou model_url iront dans les paramètres du PIPELINE, donc dans notre second exemple, le pipeline camembert-ner requiert une stratégie aggregation_strategy et une tâche task qui sont spécifiées ici alors que le pipeline gpt2 ne requiert qu'une tâche task.

Voir par exemple :
settings ml ope2

Vous pouvez maintenant double-cliquer sur l'opération Python.MLOperation et la démarrer.
Vous devez voir dans la partie Log le démarrage de votre modèle et le téléchargement.
REMARQUE : Vous pouvez actualiser ces journaux toutes les x secondes pour voir l'évolution des téléchargements. dl en temps réel

A partir de là, nous créons une PIPELINE en utilisant des transformateurs qui utilisent votre fichier de configuration qui se trouve dans le dossier comme nous l'avons vu précédemment.

4.2.2. Tests

Pour appeler ce pipeline, cliquez sur l'opération Python.MLOperation , et sélectionnez dans l'onglet de droite action, vous pouvez tester la démo.

Dans cette fenêtre test, sélectionnez :

Type de demande : Grongier.PEX.Message

Pour le classname (nom de classe), vous devez saisir :

msg.MLRequest

Et pour le json, vous devez saisir tous les arguments nécessaires à votre modèle. Voici un exemple d'appel à GPT2 ( Python.MLOperation ) :

{
    "text_inputs":"George Washington a vécu",
    "max_length":30,
    "num_return_sequences":3
}

Voici un exemple d'appel à Camembert-ner ( Python.MLOperation2 ) :

{
    "inputs":"George Washington a vécu à Washington"
}

Voici un exemple d'appel à bert-base-uncased ( Python.MLOperation3 ) :

{
    "inputs":"George Washington a vécu à [MASQUE]."
}

Voici un exemple d'appel à detr-resnet-50 à l'aide d'une url en ligne ( Python.MLOperationDETRRESNET ) :

{
    "url":"http://images.cocodataset.org/val2017/000000039769.jpg"
}

Voici un exemple d'appel à detr-resnet-50-panoptic utilisant l'url comme chemin d'accès( Python.MLOperationDetrPanoptic ) :

{
    "url":"/irisdev/app/misc/000000039769.jpg"
}

Cliquez sur Invoke Testing Service et attendez que le modèle fonctionne.
Vous pouvez maintenant cliquer sur Visual Trace pour voir en détail ce qui s'est passé et consulter les journaux.

REMARQUE : Lorsque le modèle a été téléchargé pour la première fois, la production ne le téléchargera pas à nouveau mais récupérera les fichiers mis en cache dans src/model/TheModelName/.
Si certains fichiers sont manquants, la production les téléchargera à nouveau.

Voir par exemple :
sending ml reqml reqml resp

Voir par exemple :
sending ml reqml resp

5. Dépannage

Si vous avez des problèmes, la lecture est le premier conseil que nous pouvons vous donner, la plupart des erreurs sont facilement compréhensibles simplement en lisant les journaux car presque toutes les erreurs seront capturées par un try / catch et enregistrées.

Si vous avez besoin d'installer un nouveau module, ou une dépendance Python, ouvrez un terminal à l'intérieur du conteneur et saisissez par exemple : "pip install new-module"
Il y a plusieurs façons d'ouvrir un terminal,

  • Si vous utilisez les plugins InterSystems, vous pouvez cliquer sur la barre ci-dessous dans VSCode, celle qui ressemble à docker:iris:52795[IRISAPP] et sélectionner Open Shell in Docker (Ouvrir l'enveloppe dans Docker).
  • Dans n'importe quel terminal local, saisissez : docker-compose exec -it iris bash
  • Depuis Docker-Desktop, trouvez le conteneur IRIS et cliquez sur Open in terminal (Ouvrir dans le terminal).

Certains modèles peuvent nécessiter des modifications au niveau de leur pipeline ou de leurs paramètres, par exemple, et c'est à vous qu'il incombe d'ajouter les informations adéquates dans les paramètres et dans la demande.

6. Conclusion

À partir de là, vous devriez pouvoir utiliser n'importe quel modèle dont vous avez besoin ou que vous possédez sur IRIS.
REMARQUE : vous pouvez créer une Python.MLOperation pour chacun de vos modèles et les activer en même temps.

0
0 189
Article Guillaume Rongier · Fév 24, 2023 4m read

Je vous présente mon nouveau projet, qui est irissqlcli, REPL (Read-Eval-Print Loop) pour InterSystems IRIS SQL

  • Mise en évidence de la syntaxe
  • Suggestions (tableaux, fonctions)
  • Plus de 20 formats de sortie
  • Support de stdin
  • Sortie vers des fichiers 

L'installez avec pip

pip install irissqlcli

Ou lancez avec docker

docker run -it caretdev/irissqlcli irissqlcli iris://_SYSTEM:SYS@host.docker.internal:1972/USER

Connection à IRIS

$ irissqlcli iris://_SYSTEM@localhost:1972/USER -W
Password for _SYSTEM:
Server:  InterSystems IRIS Version 2022.3.0.606 xDBC Protocol Version 65
Version: 0.1.0
[SQL]_SYSTEM@localhost:USER> select $ZVERSION
+---------------------------------------------------------------------------------------------------------+
| Expression_1                                                                                            |
+---------------------------------------------------------------------------------------------------------+
| IRIS for UNIX (Ubuntu Server LTS for ARM64 Containers) 2022.3 (Build 606U) Mon Jan 30202309:05:12 EST |
+---------------------------------------------------------------------------------------------------------+
1 row in set
Time: 0.063s
[SQL]_SYSTEM@localhost:USER> help
+----------+-------------------+------------------------------------------------------------+
| Commande  | Raccourci          | Description                                                |
+----------+-------------------+------------------------------------------------------------+
| .exit    | \q                | Sortie.                                                      |
| .mode    | \T                | Modifier le format de tableau utilisé pour les résultats.            |
| .once    | \o [-o] filename  | Ajout du résultat suivant à un fichier de sortie (écraser en utilisant -o). |
| .schemas | \ds               | Liste des schémas.                                             |
| .tables  | \dt [schema]      | Liste des tableaux.                                               |
| \e       | \e                | Commande d'édition avec éditeur (utilise $EDITOR).                   |
| help     | \?                | Montre cette utilité.                                            |
| nopager  | \n                | Désactiver le pager, imprimer vers stdout.                            |
| notee    | notee             | Arrête l'écriture des résultats dans un fichier de sortie.                    |
| pager    | \P [command]      | Definition du PAGER. Impression des résultats de la requête via PAGER.              |
| prompt   | \R                | Modification du format de l'invite.                                      |
| quit     | \q                | Quit.                                                      |
| tee      | tee [-o] filename | Ajout de tous les résultats à un fichier de sortie (écraser en utilisant -o). |
+----------+-------------------+------------------------------------------------------------+
Time: 0.012s
[SQL]_SYSTEM@localhost:USER>
$ irissqlcli --help
Usage: irissqlcli [OPTIONS] [URI] [NOM D'UTILISATEUR]

Options:
  -h, --host TEXT         Adresse hôte de l'instance IRIS.
  -p, --port INTEGER      Numéro de port sur lequel l'instance IRIS està l'écoute.
  -U, --username TEXT     Nom d'utilisateur pour se connecter à l'instance IRIS.
  -u, --user TEXT         Nom d'utilisateur pour se connecter à l'instance IRIS.
  -W, --password          Invite de mot de passe forcée.
  -v, --version           Version de irissqlcli.
  -n, --nspace TEXT       nom de l'espace de nom auquel se connecter.
  -q, --quiet             Mode silencieux, saut de l'intro au démarrage etau revoir à la
                          sortie.
  -l, --logfile FILENAME  Enregistrez chaque requête etses résultats dans un fichier.
  --irissqlclirc FILE     L'emplacement du fichier irissqlclirc.
  --auto-vertical-output  Passage automatique en mode de sortie verticale sile résultat est plus large que la largeur du terminal. résultat estplus large que la largeur du terminal.
  --row-limit INTEGER     Définissez le seuil pour l'invite de limite de rangée de . Utilisez 0 pour désactiver
                          l'invite.
  -t, --table             Affichez la sortie du lot au format tableau .
  --csv                   Affichez la sortie du lot in au format CSV.
  --warn / --no-warn      Avertissement avant d'exécuter une requête destructive.
  -e, --execute TEXT      Exécutez la commande etquitter.
  --help                  Affichage de ce message et sortie.

ou en Python Embedded (nécessite de %Service_CallIn activé)

$ irissqlcli iris+emb:///USER
Server:  IRIS for UNIX (Ubuntu Server LTS for ARM64 Containers) 2022.2 (Build 368U) Fri Oct 21202216:39:41 EDT
Version: 0.1.0
[SQL]irisowner@/usr/irissys/:USER>

L'application supporte stdin, ce qui vous permet d'envoyer un fichier SQL avec un tas de requêtes SQL et de commandes irissqcli. Par exemple, cette commande produira 3 fichiers dans différents formats (parmi plus de 20 formats disponibles)

$ cat <select top 10 TABLE_SCHEMA,TABLE_NAME
from information_schema.tables
orderby TABLE_SCHEMA,TABLE_NAME;
notee;

.mode latex;
tee -o test.tex;
select top 10 TABLE_SCHEMA,TABLE_NAME
from information_schema.tables
orderby TABLE_SCHEMA,TABLE_NAME;
notee;

.mode html;
tee -o test.html;
select top 10 TABLE_SCHEMA,TABLE_NAME
from information_schema.tables
orderby TABLE_SCHEMA,TABLE_NAME;
notee;

EOF

De plus, il est possible d'exécuter un terminal web avec docker

docker run -d --name irissqlcli \
  --restart always \
  -p 7681:7681\
  caretdev/irissqlcli-web irissqlcli iris://_SYSTEM:SYS@host.docker.internal:1972/USER

http://localhost:7681/

Et avec docker-compose

version: '3'
services:
  iris:
    image: intersystemsdc/iris-community
    ports:
      - 1972
      - 52773
    command:
      - -a
      - '##class(Security.Users).UnExpireUserPasswords("*")'
  cli:
    image: caretdev/irissqlcli-web
    ports:
      - 7681:7681
    environment:
      - IRIS_HOSTNAME:iris
      - IRIS_PORT=1972
      - IRIS_NAMESPACE=USER
      - IRIS_USERNAME=_SYSTEM
      - IRIS_PASSWORD=SYS
0
0 105
Article Lucas Enard · Déc 1, 2022 1m read

Bonjour à tous, c'est avec grand plaisir que je vous annonce la V2 de mon application 'Contest-FHIR'.

Dans cette nouvelle version, j'ai utilisé de nouveaux outils et techniques que j'ai découverts lors de l'EUROPEAN HEALTHCARE HACKATHON auquel j'ai été invité par InterSystems en tant qu'invité et mentor pour présenter les multiples projets que j'ai réalisés lors de mon stage en avril 2022.

Aujourd'hui je vous présente la V2 de mon application, elle peut maintenant transformer un fichier CSV en FHIR en SQL en JUPYTER notebook.

C'est pour moi un grand pas en avant dans les technologies d'InterSystems et je pense que cet outil sera utilisé pour de nombreux autres usages et cas.

Visitez mon GitHub pour plus d'informations, et pour ceux d'entre vous qui ne veulent pas perdre de temps, consultez la partie 5. Walkthrough de mon GitHub.

0
0 54
Article Lucas Enard · Sept 30, 2022 9m read

Dans ce GitHub nous recueillons des informations à partir d'un csv, nous utilisons une DataTransformation pour les transformer en un objet FHIR, puis nous sauvegardons ces informations sur un serveur FHIR, et tout cela en utilisant uniquement Python.

The objective is to show how easy it is to manipulate data into the output we want, here a FHIR Bundle, in the IRIS full Python framework.

1. Fhir-orga-dt

2. Préalables

Assurez-vous que git et Docker desktop sont installé.

Si vous travaillez à l'intérieur du conteneur, comme il est montré dans 3.3., vous n'avez pas besoin d'installer fhirpy et fhir.resources.

Si vous n'êtes pas dans le conteneur, vous pouvez utiliser pip pour installer fhirpy et fhir.resources.
Vérifiez fhirpy et fhir.resources pour plus d'information.

3. Installation

3.1. Installation pour le développement

Clone/git tire le repo dans n'importe quel répertoire local, par exemple comme indiqué ci-dessous :

git clone https://github.com/LucasEnard/fhir-client-python.git

Ouvrez le terminal dans ce répertoire et lancez :

docker build .

3.2. Portail de gestion et VSCode

Ce référentiel est prêt pour VS Code.

Ouvrez le dossier fhir-client-python cloné localement dans VS Code.

Si vous y êtes invité (coin inférieur droit), installez les extensions recommandées.

3.3. Avoir le dossier ouvert à l'intérieur du conteneur

Vous pouvez être à l'intérieur du conteneur avant de coder si vous le souhaitez.
Pour cela, il faut que docker soit activé avant d'ouvrir VSCode.
Ensuite, dans VSCode, lorsque vous y êtes invité ( coin inférieur droit ), rouvrez le dossier à l'intérieur du conteneur afin de pouvoir utiliser les composants python qu'il contient.
La première fois que vous effectuez cette opération, cela peut prendre plusieurs minutes, le temps que le conteneur soit préparé.

Si vous n'avez pas cette option, vous pouvez cliquer dans le coin inférieur gauche et cliquer sur Ouvrir à nouveau dans le conteneur puis sélectionner De Dockerfile

Plus d'informations ici

Architecture


En ouvrant le dossier à distance, vous permettez à VS Code et à tous les terminaux que vous ouvrez dans ce dossier d'utiliser les composants python dans le conteneur.

4. Serveur FHIR

Pour compléter cette présentation, nous allons utiliser un serveur fhir.
Ce serveur fhir était déjà intégré lorsque vous avez cloné et construit le conteneur.

L'url est localhost:52773/fhir/r4

5. Présentation pas à pas

Présentation complète de la réalisation d'IRIS en Python.

5.1. Messages and objects

Les objets et les messages contiennent les informations entre nos services, nos processus et nos opérations.

Dans le fichier obj.py nous devons créer une classe de données qui correspond au csv, ceci sera utilisé pour garder l'information avant de faire la DataTransformation.
Dans notre exemple, le csv organisation.csv ressemble à ceci,

active;name;city;country;system;value
true;Name1;city1;country1;phone;050678504
false;Name2;city2;country2;phone;123456789

Par conséquent, l'objet ressemblera à ceci,

@dataclass
# > Cette classe représente une organisation simple
class BaseOrganization:
    active:bool = None
    name:str = None
    city:str = None
    country:str = None
    system:str = None
    value:str = None

Dans le fichier msg.py, nous aurons deux types de requêtes, la première contenant les informations d'une organisation avant la DataTransformation et la seconde contenant les informations de l'organisation après la DataTransformation.

5.2. Service aux entreprises

Dans le fichier bs.py, nous avons le code qui nous permet de lire le csv et pour chaque ligne du csv (donc pour chaque organisation), le mapper dans un objet que nous avons créé plus tôt. Ensuite, pour chacune de ces lignes (organisation), nous créons une requête et l'envoyons à notre processus pour effectuer la DataTransformation.

# Nous ouvrons le fichier
with open(self.path + self.filename,encoding="utf-8") as csv:
    # Nous le lisons et le mappons en utilisant l'objet BaseOrganization précédemment utilisé
    reader = DataclassReader(csv, self.fhir_type ,delimiter=";")
    # Pour chacune de ces organisations, nous pouvons créer une requête et l'envoyer au processus
    for row in reader:
        msg = OrgaRequest()
        msg.organization = row
        self.send_request_sync('Python.ProcessCSV',msg)

5.3. Service aux entreprises

Dans le fichier bp.py, nous avons la DataTransformation, qui convertit un simple objet python contenant peu d'informations en un objet FHIR R4

Voici les étapes pour effectuer une DataTransformation en utilisant du python embarqué sur notre organisation simple,

# Création de l'objet Organisation
organisation = Organisation()

# Mappage des informations de la demande à l'objet Organisation
organization.name = base_orga.name

organization.active = base_orga.active

## Création de l'objet Adresse et mappage des informations
## de la demande à l'objet Addresse
adresse = Addresse()
adress.country = base_orga.country
adress.city = base_orga.city

### Configuration de l'adresse de notre organisation à celle que nous avons créée
organization.address = [adress]

## Création de l'objet ContactPoint et mise en correspondance
## des informations de la demande avec l'objet ContactPoint
telecom = ContactPoint()
telecom.value = base_orga.value
telecom.system = base_orga.system

### Configuration de la télécommunication de notre organisation à celle que nous avons créée
organization.telecom = [telecom]

# Maintenant, notre DT est achevé, nous avons une organisation d'objets qui est
# un objet FHIR R4 et qui contient toutes nos informations csv.

Après cela, notre mappage est terminé et notre DT fonctionne.
Maintenant, nous pouvons envoyer cette ressource FHIR R4 nouvellement créée à notre FhirClient qui est notre opération.

5.4. Opération d'un entreprise

Dans le fichier bo.py nous avons le FhirClient, ce client crée une connexion à un serveur fhir qui contiendra les informations recueillies par le csv.

Dans cet exemple, nous utilisons un serveur fhir local qui n'a pas besoin d'une clé api pour se connecter.
Pour s'y connecter, nous devons utiliser la fonction on_init,

if not hasattr(self,'url'):
    self.url = 'localhost:52773/fhir/r4'

self.client = SyncFHIRClient(url=self.url)

Maintenant, lorsque nous recevons un message/demande, nous pouvons, en trouvant le type de ressource de la ressource que nous envoyons avec notre demande au client, créer un objet lisible par le client, puis le sauvegarder sur le serveur fhir.

# Obtenez le type de ressource de la demande ( ici "Organisation" )
resource_type = request.resource["resource_type"]

# Créer une ressource de ce type en utilisant les données de la demande
resource = construct_fhir_element(resource_type, request.resource)

# Sauvegarder la ressource sur le serveur FHIR en utilisant le client
self.client.resource(resource_type,**json.loads(resource.json())).save()

Il est à noter que le client fhir fonctionne avec n'importe quelle ressource de FHIR R4 et pour utiliser et modifier notre exemple, nous devons seulement changer la DataTransformation et l'objet qui contient les informations csv.

5.5. Conclusion de la présentation

Si vous avez suivi ce parcours, vous savez maintenant exactement comment lire un csv d'une représentation d'une ressource FHIR R4, utiliser une DataTransformation pour le transformer en un véritable objet FHIR R4 et le sauvegarder sur un serveur.

6. Création d'une nouvelle DataTransformation

Ce référentiel est prêt à être codé en VSCode avec les plugins InterSystems. Ouvrez /src/python pour commencer à coder ou utiliser l'autocomplétion.

Étapes pour créer une nouvelle transformation
Pour ajouter une nouvelle transformation et l'utiliser, la seule chose que vous devez faire est d'ajouter votre csv nommé Patient.csv (par exemple) dans le dossier src/python/csv.
Ensuite, créez un objet dans src/python/obj.py appelé BasePatient qui met en correspondance votre csv.
Maintenant, créez une requête dans src/python/msg.py appelée PatientRequest qui a une variable resource de type BasePatient.
L'étape finale est la DataTransformation, pour cela, allez dans src/python/bp.py et ajoutez votre DT. Ajoutez d'abord if isinstance(request, PatientRequest): puis mappez votre ressource de requête à une fhir.resource Patient.
Maintenant si vous allez dans le portail de gestion et changez le paramètre du ServiceCSV pour ajouter filename=Patient.csv vous pouvez juste démarrer la réalisation et voir votre transformation se dérouler et votre client envoyer les informations au serveur.

Étapes détaillées pour créer une nouvelle transformation
Si vous n'êtes pas sûr de ce qu'il faut faire ou de la manière de le faire, voici une création étape par étape d'une nouvelle transformation :

Créez le fichier Patient.csv and le dossier src/python/csv pour les remplir avec le suivant:

family;given;system;value
FamilyName1;GivenName1;phone;555789675
FamilyName2;GivenName2;phone;023020202

Notre CSV contient un nom de famille, un prénom et un numéro de téléphone pour deux patients.


Dans src/python/obj.py écrivez :

@dataclass
class BasePatient:
    family:str = None
    given:str = None
    system:str = None
    value:str = None


Dans src/python/msg.py écrivez :

from obj import BasePatient
@dataclass
class PatientRequest(Message):
    resource:BasePatient = None


Dans src/python/bp.py écrivez :

from msg import PatientRequest
from fhir.resources.patient import Patient
from fhir.resources.humanname import HumanName

Dans src/python/bp.py dans la fonction on_request écrivez :

if isinstance(request,PatientRequest):
    base_patient = request.resource

    patient = Patient()

    name = HumanName()
    name.family = base_patient.family
    name.given = [base_patient.given]
    patient.name = [name]

    telecom = ContactPoint()
    telecom.value = base_patient.value
    telecom.system = base_patient.system
    patient.telecom = [telecom]

    msg = FhirRequest()
    msg.resource = patient

    self.send_request_sync("Python.FhirClient", msg)


Maintenant si vous allez dans le portail de gestion et changez le paramètre du ServiceCSV pour ajouter filename=Patient.csv vous pouvez juste arrêter et redémarrer la production et voir votre transformation se dérouler et votre client envoyer les informations au serveur.

Settings

7. Ce qu'il y a dans le référentiel

7.1. Dockerfile

Le dockerfile le plus simple pour démarrer un conteneur Python.
Utilisez docker build . pour construire et rouvrir votre fichier dans le conteneur pour travailler à l'intérieur de celui-ci.

7.2. .vscode/settings.json

Fichier de paramètres.

7.3. .vscode/launch.json

Fichier de configuration si vous voulez déboguer.

0
0 126
Article Lucas Enard · Sept 14, 2022 12m read

1. Fhir-client-python

Ceci est un client fhir simple en python pour s'exercer avec les ressources fhir et les requêtes CRUD vers un serveur FHIR.
Notez que pour la plupart, l'autocomplétion est activée, c'est la principale raison d'utiliser fhir.resources.

GitHub

2. Préalables

Assurez-vous que git et Docker desktop sont installé.

Si vous travaillez à l'intérieur du conteneur, comme il est montré dans 3.3., vous n'avez pas besoin d'installer fhirpy et fhir.resources.

Si vous n'êtes pas dans le conteneur, vous pouvez utiliser pip pour installer fhirpy et fhir.resources.
Vérifiez fhirpy et fhir.resources pour plus d'information.

3. Installation

3.1. Installation pour le développement

Clone/git tire le repo dans n'importe quel répertoire local, par exemple comme indiqué ci-dessous :

git clone https://github.com/LucasEnard/fhir-client-python.git

Ouvrez le terminal dans ce répertoire et lancez :

docker build.

3.2. Portail de gestion et VSCode

Ce référentiel est prêt pour VS Code.

Ouvrez le dossier fhir-client-python cloné localement dans VS Code.

Si vous y êtes invité (coin inférieur droit), installez les extensions recommandées.

3.3. Avoir le dossier ouvert à l'intérieur du conteneur

Vous pouvez être à l'intérieur du conteneur avant de coder si vous le souhaitez.
Pour cela, il faut que docker soit activé avant d'ouvrir VSCode.
Ensuite, dans VSCode, lorsque vous y êtes invité ( coin inférieur droit ), rouvrez le dossier à l'intérieur du conteneur afin de pouvoir utiliser les composants python qu'il contient.
La première fois que vous effectuez cette opération, cela peut prendre plusieurs minutes, le temps que le conteneur soit préparé.

Si vous n'avez pas cette option, vous pouvez cliquer dans le coin inférieur gauche et cliquer sur Ouvrir à nouveau dans le conteneur puis sélectionner De Dockerfile

Plus d'informations ici

Architecture


En ouvrant le dossier à distance, vous permettez à VS Code et à tous les terminaux que vous ouvrez dans ce dossier d'utiliser les composants python dans le conteneur.

4. Serveur FHIR

Pour réaliser cette présentation, vous aurez besoin d'un serveur FHIR.
Vous pouvez soit utiliser le vôtre, soit vous rendre sur le site InterSystems free FHIR trial et suivre les étapes suivantes pour le configurer.

En utilisant notre essai gratuit, il suffit de créer un compte et de commencer un déploiement, puis dans l'onglet Overview vous aurez accès à un endpoint comme https://fhir.000000000.static-test-account.isccloud.io que nous utiliserons plus tard.
Ensuite, en allant dans l'onglet d'informations d'identification Credentials, créez une clé api et enregistrez-la quelque part.

C'est maintenant terminé, vous avez votre propre serveur fhir pouvant contenir jusqu'à 20 Go de données avec une mémoire de 8 Go.

5. Présentation pas à pas

La présentation pas à pas du client se trouve à src/client.py.

Le code est divisé en plusieurs parties, et nous allons couvrir chacune d'entre elles ci-dessous.

5.1. Partie 1

Dans cette partie, nous connectons notre client à notre serveur en utilisant fhirpy et nous obtenons nos ressources Patient à l'intérieur de la variable patients_resources.
A partir de cette variable nous pourrons fecth n'importe quel Patient et même les trier ou obtenir un Patient en utilisant certaines conditions.

#Partie 1----------------------------------------------------------------------------------------------------------------------------------------------------
#Créer notre client connecté à notre serveur
client = SyncFHIRClient(url='url', extra_headers={"x-api-key":"api-key"})

#Obtenir les ressources de notre patient dans lesquelles nous pourrons aller chercher et rechercher
patients_resources = client.resources('Patient')

Afin de vous connecter à votre serveur, vous devez modifier la ligne :

client = SyncFHIRClient(url='url', extra_headers={"x-api-key":"api-key"})

L'url' est un point de terminaison tandis que l'"api-key" est la clé d'api pour accéder à votre serveur.

Notez que si vous n'utilisez pas un serveur InterSystems, vous pouvez vérifier comment changer extra_headers={"x-api-key":"api-key"} en authorization = "api-key".

Comme ça, nous avons un client FHIR capable d'échanger directement avec notre serveur.

5.2. Partie 2

Dans cette partie, nous créons un Patient en utilisant Fhir.Model et nous le complétons avec un HumanName, en suivant la convention FHIR, use et family sont des chaînes et given est une liste de chaînes. e la même manière, un patient peut avoir plusieurs HumanNames, donc nous devons mettre notre HumanName dans une liste avant de le mettre dans notre patient nouvellement créé.

#Partie 2----------------------------------------------------------------------------------------------------------------------------------------------------
#Nous voulons créer un patient et l'enregistrer sur notre serveur

#Créer un nouveau patient en utilisant fhir.resources
patient0 = Patient()

#Créer un HumanName et le remplir avec les informations de notre patient
name = HumanName()
name.use = "official"
name.family = "familyname"
name.given = ["givenname1","givenname2"]

patient0.name = [name]

#Vérifier notre patient dans le terminal
print()
print("Our patient : ",patient0)
print()

#Sauvegarder (post) notre patient0, cela va le créer sur notre serveur
client.resource('Patient',**json.loads(patient0.json())).save()

Après cela, nous devons sauvegarder notre nouveau Patient sur notre serveur en utilisant notre client.

Notez que si vous lancez client.py plusieurs fois, plusieurs Patients ayant le nom que nous avons choisi seront créés.
C'est parce que, suivant la convention FHIR, vous pouvez avoir plusieurs Patients avec le même nom, seul l' id est unique sur le serveur.
Alors pourquoi n'avons-nous pas rempli notre Patient avec un id de la même façon que nous avons rempli son nom ?
Parce que si vous mettez un id à l'intérieur de la fonction save(), la sauvegarde agira comme une mise à jour avant d'agir comme un sauveur, et si l'id n'est en fait pas déjà sur le serveur, il le créera comme prévu ici. Mais comme nous avons déjà des patients sue notre serveur, ce n'est pas une bonne idée de créer un nouveau patient et d'allouer à la main un Identifiant puisque la fonction save() et le serveur sont faits pour le faire à votre place.

Nous conseillons donc de commenter la ligne après le premier lancement.

5.3. Partie 3

Dans cette partie, nous avons un client qui cherche dans nos patients_resources un patient nommé d'après celui que nous avons créé précédemment.

#Partie 3----------------------------------------------------------------------------------------------------------------------------------------------------
#Maintenant, nous voulons obtenir un certain patient et ajouter son numéro de téléphone et changer son nom avant de sauvegarder nos changements sur le serveur

#Obtenez le patient en tant que fhir.resources Patient de notre liste de ressources de patients qui a le bon nom, pour la commodité, nous allons utiliser le patient que nous avons créé avant
patient0 = Patient.parse_obj(patients_resources.search(family='familyname',given='givenname1').first().serialize())

#Créer le nouveau numéro de téléphone de notre patient
telecom = ContactPoint()

telecom.value = '555-748-7856'
telecom.system = 'phone'
telecom.use = 'home'

#Ajouter le téléphone de notre patient à son dossier
patient0.telecom = [telecom]

#Changer le deuxième prénom de notre patient en "un autre prénom"
patient0.name[0].given[1] = "anothergivenname"

#Vérifiez notre Patient dans le terminal
print()
print("Notre patient avec le numéro de téléphone et le nouveau prénom : ",patient0)
print()

#Sauvegarder (mettre) notre patient0, ceci sauvera le numéro de téléphone et le nouveau prénom au patient existant de notre serveur
client.resource('Patient',**json.loads(patient0.json())).save()

Une fois que nous l'avons trouvé, nous ajoutons un numéro de téléphone à son profil et nous changeons son prénom en un autre.

Maintenant nous pouvons utiliser la fonction de mise à jour de notre client pour mettre à jour notre patient sur le serveur.

5.4. Partie 4

Dans cette partie, nous voulons créer une observation pour notre patient précédent, pour ce faire, nous cherchons d'abord notre patients_resources pour notre patient, puis nous obtenons son identifiant, qui est son identificateur unique.

#Partie 4----------------------------------------------------------------------------------------------------------------------------------------------------
#Maintenant nous voulons créer une observation pour notre client

#Obtenir l'identifiant du patient auquel vous voulez attacher l'observation
id = Patient.parse_obj(patients_resources.search(family='familyname',given='givenname1').first().serialize()).id
print("id of our patient : ",id)

#Placer notre code dans notre observation, code qui contient des codages qui sont composés de système, code et affichage
coding = Coding()
coding.system = "https://loinc.org"
coding.code = "1920-8"
coding.display = "Aspartate aminotransférase [Activité enzymatique/volume] dans le sérum ou le plasma"
code = CodeableConcept()
code.coding = [coding]
code.text = "Aspartate aminotransférase [Activité enzymatique/volume] dans le sérum ou le plasma"

#Créer une nouvelle observation en utilisant fhir.resources, nous entrons le statut et le code dans le constructeur car ils sont nécessaires pour valider une observation
observation0 = Observation(status="final",code=code)

#Définir notre catégorie dans notre observation, catégorie qui détient les codages qui sont composés de système, code et affichage
coding = Coding()
coding.system = "https://terminology.hl7.org/CodeSystem/observation-category"
coding.code = "laboratoire"
coding.display = "laboratoire"
category = CodeableConcept()
category.coding = [coding]
observation0.category = [category]

#Définir l'heure de notre date effective dans notre observation
observation0.effectiveDateTime = "2012-05-10T11:59:49+00:00"

#Régler l'heure de notre date d'émission dans notre observation
observation0.issued = "2012-05-10T11:59:49.565+00:00"

#Définir notre valueQuantity dans notre observation, valueQuantity qui est composée d'un code, d'un unir, d'un système et d'une valeur
valueQuantity = Quantity()
valueQuantity.code = "U/L"
valueQuantity.unit = "U/L"
valueQuantity.system = "https://unitsofmeasure.org"
valueQuantity.value = 37.395
observation0.valueQuantity = valueQuantity

#Définir la référence à notre patient en utilisant son identifiant
reference = Reference()
reference.reference = f"Patient/{id}"
observation0.subject = reference

#Vérifiez notre observation dans le terminal
print()
print("Notre observation : ",observation0)
print()

#Sauvegarder (poster) notre observation0 en utilisant notre client
client.resource('Observation',**json.loads(observation0.json())).save()

Ensuite, nous enregistrons notre observation à l'aide de la fonction save().

5.5. Conclusion de la présentation

Si vous avez suivi ce parcours, vous savez maintenant exactement ce que fait client.py, vous pouvez le lancer et vérifier votre Patient et votre Observation nouvellement créés sur votre serveur.

6. Comment ça marche

6.1. Les importations

from fhirpy import SyncFHIRClient

from fhir.resources.patient import Patient
from fhir.resources.observation import Observation
from fhir.resources.humanname import HumanName
from fhir.resources.contactpoint import ContactPoint

import json

La première importation est le client, ce module va nous aider à nous connecter au serveur, à obtenir et exporter des ressources.

Le module fhir.resources nous aide à travailler avec nos ressources et nous permet, grâce à l'auto-complétion, de trouver les variables dont nous avons besoin.

La dernière importation est json, c'est un module nécessaire pour échanger des informations entre nos 2 modules.

6.2. Création du client

client = SyncFHIRClient(url='url', extra_headers={"x-api-key":"api-key"})

L''url' est ce que nous avons appelé avant un point de terminaison tandis que l'"api-key"' est la clé que vous avez générée plus tôt.

Notez que si vous n'utilisez pas un serveur InterSystems, vous voudrez peut-être changer le extra_headers={"x-api-key" : "api-key"} en authorization = "api-key"
Comme ça, nous avons un client FHIR capable d'échanger directement avec notre serveur.

Par exemple, vous pouvez accéder à vos ressources Patient en faisant patients_resources = client.resources('Patient') , fà partir de là, vous pouvez soit obtenir vos patients directement en utilisant patients = patients_resources.fetch() ou en allant chercher après une opération, comme :
patients_resources.search(family='familyname',given='givenname').first() cette ligne vous donnera le premier patient qui sort ayant pour nom de famille 'familyname' et pour nom donné 'givenname'.

6.3. Travailler sur nos ressources

Une fois que vous avez les ressources que vous voulez, vous pouvez les analyser dans une ressource fhir.resources.

Par exemple :

patient0 = Patient.parse_obj(patients_resources.search(family='familyname',given='givenname1').first().serialize())

patient0 est un patient de fhir.resources, pour l'obtenir nous avons utilisé nos patients_resources comme cela a été montré précédemment où nous avons sélectionné un certain nom de famille et un prénom, après cela nous avons pris le premier qui est apparu et l'avons sérialisé.
En mettant ce patient sérialisé à l'intérieur d'un Patient.parse_obj nous allons créer un patient de fhir.resources .

Maintenant, vous pouvez accéder directement à n'importe quelle information que vous voulez comme le nom, le numéro de téléphone ou toute autre information.
Pour ce faire, utilisez juste par exemple :

patient0.name

Cela renvoie une liste de HumanName composée chacune d'un attribut use un attribut family un attribut given as the FHIR convention is asking.
Cela signifie que vous pouvez obtenir le nom de famille de quelqu'un en faisant :

patient0.name[0].family

6.4. Sauvegarder nos changements

Pour enregistrer toute modification de notre serveur effectuée sur un fhir.resources ou pour créer une nouvelle ressource serveur, nous devons utiliser à nouveau notre client.

client.resource('Patient',**json.loads(patient0.json())).save()

En faisant cela, nous créons une nouvelle ressource sur notre client, c'est-à-dire un patient, qui obtient ses informations de notre fhir.resources patient0. Ensuite, nous utilisons la fonction save() pour poster ou mettre notre patient sur le serveur.

7. Comment commencer le codage

Ce référentiel est prêt à être codé dans VSCode avec les plugins InterSystems. Ouvrez /src/client.py pour commencer à coder ou utiliser l'autocomplétion.

8. Ce qu'il y a dans le référentiel

8.1. Dockerfile

Le dockerfile le plus simple pour démarrer un conteneur Python.
Utilisez docker build . pour construire et rouvrir votre fichier dans le conteneur pour travailler à l'intérieur de celui-ci.

8.2. .vscode/settings.json

Fichier de paramètres.

8.3. .vscode/launch.json

Fichier de configuration si vous voulez déboguer.

0
0 808
Article Guillaume Rongier · Août 31, 2022 6m read

Nous continuons à observer les possibilités de Django, et son utilisation avec IRIS. Dans la première partie nous avons regardé comment définir des modèles et se connecter à des tableaux déjà existants dans IRIS, dans la suite nous avons étendu le portail d'administration intégré de Django, avec la possibilité de voir quelles données nous avons dans ces modèles, avec des filtres, l'édition et même la pagination.

Il est temps de passer à l'action, nous allons maintenant créer une API REST, sur Django, basée sur les mêmes données, que nous avons utilisées auparavant à partir du paquet posts-and-tags.

Pour ce faire, nous utiliserons Django REST Framework

Django REST Framework

Le cadre REST de Django est une boîte à outils puissante et flexible permettant de créer des API Web.

Quelques raisons pour lesquelles vous pourriez vouloir utiliser le cadre REST :

  • L'API navigable sur le Web est un avantage considérable pour vos développeurs.
  • Politiques d'authentification comprenant des paquets pour OAuth1a et OAuth2.
  • Sérialisation qui prend en charge les sources de données ORM et non ORM.
  • Personnalisable jusqu'en bas - utilisez simplement des visualisations régulières basées sur des fonctions si vous n'avez pas besoin des fonctionnalités les plus puissantes.
  • Une documentation complète et un support communautaire important.
  • Utilisé par des entreprises de renommée internationale, telles que Mozilla, Red Hat, Heroku et Eventbrite, qui lui font confiance.
Tout d'abord, nous devons mettre à jour notre fichier requirements.txt avec les dépendances
# Django itself
django>=4.0.0

# Pilote InterSystems IRIS pour Django, et pilote DB-API d'InterSystems
django-iris=>0.1.13
https://raw.githubusercontent.com/intersystems-community/iris-driver-distribution/main/DB-API/intersystems_irispython-3.2.0-py3-none-any.whl

# Cadre REST de Django et ses dépendances facultatives
djangorestframework>=3.4.4
# Support du format Markdown pour l'API navigable.
markdown>=3.0.0
# Support de filtrage
django-filter>=1.0.1

Et installez-les

python install -r requirements.txt

Première version de l'API

Pour cela, mettez à jour le fichier urls.py. Ici on dit, cela de la racine pour notre api comme api/, donc toutes les demandes à http://localhost:8000/api/ seront utilisées comme racine pour nos demandes API

from django.contrib import admin
from django.urls import path, include
from rest_framework import routers

router = routers.DefaultRouter()

urlpatterns = [
    path('api/', include(router.urls)),
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
]

Le cadre Django REST a une interface utilisateur intégrée pour les API, lorsque le serveur fonctionne en mode de développement avec DEBUG=True dans settings.py. Et nous pouvons ouvrir cette URL

Tout fonctionne, même sans rien définir, juste en connectant ce cadre à l'url. Il supporte l'autorisation, pour les requêtes nécessitant une autorisation. 

$ curl http://127.0.0.1:8000/api/
{}

Définissez une API pour le projet, nous utiliserons au minimum quelques fonctionnalités du cadre REST.

  • Les sérialiseurs permettent de convertir des données complexes, telles que des querysets et des instances de modèles, en types de données Python natifs qui peuvent ensuite être facilement convertis en JSON, XML ou d'autres types de contenu. Les sérialiseurs fournissent également une désérialisation, permettant aux données analysées d'être reconverties en types complexes, après avoir validé les données entrantes.
  • ViewSet - permet de combiner la logique d'un ensemble de visualisations connexes dans une seule classe

Ajoutons un point de terminaison pour nos messages de notification. Très simple, pourtant. Regardez le contenu mis à jour de _urls.py _

from django.contrib import admin
from django.urls import path, include
from rest_framework import routers, serializers, viewsets
from .models import CommunityPost

router = routers.DefaultRouter()

classCommunityPostSerializer(serializers.HyperlinkedModelSerializer):classMeta:# classe avec modèle
        model = CommunityPost
        # liste des champs à afficher, ou uniquement '__all__'
        fields = '__all__'# les ViewSets définissent le comportement de la visualisation.classCommunityPostViewSet(viewsets.ModelViewSet):
    queryset = CommunityPost.objects.all()
    serializer_class = CommunityPostSerializer

# connexion à l'API
router.register(r'posts', CommunityPostViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
]

Et il apparaît maintenant dans l'interface web

Il suffit de cliquer sur le lien ici, et vous obtiendrez la réponse à cette question

Faites défiler jusqu'à la fin, et vous trouverez un formulaire généré pour les nouveaux éléments, qui peuvent être ajoutés par requête POST. Tous les champs sont adaptés au type de propriétés

Dans la liste des éléments, vous pouvez cliquer sur l'URL de n'importe quel élément, et voir ceci. Seulement cet élément comme réponse, et un formulaire d'édition avec une requête PUT

Authentication

Et vous pouvez déjà changer les données, par PUT ou POST. Le besoin d'autorisation n'est pas encore activé. Le cadre REST offre diverses combinaisons d'authentifications à utiliser. Ainsi, vous pouvez ouvrir certaines ressources pour un accès anonyme en lecture seule. Et s'authentifier pour pouvoir effectuer des modifications. Ou fermer complètement tout accès. Il suffit de configurer l'accès en lecture seule pour les anonymes, et de demander une authentification pour toute modification. Pour ce faire, il suffit d'ajouter ces lignes à settings.py

REST_FRAMEWORK = {
    # Utilisez les permissions standard de Django `django.contrib.auth`,# ou autorisez l'accès en lecture seule pour les utilisateurs non authentifiés.'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
    ],
}

Avec ceci, vous ne verrez plus le formulaire jusqu'à ce que vous vous connectiez, avec le nom d'utilisateur et le mot de passe d'instance créés précédemment pour l'administration de Django.

Pagination

Par défaut, il n'y a pas de pagination, mais nous pouvons facilement l'ajouter à toute requête de liste. Mettez à jour la variable REST_FRAMEWORK dans settings.py. Configurer la classe de pagination et la taille de page par défaut

REST_FRAMEWORK = {
...
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 10,
...
}

En conséquence, cela a légèrement modifié le JSON résultant, en ajoutant des éléments pertinents, tels que les liens vers les pages suivantes et précédentes, ainsi que la quantité de tous les éléments. Et avec l'interface Web, vous pouvez parcourir les pages.

Filtrage et recherche

Il est également assez simple d'ajouter des capacités de filtrage et de recherche. Mettez à jour la variable REST_FRAMEWORK dans settings.py

REST_FRAMEWORK = {
... 'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',
    ],
...
]

Et mettez à jour CommunityPostViewSet avec une liste de champs pour le filtrage et la recherche

classCommunityPostViewSet(viewsets.ModelViewSet):
    queryset = CommunityPost.objects.all()
    serializer_class = CommunityPostSerializer
    filterset_fields = ['posttype', 'lang', 'published']
    search_fields = ['name',]

Et cela fonctionne directement depuis l'interface Web

Et finalement, nous disposons d'une API REST entièrement fonctionnelle, juste pour cette seule ressource, pour le moment. C'est assez simple pour le moment, mais il est possible de faire beaucoup de personnalisation, de connecter d'autres ressources et de les lier.

0
0 85
Article Guillaume Rongier · Août 29, 2022 9m read

Dans la première partie, j'ai montré comment démarrer un nouveau projet sur Django, ainsi que définir de nouveaux modèles et ajouter des modèles existants.

Cette fois, je vous présenterai un panneau d'administration, qui est disponible dès le départ, et comment il peut être utile.

Remarque importante : ne vous attendez pas à ce que si vous essayez de répéter les actions de cet article, cela fonctionnera pour vous, ce n'est pas le cas. Au cours de l'article, j'ai dû faire quelques corrections dans le projet django-iris, et même dans le pilote DB-API fait par InterSystems pour corriger certains problèmes là aussi, et je pense que ce pilote est encore en développement, et nous aurons un pilote plus stable dans le futur. Considérons que cet article ne fait qu'expliquer comment cela pourrait être si nous avions tous fait.

Revenons à notre code et voyons ce que nous avons dans urls.py, qui est le principal point d'entrée de toutes les requêtes web.
"""main URL Configuration

La liste `urlpatterns` dirige les URLs vers les visualisations. Pour plus d'informations, veuillez consulter :
    https://docs.djangoproject.com/en/4.0/topics/http/urls/
    Exemples :
    Visualisations des fonctions
    1. Ajoutez un import :  from my_app import views
    2. Ajouter une URL à urlpatterns :  path('', views.home, name='home')
Visualisations basées sur des classes
    1. Ajoutez un import :  from other_app.views import Home
    2. Ajouter une URL à urlpatterns :  path('', Home.as_view(), name='home')
En incluant une autre URLconf  
    1. Importez la fonction include() : from django.urls import include, path
    2. Ajoutez une URL à urlpatterns :  path('blog/', include('blog.urls'))
"""from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]

Comme vous pouvez le constater, l'URL admin y est déjà définie 

Lançons le serveur de développement, par la commande

python manage.py runserver

Si vous passez par l'URL http://localhost:8000/admin, vous trouverez le formulaire de connexion à l'administration de Django 

Pour entrer ici, nous avons besoin d'un utilisateur, et nous pouvons le créer avec cette commande

$ python manage.py createsuperuser
Nom d'utilisateur (laissez vide pour utiliser 'daimor') : admin
Adresse e-mail : admin@example.com
Mot de passe : 
Mot de passe ( de nouveau) : 
Le mot de passe est trop similaire au nom d'utilisateur.
Ce mot de passe est trop court. Il doit contenir au moins 8 caractères.
Ce mot de passe est trop courant.
Contourner la validation du mot de passe et créer un utilisateur quand même ? [O/N] : O
Le superutilisateur a été créé avec succès.

Nous pouvons maintenant utiliser ce nom d'utilisateur et ce mot de passe. Il est assez vide pour le moment, mais il donne déjà accès aux groupes et aux utilisateurs.

Plus de données

Précédemment j'ai déjà installé le paquet post-and-tags avec zpm, vous pouvez le faire aussi

zpm "install posts-and-tags"

Maintenant nous pouvons obtenir les modèles pour tous les tableaux (community.post, community.comment, community.tag) installés par ce paquet

$ python manage.py inspectdb community.post community.comment community.tag > main/models.py

Le fichier sera un peu long, donc, je l'ai mis dans un spoiler

 
main/models.py
# This is an auto-generated Django model module.# Vous devrez effectuer les opérations suivantes manuellement pour nettoyer tout cela :#   * Réorganiser les modèles' order#   * Assurez-vous que chaque modèle a un champ avec primary_key=True#   * Assurez-vous que chaque ForeignKey et OneToOneField a `on_delete` réglé sur la valeur désirée behavior#   * Supprimez les lignes `managed = False` si vous souhaitez autoriser Django à créer, modifier et supprimer la table# N'hésitez pas à renommer les modèles, mais ne renommez pas les valeurs de db_table ou les noms de champs.from django.db import models

classCommunityPost(models.Model): acceptedanswerts = models.DateTimeField(db_column='AcceptedAnswerTS', blank=True, null=True) # Nom du champ en minuscules. author = models.CharField(db_column='Author', max_length=50, blank=True, null=True) # Nom du champ en minuscules. avgvote = models.IntegerField(db_column='AvgVote', blank=True, null=True) # Nom du champ en minuscules. commentsamount = models.IntegerField(db_column='CommentsAmount', blank=True, null=True) # Nom du champ en minuscules. created = models.DateTimeField(db_column='Created', blank=True, null=True) # Nom du champ en minuscules. deleted = models.BooleanField(db_column='Deleted', blank=True, null=True) # Nom du champ en minuscules. favscount = models.IntegerField(db_column='FavsCount', blank=True, null=True) # Nom du champ en minuscules. hascorrectanswer = models.BooleanField(db_column='HasCorrectAnswer', blank=True, null=True) # Nom du champ en minuscules. hash = models.CharField(db_column='Hash', max_length=50, blank=True, null=True) # Nom du champ en minuscules. lang = models.CharField(db_column='Lang', max_length=50, blank=True, null=True) # Nom du champ en minuscules. name = models.CharField(db_column='Name', max_length=250, blank=True, null=True) # Nom du champ en minuscules. nid = models.IntegerField(db_column='Nid', primary_key=True) # Nom du champ en minuscules. posttype = models.CharField(db_column='PostType', max_length=50, blank=True, null=True) # Nom du champ en minuscules. published = models.BooleanField(db_column='Published', blank=True, null=True) # Nom du champ en minuscules. publisheddate = models.DateTimeField(db_column='PublishedDate', blank=True, null=True) # Nom du champ en minuscules. subscount = models.IntegerField(db_column='SubsCount', blank=True, null=True) # Nom du champ en minuscules. tags = models.CharField(db_column='Tags', max_length=350, blank=True, null=True) # Nom du champ en minuscules. text = models.TextField(db_column='Text', blank=True, null=True) # Nom du champ en minuscules. translated = models.BooleanField(db_column='Translated', blank=True, null=True) # Nom du champ en minuscules. type = models.CharField(db_column='Type', max_length=50, blank=True, null=True) # Nom du champ en minuscules. views = models.IntegerField(db_column='Views', blank=True, null=True) # Nom du champ en minuscules. votesamount = models.IntegerField(db_column='VotesAmount', blank=True, null=True) # Nom du champ en minuscules.classMeta: managed = False db_table = 'community.post'classCommunityComment(models.Model): id1 = models.CharField(db_column='ID1', primary_key=True, max_length=62) # Nom du champ en minuscules. acceptedanswerts = models.DateTimeField(db_column='AcceptedAnswerTS', blank=True, null=True) # Nom du champ en minuscules. author = models.CharField(db_column='Author', max_length=50, blank=True, null=True) # Nom du champ en minuscules. avgvote = models.IntegerField(db_column='AvgVote', blank=True, null=True) # Nom du champ en minuscules. correct = models.BooleanField(db_column='Correct', blank=True, null=True) # Nom du champ en minuscules. created = models.DateTimeField(db_column='Created', blank=True, null=True) # Nom du champ en minuscules. hash = models.CharField(db_column='Hash', max_length=50, blank=True, null=True) # Nom du champ en minuscules. id = models.IntegerField(db_column='Id') # Nom du champ en minuscules. post = models.CharField(db_column='Post', max_length=50, blank=True, null=True) # Nom du champ en minuscules. text = models.TextField(db_column='Text', blank=True, null=True) # Nom du champ en minuscules. texthash = models.CharField(db_column='TextHash', max_length=50, blank=True, null=True) # Nom du champ en minuscules. type = models.CharField(db_column='Type', max_length=50) # Nom du champ en minuscules. votesamount = models.IntegerField(db_column='VotesAmount', blank=True, null=True) # Nom du champ en minuscules.classMeta: managed = False db_table = 'community.comment' unique_together = (('type', 'id'),)

classCommunityTag(models.Model): description = models.TextField(db_column='Description', blank=True, null=True) # Nom du champ en minuscules. name = models.TextField(db_column='Name', primary_key=True) # Nom du champ en minuscules.classMeta: managed = False db_table = 'community.tag'

Le tableau de bord d'administration en Django peut être étendu par le développeur. Il est ainsi possible d'ajouter des tableaux supplémentaires. Pour ce faire, nous devons ajouter un nouveau fichier nommé main/admin.py. J'ai ajouté quelques commentaires dans le code, pour expliquer certaines lignes.

from django.contrib import admin

# Importation de nos modèles communautaires pour nos tableaux dans IRISfrom .models import (CommunityPost, CommunityComment, CommunityTag)

# classe de registre qui remplace le comportement par défaut du modèle CommunityPost@admin.register(CommunityPost)classCommunityPostAdmin(admin.ModelAdmin):# liste des propriétés à afficher dans le tableau view
  list_display = ('posttype', 'name', 'publisheddate')
  # liste des propriétés pour lesquelles il faut afficher un filtre à la droite du tableau
  list_filter = ('posttype', 'lang', 'published')
  # ordre par défaut, c'est-à-dire à partir de la date la plus récente de PublishedDate
  ordering = ['-publisheddate', ]

@admin.register(CommunityComment)classCommunityCommentAdmin(admin.ModelAdmin):# seuls ces deux champs apparaissent, ( le post est numérique par id dans le tableau post)
  list_display = ('post', 'created')
  # classées par date de création
  ordering = ['-created', ]

@admin.register(CommunityTag)classCommunityTagAdmin(admin.ModelAdmin):# pas tellement à montrer
  list_display = ('name', )

Portail d'extension

Retournons à notre page d'administration de Django, et examinons les nouveaux éléments qui y ont été ajoutés

Sur le côté droit, vous verrez le panneau de filtrage, et ce qui est important, c'est qu'il contient toutes les valeurs possibles dans des champs particuliers et qu'il les affiche.

Malheureusement, InterSystems SQL ne permet pas d'utiliser les fonctions LIMIT, OFFSET, attendues d'une manière ou d'une autre par Django. Par ailleurs, Django ne permet pas d'utiliser la fonction TOP. Ainsi, la pagination sera affichée ici mais ne fonctionnera pas. Et il n'y a aucun moyen de la faire fonctionner pour le moment, et je ne pense pas que cela fonctionnera un jour, malheureusement.

Vous pouvez même plonger dans l'objet, et Django affichera le formulaire, avec les types de champs corrects. ( remarque : Cet ensemble de données ne contient pas de données dans le champ Texte)

Objet du commentaire

 
Problèmes avec les licences à prévoir sur Community Edition
Si vous travaillez avec Community Edition, vous pouvez être confronté à ce problème. Voici à quoi cela ressemble lorsque toutes les connexions sont occupées, et cela peut arriver très vite. Et si vous voyez que la réponse de votre serveur est assez longue, c'est probablement le cas, car IRIS ne répond pas rapidement dans ce cas, pour des raisons inconnues il prend beaucoup de temps.
<p>
  <img src="/sites/default/files/inline/images/images/image(4239).png" />
</p>

<p>
  Même quand IRIS dit qu'il vous reste plus des places
</p>

<p>
  <img src="/sites/default/files/inline/images/images/image(4240).png" />
</p>

<p>
  Il n'autorise pas plus de 5 connexions, il faut donc terminer un ou plusieurs processus pour que cela fonctionne, ou redémarrer le serveur Django
</p>

<p>
  <img src="/sites/default/files/inline/images/images/image(4241).png" />
</p>

<p>
  Dans le cadre du développement, vous pouvez également limiter le serveur Django à un mode sans threads, afin qu'il fonctionne dans un seul processus. Et il ne devrait pas obtenir plus de connexions à IRIS
</p>

<pre>python manage.py runserver --nothreading</pre>
0
0 84
Article Guillaume Rongier · Août 24, 2022 9m read

Il y a quelque temps, j'ai présenté un nouveau pilote de Django pour IRIS. Maintenant, voyons comment utiliser Django avec IRIS en pratique.

Meilleures pratiques pour les nouveaux projets Python et Django | de Luan Pablo |  Analytics Vidhya | Medium

Remarque importante : l'utilisation de Django avec IRIS Community Edition ne fonctionnera pratiquement pas, Community Edition n'a que 5 connexions disponibles, et Django les utilisera très rapidement. Malheureusement, pour cette raison, je ne peux pas recommander cette méthode pour le développement de nouvelles applications, en raison de la difficulté à prévoir l'utilisation des licences.

Lancement du projet Django

Tout d'abord, démarrons notre nouveau projet Django. Pour ce faire, nous devons d'abord installer Django lui-même.

pip install django

Ensuite, créez un projet nommé demo, cela permettra de créer un dossier de projets avec le même nom

django-admin startproject demo

cd demo

ou vous pouvez le faire dans un dossier existant

django-admin startproject main .

Cette commande va remplir quelques fichiers python pour nous. 

Where, 

  • manage.py: utilitaire de ligne de commande qui vous permet d'interagir avec ce projet Django de diverses manières 
  • main le répertoire correspondant au paquetage Python de votre projet
  • main/__init__.py: un fichier vide qui indique à Python que ce répertoire doit être considéré comme un package Python
  • main/settings.py: paramètres/configuration pour ce projet Django
  • main/urls.py: Les déclarations d'URL pour ce projet Django ; une "table des matières" de votre site alimenté par Django.
  • main/asci.py: Un point d'entrée pour les serveurs web compatibles avec ASGI pour servir votre projet.
  • main/wsci.py: Un point d'entrée pour les serveurs web compatibles avec WSGI pour servir votre projet.

Même à partir de ce point, nous pouvons commencer notre projet et il fonctionnera dans une certaine mesure

$ python manage.py runserver                                                                                                                              
Contrôle des modifications de fichiers avec StatReloader
Réalisation de vérifications du système...

La vérification du système n'a identifié aucun problème (0 désactivé). Vous avez 18 migration(s) non appliquée(s). Votre projet ne fonctionnera pas correctement tant que vous n'aurez pas appliqué les migrations pour les applications suivantes : admin, auth, contenttypes, sessions.
Lancez 'python manage.py migrate' pour les appliquer.
22 juillet 2022 - 15:24:12
Django version 4.0.6, en utilisant les paramètres 'main.settings'.
Démarrage du serveur de développement à l'adresse http://127.0.0.1:8000/
Quittez le serveur avec CONTROL-C.

Now you can go to the browser and open URL http://127.0.0.1:8000 there

Ajout IRIS

Ajoutons l'accès à IRIS, et pour le faire nous devons installer quelques dépendances à notre projet, et la bonne façon de le faire, est de le définir dans un fichier nommé requirements.txt avec ce contenu, où nous devons ajouter django comme une dépendance_

# Django itself
django>=4.0.0

Et ensuite, le pilote pour IRIS pour Django, est publié. Malheureusement, InterSystems ne veut pas publier ses propres pilotes sur PyPI, nous devons donc les définir de cette horrible façon. Sachez qu'ils peuvent le supprimer à tout moment, et qu'il peut donc ne plus fonctionner à l'avenir. (S'il était dans PyPI, il serait installé comme une dépendance de django-iris, et ne serait pas nécessaire de le définir explicitement)

# Pilote IRIS d'InterSystems pour Django et pilote DB-API d'InterSystems
django-iris==0.1.13
https://raw.githubusercontent.com/intersystems-community/iris-driver-distribution/main/DB-API/intersystems_irispython-3.2.0-py3-none-any.whl

Installez les dépendances définies dans ce fichier avec la commande

pip install -r requirements.txt

Maintenant, nous pouvons configurer notre projet pour utiliser IRIS, pour ce faire, nous devons mettre à jour le paramètre DATABASES dans le fichier settings.py, avec des lignes comme celle-ci, où NAME pointe vers l'espace de nom dans IRIS, et le port vers le SuperPort où IRIS est disponible

DATABASES = {
    'default': {
        'ENGINE': 'django_iris',
        'NAME': 'USER',
        'USER': '_SYSTEM',
        'PASSWORD': 'SYS',
        'HOST': 'localhost',
        'PORT': 1982,
    }
}

Django a un ORM, et des modèles stockés dans le projet, et cela nécessite de synchroniser les modèles Django avec la base de données en tant que tableaux. Par défaut, il y a quelques modèles liés à l'authentification. Et nous pouvons lancer le processus de migration maintenant

$ python manage.py migrate
Opérations à effectuer :
  Appliquer toutes les migrations : admin, auth, contenttypes, sessions
Exécution des migrations :
  Application de contenttypes.0001_initial... OK
  Application d'auth.0001_initial... OK
  Application d'admin.0001_initial... OK
  Application d'admin.0002_logentry_remove_auto_add... OK
  Application d'admin.0003_logentry_add_action_flag_choices... OK
  Application de contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Application d'auth.0003_alter_user_email_max_length... OK
  Application d'auth.0004_alter_user_username_opts... OK
  Application d'auth.0005_alter_user_last_login_null... OK
  Application d'auth.0006_require_contenttypes_0002... OK
  Application d'auth.0007_alter_validators_add_error_messages... OK
  Application d'auth.0008_alter_user_username_max_length... OK
  Application d'auth.0009_alter_user_last_name_max_length... OK
  Application d'auth.0010_alter_group_name_max_length... OK
  Application d'auth.0011_update_proxy_permissions... OK
  Application d'auth.0012_alter_user_first_name_max_length... OK
  Application de sessions.0001_initial... OK

Si vous allez à l'IRIS, vous y trouverez des tableaux supplémentaires

Définissez d'autres modèles

Il est temps d'ajouter certains de nos modèles. Pour ce faire, ajoutez un nouveau fichier models.py, avec un contenu comme suit

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    dob = models.DateField()
    sex = models.BooleanField()    

Comme vous pouvez le voir, il comporte différents types de champs. Ensuite, ce modèle doit être préparé pour la base de données. Avant de le faire, ajoutez notre projet main à INSTALLED_APPS dans settings.py

INSTALLED_APPS = [
    ....    'main',
]

Et nous pouvons exécuter makemigrations. Cette commande doit être appelée après toute modification du modèle, elle s'occupe des modifications historiques du modèle, et quelle que soit la version de l'application installée, la migration saura mettre à jour le schéma de la base de données

$ python manage.py makemigrations main
Migrations pour 'main':
  main/migrations/0001_initial.py
    - Créez le modèle Person

Nous pouvons exécuter migrate à nouveau, il sait déjà que les migrations précédentes ont déjà été effectuées, donc, il exécute seulement la nouvelle migration

$ python manage.py migrate            
Opérations à effectuer :
  Application de toutes les migrations : admin, auth, contenttypes, main, sessions
Exécution des migrations :
  Application de main.0001_initial... OK

Et actuellement, nous pouvons voir comment la migration se présente du point de vue de SQL

$ python manage.py sqlmigrate main 0001
--
-- Créez le modèle Person
--
CREAEZ TABLEAU "main_person" ("id" BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY, "first_name" VARCHAR(30) NULL, "last_name" VARCHAR(30) NULL, "dob" DATE NOT NULL, "sex" BIT NOT NULL);

Mais il est possible d'avoir accès aux tableaux déjà existants dans la base de données, par exemple, si vous avez déjà une application qui fonctionne. J'ai installé le paquet zpm posts-and-tags, faisons un modèle pour le tableau community.posts

$ python manage.py inspectdb community.post 
# Ceci est un module de modèle Django généré automatiquement.
# Vous devrez faire ce qui suit manuellement pour nettoyer tout ceci :
# * Réorganiser l'ordre des modèles
# * S'assurer que chaque modèle a un champ avec primary_key=True
# * Assurez-vous que chaque ForeignKey, et OneToOneField a un `on_delete` réglé sur le comportement désiré.
# * Supprimez les lignes `managed = False` si vous souhaitez autoriser Django à créer, modifier et supprimer le tableau.
# N'hésitez pas à renommer les modèles, mais ne renommez pas les valeurs de db_table ou les noms de champs
à partir de django.db import models

classe CommunityPost(models.Model):
    id = models.AutoField(db_column='ID')  # Nom du champ en minuscules.
    acceptedanswerts = models.DateTimeField(db_column='AcceptedAnswerTS', blank=True, null=True)  # Nom du champ en minuscules.
    author = models.CharField(db_column='Author', max_length=50, blank=True, null=True)  # Nom du champ en minuscules.
    avgvote = models.IntegerField(db_column='AvgVote', blank=True, null=True)  # Nom du champ en minuscules.
    commentsamount = models.IntegerField(db_column='CommentsAmount', blank=True, null=True)  # Nom du champ en minuscules.
    created = models.DateTimeField(db_column='Created', blank=True, null=True)  # Nom du champ en minuscules.
    deleted = models.BooleanField(db_column='Deleted', blank=True, null=True)  # Nom du champ en minuscules.
    favscount = models.IntegerField(db_column='FavsCount', blank=True, null=True)  # Nom du champ en minuscules.
    hascorrectanswer = models.BooleanField(db_column='HasCorrectAnswer', blank=True, null=True)  # Nom du champ en minuscules.
    hash = models.CharField(db_column='Hash', max_length=50, blank=True, null=True)  # Nom du champ en minuscules.
    lang = models.CharField(db_column='Lang', max_length=50, blank=True, null=True)  # Nom du champ en minuscules.
    name = models.CharField(db_column='Name', max_length=250, blank=True, null=True)  # Nom du champ en minuscules.
    nid = models.IntegerField(db_column='Nid', primary_key=True)  # Nom du champ en minuscules.
    posttype = models.CharField(db_column='PostType', max_length=50, blank=True, null=True)  # Nom du champ en minuscules.
    published = models.BooleanField(db_column='Published', blank=True, null=True)  # Nom du champ en minuscules.
    publisheddate = models.DateTimeField(db_column='PublishedDate', blank=True, null=True)  # Nom du champ en minuscules.
    subscount = models.IntegerField(db_column='SubsCount', blank=True, null=True)  # Nom du champ en minuscules.
    tags = models.CharField(db_column='Tags', max_length=350, blank=True, null=True)  # Nom du champ en minuscules.
    text = models.CharField(db_column='Text', max_length=-1, blank=True, null=True)  # Nom du champ en minuscules.
    translated = models.BooleanField(db_column='Translated', blank=True, null=True)  # Nom du champ en minuscules.
    type = models.CharField(db_column='Type', max_length=50, blank=True, null=True)  # Nom du champ en minuscules.
    views = models.IntegerField(db_column='Views', blank=True, null=True)  # Nom du champ en minuscules.
    votesamount = models.IntegerField(db_column='VotesAmount', blank=True, null=True)  # Nom du champ en minuscules.    
    
    classe Meta:
        managed = False
        db_table = 'community.post'

Elle est marquée comme managed = False, ce qui signifie que makemigrations et migrate ne fonctionneront pas pour cette table. En omettant le nom du tableau, vous obtiendrez une grande liste de modules, y compris les tableaux déjà créés par Django auparavant

0
0 98
Article Guillaume Rongier · Août 17, 2022 3m read

Avec les dernières améliorations concernant le support de Python dans IRIS, et la poursuite du travail sur le support de Python DB-API par InterSystems. J'ai implémenté le support IRIS dans le projet Django où Python DB-API est utilisé pour travailler avec d'autres bases de données.

Essayons une application simple sur Django, qui stocke ses données dans IRIS.

todo App

Cette application est disponible sur [GitHub](https://github.com/caretdev/django-iris-todo), clonons-la
git clone https://github.com/caretdev/django-iris-todo
cd django-iris-todo

Et nous pouvons le construire et le démarrer avec Docker-compose

docker-compose up -d --build

Cela prendra un certain temps, quand IRIS sera démarré, et l'application Django l'attrapera, migrez les modèles là et lancez l'application aussi, une fois qu'elle est démarrée, elle sera disponible par http://localhost:8000/ et vous devriez avoir l'image comme ci-dessus.

Mais, comment cela fonctionne-t-il ?

Pour le faire fonctionner, il faut que l'interface InterSystems Python DB-API soit installée, elle est livrée avec la dernière version de l'aperçu, vous devez donc avoir la version 2022.1.0.114.0 ou une version supérieure et elle se trouve dans le dossier de l'instance &lt;INSTALL_DIR>/dev/python/. Ce fichier peut également être téléchargé à partir de ce depôt GitHub 

pip3 install intersystems_irispython-3.2.0-py3-none-any.whl

Le back-end IRIS de Django est implémenté par un autre projet, et qui peut être installé avec pip, et pour sûr nous avons besoin de django lui-même, installons-les

pip3 install django django-iris

Une autre façon d'installer les paquets requis dans Python est d'utiliser le fichier requirements.txt

pip3 install -r requirements.txt

Alors que ce fichier contient, les lignes suivantes

https://raw.githubusercontent.com/intersystems-community/iris-driver-distribution/main/intersystems_irispython-3.2.0-py3-none-any.whl
Django~=4.0.2
django-iris~=0.1.5

Connectons notre application Django à l'IRIS, ouvrons le fichier todoApp/settings.py

DATABASES définit les paramètres de connexion à la base de données

ENGINE doit être django_IRIS

NAME doit pointer vers l'espace de nom Namespace dans IRIS.

Il suffit de le changer en quelque chose, où il peut se connecter. Par exemple

DATABASES = {
    'default': {
        'ENGINE': 'django_iris',
        'NAME': 'DJANGOTODO',
        'HOST': 'localhost',
        'PORT': 1972,
        'USER': '_SYSTEM',
        'PASSWORD': 'SYS',
    }
}

Et lançons la migration

python3 manage.py migrate

Aucune erreur, tous les tableaux du côté d'IRIS sont créés.

Et nous sommes prêts à démarrer notre application

python3 manage.py runserver

Django est livré avec un panneau d'administration

python3 manage.py createsuperuser

Et le panneau d'administration est disponible par le lien http://localhost:8000/admin/

Et comment il est stocké dans IRIS

  Le travail est toujours en cours pour le pilote Python DB-API d'InterSystems, et aussi pour ce projet django-iris.

Soyez conscient que cela ne fonctionnera pas aussi bien sur la version Community Edition, en raison de la façon dont Django se connecte à la base de données, il peut utiliser toutes les licences très rapidement.

Si vous aimez le projet, et son impact futur sur l'utilisation d'IRIS, veuillez voter sur Compétition OpenExchange

0
0 78
Article Lorenzo Scalese · Août 10, 2022 11m read

Depuis IRIS 2021.2, il est possible d'écrire des Méthodes de classe en utilisant le langage Python. J'ai utilisé cette nouvelle fonctionnalité pour détecter des personnes et des objets dans des images, en utilisant ImageAI. Le créateur d'ImageAI la définit comme suit : "Une bibliothèque python open-source construite pour permettre aux développeurs de créer des applications et des systèmes avec des capacités autonomes de Deep Learning et de vision par ordinateur en utilisant des lignes de code simples et peu nombreuses." Dans cet article, vous apprendrez comment appliquer la Vision par ordinateur de l'IA pour détecter des objets et des personnes à l'intérieur d'images.

Étapes de l'analyse des images à l'aide d'ImageAI

  1. Cliquez sur https://openexchange.intersystems.com/package/AI-Image-Object-Detector et sur le bouton Télécharger (Download) pour accéder au projet Git.
  2. Clone/git tire le référentiel dans n'importe quel répertoire local
$ git clone https://github.com/yurimarx/image-analyzer.git
  1. Ouvrez un terminal Docker dans ce répertoire et exécutez :
$ docker-compose build
  1. Lancez le conteneur IRIS :
$ docker-compose up -d
  1. Connectez-vous à votre Postman (ou autre client REST similaire) et configurez la requête conformément à cette image :

Request Image Analysis input

  • Méthode : POST
  • URL: http://localhost:52773/image-analyzer/analyzeImage
  • Corps : données du formulaire "form-data"
  • Clé : fichier (le nom du champ fichier doit être fichier) et type Fichier
  • Valeur : sélectionnez une image avec des personnes et/ou des objets sur votre ordinateur
  1. Cliquez sur "envoyer" (send) et obtenez une réponse avec les objets détectés comme suit :

Request Image Analysis output

Les coulisses - le code source

Le fichier Dockerfile

Il s'agit d'une étape d'importation. Pour utiliser les bibliothèques python, vous devez les installer au préalable, mais vous devez faire attention à les installer dans le dossier IRIS Python correct (/usr/irissys/mgr/python) :

 
Dockerfile
FROMintersystemsdc/iris-community
 
      <div>
        <span style="color: #c586c0;">USER</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">root</span>
      </div>  

      <div>
        <span style="color: #c586c0;">ENV</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">DEBIAN_FRONTEND</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">noninteractive</span>
      </div>  

      <div>
        <span style="color: #6a9955;"># installation des bibliothèques requises ImageAI/OpenCV pour traiter les images et les vidéos</span>
      </div>

      <div>
        <span style="color: #c586c0;">RUN</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">apt-get</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">-y</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">update</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">\</span>
      </div>

      <div>
        <span style="color: #d4d4d4;">    </span><span style="color: #9cdcfe;">&&</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">apt-get</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">-y</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">install</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">apt-utils</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">\</span>
      </div>

      <div>
        <span style="color: #d4d4d4;">    </span><span style="color: #9cdcfe;">&&</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">apt-get</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">install</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">-y</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">build-essential</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">unzip</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">pkg-config</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">\</span>
      </div>

      <div>
        <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">zlib1g-dev</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">libncurses5-dev</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">libgdbm-dev</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">libnss3-dev</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">\</span>
      </div>

      <div>
        <span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">libssl-dev</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">libreadline-dev</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">libffi-dev</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">wget</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">\</span>
      </div>

      <div>
        <span style="color: #d4d4d4;">    </span><span style="color: #9cdcfe;">&&</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">apt-get</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">install</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">-y</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">ffmpeg</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">libsm6</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">libxext6</span><span style="color: #d4d4d4;">  </span>
      </div>  

      <div>
        <span style="color: #6a9955;"># utiliser pip3 (le zpm de python) pour installer imageai et les dépendances d'imageai</span>
      </div>

      <div>
        <span style="color: #c586c0;">RUN</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">pip3</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">install</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">--upgrade</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">pip</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">setuptools</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">wheel</span>
      </div>

      <div>
        <span style="color: #c586c0;">RUN</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">pip3</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">install</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">--target</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">/usr/irissys/mgr/python</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">tensorflow==2.4.0</span>
      </div>

      <div>
        <span style="color: #c586c0;">RUN</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">pip3</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">install</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">--target</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">/usr/irissys/mgr/python</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">keras==2.4.3</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">numpy==1.19.3</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">pillow==8.1.1</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">scipy==1.4.1</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">h5py==2.10.0</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">matplotlib==3.3.2</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">opencv-python</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">keras-resnet==0.2.0</span>
      </div>

      <div>
        <span style="color: #c586c0;">RUN</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">pip3</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">install</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">--target</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">/usr/irissys/mgr/python</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">imageai</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">--upgrade</span>
      </div>  

      <div>
        <span style="color: #c586c0;">USER</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">root</span><span style="color: #d4d4d4;">   </span>
      </div>

      <div>
        <span style="color: #c586c0;">WORKDIR</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">/opt/irisbuild</span>
      </div>

      <div>
        <span style="color: #c586c0;">RUN</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">chown</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">${ISC_PACKAGE_MGRUSER}</span><span style="color: #9cdcfe;">:</span><span style="color: #9cdcfe;">${ISC_PACKAGE_IRISGROUP}</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">/opt/irisbuild</span>
      </div>

      <div>
        <span style="color: #c586c0;">USER</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">${ISC_PACKAGE_MGRUSER}</span>
      </div>  

      <div>
        <span style="color: #c586c0;">WORKDIR</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">/opt/irisbuild</span>
      </div>

      <div>
        <span style="color: #c586c0;">COPY</span><span style="color: #d4d4d4;">  </span><span style="color: #9cdcfe;">python</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">python</span>
      </div>

      <div>
        <span style="color: #c586c0;">COPY</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">input</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">input</span>
      </div>

      <div>
        <span style="color: #c586c0;">COPY</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">output</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">output</span>
      </div>

      <div>
        <span style="color: #c586c0;">COPY</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">models</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">models</span>
      </div>

      <div>
        <span style="color: #c586c0;">COPY</span><span style="color: #d4d4d4;">  </span><span style="color: #9cdcfe;">src</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">src</span>
      </div>

      <div>
        <span style="color: #c586c0;">COPY</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">module.xml</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">module.xml</span>
      </div>

      <div>
        <span style="color: #c586c0;">COPY</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">iris.script</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">iris.script</span>
      </div>  

      <div>
        <span style="color: #6a9955;"># download the trained model used to detect objects and persons inside images</span>
      </div>

      <div>
        <span style="color: #c586c0;">ADD</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">https://github.com/OlafenwaMoses/ImageAI/releases/download/essentials-v5/resnet50_coco_best_v2.1.0.h5</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">models</span>
      </div>  

      <div>
        <span style="color: #c586c0;">USER</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">root</span>
      </div>

      <div>
        <span style="color: #c586c0;">RUN</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">chmod</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">-R</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">777</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">input</span>
      </div>

      <div>
        <span style="color: #c586c0;">RUN</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">chmod</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">-R</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">777</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">output</span>
      </div>

      <div>
        <span style="color: #c586c0;">RUN</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">chmod</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">-R</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">777</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">models</span>
      </div>  

      <div>
        <span style="color: #c586c0;">USER</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">${ISC_PACKAGE_MGRUSER}</span>
      </div>  

      <div>
        <span style="color: #c586c0;">RUN</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">iris</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">start</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">IRIS</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">\</span>
      </div>

      <div>
        <span style="color: #d4d4d4;">    </span><span style="color: #9cdcfe;">&&</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">iris</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">session</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">IRIS</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">&lt;</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">iris.script</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">\</span>
      </div>

      <div>
        <span style="color: #d4d4d4;">    </span><span style="color: #9cdcfe;">&&</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">iris</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">stop</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">IRIS</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">quietly</span>
      </div>
    </div>
  </div>
</div>
  • pip3 est l'outil python utilisé pour installer les bibliothèques python, comme imageai, opencv, tensorflow et autres.
  • le paramètre target a été utilisé pour installer les bibliothèques python là où IRIS en a besoin, le dossier /usr/irissys/mgr/python.
  • ImageAI utilise les bibliothèques python suivantes :
    • TensorFlow : " C'est une bibliothèque open source pour le calcul numérique et l'apprentissage automatique à grande échelle. TensorFlow regroupe un grand nombre de modèles et d'algorithmes d'apprentissage automatique et d'apprentissage profond (alias réseaux neuronaux) et les rend utiles grâce à une métaphore commune. Il utilise Python pour fournir une API frontale pratique permettant de créer des applications à l'aide du cadre, tout en exécutant ces applications dans un C++ haute performance" (source : https://www.infoworld.com/article/3278008/what-is-tensorflow-the-machine-learning-library-explained.html)
    • Keras: "Keras est une API d'apprentissage profond écrite en Python, fonctionnant au-dessus de la plateforme d'apprentissage automatique TensorFlow. Elle a été développée dans le but de permettre une expérimentation rapide. Il est essentiel de pouvoir passer de l'idée au résultat aussi rapidement que possible pour effectuer de bonnes recherches" (source: https://keras.io/about/)
    • OpenCV : "( Bibliothèque de vision par ordinateur à source ouverte, Open Source Computer Vision Library) est une bibliothèque logicielle de vision par ordinateur et d'apprentissage automatique à source ouverte. OpenCV a été construite pour fournir une infrastructure commune pour les applications de vision par ordinateur et pour accélérer l'utilisation de la perception par machine dans les produits commerciaux." (source: https://opencv.org/about/).
  • ImageAI est un cadre qui combine TensorFlow, Keras et OpenCV pour faciliter la formation et/ou l'utilisation des modèles d'apprentissage profond du marché :
    • Prédiction de l'image;
    • Détection d'objets;
    • Détection et suivi d'objets vidéo;
    • Video analysis;
    • Apprentissage de modèles personnalisés (imaginez, par exemple, l'apprentissage d'un modèle pour détecter le risque de chute d'un patient hors de son lit dans le service de soins intensifs d'un hôpital).
  • ImageAI travaille avec les 3 principaux modèles de vision par ordinateur utilisés sur le marché pour la détection d'objets :
    • RetinaNet(Dimension = 145 Mo, haute performance et précision, avec un temps de détection plus long)
    • YOLOv3(Dimension = 237 Mo, performance et précision modérées, avec un temps de détection modéré)
    • TinyYOLOv3(Dimension = 34 Mo, optimisé pour la vitesse et les performances modérées, avec un temps de détection rapide)
  • Dans le dossier d'entrée se trouvent les images à analyser ;
  • Dans le dossier de sortie se trouvent les résultats (images avec balises de résultats visuels) ;
  • Dans le dossier des modèles se trouvent les modèles formés qui seront utilisés avec l'imageai.
  • Cet échantillon utilise le modèle RetinaNet (restnet50)

Mise en œuvre de la version Embedded Python

L'implémentation du code source est simple, et en quelques lignes nous réalisons la détection d'objets ( grâce à ImageAI). Si tensorflow était utilisé directement avec OpenCV et Keras, beaucoup plus de lignes de code auraient été écrites. Consultez le code commenté :

 
Mise en œuvre d'ImageAI
///Détection d'objets et de personnes dans les images et les vidéos
  <div>
    <span style="color: #85a6ff;">Class</span><span style="color: #d4d4d4;"> </span><span style="color: #4ec9b0;">dc</span><span style="color: #4ec9b0;">.</span><span style="color: #4ec9b0;">imageanalyzer</span><span style="color: #4ec9b0;">.</span><span style="color: #4ec9b0;">Detector</span>
  </div>

  <div>
    <span style="color: #ffffff;">{</span>
  </div>  

  <div>
    <span style="color: #80bd66;">///</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">Détection des personnes et des objets dans les paramètres de l'image</span>
  </div>

  <div>
    <span style="color: #85a6ff;">ClassMethod</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">GetImageFeatures</span><span style="color: #ffffff;">(</span><span style="color: #ff75f4;">Image</span><span style="color: #ffffff;">)</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">[</span><span style="color: #d4d4d4;"> </span><span style="color: #85a6ff;">Language</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">python</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">]</span>
  </div>

  <div>
    <span style="color: #ffffff;">{</span>
  </div>

  <div>
    <span style="color: #80bd66;">    # </span><span style="color: #80bd66;">import</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">imageai</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">and</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">json</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">libs</span>
  </div>

  <div>
    <span style="color: #85a6ff;">    </span><span style="color: #85a6ff;">from</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">imageai</span><span style="color: #ffffff;">.</span><span style="color: #ade2ff;">Detection</span><span style="color: #85a6ff;"> </span><span style="color: #85a6ff;">import</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">ObjectDetection</span>
  </div>

  <div>
    <span style="color: #85a6ff;">    </span><span style="color: #85a6ff;">import</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">json</span>
  </div>

  <div>
    <span style="color: #80bd66;">    </span>
  </div>

  <div>
    <span style="color: #80bd66;">    # </span><span style="color: #80bd66;">instantiate</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">imageai</span>
  </div>

  <div>
    <span style="color: #ade2ff;">    </span><span style="color: #ade2ff;">detector</span><span style="color: #ffffff;"> =</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">ObjectDetection</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
  </div>  

  <div>
    <span style="color: #80bd66;">    # </span><span style="color: #80bd66;">set</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">retinanet</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">as</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">model</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">to</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">detect</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">objects</span>
  </div>

  <div>
    <span style="color: #ade2ff;">    </span><span style="color: #ade2ff;">model</span><span style="color: #ade2ff;">_</span><span style="color: #ade2ff;">path</span><span style="color: #ffffff;"> =</span><span style="color: #d4b57c;"> </span><span style="color: #d4b57c;">"/opt/irisbuild/models/resnet50_coco_best_v2.1.0.h5"</span>
  </div>

  <div>
    <span style="color: #80bd66;">    # </span><span style="color: #80bd66;">set</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">folder</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">to</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">receive</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">the</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">image</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">to</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">be</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">processed</span>
  </div>

  <div>
    <span style="color: #ade2ff;">    </span><span style="color: #ade2ff;">input</span><span style="color: #ade2ff;">_</span><span style="color: #ade2ff;">path</span><span style="color: #ffffff;"> =</span><span style="color: #d4b57c;"> </span><span style="color: #d4b57c;">"/opt/irisbuild/input/"</span><span style="color: #ffffff;"> +</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">Image</span>
  </div>

  <div>
    <span style="color: #80bd66;">    # </span><span style="color: #80bd66;">set</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">folder</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">to</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">stores</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">the</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">results</span><span style="color: #80bd66;"> (</span><span style="color: #80bd66;">visual</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">tags</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">inside</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">image</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">processed</span><span style="color: #80bd66;">)</span>
  </div>

  <div>
    <span style="color: #ade2ff;">    </span><span style="color: #ade2ff;">output</span><span style="color: #ade2ff;">_</span><span style="color: #ade2ff;">path</span><span style="color: #ffffff;"> =</span><span style="color: #d4b57c;"> </span><span style="color: #d4b57c;">"/opt/irisbuild/output/"</span><span style="color: #ffffff;"> +</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">Image</span>
  </div>  

  <div>
    <span style="color: #80bd66;">    # </span><span style="color: #80bd66;">instantiate</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">retina</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">model</span>
  </div>

  <div>
    <span style="color: #ade2ff;">    </span><span style="color: #ade2ff;">detector</span><span style="color: #ffffff;">.</span><span style="color: #ade2ff;">setModelTypeAsRetinaNet</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #80bd66;">    </span>
  </div>

  <div>
    <span style="color: #80bd66;">    # </span><span style="color: #80bd66;">set</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">trained</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">detection</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">model</span><span style="color: #80bd66;"> - </span><span style="color: #80bd66;">retina</span>
  </div>

  <div>
    <span style="color: #ade2ff;">    </span><span style="color: #ade2ff;">detector</span><span style="color: #ffffff;">.</span><span style="color: #ade2ff;">setModelPath</span><span style="color: #ffffff;">(</span><span style="color: #ade2ff;">model</span><span style="color: #ade2ff;">_</span><span style="color: #ade2ff;">path</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #80bd66;">    # </span><span style="color: #80bd66;">load</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">the</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">model</span>
  </div>

  <div>
    <span style="color: #ade2ff;">    </span><span style="color: #ade2ff;">detector</span><span style="color: #ffffff;">.</span><span style="color: #ade2ff;">loadModel</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #80bd66;">    # </span><span style="color: #80bd66;">do</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">the</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">object</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">image</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">detection</span>
  </div>

  <div>
    <span style="color: #ade2ff;">    </span><span style="color: #ade2ff;">detection</span><span style="color: #ffffff;"> =</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">detector</span><span style="color: #ffffff;">.</span><span style="color: #ade2ff;">detectObjectsFromImage</span><span style="color: #ffffff;">(</span><span style="color: #ade2ff;">input</span><span style="color: #ade2ff;">_</span><span style="color: #ade2ff;">image</span><span style="color: #ffffff;">=</span><span style="color: #ade2ff;">input</span><span style="color: #ade2ff;">_</span><span style="color: #ade2ff;">path</span><span style="color: #ffffff;">,</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">output</span><span style="color: #ade2ff;">_</span><span style="color: #ade2ff;">image</span><span style="color: #ade2ff;">_</span><span style="color: #ade2ff;">path</span><span style="color: #ffffff;">=</span><span style="color: #ade2ff;">output</span><span style="color: #ade2ff;">_</span><span style="color: #ade2ff;">path</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #80bd66;">    # </span><span style="color: #80bd66;">return</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">json</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">with</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">the</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">results</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">of</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">the</span><span style="color: #80bd66;"> </span><span style="color: #80bd66;">processing</span><span style="color: #80bd66;"> </span>
  </div>

  <div>
    <span style="color: #80bd66;">    </span><span style="color: #80bd66;"># if</span><span style="color: #80bd66;"> vous voulez, vous pouvez voir l'image du résultat dans le dossier de sortie</span>
  </div>

  <div>
    <span style="color: #85a6ff;">    </span><span style="color: #85a6ff;">return</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">json</span><span style="color: #ffffff;">.</span><span style="color: #ade2ff;">dumps</span><span style="color: #ffffff;">(</span><span style="color: #ade2ff;">detection</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #ffffff;">}</span>
  </div>  

  <div>
    <span style="color: #80bd66;">///</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">Get JSON</span>
  </div>

  <div>
    <span style="color: #85a6ff;">ClassMethod</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">GetJSON</span><span style="color: #ffffff;">(</span><span style="color: #ff75f4;">pythonObj</span><span style="color: #ffffff;">)</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">[</span><span style="color: #d4d4d4;"> </span><span style="color: #85a6ff;">Language</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">python</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">]</span>
  </div>

  <div>
    <span style="color: #ffffff;">{</span>
  </div>

  <div>
    <span style="color: #85a6ff;">    </span><span style="color: #85a6ff;">import</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">json</span>
  </div>

  <div>
    <span style="color: #85a6ff;">    </span><span style="color: #85a6ff;">return</span><span style="color: #ade2ff;"> </span><span style="color: #ade2ff;">json</span><span style="color: #ffffff;">.</span><span style="color: #ade2ff;">dumps</span><span style="color: #ffffff;">(</span><span style="color: #ade2ff;">pythonObj</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #ffffff;">}</span>
  </div>  

  <div>
    <span style="color: #80bd66;">///</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">Description</span>
  </div>

  <div>
    <span style="color: #85a6ff;">ClassMethod</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">GetImageAI</span><span style="color: #ffffff;">(</span><span style="color: #ff75f4;">Image</span><span style="color: #ffffff;">)</span><span style="color: #d4d4d4;"> </span><span style="color: #85a6ff;">As</span><span style="color: #d4d4d4;"> </span><span style="color: #4ec9b0;">%Status</span>
  </div>

  <div>
    <span style="color: #ffffff;">{</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">sc</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">$$$</span><span style="color: #dcdcaa;">OK</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">Write</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">..</span><span style="color: #dcdcaa;">GetImageFeatures</span><span style="color: #ffffff;">(</span><span style="color: #ff75f4;">Image</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">Return</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">sc</span>
  </div>

  <div>
    <span style="color: #ffffff;">}</span>
  </div>  

  <div>
    <span style="color: #ffffff;">}</span>
  </div>
</div>

L'API IRIS pour exposer la détection d'objets en tant que Microservice IRIS de détection d'objets

Il est très facile d'appeler la méthode de classe python, c'est similaire d'appeler n'importe quelle méthode de classe objectcript, voir :

 
Microservice IRIS pour la détection d'objets dans les images
Classdc.imageanalyzer.ImageAnalyzerRESTAppExtends%CSP.REST
  <div>
    <span style="color: #ffffff;">{</span>
  </div>  

  <div>
    <span style="color: #85a6ff;">Parameter</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">CHARSET</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"utf-8"</span><span style="color: #ffffff;">;</span>
  </div>  

  <div>
    <span style="color: #85a6ff;">Parameter</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">CONVERTINPUTSTREAM</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">1</span><span style="color: #ffffff;">;</span>
  </div>  

  <div>
    <span style="color: #85a6ff;">Parameter</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">CONTENTTYPE</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"application/json"</span><span style="color: #ffffff;">;</span>
  </div>  

  <div>
    <span style="color: #85a6ff;">Parameter</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">Version</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"1.0.0"</span><span style="color: #ffffff;">;</span>
  </div>  

  <div>
    <span style="color: #85a6ff;">Parameter</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">HandleCorsRequest</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">1</span><span style="color: #ffffff;">;</span>
  </div>  

  <div>
    <span style="color: #85a6ff;">XData</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">UrlMap</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">[</span><span style="color: #d4d4d4;"> </span><span style="color: #85a6ff;">XMLNamespace</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #d4b57c;">"http://www.intersystems.com/urlmap"</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">]</span>
  </div>

  <div>
    <span style="color: #ffffff;">{</span>
  </div>

  <div>
    <span style="color: #ffffff;">&lt;</span><span style="color: #85a6ff;">Routes</span><span style="color: #ffffff;">></span>
  </div>  

  <div>
    <span style="color: #80bd66;"><!--</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">Detect</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">objects</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">inside</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">an</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">image</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">--></span>
  </div>

  <div>
    <span style="color: #ffffff;">&lt;</span><span style="color: #85a6ff;">Route</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Url</span><span style="color: #ffffff;">=</span><span style="color: #d4b57c;">"/analyzeImage"</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Method</span><span style="color: #ffffff;">=</span><span style="color: #d4b57c;">"POST"</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">Call</span><span style="color: #ffffff;">=</span><span style="color: #d4b57c;">"AnalyzeImage"</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">/></span>
  </div>  

  <div>
    <span style="color: #ffffff;">&lt;/</span><span style="color: #85a6ff;">Routes</span><span style="color: #ffffff;">></span>
  </div>

  <div>
    <span style="color: #ffffff;">}</span>
  </div>  

  <div>
    <span style="color: #80bd66;">//</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">Detect objects inside an image</span>
  </div>  

  <div>
    <span style="color: #85a6ff;">ClassMethod</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">AnalyzeImage</span><span style="color: #ffffff;">()</span><span style="color: #d4d4d4;"> </span><span style="color: #85a6ff;">As</span><span style="color: #d4d4d4;"> </span><span style="color: #4ec9b0;">%Status</span>
  </div>

  <div>
    <span style="color: #ffffff;">{</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">tSC</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">$$$</span><span style="color: #dcdcaa;">OK</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">    </span>
  </div>

  <div>
    <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">try</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">{</span>
  </div>

  <div>
    <span style="color: #6a9955;">        </span><span style="color: #80bd66;">// Obtient le fichier à partir de la requête multipart</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">source</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #64c9ff;">%request</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">GetMimeData</span><span style="color: #ffffff;">(</span><span style="color: #d4b57c;">"file"</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span>
  </div>

  <div>
    <span style="color: #6a9955;">        </span><span style="color: #80bd66;">// enregistrement du fichier dans le dossier d'entrée, pour être traité avec imageai</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">destination</span><span style="color: #ffffff;">=</span><span style="color: #85a6ff;">##class</span><span style="color: #ffffff;">(</span><span style="color: #4ec9b0;">%Stream</span><span style="color: #4ec9b0;">.</span><span style="color: #4ec9b0;">FileBinary</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">%New</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">destination</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Filename</span><span style="color: #ffffff;">=</span><span style="color: #d4b57c;">"/opt/irisbuild/input/"</span><span style="color: #ffffff;">_</span><span style="color: #ade2ff;">source</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">FileName</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">tSC</span><span style="color: #ffffff;">=</span><span style="color: #ade2ff;">destination</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">CopyFrom</span><span style="color: #ffffff;">(</span><span style="color: #ade2ff;">source</span><span style="color: #ffffff;">)</span><span style="color: #6a9955;"> </span><span style="color: #80bd66;">//reader open the file</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">result</span><span style="color: #ffffff;">=</span><span style="color: #ade2ff;">destination</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">%Save</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #64c9ff;">%response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">ContentType</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">..</span><span style="color: #dcdcaa;">#</span><span style="color: #dcdcaa;">CONTENTTYPEJSON</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #64c9ff;">%response</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">Headers</span><span style="color: #ffffff;">(</span><span style="color: #d4b57c;">"Access-Control-Allow-Origin"</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">=</span><span style="color: #d4b57c;">"*"</span>
  </div>  

  <div>
    <span style="color: #6a9955;">        </span><span style="color: #80bd66;">//Appelle de la méthode de classe python intégrée pour détecter les objets et écrire les résultats en tant que contenu json</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">Write</span><span style="color: #d4d4d4;"> </span><span style="color: #85a6ff;">##class</span><span style="color: #ffffff;">(</span><span style="color: #4ec9b0;">dc</span><span style="color: #4ec9b0;">.</span><span style="color: #4ec9b0;">imageanalyzer</span><span style="color: #4ec9b0;">.</span><span style="color: #4ec9b0;">Detector</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">GetImageAI</span><span style="color: #ffffff;">(</span><span style="color: #ade2ff;">source</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">FileName</span><span style="color: #ffffff;">)</span>
  </div>  

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">tSC</span><span style="color: #ffffff;">=</span><span style="color: #dcdcaa;">$$$</span><span style="color: #dcdcaa;">OK</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">    </span>
  </div>

  <div>
    <span style="color: #6a9955;">    </span><span style="color: #80bd66;">//Renvoie d'un message d'erreur à l'utilisateur</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">}</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">catch</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">e</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">{</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">tSC</span><span style="color: #ffffff;">=</span><span style="color: #ade2ff;">e</span><span style="color: #ffffff;">.</span><span style="color: #dcdcaa;">AsStatus</span><span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">        </span><span style="color: #ffffff;">Set</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">pOutput</span><span style="color: #d4d4d4;"> </span><span style="color: #ffffff;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">tSC</span>
  </div>

  <div>
    <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">}</span>
  </div>  

  <div>
    <span style="color: #d4d4d4;">    </span><span style="color: #ffffff;">Quit</span><span style="color: #d4d4d4;"> </span><span style="color: #ade2ff;">tSC</span>
  </div>

  <div>
    <span style="color: #ffffff;">}</span>
  </div>

  <br /><br /><br /> 

  <div>
    <span style="color: #ffffff;">}</span>
  </div>
</div>

Vous pouvez faire beaucoup de choses avec Embedded Python et ImageAI. Pour en savoir plus sur ImageAI, consultez le site : https://github.com/OlafenwaMoses/ImageAI.

Cette application utilisant imageai participera au concours Python, si vous l'aimez, votez-la. Merci !

0
0 198
Article Irène Mykhailova · Août 3, 2022 5m read

Motivation

Ce projet a vu le jour lorsque j'ai réfléchi à la manière de permettre au code Python de traiter naturellement le mécanisme de stockage évolutif et de récupération efficace fourni par les globales IRIS, par le biais de la technologie Embedded Python.

Mon idée initiale était de créer une sorte d'implémentation de dictionnaire Python en utilisant les globales, mais j'ai vite réalisé que je devais d'abord m'occuper de l'abstraction des objets.

J'ai donc commencé à créer des classes Python capables d'envelopper des objets Python, de stocker et de récupérer leurs données dans des globales, c'est-à-dire de sérialiser et de désérialiser des objets Python dans des globales IRIS.

Comment cela fonctionne-t-il ?

Comme ObjectScript%DispatchGetProperty(), %DispatchSetProperty() et %DispatchMethod(), Python dispose de méthodes permettant de déléguer les appels aux propriétés et aux méthodes des objets.

Lorsque vous définissez ou récupérez une propriété d'objet, l'interpréteur Python vous permet d'intercepter cette opération par les méthodes __setattr__(self, name, value) et __getattr(self, name)__.

Regardez cet exemple de base :

>>> class Test:
...         def __init(self, prop1):
...                 self.prop1 = prop1
...         def __setattr__(self, name, value):
...                 print(f"setting property {name} to value {value}")
...         def __getattr__(self, name):
...                 print(f"getting property {name}")
...
>>> obj = Test()
>>> obj.prop1 = "test"
setting property prop1 to value test
>>> obj.prop1
getting property prop1
>>> obj.prop2
getting property prop2
>>> obj.prop2
getting property prop2
>>>

Notez que les méthodes __setattr__() et __getattr()__ ont été appelées indirectement par les opérations set et get sur les objets de la classe Test - qui implémente ces méthodes. Même une propriété non déclarée, comme prop2 dans cet exemple, émet des appels vers elles.

Ce mécanisme est le cœur du test de sérialisation que j'ai essayé dans mon projet python-globales-convertisseur-exemple. Avec ce mécanisme, vous pouvez intercepter les opérations set/get et stocker/récupérer les données des globales IRIS.

Modèle d'objet

Les globales offrent une structure hautement personnalisable. En utilisant leur modèle hiérarchique pour l'accès aux informations, qui est assez similaire aux objets JSON et aux dictionnaires Python, nous pouvons stocker les données des propriétés des objets et les métadonnées.

Voici comment j'ai utilisé une globale pour créer un modèle d'objet simple pour sérialiser des objets Python :

Pour chaque objet sérialisé, son nom de classe est sérialisé dans un nœud étiqueté "class" :

^test(1,"class")="<class 'employee.SalaryEmployee'>"

Le premier indice est un nombre incrémental qui est utilisé comme référence à cet objet dans le modèle. Ainsi, dans l'exemple ci-dessus, un objet de la classe employee.SalaryEmployee est stocké avec la valeur de référence 1.

Pour les propriétés de types de données primitives, leur type et leur valeur sont stockés. Par exemple :

^test(1,"name","type")="<class 'str'>"
^test(1,"name","value")="me"

Cette structure est interprétée comme l'objet référencé par l'index 1, a une propriété appelée name, avec une valeur égale à 'me'.

Pour les propriétés référençant des objets, le modèle est légèrement différent, car contrairement aux objets JSON ou aux dictionnaires Python, les globales sont destinés à stocker uniquement des données de type primitif. Donc un autre noeud "classe" est créé pour cet objet référencé, et son index de noeud (c'est-à-dire sa référence) est stocké dans le noeud de propriété :

^test(1,"company","oref")=2
^test(1,"company","type")="<class 'iris_global_object.IrisGlobalObject'>"
^test(2,"class")="<class 'employee.Company'>"
^test(2,"name","type")="<class 'str'>"
^test(2,"name","value")="Company ABC"

Ces structures signifient que l'objet 1 a une propriété appelée company, dont les valeurs sont stockées dans l'index 2 - notez la valeur de ^test(1, "company", "oref").

Processus de sérialisation/désérialisation

Lorsque vous créez un wrapper pour sérialiser ou désérialiser des objets Python, vous devez définir le nom de la globale qui stocke l'objet.

Ensuite, le processus de sérialisation est effectué lorsqu'une opération set est exécutée. La méthode __setattr__() définit la valeur et le type de la propriété dans la globale définie pour stocker l'objet, en utilisant le modèle d'objet simple expliqué précédemment.

Dans le sens inverse, une désérialisation est effectuée par la méthode __getattr__, lorsqu'une opération get est effectuée.

Pour les types de données primitifs, ce processus est simple : il suffit de récupérer la valeur stockée dans la globale et de la retourner.

Mais pour les objets, le processus doit instancier le type de données de leur classe et définir également toutes leurs propriétés. De cette façon, un objet Python restauré peut être utilisé, y compris les appels à ses méthodes.

Les travaux futurs

Comme nous l'avons dit au début de cette entrée, ce projet est né comme une simplification d'une façon de laisser le code Python utiliser les globales comme un moteur de stockage naturel, et vise à être juste une preuve de concept.

La sérialisation/désérialisation d'objets n'est que le début de cet objectif. Il y a donc beaucoup d'efforts à faire pour que cette idée arrive à maturité.

J'espère que cette entrée vous permettra de comprendre le but de mon travail dans ce projet, et qu'elle pourra vous inspirer à réfléchir à de nouvelles façons d'utiliser les globales IRIS pour rapprocher Python d'IRIS.

0
0 65
Article Lorenzo Scalese · Juil 25, 2022 2m read

J'aimerais partager avec vous un exemple de la manière dont la nouvelle fonctionnalité d'Embedded Python d'IRIS m'a aidé dans mes tâches quotidiennes.

Dans le cadre de ma participation au projet iris-kaggle-socrata-generator avec Henrique Dias, j'ai dû dézipper des jeux de données de Kaggle afin de les importer.

Une telle tâche a été facilement réalisée en utilisant la librairie de zipfile en Python (ce code a été copié à partir de stackoverflow):

Method UnZip(pZipFileName As %String, pExtractToDir As %String) As %DynamicArray [ Language = python ]
{
    import zipfile
    import iris
    with zipfile.ZipFile(pZipFileName, 'r') as zip_ref:
        zip_ref.extractall(pExtractToDir)
        fileList = zip_ref.namelist()

    dynarray = iris.cls("%DynamicArray")._New()
    for file in fileList:
        dynarray._Push(file)
    return dynarray
}

Notez le modificateur de méthode [Language = python]. Cette fonctionnalité a été testée dans l'image IRIS intersystemsdc/iris-ml-community:2021.2.0.617.0-zpm. Consultez l'application OEX correspondante pour un exemple fonctionnel.

Vous pouvez voir qu'il s'agit d'un code Embedded Python dans une méthode ObjectScript. Vous pouvez donc l'utiliser dans tout code ObjectScript. Par exemple :

Method HttpDownloadZIP(pHttpParams As %DynamicObject) As %DynamicObject
{
    Set retorno = {
        "warnings": []
    }
    …
    Set fileName = ..SaveRequestToFile(request)
    …
    Set fileList = ..UnZip(fileName, zipTempDir)
    If (fileList.%Size() > 1) {
        Do retorno.warnings.%Push("Il y a plus d'un fichier dans le fichier zip. J'utilise le premier.")
    }
    …
    Return retorno
}

Vous pouvez également accéder au code complet ici.

Notez que la méthode Embedded Python utilise la librairie Python zipfile et renvoie les résultats de la méthode dans un %DynamicArray, utilisé dans les méthodes ObjectScript. Cela signifie qu'un objet créé dans un contexte Python peut être accédé par un contexte ObjectScript de manière transparente.

Vous pouvez en savoir plus sur la façon d'utiliser Embedded Python ici.

Et voilà, c'est tout ! J'espère que cela pourra vous être utile pour vos projets. A bientôt !

0
0 86
Article Guillaume Rongier · Juil 22, 2022 10m read

Introduction

Depuis la version 2019.2, InterSystems IRIS fournit son API native pour Python comme méthode d'accès aux données haute performance. L'API native vous permet d'interagir directement avec la structure de données IRIS native.

Globales

En tant que développeurs InterSystems, vous êtes probablement déjà familiarisés avec les globales. Nous allons passer en revue les bases au cas où vous souhaiteriez un rafraîchissement, mais n'hésitez pas à passer directement à la section suivante.

InterSystems IRIS utilise des globales pour stocker les données. Une globale est un tableau clairsemé qui se compose de nœuds qui peuvent ou non avoir une valeur et de sous-nœuds. Ce qui suit est un exemple abstrait d'une globale :

Représentation arborescente d'une globale

Dans cet exemple, a il y a un nœud racine, appelé nom global. Chaque nœud possède une adresse de nœud qui se compose du nom global et d'un ou plusieurs indices (noms des sous-nœuds). a possède les indices b and c; l'adresse de ces noeuds est a->b et a->c.

Les noeuds a->b et a->c->g ont une valeur (d et h), les noeuds a->b->e et a->b->f n'ont aucune valeur. Le noeud a->b possède les indices e et f.

Une description approfondie de cette structure peut être trouvée dans le livre InterSystems "Utilisation des globaux" ("Using Globals").

Lecture et écriture dans la globale

Native Python API permet de lire et d'écrire directement des données dans la globale IRIS. Le paquet irisnative est disponible sur GitHub — ou si InterSystems IRIS est installé localement sur votre machine, vous le trouverez dans le sous-répertoire dev/python de votre répertoire d'installation.

La fonction irisnative.createConnection vous permet de créer une connexion à IRIS et la fonction irisnative.createIris vous donne un objet de cette connexion avec lequel nous pouvons manipuler la globale. Cet objet possède les méthodes get et set pour lire/écrire depuis/vers la globale, et une méthode kill pour supprimer un nœud et ses sous-nœuds. Il possède également une méthode isDefined qui renvoie 0 si le noeud demandé n'existe pas ; 1 s'il a une valeur, mais pas de descendants ; 10 s'il n'a pas de valeur et a des descendants ; ou 11 s'il a une valeur et des descendants.

import irisnative conn = irisnative.createConnection("127.0.0.1", 51773, "USER", "", "") iris = irisnative.createIris(conn) iris.set("value", "root", "sub1", "sub2") # sets "value" to root->sub1->sub2 print(iris.get("root", "sub1", "sub2")) print(iris.isDefined("root", "sub1")) iris.kill("root") conn.close()

Il dispose également d'une méthode iterator pour boucler sur les sous-nœuds d'un certain nœud. (L'utilisation sera démontrée dans la section suivante.)

Pour une description complète de chaque méthode, reportez-vous à la documentation de l'interface API .

Les fichiers de données sur le trafic de San Francisco GTFS

Stockage des données dans la globale

La Spécification générale des flux de transport en commun (GTFS) est un format pour les horaires et les itinéraires des transports publics. Regardons comment nous pouvons utiliser l'API native IRIS pour travailler avec les données GTFS de San Francisco à partir du 10 juin 2019.

Tout d'abord, nous allons stocker les informations des fichiers de données dans la globale IRIS. (Tous les fichiers et toutes les colonnes ne seront pas utilisés dans cette démo). Les fichiers sont au format CSV, où la première ligne indique les noms des colonnes et toutes les autres lignes contiennent les données. En Python, nous commencerons par effectuer les importations nécessaires et établir une connexion à IRIS :

import csv import irisnative

conn = irisnative.createConnection("127.0.0.1", 51773, "USER", "", "") iris = irisnative.createIris(conn)

Sur la base des noms de colonnes et des données, nous pouvons construire une arborescence judicieuse pour chaque fichier et utiliser iris.set pour stocker les données dans la globale.

Commençons par le fichier stops.txt, qui contient tous les arrêts de transport public de la ville. Dans ce fichier, nous n'utiliserons que les colonnes stop_id et stop_name. Nous allons les stocker dans une globale nommée stops une structure arborescente avec une couche de nœuds, avec les ID des arrêts comme indices et le nom des arrêts comme valeurs des nœuds. Notre structure ressemble donc à stops → [stop_id]=[stop_name]. (Pour cet article, j'utiliserai des crochets pour indiquer quand un indice n'est pas littéral, mais plutôt une valeur lue dans les fichiers de données.)

with open("stops.txt", "r") as csvfile: reader = csv.reader(csvfile) next(reader) # Ignorez les noms des colonnes

# stops -> [stop_id]=[stop_name]
for row in reader:
    iris.set(row[6], "stops", row[4])

csv.reader retourne un itérateur de listes qui contiennent les valeurs séparées par des virgules. La première ligne contient les noms des colonnes, nous allons donc la sauter avec next(reader). Nous utiliserons iris.set pour définir le nom de l'arrêt comme valeur de stops -> [stop_id].

Ensuite, il y a le fichier routes.txt dont nous utiliserons les colonnes route_type, route_id, route_short_name et route_long_name. Une structure globale raisonnable est routes -> [route_type] -> [route_id] -> [route_short_name]=[route_long_name]. (Le type d'itinéraire est 0 pour un tram, 3 pour un bus et 5 pour un téléphérique.) Nous pouvons lire le fichier CSV et placer les données dans la globale exactement de la même manière.

with open("routes.txt", "r") as csvfile: reader = csv.reader(csvfile) next(reader) # Ignorez les noms des colonnes

# routes -> [route_type] -> [route_id] -> [route_short_name]=[route_long_name]
for row in reader:
    iris.set(row[0], "routes", row[1], row[5], row[8])

Chaque itinéraire a des trajets trips, stockés dans trips.txt, dont nous utiliserons les colonnes route_id, direction_id, trip_headsign et trip_id. Les trajets sont identifiés de manière unique par leur trip ID (que nous verrons plus tard dans le fichier des temps d'arrêt). Les trajets sur une route peuvent être séparés en deux groupes en fonction de leur direction, et les directions sont associées à des panneaux de tête. Cela conduit à la structure arborescente trips -> [route_id] -> [direction_id]=[trip_headsign] -> [trip_id].

Nous avons besoin de deux appels iris.set ici — un pour définir la valeur du nœud ID de la direction, et un pour créer le nœud sans valeur de l'ID du trajet.

with open("trips.txt", "r") as csvfile: reader = csv.reader(csvfile) next(reader) # Ignorez les noms des colonnes

# trips -> [route_id] -> [direction_id]=[trip_headsign] ->[trip_id]
for row in reader:
    iris.set(row[3], "trips", row[1], row[2])
    iris.set(None, "trips", row[1], row[2], row[6])

Enfin, nous allons lire et stocker les temps d'arrêt. Ils sont stockés dans le fichier stop_times.txt et nous allons utiliser les colonnes stop_id, trip_id, stop_sequence et departure_time. Une première option pourrait consister à utiliser stoptimes -> [stop_id] -> [trip_id] -> [departure_time] ou si nous voulons conserver la séquence des arrêts, stoptimes -> [stop_id] -> [trip_id] -> [stop_sequence]=[departure_time].

with open("stop_times.txt", "r") as csvfile: reader = csv.reader(csvfile) next(reader) # Ignorez les noms des colonnes
# stoptimes -> [stop_id] -> [trip_id] -> [stop_sequence]=[departure_time]
for row in reader:
    iris.set(row[2], "stoptimes", row[3], row[0], row[4])

Interrogation des données à l'aide de l'API native

Ensuite, notre objectif est de trouver toutes les heures de départ pour l'arrêt avec le nom donné.

Tout d'abord, nous récupérons l'ID de l'arrêt à partir du nom de l'arrêt donné, puis nous utilisons cet ID pour trouver les heures pertinentes dans le fichier stop_times.

L'appel iris.iterator("stops") nous permet d'itérer sur les sous-nœuds du nœud racine stops. Nous voulons itérer sur les paires d'indices et de valeurs (pour comparer les valeurs avec le nom donné, et connaître immédiatement l'indice s'il correspond), nous appelons donc .items() sur l'itérateur, ce qui définit le type de retour en tuples (indice, valeur). Nous pouvons alors itérer sur tous ces tuples et trouver le bon arrêt.

stop_name = "Silver Ave & Holyoke St"

iter = iris.iterator("stops").items()

stop_id = None

for item in iter: if item[1] == stop_name: stop_id = item[0] break

if stop_id is None: print("Stop not found.") import sys sys.exit()

Il convient de noter que la recherche d'une clé par sa valeur par itération n'est pas très efficace s'il y a beaucoup de nœuds. Une façon d'éviter cela serait d'avoir un autre tableau, où les indices sont les noms des arrêts et les valeurs sont les IDs. La recherche de la valeur --> clé consisterait alors en une requête dans ce nouveau tableau.

Vous pouvez également utiliser le nom de l'arrêt comme identifiant partout dans votre code au lieu de l'ID de l'arrêt - le nom de l'arrêt est également unique.

Comme vous pouvez le voir, si nous avons une quantité importante d'arrêts, cette recherche peut prendre un certain temps - elle est également connue sous le nom de "balayage complet". Mais nous pouvons profiter des globales et construire le tableau inversé où les noms seront les clés et les IDs les valeurs.

iter = iris.iterator("stops").items()

stop_id = None

for item in iter: iris.set(item[0], "stopnames", item[1])

En disposant de la globale de stopnames, où l'index est le nom et la valeur est l'ID, le code ci-dessus pour trouver le stop_id par le nom sera remplacé par le code suivant qui s'exécutera sans une recherche par balayage complet :

stop_name = "Silver Ave & Holyoke St" stop_id=iris.get("stopnames", stop_name) if stop_id is None: print("Stop not found.") import sys sys.exit()

À ce stade, nous pouvons trouver les heures d'arrêt. Le sous-arbre stoptimes -> [stop_id] contient les ID des trajets en tant que sous-nœuds, qui contiennent les temps d'arrêt en tant que sous-nœuds. Nous ne sommes pas intéressés par les ID de trajet - seulement par les temps d'arrêt - donc nous allons itérer sur tous les ID de trajet et collecter tous les temps d'arrêt pour chacun d'eux.

all_stop_times = set()

trips = iris.iterator("stoptimes", stop_id).subscripts() for trip in trips: all_stop_times.update(iris.iterator("stoptimes", stop_id, trip).values())

Nous n'utilisons pas .items() sur l'itérateur ici, mais nous utiliserons .subscripts() et .values() car les ID de trajet sont des subscripts (sans valeurs associées) ou la couche inférieure ([stop_sequence]=[departure_time]), nous sommes seulement intéressés par les valeurs et les heures de départ. L'appel .update ajoute tous les éléments de l'itérateur à notre ensemble existant. L'ensemble contient maintenant toutes les heures d'arrêt (uniques) :

for stop_time in sorted(all_stop_times): print(stop_time)

Rendons les choses un peu plus compliquées. Au lieu de trouver toutes toutes les heures de départ d'un arrêt, nous allons trouver uniquement les heures de départ d'un arrêt pour un itinéraire donné (dans les deux sens) où l'ID de l'itinéraire est donné. Le code permettant de trouver l'ID de l'arrêt à partir du nom de l'arrêt peut être conservé dans son intégralité. Ensuite, tous les ID des arrêts sur l'itinéraire donné seront récupérés.

Le sous-arbre de trips -> [route_id] est divisé en deux directions, qui ont tous les ID de trajets comme sous-nœuds. Nous pouvons itérer sur les directions comme précédemment, et ajouter tous les sous-noeuds des directions à un ensemble.

route = "14334"

selected_trips = set()

directions = iris.iterator("trips", route).subscripts() pour la direction dans les directions : selected_trips.update(iris.iterator("trips", route, direction).subscripts())

L'étape suivante consiste à trouver les valeurs de tous les sous-nœuds de stoptimes -> [stop_id] -> [trip_id][stop_id] est l'identifiant de l'arrêt récupéré et [trip_id] est l'un des identifiants de trajet sélectionnés. Nous itérons sur l'ensemble selected_trips pour trouver toutes les valeurs pertinentes :

all_stop_times = set()

pour le trajet dans selected_trips: all_stop_times.update(iris.iterator("stoptimes", stop_id, trip).values())

pour stop_time dans sorted(all_stop_times): print(stop_time)

Un dernier exemple montre l'utilisation de la fonction isDefined. Nous allons développer le code écrit précédemment : au lieu de coder en dur l'ID de la route, le nom court d'une route est donné, puis l'ID de la route doit être récupéré sur cette base. Les noeuds avec les noms de route sont sur la couche inférieure de l'arbre. La couche supérieure contient les ID des routes. Nous pouvons itérer sur tous les types de route, puis sur tous les ID de route, et si le noeud routes -> [route_type] -> [route_id] -> [route_short_name] existe et a une valeur (isDefined retourne 1), alors nous savons que [route_id] est l'ID que nous recherchons.

route_short_name = "44" route = None

types = iris.iterator("routes").subscripts() for type in types: route_ids = iris.iterator("routes", type).subscripts() for route_id in route_ids: if iris.isDefined("routes", type, route_id, route_short_name) == 1: route = route_id

if route is None: print("No route found.") import sys sys.exit()

Ce code sert à remplacer la ligne route = "14334" codée en dur.

Lorsque toutes les opérations IRIS sont terminées, nous pouvons fermer la connexion à la base de données :

conn.close()

Prochaines étapes

Nous avons couvert comment l'API native de Python peut être utilisée pour accéder à la structure de données d'InterSystems IRIS, puis être appliquée aux données des transports publics de San Francisco. Pour une plongée plus profonde dans l'API, vous pouvez consulter la documentation . L'API native est également disponible pour Java, .NET et Node.js.

0
0 128
Annonce Irène Mykhailova · Juil 17, 2022

Salut la communauté,

Nous sommes ravis d'annoncer que les rencontres de développeurs InterSystems sont enfin de retour en personne !

Le premier meetup lié au Python aura lieu le 21 juillet à 18h00 à Democracy Brewing, Boston, MA. Il y aura 2-3 courtes présentations liées au Python, des questions-réponses, des sessions de réseautage ainsi que de la bière gratuite avec des collations et des visites de la brasserie.

AGENDA:

0
0 48
Article Robert Cemper · Juil 1, 2022 8m read

Je m'intéresse particulièrement à l'utilisation des Globales avec Embedded Python.
Alors, j'ai commencé à consulter la documentation officielle.

#1 Introduction to Globals
Une tentative de description générique de ce qu'est une Globale. Pointant ensuite vers:

#2 A Closer Look at ObjectScript
Mais où puis-je trouver Embedded Python ?
Plus bas, se trouve:

#3 Embedded Python

3.1 Embedded Python Overview
3.1.1 Work with Globals

Idéal si vous n'avez jamais vu une Globale.
Sinon ce n'est qu'un exemple primitif choquant
3.2 Using Embedded Python
Dernier espoir: >>> Mais, absolument RIEN de visible.

3
0 139
Article Guillaume Rongier · Juil 8, 2022 3m read

InterSystems Native SDK pour Python est une interface légère pour les API d'InterSystems IRIS qui n'étaient auparavant disponibles que via ObjectScript.

Je suis particulièrement intéressé par la possibilité d'appeler des méthodes ObjectScript, plus précisément des méthodes de classe. Cela fonctionne, et cela fonctionne très bien, mais par défaut, les appels ne supportent que les arguments scalaires : chaînes de caractères, booléens, nombres intégraux et flottants.

Mais si vous voulez :

  • Transmettre ou retourner des structures, telles que des dicts ou des listes
  • Transmettre ou retourner des flux

Vous aurez besoin d'écrire un code glue ou de prendre ce projet (s'installe avec pip install edpy). Le paquet edpy vous donne une signature simple :

call(iris, class_name, method_name, args)

qui vous permet d'appeler n'importe quelle méthode ObjectScript et d'obtenir des résultats en retour. Importez-le comme ceci :

from edpy import iris

call accepte 4 arguments requis :

  • iris - la référence à un objet IRIS
  • class_name - Classe IRIS à appeler
  • method_name - Méthode IRIS à appeler
  • args - liste de 0 ou plusieurs arguments

Arguments

Chaque argument peut être l'un des suivants :

  • une chaîne de caractères (n'importe quelle longueur, si elle est supérieure à $$$MaxStringLength ou à 3641144 symboles, elle sera automatiquement convertie en un flux de données
  • booléen
  • nombre entier
  • flottant
  • dict (se transforme en un objet dynamique)
  • liste ou tuplet (converti en tableau dynamique)

Les arguments de type dict, liste et tuplet peuvent contenir récursivement d'autres dicts, listes et tuplets (tant que la mémoire le permet).

Valeur de retour

En retour, nous attendons soit une table/ un objet dynamique, soit une chaîne/un flux JSON. Dans ce cas, edpy le convertit d'abord en chaîne Python et, si possible, l'interprète comme un dict ou une liste Python. Sinon, le résultat sera retourné à l'appelant tel quel.

C'est à peu près tout, mais laissez-moi vous donner quelques exemples de méthodes ObjectScript et comment les appeler en utilisant cette fonction Python.

Exemple 1: Pong

ClassMethod Test(arg1, arg2, arg3) As %DynamicArray
{
    renvoie [(arg1), (arg2), (arg3)]
}

Appelez avec:

>>> iris.call(iris_native, "User.Py", "Test", [1, 1.2, "ABC"])
[1, 1.2, 'ABC']

Pas de surprise ici. Les arguments sont regroupés dans une liste et renvoyés à l'appelant.

Exemple 2: Propriétés

ClassMethod Test2(arg As %DynamicObject) As %String
{
    renvoie arg.Prop
}

Appelez comme ça :

>>> iris.call(iris_native, "User.Py", "Test2", [{"Prop":123}])
123

Maintenant, pour une invocation plus intégrée :

>>> iris.call(iris_native, "User.Py", "Test2", [{"Prop":{"Prop2":123}}])
{'Prop2': 123}

Si une propriété est trop longue, ce n'est pas grave non plus - des flux seront utilisés pour l'envoyer à IRIS et/ou la renvoyer :

ret = iris.call(iris_native, "User.Py", "Test2", [{"Prop":"A" * 10000000}])
>>> len(ret)
10000000

Si vous avez besoin de flux garantis du côté d'InterSystems IRIS, vous pouvez utiliser %Get:

set stream = arg.%Get("Prop",,"stream")

Si le flux est codé en base64, vous pouvez le décoder automatiquement avec :

set stream = arg.%Get("Prop",,"stream<base64")

Exemple 3: Chaîne ou flux

ClassMethod Test3(arg As %Stream.Object) As %String
{
    set file = ##class(%Stream.FileCharacter).%New()
    set file.TranslateTable = "UTF8"
    set filename = ##class(%File).ManagerDirectory() _ "test.txt"
    do file.LinkToFile(filename)
    if $isObject(arg) {
        set sc = file.CopyFromAndSave(arg)
    } else {
        do file.Write(arg)
        set sc = file.%Save()
    }
    if $$$ISERR(sc) {
        set jsonret = {"status":0, "payload":($system.Status.GetErrorText(sc))}
    } else {
        set jsonret = {"status":1}
    }
    quit jsonret.%ToJSON()
}

Ici, nous écrivons soit une chaîne de caractères, soit un flux à <mgr>test.txt.

>>> iris.call(iris_native, "User.Py", "Test3", ["&#x1f60a;"])
{'status': 1}

Remarque: dans tous les échantillons de code, "&# x1f642 ;" est saisi comme 😊.

Et si j'ouvre le fichier, je verrai un &#x1f60a ; et non deux ?? - donc nous préservons l'encodage.

>>> iris.call(iris_native, "User.Py", "Test3", ["&#x1f642;" * 10000000])
{'status': 1}

Je vais omettre la sortie du fichier pour des raisons de brièveté, mais c'est le cas.

Enfin, en passant un objet ou un tableau dynamique à l'intérieur, vous pouvez éviter complètement la dichotomie chaîne/flux, même si vous ne savez pas si la propriété sera plus courte ou plus longue que la limite de la chaîne. Dans ce cas, vous pouvez toujours obtenir votre propriété suspecte comme un flux.

Exemple 4: Les flux de retour

ClassMethod Test4(arg As %DynamicArray) As %String
{
    return arg.%Get(0)
}

Voilà à quoi ça ressemble :

>>> ret = iris.call(iris_native, "User.Py", "Test4", [["&#x1f60a;" * 10000000]])
>>> len(ret)
10000000
>>> ret[:5]
'&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;'

Une dernière chose

Il existe également une fonction get_iris(ip="localhost", port=1972, espace de nom="USER", nom d'utilisateur="_SYSTEM", mot de passe="SYS") qui vous permet d'obtenir un objet IRIS fonctionnel.. Voici donc un exemple complet, si vous voulez l'essayer vous-même :

Téléchargez d'abord la classe User.Py et installez la bibliothèque python edpy :

pip install edpy

Et ensuite dans l'appel python :

from edpy import iris
iris_native = iris.get_iris()
iris.call(iris_native, "User.Py", "Test",  [1, 1.2, "ABC"])
iris.call(iris_native, "User.Py", "Test2", [{"Prop":123}])
iris.call(iris_native, "User.Py", "Test2", [{"Prop":{"Prop2":123}}])
ret2 = iris.call(iris_native, "User.Py", "Test2", [{"Prop":"A" * 10000000}])
iris.call(iris_native, "User.Py", "Test3", ["&#x1f60a;"])
iris.call(iris_native, "User.Py", "Test3", ["&#x1f60a;" * 10000000])
ret4 = iris.call(iris_native, "User.Py", "Test4", [["&#x1f60a;" * 10000000]])

Conclusion

Native SDK for Python est un outil puissant, vous fournissant un accès complet et sans restriction à InterSystems IRIS. J'espère que ce projet vous fera gagner du temps dans le traitement des appels InterSystems IRIS. Y a-t-il une combinaison d'arguments de méthode qu'il ne supporte pas ? Si oui, partagez dans les commentaires comment vous les appelez.

Liens

0
0 67
Article Guillaume Rongier · Juil 4, 2022 11m read

Iris-python-template

Projet modèle avec divers codes Python à utiliser pour InterSystems IRIS Community Edition avec conteneur.

Caractéristiques :

  • Notebooks
  • Noyau Python intégré
    • Noyau ObjectScript
    • Noyau Vanilla Python
  • Python intégré
  • Code exemplaire
    • Démonstration de Flask
  • API natives Python d'IRIS
  • Code exemplaire

Diagram

2. Table de matières

3. Installation

3.1. Docker

Le dépôt est dockerisé, vous pouvez donc cloner/git puller le dépôt dans n'importe quel local

git clone https://github.com/grongierisc/iris-python-template.git

Ouvrez le terminal dans ce dossier et exécutez :

docker-compose up -d

et ouvrez ensuite http://localhost:8888/tree pour Notebooks

Ou bien, ouvrez le dossier cloné dans VSCode, démarrez docker-compose et ouvrez l'URL via le menu VSCode : VsCodeNotebooks

4. Comment commencer le codage

4.1. Conditions préalables

Vérifiez que vous avez git and Docker desktop installé.

TCe dépôt est prêt à être codé dans VSCode avec le plugin ObjectScript. Installer le plugin VSCode, Docker et ObjectScript et ouvrir le dossier dans VSCode.

4.1.1. Commencer le codage en ObjectScript

Ouvrez la classe /src/ObjectScript/Embedded/Python.cls et essayez d'y apporter des modifications - elles seront compilées dans le conteneur docker IRIS en cours d'exécution.

4.1.2. Commencer le codage avec Python intégré

Le moyen le plus simple est d'exécuter VsCode dans le conteneur.

Pour vous attacher à un conteneur Docker, sélectionnez Remote-Containers : Attach to Running Container... dans la palette de commande (kbstyle(F1)) ou utiliser le Remote Explorer dans la barre d'activité et dans la vue Containers, sélectionner l'action en ligne Attach to Container sur le conteneur auquel vous voulez vous connecter.

Capture d'écran de Containers Explorer

Ensuite, configurez votre interpréteur python pour /usr/irissys/bin/irispython

PythonInterpreter

4.1.3. Commencez le codage avec les Notebooks

Ouvrez cette url : http://localhost:8888/tree

Vous avez alors accès à trois notebooks différents avec trois noyaux différents.

  • Noyau Python E;Embedded
  • Noyau ObjectScript
  • Noyau Vanilla python3
Notebooks

5. Le contenu du dépôt

5.1. Dockerfile

Un dockerfile qui installe quelques dépendances de python (pip, venv) et sudo dans le conteneur pour faciliter le travail. Puis il crée le dossiers dev et y copie ce dépôt git.

Il lance IRIS et importe les fichiers csv de Titanics, puis il active %Service_CallIn pour Python Shell. Utilisez le fichier docker-compose.yml correspondant pour configurer facilement des paramètres supplémentaires tels que le numéro de port et l'emplacement des clés et des dossiers d'hôte.

Ce dockerfile se termine par l'installation des exigences pour les modules python.

La dernière partie concerne l'installation de Jupyter Notebook et de ses noyaux.

Utilisez le fichier .env/ pour ajuster le dockerfile utilisé dans docker-compose.

5.2. .vscode/settings.json

Fichier de configuration pour vous permettre de coder immédiatement en VSCode avec le plugin VSCode ObjectScript

5.3. .vscode/launch.json

Fichier de configuration si vous voulez déboguer avec VSCode ObjectScript.

Découvrez tous les fichiers dans cet article

5.4. .vscode/extensions.json

Fichier de recommandation pour ajouter des extensions si vous voulez fonctionner avec VSCode dans le conteneur.

Plus d'informations ici

Architecture

C'est très utile pour travailler avec du python intégré.

5.5. src folder

Ce dossier est divisé en deux parties, une pour les exemples ObjectScript et une pour le code Python..

5.5.1. src/ObjectScript

Un fragment de code différent qui montre comment utiliser python en IRIS.

5.5.1.1. src/ObjectScript/Embedded/Python.cls

Tous les commentaires sont en français pour vous permettre d'améliorer vos compétences en français également.

/// Exemple de python intégré
Class ObjectScript.Embbeded.Python Extends %SwizzleObject
{

/// HelloWorld avec un paramètre
ClassMethod HelloWorld(name As %String = "toto") As %Boolean [ Language = python ]
{
    print("Hello",name)
    return True
}

/// Description
Method compare(modèle, chaine) As %Status [ Language = python ]
{
    import re

    # compare la chaîne [chaîne] au modèle [modèle]
    # affichage résultats
    print(f"\nRésultats({chaine},{modèle})")
    match = re.match(modèle, chaine)
    if match:
        print(match.groups())
    else:
        print(f"La chaîne [{chaine}] ne correspond pas au modèle [{modèle}]")
}

/// Description
Method compareObjectScript(modèle, chaine) As %Status
{
    w !,"Résultats("_chaine_","_modèle_")",!
    set matcher=##class(%Regex.Matcher).%New(modèle)                             
    set matcher.Text=chaine
    if matcher.Locate() {
        write matcher.GroupGet(1)
    }
    else {
        w "La chaîne ["_chaine_"] ne correspond pas au modèle ["_modèle_"]"
    }
}

/// Description
Method DemoPyhtonToPython() As %Status [ Language = python ]
{
    # expression régulières en python
    # récupérer les différents champs d'une chaîne
    # le modèle : une suite de chiffres entourée de caractères quelconques
    # on ne veut récupérer que la suite de chiffres
    modèle = r"^.*?(\d+).*?$"

    # on confronte la chaîne au modèle
    self.compare(modèle, "xyz1234abcd")
    self.compare(modèle, "12 34")
    self.compare(modèle, "abcd")
}

Method DemoPyhtonToObjectScript() As %Status [ Language = python ]
{
    # expression régulières en python
    # récupérer les différents champs d'une chaîne
    # le modèle : une suite de chiffres entourée de caractères quelconques
    # on ne veut récupérer que la suite de chiffres
    modèle = r"^.*?(\d+).*?$"

    # on confronte la chaîne au modèle
    self.compareObjectScript(modèle, "xyz1234abcd")
    self.compareObjectScript(modèle, "12 34")
    self.compareObjectScript(modèle, "abcd")
}

/// Description
Method DemoObjectScriptToPython() As %Status
{
    // le modèle - une date au format jj/mm/aa
    set modèle = "^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$"
    do ..compare(modèle, "10/05/97")
    do ..compare(modèle, " 04/04/01 ")
    do ..compare(modèle, "5/1/01")
}

}
  • HelloWorld
    • Une fonction simple pour dire "Bonjour!" en python
    • Il utilise l'enveloppe OjectScript avec la balise [ Language = python ]
  • comparer
    • Une fonction python qui compare une chaîne de caractères avec un regx, s'il y a une correspondance, elle l'affiche, sinon elle affiche qu'aucune correspondance n'a été trouvée
  • compareObjectScript
    • Même fonction que celle en python mais en ObjectScript
  • DemoPyhtonToPython
    • Montrer comment utiliser une fonction python avec du code python enveloppé dans de l'ObjectScript.
set demo = ##class(ObjectScript.Embbeded.Python).%New()

zw demo.DemoPyhtonToPython()
  • DemoPyhtonToObjectScript
    • Une fonction python qui montre comment lancer une fonction ObjecScript
  • DemoObjectScriptToPython
    • Une fonction ObjectScript qui montre comment appeler une fonction python

5.5.1.2. src/ObjectScript/Gateway/Python.cls

Une classe ObjectScript qui montre comment appeler un code phyton externe avec la fonctionnalité de la passerelle.

Dans cet exemple, le code python n'est pas exécuté dans le même processus d'IRIS.

/// Description
Classe Gateway.Python
{

/// Démonstration d'une passerelle python pour exécuter du code python en dehors d'un processus iris.
ClassMethod Demo() As %Status
{
    Set sc = $$$OK

    set pyGate = $system.external.getPythonGateway()

    d pyGate.addToPath("/irisdev/app/src/Python/gateway/Address.py")

    set objectBase = ##class(%Net.Remote.Object).%New(pyGate,"Address")

    set street = objectBase.street

    zw street

    Return sc
}

}

5.5.2. src/Python

Un autre fragment de code python qui montre comment utiliser le python intégré dans IRIS.

5.5.2.1. src/Python/embedded/demo.cls

Tous les commentaires sont en français pour vous permettre d'améliorer vos compétences en français également.

import iris

person = iris.cls('Titanic.Table.Passenger')._OpenId(1)

print(person.__dict__)

Importez d'abord le module iris qui permet d'activer les capacités de python intégré. Ouvrez une classe persistante avec la fonction cls du module iris. Notez que toutes les fonctions % sont remplacées par _.

Pour exécuter cet exemple, vous devez utiliser le shell iris python :

/usr/irissys/bin/irispython /opt/irisapp/src/Python/embedded/demo.py

5.5.2.2. src/Python/native/demo.cls

Montrer comment utiliser l'api native dans le code python.

import irisnative

# créer une connexion à la base de données et une instance IRIS
connection = irisnative.createConnection("localhost", 1972, "USER", "superuser", "SYS", sharedmemory = False)
myIris = irisnative.createIris(connection)

# classMethod
passenger = myIris.classMethodObject("Titanic.Table.Passenger","%OpenId",1)
print(passenger.get("name"))

# globale
myIris.set("hello","myGlobal")
print(myIris.get("myGlobal"))

Pour importer iris native, vous devez installer les Api Wheels native dans votre environnement Python.

pip3 install /usr/irissys/dev/python/intersystems_irispython-3.2.0-py3-none-any.whl

Ensuite, vous pouvez exécuter ce code python

/usr/bin/python3 /opt/irisapp/src/Python/native/demo.py

Notez que dans ce cas, une connexion est établie avec la base de données IRIS, ce qui signifie que ce code est exécuté dans un processus différent de celui d'IRIS.

5.5.2.3. src/Python/flask

Une démo complète de la combinaison entre python intégré et le micro framework flask. Vous pouvez tester ce point final :

GET http://localhost:4040/api/passengers?currPage=1&pageSize=1
5.5.2.3.1. Comment cela fonctionne

Afin d'utiliser Python embarqué, nous utilisons irispython comme interpréteur python, et faisons :

import iris

Juste au début du fichier.

Nous serons alors en mesure d'appliquer des méthodes telles que :

flaskExample

Comme vous pouvez le voir, pour obtenir un passager avec un ID, il suffit d'exécuter une requête et d'utiliser son ensemble de résultats.

Nous pouvons également utiliser directement les objets IRIS :

flaskObjectExample

Ici, nous utilisons une requête SQL pour obtenir tous les IDs dans le tableau, et nous récupérons ensuite chaque passager du tableau avec la méthode %OpenId() de la classe Titanic.Table.Passenger (notez que puisque % est un caractère illégal en Python, nous utilisons _ au lieu de cela).

Grâce à Flask, nous implémentons toutes nos itinéraires et méthodes de cette façon.

5.5.2.3.2. Lancement du serveur flask

Pour lancer le serveur, nous utilisons gunicorn avec irispython.

Dans le fichier docker-compose, nous ajoutons la ligne suivante :

iris:
  command: -a "sh /opt/irisapp/server_start.sh"

Cela lancera, après le démarrage du conteneur (grâce au flag -a), le script suivant :

#!/bin/bash

cd ${SRC_PATH}/src/Python/flask

${PYTHON_PATH} -m gunicorn --bind "0.0.0.0:8080" wsgi:app &

exit 1

Avec les variables d'environnement définies dans le Dockerfile comme suit :

ENV PYTHON_PATH=/usr/irissys/bin/irispython
ENV SRC_PATH=/opt/irisapp/

5.5.3. src/Notebooks

Trois notebooks avec trois noyaux différents :

  • Un noyau Python3 pour exécuter les API natives.
  • Un noyau Python intégré
  • Un noyau ObjectScript

Les notebooks sont accessibles ici http://localhost:8888/tree

Notebooks

5.5.3.1. src/Notebooks/HelloWorldEmbedded.ipynb

Ce notebook utilise le noyau python intégré d'IRIS.

Il montre des exemples pour ouvrir et sauvegarder des classes persistantes et comment exécuter des requêtes SQL.

5.5.3.2. src/Notebooks/IrisNative.ipynb

Ce notebook utilise le noyau python vanilla.

Il montre un exemple d'exécution d'iris native apis.

5.5.3.3. src/Notebooks/ObjectScript.ipynb

Ce notebook utilise le noyau ObjectScript.

Il montre un exemple d'exécution de code ObjectSCript et comment utiliser python intégré dans ObjectScript.

0
0 750