Find

Article
· Oct 9 6m read

Writing a REST api service for exporting the generated patient data in .csv

Hi,

 

It's me again😁, recently I am working on generating some fake patient data for testing purpose with the help of Chat-GPT by using Python. And, at the same time I would like to share my learning curve.😑

1st of all for building a custom REST api service is easy by extending the %CSP.REST

Creating a REST Service Manually

Let's Start !😂

1. Create a class datagen.restservice which extends  %CSP.REST 

Class datagen.restservice Extends %CSP.REST
{
Parameter CONTENTTYPE = "application/json";
}

 

2. Add a function genpatientcsv() to generate the patient data, and package it into csv string

Class datagen.restservice Extends %CSP.REST
{
Parameter CONTENTTYPE = "application/json";
ClassMethod genpatientcsv() As %String [ Language = python ]
{
    # w ##class(datagen.restservice).genpatientcsv()
    # python.exe -m pip install faker
    # python.exe -m pip install pandas

    from faker import Faker
    import random
    import pandas as pd
    from io import StringIO

    # Initialize Faker
    fake = Faker()

    def generate_patient(patient_id):
        return {
            "PatientID": patient_id,
            "Name": fake.name(),
            "Gender": random.choice(["Male", "Female"]),
            "DOB": fake.date_of_birth(minimum_age=0, maximum_age=100).strftime("%Y-%m-%d"),
            "City": fake.city(),
            "Phone": fake.phone_number(),
            "Email": fake.email(),
            "BloodType": random.choice(["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]),
            "Diagnosis": random.choice(["Hypertension", "Diabetes", "Asthma", "Healthy", "Flu"]),
            "Height_cm": round(random.uniform(140, 200), 1),
            "Weight_kg": round(random.uniform(40, 120), 1),
        }

    # Generate 10 patients
    patients = [generate_patient(i) for i in range(1, 11)]

    # Convert to DataFrame
    df = pd.DataFrame(patients)

    # Convert to CSV string (without saving to file)
    csv_buffer = StringIO()
    df.to_csv(csv_buffer, index=False)
    csv_string = csv_buffer.getvalue()

    return csv_string
}
}

you may test the function in the terminal by typing

w ##class(datagen.restservice).genpatientcsv()

3. Add a function GetMyDataCSV() in Python for populating the csv string as a csv file and then output through the REST api service. This can be achieve by,
   3.1. calling the patient data generate function to get the csv string
   3.2. set the %response.ContentType = "text/csv"
   3.3. set the header "Content-Disposition" value to "attachment; filename=mydata.csv"
   3.4.  write the generated csv string as output

remember to pip install the related libraries

Class datagen.restservice Extends %CSP.REST
{
Parameter CONTENTTYPE = "application/json";
ClassMethod GetMyDataCSV() As %Status
{
    // Build CSV string
    Set tCSVString = ##class(datagen.restservice).genpatientcsv()

    //Set headers and output CSV
    Set %response.ContentType = "text/csv"
    Do %response.SetHeader("Content-Disposition","attachment; filename=mydata.csv")
    
    // Output the data
    W tCSVString

    Quit $$$OK
}

ClassMethod genpatientcsv() As %String [ Language = python ]
{
    # w ##class(datagen.restservice).genpatientcsv()
    # python.exe -m pip install faker
    # python.exe -m pip install pandas

    from faker import Faker
    import random
    import pandas as pd
    from io import StringIO

    # Initialize Faker
    fake = Faker()

    def generate_patient(patient_id):
        return {
            "PatientID": patient_id,
            "Name": fake.name(),
            "Gender": random.choice(["Male", "Female"]),
            "DOB": fake.date_of_birth(minimum_age=0, maximum_age=100).strftime("%Y-%m-%d"),
            "City": fake.city(),
            "Phone": fake.phone_number(),
            "Email": fake.email(),
            "BloodType": random.choice(["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]),
            "Diagnosis": random.choice(["Hypertension", "Diabetes", "Asthma", "Healthy", "Flu"]),
            "Height_cm": round(random.uniform(140, 200), 1),
            "Weight_kg": round(random.uniform(40, 120), 1),
        }

    # Generate 10 patients
    patients = [generate_patient(i) for i in range(1, 11)]

    # Convert to DataFrame
    df = pd.DataFrame(patients)

    # Convert to CSV string (without saving to file)
    csv_buffer = StringIO()
    df.to_csv(csv_buffer, index=False)
    csv_string = csv_buffer.getvalue()

    return csv_string
}
}

4. Add the route to this function and compile the class

Class datagen.restservice Extends %CSP.REST
{
Parameter CONTENTTYPE = "application/json";
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
        <Route Url="/export/patientdata" Method="GET" Call="GetMyDataCSV"/>
</Routes>
}

ClassMethod GetMyDataCSV() As %Status
{
    // Build CSV string
    Set tCSVString = ##class(datagen.restservice).genpatientcsv()

    //Set headers and output CSV
    Set %response.ContentType = "text/csv"
    Do %response.SetHeader("Content-Disposition","attachment; filename=mydata.csv")
    
    // Output the data
    W tCSVString

    Quit $$$OK
}

ClassMethod genpatientcsv() As %String [ Language = python ]
{
    # w ##class(datagen.restservice).genpatientcsv()
    # python.exe -m pip install faker
    # python.exe -m pip install pandas

    from faker import Faker
    import random
    import pandas as pd
    from io import StringIO

    # Initialize Faker
    fake = Faker()

    def generate_patient(patient_id):
        return {
            "PatientID": patient_id,
            "Name": fake.name(),
            "Gender": random.choice(["Male", "Female"]),
            "DOB": fake.date_of_birth(minimum_age=0, maximum_age=100).strftime("%Y-%m-%d"),
            "City": fake.city(),
            "Phone": fake.phone_number(),
            "Email": fake.email(),
            "BloodType": random.choice(["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]),
            "Diagnosis": random.choice(["Hypertension", "Diabetes", "Asthma", "Healthy", "Flu"]),
            "Height_cm": round(random.uniform(140, 200), 1),
            "Weight_kg": round(random.uniform(40, 120), 1),
        }

    # Generate 10 patients
    patients = [generate_patient(i) for i in range(1, 11)]

    # Convert to DataFrame
    df = pd.DataFrame(patients)

    # Convert to CSV string (without saving to file)
    csv_buffer = StringIO()
    df.to_csv(csv_buffer, index=False)
    csv_string = csv_buffer.getvalue()

    return csv_string
}
}

 

 

OK, now our code is ready. 😁 The next thing is to add the REST service to the web application

Input your Path, Namespace, and Rest service class name, and then Save

Assign the proper application role to this web application (because I am lazy, I just simply assign %All for testing 🤐)

 

OK everything is ready!!😁 Let's test the REST api!!!😂

Input the following path in a bowser

http://localhost/irishealth/csp/mpapp/export/patientdata

It trigger a file download, the file name is mydata.csv😗

Let's check the file 😊

 

Yeah!!! Work well!! 😁😁

Thank you so much for the reading. 😉

3 Comments
Discussion (3)2
Log in or sign up to continue
Article
· Oct 9 4m read

Expanda a capacidade do ObjectScript de processar YAML

A linguagem ObjectScript possui um suporte incrível a JSON por meio de classes como %DynamicObject e %JSON.Adaptor. Esse suporte se deve à imensa popularidade do formato JSON em relação ao domínio anterior do XML. O JSON trouxe menos verbosidade à representação de dados e aumentou a legibilidade para humanos que precisavam interpretar conteúdo JSON. Para reduzir ainda mais a verbosidade e aumentar a legibilidade, o formato YAML foi criado. O formato YAML, muito fácil de ler, rapidamente se tornou o formato mais popular para representar configurações e parametrizações, devido à sua legibilidade e verbosidade mínima. Embora o XML raramente seja usado para parametrização e configuração, com o YAML, o JSON está gradualmente se limitando a ser um formato de troca de dados, em vez de ser usado para configurações, parametrizações e representações de metadados. Agora, tudo isso é feito com YAML. Portanto, a linguagem primária das tecnologias InterSystems precisa de amplo suporte para processamento YAML, no mesmo nível que para JSON e XML. Por esse motivo, lancei um novo pacote para tornar o ObjectScript um poderoso processador YAML. O nome do pacote é yaml-adaptor.

Vamos começar instalando o pacote

1. Se for de IPM, abra o IRIS Terminal e execute:

USER>zpm “install yaml-adaptor”

2. Se for de Docker, Clone/git pull o repositório do yaml-adaptor em uma pasta local:

$ git clone https://github.com/yurimarx/yaml-adaptor.git

3. Abra o terminal na pasta e execute:

$ docker-compose build

4. Execute o IRIS container do projeto:

$ docker-compose up -d

Por que usar o pacote?

Com este pacote, você poderá interoperar, ler, escrever e transformar YAML em DynamicObjects, JSON e XML bidirecionalmente. Este pacote permite ler e gerar dados, configurações e parametrizações nos formatos mais populares do mercado de forma dinâmica, com pouco código, alto desempenho e em tempo real.

O pacote em ação!

É muito simples. As capacidades são:

1. Converter de YAML string para JSON string

ClassMethod TestYamlToJson() As %Status
{
    Set sc = $$$OK
    set yamlContent = ""_$CHAR(10)_
        "user:"_$CHAR(10)_
        "    name: 'Jane Doe'"_$CHAR(10)_
        "    age: 30"_$CHAR(10)_
        "    roles:"_$CHAR(10)_
        "    - 'admin'"_$CHAR(10)_
        "    - 'editor'"_$CHAR(10)_
        "database:"_$CHAR(10)_
        "    host: 'localhost'"_$CHAR(10)_
        "    port: 5432"_$CHAR(10)_
        ""
    Do ##class(dc.yamladapter.YamlUtil).yamlToJson(yamlContent, .jsonContent)
    Set jsonObj = {}.%FromJSON(jsonContent)
    Write jsonObj.%ToJSON()

    Return sc
}

2. Gerar arquivo YAML de um arquivo JSON 

ClassMethod TestYamlFileToJsonFile() As %Status
{

    Set sc = $$$OK
    Set yamlFile = "/tmp/samples/sample.yaml"
    Set jsonFile = "/tmp/samples/sample_result.json"
    Write ##class(dc.yamladapter.YamlUtil).yamlFileToJsonFile(yamlFile,jsonFile)
    

    Return sc
}

3. Converter de JSON string para YAML string

ClassMethod TestJsonToYaml() As %Status
{
    Set sc = $$$OK
    set jsonContent = "{""user"":{""name"":""Jane Doe"",""age"":30,""roles"":[""admin"",""editor""]},""database"":{""host"":""localhost"",""port"":5432}}"
    Do ##class(dc.yamladapter.YamlUtil).jsonToYaml(jsonContent, .yamlContent)
    Write yamlContent

    Return sc
}

4. Gerar arquivo JSON de um arquivo YAML 

ClassMethod TestJsonFileToYamlFile() As %Status
{

    Set sc = $$$OK
    Set jsonFile = "/tmp/samples/sample.json"
    Set yamlFile = "/tmp/samples/sample_result.yaml"
    Write ##class(dc.yamladapter.YamlUtil).jsonFileToYamlFile(jsonFile, yamlFile)
    

    Return sc
}

5. Carregar um objeto dinâmico a partir de YAML string ou arquivos YAML 

ClassMethod TestYamlFileToDynamicObject() As %Status
{
    Set sc = $$$OK
    Set yamlFile = "/tmp/samples/sample.yaml"
    Set dynamicYaml = ##class(YamlAdaptor).CreateFromFile(yamlFile)

    Write "Title: "_dynamicYaml.title, !
    Write "Version: "_dynamicYaml.version, !

    Return sc
}

6. Gerar YAML de objetos dinâmicos

ClassMethod TestDynamicObjectToYaml() As %Status
{
    Set sc = $$$OK
    Set dynaObj = {}
    Set dynaObj.project = "Project A"
    Set dynaObj.version = "1.0"
    Set yamlContent = ##class(YamlAdaptor).CreateYamlFromDynamicObject(dynaObj)

    Write yamlContent

    Return sc
}

7. Gerar arquivo XML de arquivo YAML

ClassMethod TestXmlFileToYamlFile() As %Status
{

    Set sc = $$$OK
    Set xmlFile = "/tmp/samples/sample.xml"
    Set yamlFile = "/tmp/samples/sample_xml_result.yaml"
    Write ##class(dc.yamladapter.YamlUtil).xmlFileToYamlFile(xmlFile, yamlFile)
    

    Return sc
}

8. Gerar arquivo YAML de arquivo XML

ClassMethod TestYamlFileToXmlFile() As %Status
{

    Set sc = $$$OK
    Set yamlFile = "/tmp/samples/sample.yaml"
    Set xmlFile = "/tmp/samples/sample_result.xml"
    Write ##class(dc.yamladapter.YamlUtil).yamlFileToXmlFile(yamlFile, "sample", xmlFile)
    

    Return sc
}
Discussion (0)1
Log in or sign up to continue
Article
· Oct 9 4m read

Expand ObjectScript's ability to process YAML

The ObjectScript language has incredible JSON support through classes like %DynamicObject and %JSON.Adaptor. This support is due to the JSON format's immense popularity over the previous dominance of XML. JSON brought less verbosity to data representation and increased readability for humans who needed to interpret JSON content. To further reduce verbosity and increase readability, the YAML format was created. The very easy-to-read YAML format quickly became the most popular format for representing configurations and parameterizations, due to its readability and minimal verbosity. While XML is rarely used for parameterization and configuration, with YAML, JSON is gradually becoming limited to being a data exchange format rather than for configurations, parameterizations, and metadata representations. Now, all of this is done with YAML. Therefore, the primary language of InterSystems technologies needs broad support for YAML processing, at the same level as it does for JSON and XML. For this reason, I've released a new package to make ObjectScript a powerful YAML processor. The package name is yaml-adaptor.

Let's start by installing the package

1. If you using IPM, open the IRIS Terminal and call:

USER>zpm “install yaml-adaptor”

2. If you using Docker, Clone/git pull the yaml-adaptor repo into any local directory:

$ git clone https://github.com/yurimarx/yaml-adaptor.git

3. Open the terminal in this directory and run:

$ docker-compose build

4. Run the IRIS container with your project:

$ docker-compose up -d

Why use this package?

With this package, you'll be able to easily interoperate, read, write, and transform YAML to DynamicObjects, JSON, and XML bidirectionally. This package allows you to read and generate data, configurations, and parameterizations in the most popular market formats dynamically, with little code, high performance, and in real time.

The package in action!

It is very simple use this package. The features are:

1. Convert from YAML string to JSON string

ClassMethod TestYamlToJson() As %Status
{
    Set sc = $$$OK
    
    set yamlContent = ""_$CHAR(10)_
        "user:"_$CHAR(10)_
        "    name: 'Jane Doe'"_$CHAR(10)_
        "    age: 30"_$CHAR(10)_
        "    roles:"_$CHAR(10)_
        "    - 'admin'"_$CHAR(10)_
        "    - 'editor'"_$CHAR(10)_
        "database:"_$CHAR(10)_
        "    host: 'localhost'"_$CHAR(10)_
        "    port: 5432"_$CHAR(10)_
        ""

    Do ##class(dc.yamladapter.YamlUtil).yamlToJson(yamlContent, .jsonContent)
    Set jsonObj = {}.%FromJSON(jsonContent)
    Write jsonObj.%ToJSON()

    Return sc
}

2. Generate YAML file from a JSON file

ClassMethod TestYamlFileToJsonFile() As %Status
{

    Set sc = $$$OK

    Set yamlFile = "/tmp/samples/sample.yaml"
    Set jsonFile = "/tmp/samples/sample_result.json"

    Write ##class(dc.yamladapter.YamlUtil).yamlFileToJsonFile(yamlFile,jsonFile)
    

    Return sc
}

3. Convert from JSON string to YAML string

ClassMethod TestJsonToYaml() As %Status
{
    Set sc = $$$OK
    
    set jsonContent = "{""user"":{""name"":""Jane Doe"",""age"":30,""roles"":[""admin"",""editor""]},""database"":{""host"":""localhost"",""port"":5432}}"

    Do ##class(dc.yamladapter.YamlUtil).jsonToYaml(jsonContent, .yamlContent)
    Write yamlContent

    Return sc
}

4. Generate JSON file from YAML file

ClassMethod TestJsonFileToYamlFile() As %Status
{

    Set sc = $$$OK

    Set jsonFile = "/tmp/samples/sample.json"
    Set yamlFile = "/tmp/samples/sample_result.yaml"

    Write ##class(dc.yamladapter.YamlUtil).jsonFileToYamlFile(jsonFile, yamlFile)
    

    Return sc
}

5. Load a dynamic object from YAML string or YAML files

ClassMethod TestYamlFileToDynamicObject() As %Status
{
    Set sc = $$$OK

    Set yamlFile = "/tmp/samples/sample.yaml"
    
    Set dynamicYaml = ##class(YamlAdaptor).CreateFromFile(yamlFile)

    Write "Title: "_dynamicYaml.title, !
    Write "Version: "_dynamicYaml.version, !

    Return sc
}

Generate YAML from Dynamic Objects

ClassMethod TestDynamicObjectToYaml() As %Status
{
    Set sc = $$$OK

    Set dynaObj = {}
    Set dynaObj.project = "Project A"
    Set dynaObj.version = "1.0"
    
    Set yamlContent = ##class(YamlAdaptor).CreateYamlFromDynamicObject(dynaObj)

    Write yamlContent

    Return sc
}

Generate XML file from YAML file

ClassMethod TestXmlFileToYamlFile() As %Status
{

    Set sc = $$$OK

    Set xmlFile = "/tmp/samples/sample.xml"
    Set yamlFile = "/tmp/samples/sample_xml_result.yaml"

    Write ##class(dc.yamladapter.YamlUtil).xmlFileToYamlFile(xmlFile, yamlFile)
    

    Return sc
}

Generate YAML file from XML File

ClassMethod TestYamlFileToXmlFile() As %Status
{

    Set sc = $$$OK

    Set yamlFile = "/tmp/samples/sample.yaml"
    Set xmlFile = "/tmp/samples/sample_result.xml"

    Write ##class(dc.yamladapter.YamlUtil).yamlFileToXmlFile(yamlFile, "sample", xmlFile)
    

    Return sc
}
1 Comment
Discussion (1)1
Log in or sign up to continue
Article
· Oct 9 1m read

IRIS のベクトル検索を活用しユーザーへ最新で正確な応答を提供する RAG AI チャットボットを作成するチュートリアル

開発者の皆さん、こんにちは!

この記事では、Developer Hub にあるチュートリアルに新しいチュートリアル:InterSystems IRIS ベクトル検索を使用した RAG が追加されましたので内容をご紹介します。(準備不要でブラウザがあれば試せるチュートリアルです!)

このチュートリアルでは、生成 AI アプリケーションの精度向上に向けて、ベクトル検索と検索拡張生成(Retrieval Augmented Generation)の活用を体験できます。

具体的には、InterSystems IRIS のベクトル検索機能を活用し、生成 AI チャットボット向けのナレッジベースをサンプルコードを利用して作成します。

また、Streamlit を使用して作成したチャットボットを動かしながら、ナレッジベースの情報を追加することで生成 AI からの回答が変化していくことを確認していきます。

アカウント作成やログインも不要で  ボタンをクリックするだけで始められます👍

チュートリアルへのリンクは「開発者コミュニティのリソース」からも辿れます!

ぜひ、お試しください!​​​​​​

Discussion (0)1
Log in or sign up to continue
Announcement
· Oct 9

Security & AI Meetup for Developers and Startups

Join our next in-person Developer Meetup in Boston to explore Security & AI for Developers and Startups.

This event is hosted at CIC Venture Cafe.

Talk 1: When Prompts Become Payloads
Speaker: Mark-David McLaughlin, Director, Corporate Security, InterSystems

Talk 2: Serial Offenses: Common Vulnerability Types
Speaker: Jonathan Sue-Ho, Senior Security Engineer, InterSystems

>> Register here
 

⏱ Day and Time: October 21, 5:30 p.m. to 7:30 p.m.
📍CIC Venture Café in Cambridge, MA

Save your seat now!

Food, beverages, and networking opportunities will be provided as always.
Join our Discord channel to connect with developers from the InterSystems developer ecosystem.

Discussion (0)1
Log in or sign up to continue