0 Seguidores · 24 Publicaciones

Open Database Connectivity (ODBC) es una interfaz de programación de aplicaciones (API) estándar, la cual permite tener acceso a los sistemas que se encargan de administrar las bases de datos.

Obtener más información.

Artículo Arsh Hasan · oct 29, 2025 2m read

Tuve el mismo problema que contaba Jerry en el siguiente enlace al conectar IRIS con el servidor SQL. Mi conexión ODBC está configurada para autenticarse mediante autenticación nativa de Windows.

Configurad la conexión ODBC de IRIS con autenticación de Windows utilizando una cuenta de dominio específica en lugar de la cuenta predeterminada del servidor IRIS

¿Cómo lo solucioné yo?

La raíz del problema

0
0 20
Artículo Alberto Fuentes · jul 4, 2025 3m read

Estoy escribiendo esta publicación principalmente para recopilar un consenso informal sobre cómo los desarrolladores están utilizando Python junto con IRIS, ¡así que por favor responded a la encuesta al final del artículo! En el cuerpo del artículo, daré un poco de contexto sobre cada una de las opciones proporcionadas, así como sus ventajas, pero si lo preferís, podéis hacer una lectura rápida y simplemente responder la encuesta.

0
0 36
Artículo Alberto Fuentes · abr 11, 2025 2m read

Debido a que la interpretación de SCHEMA por parte de MySQL difiere de la comprensión interpretación común en SQL (como se ve en IRIS, SQL Server u Oracle), nuestro asistente automático de tablas vinculadas puede encontrar errores al intentar recuperar la información de metadatos para construir la tabla vinculada.

(Esto también se aplica a procedimientos y vistas vinculadas)

Al intentar crear una tabla vinculada mediante el asistente, os encontraréis con un error que se parece a esto:

0
0 61
Artículo Arsh Hasan · ene 17, 2025 2m read

En este tutorial, voy a explicar cómo podéis conectar la plataforma de datos IRIS a una base de datos SQL Server utilizando ODBC.

Prerequisitos: 

0
0 99
Artículo Ricardo Paiva · jul 15, 2024 1m read

Hola, espero que este post ayude:

En resumen: MAXLEN es relevante sobre todo para conexiones odbc/jdbc y necesitas especificar un valor apropiado dentro de tus tablas (clases), de lo contrario los datos podrían truncarse cuando los consultes, o incluso fallar cuando intentes insertar datos.

Una larga historia:

0
0 155
Artículo Ricardo Paiva · jun 21, 2024 5m read

Estamos emocionados de seguir lanzando nuevas funciones para InterSystems IRIS Cloud SQL, como la nueva capacidad de Búsqueda Vectorial que se estrenó por primera vez con InterSystems IRIS 2024.1. Cloud SQL es un servicio en la nube que ofrece precisamente eso: acceso SQL en la nube. Esto significa que estaréis usando tecnologías de controladores estándar de la industria como JDBC, ODBC y DB-API para conectaros a este servicio y acceder a vuestros datos. La documentación describe en detalle cómo configurar los ajustes importantes a nivel de controlador, pero no cubre herramientas específicas de terceros, ya que, como podéis imaginar, hay un número infinito de ellas.

En este artículo, complementaremos esa documentación de referencia con pasos más detallados para una popular herramienta de visualización de datos de terceros que varios de nuestros clientes usan para acceder a datos basados en IRIS: Microsoft Power BI.

0
0 243
Artículo Alberto Fuentes · abr 11, 2024 3m read

Veamos cómo crear de forma sencilla una conexión ODBC a IRIS en Windows para principiantes :D, probar la conexión y extraer datos en Excel.

Excel puede conectarse a bases de datos externas a través de ODBC. Dado que IRIS habla ODBC, podemos aprovechar el InterSystems ODBC Driver para crear una conexión ODBC con IRIS que Excel puede utilizar.

0
0 280
Artículo Jose-Tomas Salvador · mar 25, 2024 2m read

Recientemente, mientras discutía con mis alumnos el acceso a los datos almacenados en IRIS desde diferentes lenguajes, surgió la pregunta de si era posible iniciar la conexión y obtener datos de la solución Cloud (InterSystems IRIS CloudSQL) desde Microsoft Excel, y no al revés. Teniendo en cuenta las muchas y variadas formas en las que uno puede obtener datos en Excel (importar datos de fuentes externas, conectarse a bases de datos utilizando drivers ODBC, utilizando power queries y web queries, etc.) la opción obvia era probar con el driver ODBC. La única tarea que quedaba era tratar de conectarse a la base de datos en la nube utilizando el driver ODBC.

0
0 163
Artículo Heloisa Paiva · abr 11, 2023 3m read

Introducción

Este artículo tiene la intención de ser un sencillo tutorial de cómo crear conexiones ODBC y trabajar con ellas, ya que me pareció que empezar con ellas es un poco confuso. Yo tuve la ayuda de unas personas increíbles, y creo que todos merecemos ese apoyo.

Voy dividir cada pequeña parte en sesiones, así que puedes ir directamente a la que necesites, aunque recomiendo leerlo todo.

Voy a usar los datos de ejemplo creados en un artículo previo, Tutorial rápido para crear bases de datos de ejemplo: Samples.PersistentData, con las propiedades Name y Age.
 

Creando la conexión

0
0 488
Artículo Luis Angel Pérez Ramos · nov 22, 2022 5m read

Últimamente me han preguntado en varias ocasiones cómo hacer que el Framework Laravel funcione con InterSystems IRIS Data Platform. Ha pasado un tiempo desde la publicación de este anuncio sobre Laravel e InterSystems Caché. En este artículo mostraremos unas breves instrucciones sobre cómo configurar un proyecto Laravel para usarlo con InterSystems IRIS a través de ODBC.

¿Qué es Laravel?

0
1 144
Artículo Jean Millette · mar 14, 2022 2m read

Una de nuestras apps utiliza una consulta de clase para un informe ZEN y funciona perfectamente en ese informe, produciendo los resultados esperados. Hemos migrado a InterSystems Reports y nos hemos dado cuenta de que, para un informe que utiliza la misma consulta de clase, aparecen en la parte de abajo más de 100 filas extra con los mismos valores en las columnas.

Descartamos InterSystems Reports como fuente del problema reproduciendo el problema de "filas extra" con una hoja de cálculo de Excel que llama a la misma consulta de clase utilizando un procedimiento almacenado.

¿Cuál era el problema? Cuando llamábamos al procedimiento almacenado desde el antiguo ZEN Report o desde la función SQL Query en el Portal de Administración, no veíamos estas filas adicionales.

0
0 181
Artículo Muhammad Waseem · nov 19, 2021 2m read

En mis artículos anteriores, mostré los pasos para conectar, recuperar y guardar datos en Caché desde Appeon PowerBuilder usando ODBC.

En este artículo, mostraré cómo eliminar datos de Caché con Appeon PowerBuilder (https://www.appeon.com/products/powerbuilder) usando ODBC.

Estoy usando Company.cls de Samples-Data (https://github.com/intersystems/Samples-Data/tree/master/cls/Sample)

¡Empecemos!
 

Paso 1:En primer lugar, debemos establecer una conexión (https://community.intersystems.com/post/connecting-cach%C3%A9-appeon-powerbuilder-using-odbc)

0
0 403
Artículo Ariel Arias · nov 8, 2021 8m read

MODELO RESUMIDO {#1}

Siguiendo el ejemplo disponible en GitHub FHIR IntegratedML vamos usar el modelo resumido para entrenar el modelo de predicción de "No Asistirá" (NotShow).

Haremos un match entre los campos de la tabla PackageSample.NoShowMLRow y los campos de TrakCare. El punto de partida en TrakCare será la tabla SQLUser.RB_Appointment.

CAMPOTRAKCAREOBSERVACIONES
GenderAPPT_PAPMI_DR->PAPMI_Sex_DR->CTSEX_GenderSe espera valores "F" y "M"
ScheduledWeekDay{fn DAYOFWEEK(APPT_DateComp) }Días de la semana Domingo (1) a Sábado (7)
ScheduledWeek{fn WEEK(APPT_DateComp)}El número de la semana (1 a 52)
WaitingDaysDATEDIFF('dd',APPT_BookedDate, APPT_DateComp)Días entre el agendamiento y la fecha del compromiso)
AgeDATEDIFF('YY',APPT_PAPMI_DR->PAPMI_PAPER_DR->PAPER_DOB,APPT_DateComp)Edad del paciente (en años) al día de la cita.
HypertensionCIE10: (I10-I15) Enfermedades hipertensivas
DiabetesCIE10: (E10-E14) Diabetes mellitus
AlcoholismCIE10: (F10) Trastornos mentales y de comportamiento debidos al consumo de alcohol
HandicapCIE10: (Z73.6) Problemas relacionados con la limitación de las actividades debido a discapacidad
SMSreceivedAPPT_ConfirmationSi no tenemos sistema de envío de mensajes, usaremos el campo "Confirmado"
NoshowAPPT_StatusUsaremos el estado de cita para saber si el paciente fue atendido o se presentó al menos al compromiso

Preparamos la consulta para traer los datos de las citas {#2}

Para traer los datos desde TrakCare, vamos a preparar la consulta, y teniendo en cuenta los campos que se requieren, la query quedaría así:

Select
APPT_PAPMI_DR->PAPMI_PAPER_DR PatientID,
APPT_RowId ApptID,
APPT_DateComp ApptDate,
APPT_PAPMI_DR->PAPMI_Sex_DR->CTSEX_Gender Gender,
{fn DAYOFWEEK(APPT_DateComp)} ScheduledWeekDay,
{fn WEEK(APPT_DateComp)} ScheduledWeek,
DATEDIFF('dd',APPT_BookedDate, APPT_DateComp) WaitingDays,
DATEDIFF('YY',APPT_PAPMI_DR->PAPMI_PAPER_DR->PAPER_DOB,APPT_DateComp) Age,
CASE APPT_Confirmation
WHEN 'Y' THEN 1
ELSE 0
END SMSreceived,
CASE APPT_Status
WHEN 'P' THEN 1
WHEN 'A' THEN 0
WHEN 'X' THEN 0
WHEN 'I' THEN 0
WHEN 'N' THEN 1
WHEN 'T' THEN 0
WHEN 'H' THEN 0
WHEN 'C' THEN 0
WHEN 'S' THEN 0
WHEN 'D' THEN 0
ELSE APPT_Status
END Noshow
from RB_Appointment

Se puede modificar para traer todos los registros o filtrar por ejemplo el año en curso (dejar al menos fuera las citas futuras, pues estas servirán posteriormente, una vez entrenado el modelo para predecir el comportamiento de citas futuras. Se puede igualmente filtrar por establecimiento (APPT_AS_ParRef->AS_RES_ParRef->RES_CTLOC_DR->CTLOC_HOSPITAL_DR) pues es posible que el comportamiento sea diferente dependiendo esta variable (por cercanía al centro de atención por ejemplo).

Nota: Considerar si excluir del análsis citas canceladas (X) u otros estados como Transferido (T) pues son citas que se mostrarán como "NoShow" pero no se puede atribuir eso a un comportamiento del paciente necesariamente. Para este ejemplo se han considerado, pero a valor "0", es decir NoShow = False.

import pandas as pd
import jaydebeapi as jdbc
import time
import pyodbc as odbc
import irisnative

Función Diagnósticos {#3}

Tendremos funciones para determinar si el paciente está diagnosticado con Huipertensión, Diabetes, Alcoholismo o alguna restricción física (invalidez).

La función recibirá un arreglo con los diagnósticos del paciente al momento de la cita (filtrados por fecha) para retornar un 0 (False) o un 1 (True). Basta con que uno de los diagnósticos sea HTA para saber que el paciente en ese momento es hipertenso.

def is_hta (dxlist):
    ishta = 0
    htalist = ('I10', 'I11','I12', 'I13', 'I14', 'I15')
    for i in dxlist:
        if i in htalist:
            ishta = 1
    return ishta

def is_dbt (dxlist):
    isdbt = 0
    dbtlist = ('E10', 'E11','E12', 'E13', 'I14')
    for i in dxlist:
        if i in dbtlist:
            isdbt = 1
    return isdbt

def is_disabilited (dxlist):
    isdisabilited = 0
    disabilitedlist = ('Z73.6','1')
    for i in dxlist:
        if i in disabilitedlist:
            isdisabilited = 1
    return isdisabilited

def is_alcoholism (dxlist):
    isalcoholism = 0
    alcoholismlist = ('F10','1')
    for i in dxlist:
        if i in alcoholismlist:
            isalcoholism = 1
    return isalcoholism

def listdxbypatid (patid):
listadxsql = ()
if patid:
    idpaciente = patid
    sqlpatdx = """
    select %nolock
    MR_DIAGNOS.MRDIA_ICDCode_DR->MRCID_Code,
    MR_DIAGNOS.MRDIA_DATE
    from    SQLUser.MR_ADM, SQLUser.MR_DIAGNOS
    where   MR_ADM.MRADM_RowId IN (SELECT PAADM_MainMRADM_DR
    FROM  PA_Adm
    WHERE PAADM_PAPMI_DR = """ + str(idpaciente) + """ )
    and MR_ADM.MRADM_RowId = MR_DIAGNOS.MRDIA_MRADM_ParRef
    """
    listadxsql = pd.read_sql(sqlpatdx, conn)
return listadxsql

Preparar la Conexión {#4}

Preparamos la conexión utilizando la librería jaydebeapi y el conector que corresponde al ambiente a utilizar. En este caso, se trata de un ambiente sobre HealthShare, por lo que usaremos el JDBC de Cache.

# Establecemos nuestras variables de conexión (host, port, namespace)
envhost = "localhost"
envport = 1983
envns = "TRAK"

dbuser = "superuser"
dbaccess = "SYS"

url = "jdbc:Cache://" + envhost + ":" + str(envport) + "/" + envns
driver = 'com.intersys.jdbc.CacheDriver'
irisdriver = 'com.intersystems.jdbc.IRISDriver'

user = dbuser
password = dbaccess
# Para este ejemplo, el jar para Cache se encuentra bajo la carpeta "resources"
# ruta relativa a la ubicación de este notebook
#jarfile = "resources/cachejdbc.jar"
jarfile = "/Users/ArielArias/cachejdbc.jar"
conn = jdbc.connect(driver, url, [user, password], jarfile)
curs = conn.cursor()

Asignamos la consulta en una variable, para poder modificar posteriormente si es necesario. De esta forma además podemos utilizar asignación en múltiples líneas para tener una mejor vosión de lo que estamos extrayendo desde TrakCare.

sql_str = """Select TOP 3500
APPT_PAPMI_DR->PAPMI_PAPER_DR PatientID,
APPT_RowId ApptID,
APPT_DateComp ApptDate,
APPT_PAPMI_DR->PAPMI_Sex_DR->CTSEX_Gender Gender,
{fn DAYOFWEEK(APPT_DateComp)} ScheduledWeekDay,
{fn WEEK(APPT_DateComp)} ScheduledWeek,
DATEDIFF('dd',APPT_BookedDate, APPT_DateComp) WaitingDays,
DATEDIFF('YY',APPT_PAPMI_DR->PAPMI_PAPER_DR->PAPER_DOB,APPT_DateComp) Age,
CASE APPT_Confirmation
WHEN 'Y' THEN 1
ELSE 0
END SMSreceived,
CASE APPT_Status
WHEN 'P' THEN 1
WHEN 'A' THEN 0
WHEN 'X' THEN 0
WHEN 'I' THEN 0
WHEN 'N' THEN 1
WHEN 'T' THEN 0
WHEN 'H' THEN 0
WHEN 'C' THEN 0
WHEN 'S' THEN 0
WHEN 'D' THEN 0
ELSE APPT_Status
END Noshow
from RB_Appointment
Where 
APPT_DateComp BETWEEN to_date('01/01/2021','dd/mm/yyyy') AND NOW()
AND APPT_AS_ParRef->AS_RES_ParRef->RES_CTLOC_DR->CTLOC_HOSPITAL_DR IN (12129)"""

Ejecutar la consulta (DataFrame) {#5}

Utilizando la librerías pandas ejecutamos la consulta SQL y la dejamos en un DataFrame para posterior manipulación. Nos falta aún las columnas relacionadas a diagnósticos del paciente a la fecha de la cita (por ahora no consideraremos TODOS los diagnósticos del paciente, sólo los confirmados y que fueron ingresados previo a la fecha del compromiso.

start = time.time()
data = pd.read_sql(sql_str, conn)
end = time.time()
elapsedtime = end - start

# Sólo para tener una referencia veremos el tiempo de ejecución de la consulta
# Esto ayudará a evaluar cuántos registros se puede procesar
# O planificar una ejecución por períodos de tiempo más reducidos
print("Tiempo de Ejecución SQL: ",int(elapsedtime), " Segundos")

# Agregamos las columnas de Dx;  con valores negativos por ahora
data["Hypertension"] = 0
data["Diabetes"] = 0
data["Alcoholism"] = 0
data["Handicap"] = 0

# Verificamos nuestro dataframe
data.head()
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
</style>
PatientIDApptIDApptDateGenderScheduledWeekDayScheduledWeekWaitingDaysAgeSMSreceivedNoshowHypertensionDiabetesAlcoholismHandicap
059820511683||11250||12021-01-21F54027000000
159820511683||11804||12021-01-28F55127010000
259820511683||13466||12021-02-18F58027000000
359820511683||15128||12021-03-11F511027000000
459820511683||15682||12021-03-18F512027000000

Recorremos el Arreglo y traemos la lista de diagnósticos para cada paciente. Para optimizar el tiempo, verificamos si ya tenemos los diagnósticos del paciente teniendo una lista con los PatientID

start = time.time()
patient = []
## is_hta
## is_dbt
## is_disabilited
## is_alcoholism
for index, row in data.iterrows():
    if row['PatientID'] not in patient:
        patient.append(row['PatientID'])
        patappt = (row['ApptID'], row['PatientID'], row['ApptDate'])
        listpatdx = listdxbypatid(row['PatientID'])
    # Ya tenemos los diagnósticos del Paciente; 
    # ahora filtramos sólo los previos a la cita y los dejamos en una lista:
    if len(listpatdx):
        low_apptdate = listpatdx[listpatdx["MRDIA_Date"] <= patappt[2]]
        if len(low_apptdate):
            # Ahora necesitamos saber si el paciente "ES" o "ERA" Hipertenso para la fecha de la cita:
            diaghta = is_hta(low_apptdate.MRCID_Code)
            diagdbt = is_dbt(low_apptdate.MRCID_Code)
            diagdis = is_disabilited(low_apptdate.MRCID_Code)
            diagalcohol = is_alcoholism(low_apptdate.MRCID_Code)
        else:
            diaghta = 0
            diagdbt = 0
            diagdis = 0
    else:
        diaghta = 0
        diagdbt = 0
        diagdis = 0
    # Modificamos la información en la fila correspondiente
    # Sabemos que por ApptID habrá sólo un registro:
    data.loc[data.ApptID == row['ApptID'],'Hypertension'] = diaghta
    data.loc[data.ApptID == row['ApptID'],'Diabetes'] = diagdbt
    data.loc[data.ApptID == row['ApptID'],'Handicap'] = diagdis
    data.loc[data.ApptID == row['ApptID'],'Alcoholism'] = diagalcohol
    
end = time.time()

print(end - start)

Cerramos la conexión, de momento no la usaremos.

conn.close()

LLEVAR LOS REGISTROS A UNA INSTANCIA CON ML INTEGRADO {#6}

En este ejemplo, no podemos usar el mismo servidor pues en su versión no incluye la función de ML; así es que usaremos una instancia con IRIS for Health que incorpora ML.

Dado que la librería de python jaydebeapi soporta sólo un dirver conexión por ejecución, no podemos usar el mismo método pues habrá un error al intentar usarla para conectar IRIS (posterior a conectar Caché).

Para seguir con el ejemplo y no perder el DataFrame obtenido, vamos a crear una conexión a IRIS utilizando ODBC

Usaremos la misma instancia del ejemplo que hemos usado hasta ahora, es decir el NameSpace FHIRSERVER

dsn = 'IRIS FHIRML'
server = 'localhost' #IRIS server container or the docker machine's IP
port = '32782' # or 8091 if docker machine IP is used
database = 'FHIRSERVER'
username = 'SUPERUSER'
password = 'SYS'

irisconn = odbc.connect('DSN='+dsn+';')
irisconn.setencoding(encoding='utf-8')
iriscurs = irisconn.cursor()

modelName = "TrakNoShow"

fhirsql = """Select
Age, Alcoholism, Diabetes, 
Gender, Handicap, Hypertension, 
Noshow, SMSreceived, ScheduledWeek, 
ScheduledWeekDay, WaitingDays
FROM PackageSample.""" + modelName + "MLRow"

# Copiamos la tabla NoShowMLRow a nuestra TrakNoShowMLRow:
sqlcreate = "CREATE TABLE PackageSample." + modelName + "MLRow ("
sqlcreate = sqlcreate + "Gender CHAR(30)," 
sqlcreate = sqlcreate + "ScheduledWeekDay INT," 
sqlcreate = sqlcreate + "ScheduledWeek INT," 
sqlcreate = sqlcreate + "WaitingDays INT," 
sqlcreate = sqlcreate + "Age INT," 
sqlcreate = sqlcreate + "Hypertension BIT," 
sqlcreate = sqlcreate + "Diabetes BIT," 
sqlcreate = sqlcreate + "Alcoholism BIT," 
sqlcreate = sqlcreate + "Handicap BIT," 
sqlcreate = sqlcreate + "SMSreceived BIT," 
sqlcreate = sqlcreate + "Noshow BIT)" 

Ejecutamos la creción de la tabla:

iriscurs.execute(sqlcreate)
iriscurs.commit()

Inserción del DataFrame TrakCare {#7}

Para hacer una inserción directa de los datos, haremos una copia del DataFrame para eliminar luego algunas columnas que no usaremos de momento; esto sólo para hacer un INSERT más directo al momento de recorrer el DataFrame.

sqltest = "INSERT INTO PackageSample." + modelName + "MLRow"
sqltest = sqltest + " (Gender,ScheduledWeekDay,ScheduledWeek,WaitingDays,"
sqltest = sqltest + "Age,SMSreceived,Noshow,Hypertension,Diabetes,Alcoholism,Handicap) "
sqltest = sqltest + "values(?,?,?,?,?,?,?,?,?,?,?)"

for index, row in data.iterrows():
    params = [[row.Gender,row.ScheduledWeekDay,row.ScheduledWeek,row.WaitingDays,row.Age,row.SMSreceived,row.Noshow,row.Hypertension,row.Diabetes,row.Alcoholism,row.Handicap]]
    iriscurs.executemany(sqltest,params)

iriscurs.commit()

Preparación del Modelo {#8}

Para efecto de visualización, vamos a trabajar con variables para nombrar nuestro modelo, y definir con cuántos datos vamos a entrenar y cuántos vamos a utilizar para validar.

datasize = len(irisdata)
modelName = "TrakNoShow"
predictingCol = "Noshow"
# si requiere reiniciar el modelo, se elimina las tablas creadas:
sqldropcross = "DROP TABLE PackageSample." + modelName + "MLRowCrossValidation"
sqldroptest = "DROP TABLE PackageSample." + modelName + "MLRowTest"
sqldroptrain = "DROP TABLE PackageSample." + modelName + "MLRowTraining"
sqldropval = "DROP TABLE PackageSample." + modelName + "MLRowValidation"
sqldropmodel = "DROP MODEL " + modelName + "Model"

# definimos con qué porcentaje de los datos realizaremos el crossvalidation:
cvLen = int(datasize * 0.9)
# Y el resto para testing:
testLen = datasize - cvLen
# tamaño de los datos para entrenamiento:
trainLen = int(cvLen * 0.75)
validationLen = cvLen - trainLen
# Crearemos modelo con CrossValidation:
sqlcrossval = "CREATE TABLE PackageSample." + modelName + "MLRowCrossValidation AS "
sqlcrossval = sqlcrossval + "SELECT * FROM PackageSample." + modelName + "MLRow WHERE Id IN ("
sqlcrossval = sqlcrossval + "SELECT TOP " + str(cvLen) + " idx "
sqlcrossval = sqlcrossval + "FROM community.randrange(1, " + str(datasize+1)  + ") "
sqlcrossval = sqlcrossval + "ORDER BY randValue)"

# Creamos la tabla para pruebas del modelo
sqltest = "CREATE TABLE PackageSample." + modelName + "MLRowTest AS "
sqltest = sqltest + "SELECT TOP " + str(testLen) + " * FROM PackageSample." + modelName + "MLRow WHERE Id NOT IN ("
sqltest = sqltest + "SELECT Id FROM PackageSample." + modelName + "MLRowCrossValidation)"

# Creamos tabla para entrenamiento:
sqltrain = "CREATE TABLE PackageSample." + modelName + "MLRowTraining AS "
sqltrain = sqltrain + "SELECT * FROM PackageSample." + modelName + "MLRowCrossValidation WHERE Id IN ("
sqltrain = sqltrain + "SELECT TOP " + str(trainLen) + " idx "
sqltrain = sqltrain + "FROM community.randrange(1, " + str(datasize+1) + ") "
sqltrain = sqltrain + "ORDER BY randValue)"

# Tabla para validación:
sqlval = "CREATE TABLE PackageSample." + modelName + "MLRowValidation AS "
sqlval = sqlval + "SELECT TOP " + str(validationLen) + " * "
sqlval = sqlval + "FROM PackageSample." + modelName + "MLRowCrossValidation "
sqlval = sqlval + "WHERE Id NOT IN ("
sqlval = sqlval + "SELECT Id FROM PackageSample." + modelName + "MLRowTraining)"

# Para creación del modelo:
sqlcreatemodel = "CREATE MODEL "+ modelName + "Model PREDICTING (" + predictingCol + ") "
sqlcreatemodel = sqlcreatemodel + "FROM PackageSample." + modelName + "MLRowTraining"

# Para entrenar modelo:
sqltrainmodel = 'TRAIN MODEL ' + modelName + 'Model USING {"seed": 1}'

# Para validar modelo:
sqlvalmodel = "VALIDATE MODEL " + modelName + "Model FROM PackageSample." + modelName + "MLRowValidation"

Podemos ejecutar una a una las sentencias desde nuestro notebook para crear el modelo, y luego entrenarlo.

# Creamos tabla CrossValidation:
iriscurs.execute(sqlcrossval)
iriscurs.commit()

# Creamos tabla Test:
iriscurs.execute(sqltest)
iriscurs.commit()

# Creamos tabla para entrenamiento:
iriscurs.execute(sqltrain)
iriscurs.commit()

# Creamos tabla para validacion:
iriscurs.execute(sqlval)
iriscurs.commit()

# Creamos el modelo:
iriscurs.execute(sqlcreatemodel)
iriscurs.commit()

# Entrenamos el modelo:
iriscurs.execute(sqltrainmodel)
iriscurs.commit()

# Validamos el modelo:
iriscurs.execute(sqlvalmodel)
iriscurs.commit()

Entrenado el modelo, podemos utilizarlo para conocer la predicción, ya sea que enviamos datos desde otro origen o podemos utilizar consultas directamente sobre el modelo. Un ejemplo:

# TrakNoShowModel
# Probar consultas hacia el modelo:

sqlpredict = "SELECT top 10 PREDICT(TrakNoShowModel) AS PredictedNoshow, Noshow AS ActualNoshow FROM PackageSample.TrakNoShowMLRowTest"

predictdata = pd.read_sql(sqlpredict, irisconn)
predictdata
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
</style>
PredictedNoshowActualNoshow
0FalseFalse
1TrueTrue
2FalseFalse
3FalseFalse
4FalseFalse
5FalseFalse
6FalseFalse
7FalseFalse
8FalseFalse
9TrueFalse

ALGUNOS PROBLEMAS ENCONTRADOS {#9}

Durante la preparación de este documento se debió ajustar algunos parámetros y consultas para poder terminarlo. Se detalla a continuación para posible solución al replicar los pasos en otro ambiente:

  • Se ajustó la conexión a IRIS para forzar utilización de encoding UTF8; al no hacerlo, se detectó que el campo "Gender" quedaba vacío.
  • Problema de Performance al consultar los diagnósticos del paciente de forma iterativa; por eso se ajustó la consulta para traer todos los diagnósticos del paciente con fecha de ingreso, y luego con Python filtrar según fecha de la cita.
  • jaydebeapi soporta una conexión por ejecución; por esto se trabajó la conexión a TrakCare (sobre Caché) con esta librería y se utilizó pyodbc para conectar IRIS. Se puede hacer lo contrario, ODBC para Caché y JDBC para IRIS.

TO DO {#10}

Algunas mejoras a la aplicación de este ejemplo, y que pueden estar disponible en nuevos post:

  1. Se puede trabajar estos mismos pasos, direcamente desde IRIS, aprovechando aún más sus propiedades y facilidad para acceder a los datos. Se hizo como notebook sólo para ejemplificar que se puede traer varios origenes de datos a IRIS para crear un modelo de Machine Learning, entrenarlo, y validarlo.

  2. Tener estos pasos en una clase de IRIS, permitirá además operativizar el modelo, por medio de webservice como el ejemplo disponible en readmision demo

  3. Contar con una carga programada desde el origen que permita incluso actualizar datos, por ejemplo, del estado de cita. Esto permitirá por ejemplo, construir un cubo y posterior cuadro de mando que permita identificar a los pacientes con alta posibilidad de no asistir para reforzar el contacto.

0
2 149
Artículo Muhammad Waseem · sep 29, 2021 1m read

https://www.appeon.com/products/powerbuilder

Appeon PowerBuilder es una herramienta de desarrollo empresarial que permite crear componentes y aplicaciones empresariales basadas en datos.
Es un producto de una suite de Appeon que ofrece las herramientas para desarrollar aplicaciones cliente/servidor, web, móviles y distribuidas.

En este artículo, mostraré los pasos para conectarse a Caché con Appeon PowerBuilder usando ODBC.
 

Paso 1 : Asegúrate de que la opción "ODBC Driver" está seleccionada al instalar IRIS:

0
0 361
Artículo Eduardo Anglada · sep 7, 2021 3m read
Este es un ejemplo de código que funciona en IRIS 2020.1 y en Caché 2018.1.3 
No se mantendrá sincronizado con las nuevas versiones.  
Y NO cuenta con el servicio de soporte de InterSystems.
De vez en cuando, puedes encontrarte una situación en la que, por diferentes razones, ODBC es la única opción para acceder a un sistema remoto. Lo cual es suficiente mientras necesites examinar o cambiar tablas. Pero no puedes ejecutar directamente algunos comandos o cambiar algunos globals.
0
0 154
Artículo Jose-Tomas Salvador · abr 20, 2021 9m read

Palabras clave: Python, JDBC, SQL, IRIS, Jupyter Notebook, Pandas, Numpy y aprendizaje automático 

Hoy me he encontrado con este artículo de Zphong Li, que publicó en Enero de 2020 pero que creo que es muy interesante y aún útil a día de hoy. Así que... para los que estéis haciendo vuestros primeros pinitos en Machine Learning con InterSystems IRIS, Python y Jupyter... aquí lo tenéis!!

1. Objetivo

Esta es una nota sencilla de 5 minutos, donde os muestro cómo invocar el controlador JDBC de IRIS con la ayuda de Python 3, por ejemplo desde un Jupyter Notebook, para leer y escribir datos en una instancia de la base de datos de IRIS vía SQL.

El año pasado Zhong Li publicó una nota breve sobre como Enlazar Python con una base de datos Caché (sección 4.7). Ahora podría ser el momento de recapitular algunas opciones y discusiones sobre el uso de Python para acceder a una base de datos de IRIS, para leer sus datos en un dataframe de Pandas y una matriz de NumPy para realizar un análisis básico, y después escribir algunos datos pre-procesados o normalizados de nuevo en IRIS y que esté listo para canalizaciones (pipelines) adicionales de ML/DL.

Inmediatamente se me ocurren varias opciones:

  1.    ODBC: ¿Cómo hacerlo con PyODBC para Python 3 y SQL nativo?
  2.    JDBC: ¿Cómo hacerlo con JayDeBeApi para Python 3 y SQL nativo?
  3.    Spark:  ¿Cómo hacerlo con PySpark y SQL?
  4.    API nativa de Python para IRIS: ¿Qué hay más allá del anterior Python Binding para Caché?
  5.   ** ¿IPtyhon Magic SQL %%sql**? ¿Podría  funcionar con IRIS?

 ¿Hay alguna otra opción que se me haya escapado? También estoy interesado en probarla. 

2. Alcance 

¿Comenzamos con un enfoque JDBC común? En la siguiente nota breve recapitularemos ODBC, Spark y la API nativa de Python. 

En el alcance:

Los siguientes componentes comunes se abordan en esta demostración rápida:

  • Anaconda
  • Jupyter Notebook 
  • Python 3
  • JayDeBeApi
  • JPyPe
  • Pandas
  • NumPy
  • Una instancia de IRIS 2019.x
  • ### Fuera del alcance:

    En esta nota rápida NO se abordarán los siguientes aspectos - son importantes y pueden tratarse por separado con soluciones, implementaciones y servicios específicos: 

  • Seguridad de extremo a extremo.
  • Rendimiento no funcional, etc.
  • Solución de problemas y soporte.
  • Licencias. 
  • 3. Demostración

    3.1 Ejecución de una instancia de IRIS:

    Simplemente ejecuté un contenedor IRIS 2019.4 como servidor "remoto" de la base de datos. Puedes utilizar cualquier instancia de IRIS a la que tengas acceso autorizado.

    zhongli@UKM5530ZHONGLI MINGW64 /c/Program Files/Docker Toolbox
    $ docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                PORTS                                              NAMES
    d86be69a03ab        quickml-demo        "/iris-main"        3 days ago          Up 3 days (healthy)   0.0.0.0:9091->51773/tcp, 0.0.0.0:9092->52773/tcp   quickml

    3.2 Anaconda y Jupyter Notebook:

    Reutilizaremos el mismo enfoque de configuración descrito aquí para Anaconda (sección 4.1) y aquí para Jupyter Notebook (sección 4) en un ordenador portátil. Python 3.x se instala junto con este paso.

    3.3 Instalar JayDeBeApi y JPyPe:

    Inicié mi JupyterNotebook, y luego simplemente ejecuté lo siguiente en sus celdas para configurar un puente desde Python-a-JDBC/Java:
     
      !conda install --yes -c conda-forge jaydebeapi

    JayDeBeApi utiliza JPype 0.7 en el momento de escribir este artículo (enero del 2020), pero no funciona debido a un error conocido, por lo que tuve que utilizar la 0.6.3

    !conda install --yes -c conda-forge JPype1=0.6.3 --force-reinstall

    3.4 Conectar a una base de datos de IRIS por medio de JDBC 

    Hay una documentación oficial de JDBC en IRIS aquí. 

    Para las ejecuciones de Python SQL sobre JDBC, utilicé los siguientes códigos como ejemplo. Se conecta a una tabla de datos llamada "DataMining.IrisDataset" dentro del namespace "USER" de esta instancia de IRIS. 

    ### 1. Establezca las variables de entorno, si es necesario #importa os #os.environ['JAVA_HOME']='C:\Progra~1\Java\jdk1.8.0_241' #os.environ['CLASSPATH'] = 'C:\interSystems\IRIS20194\dev\java\lib\JDK18\intersystems-jdbc-3.0.0.jar' #os.environ['HADOOP_HOME']='C:\hadoop\bin'   #winutil binary must be in Hadoop's Home
    ### 2. Obtiene la conexión JDBC y el cursor import JayDeBeApi url = "jdbc:IRIS://192.168.99.101:9091/USER" driver = 'com.intersystems.jdbc.IRISDriver' user = "SUPERUSER" password = "SYS" #libx = "C:/InterSystems/IRIS20194/dev/java/lib/JDK18" jarfile = "C:/InterSystems/IRIS20194/dev/java/lib/JDK18/intersystems-jdbc-3.0.0.jar" conn = jaydebeapi.connect(driver, url, [user, password], jarfile) curs = conn.cursor()
    ### 3. Especifica la fuente de la tabla de datos dataTable = "DataMining.IrisDataset"
    ### 4. Obtiene el resultado y visualiza curs.execute("select TOP 20 * from %s" % dataTable) result = curs.fetchall() print("Total records: " + str(len(result))) for i in range(len(result)):     print(result[i])
    ### 5. Cerrar y limpiar - Los mantendre abiertos para los próximos accesos. #curs.close() #conn.close()
    Total records: 150
    (1, 1.4, 0.2, 5.1, 3.5, 'Iris-setosa')
    (2, 1.4, 0.2, 4.9, 3.0, 'Iris-setosa')
    (3, 1.3, 0.2, 4.7, 3.2, 'Iris-setosa')
    ... ...
    (49, 1.5, 0.2, 5.3, 3.7, 'Iris-setosa')
    (50, 1.4, 0.2, 5.0, 3.3, 'Iris-setosa')
    (51, 4.7, 1.4, 7.0, 3.2, 'Iris-versicolor')
    ... ... 
    (145, 5.7, 2.5, 6.7, 3.3, 'Iris-virginica')
    ... ... 
    (148, 5.2, 2.0, 6.5, 3.0, 'Iris-virginica')
    (149, 5.4, 2.3, 6.2, 3.4, 'Iris-virginica')
    (150, 5.1, 1.8, 5.9, 3.0, 'Iris-virginica')

      Ahora hemos verificado que Python en JDBC estaba funcionando. Lo siguiente es solo un poco de análisis de datos de rutina y preprocesamiento para los canales habituales de ML que deberíamos mencionar una y otra vez para demostraciones y comparaciones posteriores, por lo que se adjunta para mayor comodidad

    3.5 Convertir los resultados de SQL al DataFrame de Pandas y después a las matrices de NumPy

    Instala los paquetes Pandas y NumPy a través de Conda si aún no están instalados, como se explicó en el punto 3.3.

    A continuación, ejecute lo siguiente como un ejemplo:

    ### Transforma los resultados de SQL "sqlData" en un dataframe de Pandas "df", y después en una matriz de NumPy "arrayN" para otras canalizaciones (*pipelines*) de ML import pandas as pd sqlData = "SELECT * from DataMining.IrisDataset" df= pd.io.sql.read_sql(sqlData, conn) df = df.drop('ID', 1) df = df[['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species']]
    # Establece las etiquetas en 0, 1, 2, para la matriz NumPy df.replace('Iris-setosa', 0, inplace=True) df.replace('Iris-versicolor', 1, inplace=True) df.replace('Iris-virginica', 2, inplace=True)
    # Convierte el dataframe en una matriz Numpy arrayN = df.to_numpy()
    ### 6. Cierra y limpia - ¿si la conexión ya no es necesaria? #curs.close() #conn.close()

    Echemos un vistazo rutinario a los datos actuales:

    df.head(5)

    df.describe()

    Ahora tenemos un DataFrame, y una matriz NumPy normalizada de una tabla de datos fuente a nuestra disposición.  

    Ciertamente, ¿podemos probar varios análisis de rutina con los que comenzaría un experto en ML, como se indica a continuación, en Python para reemplazar a R, como en el enlace que se encuentra aquí?

    La fuente de datos se cita aquí

    3.6 Dividir los datos y volver a escribirlos en la base de datos de IRIS por medio de SQL:

    Ciertamente, podemos dividir los datos en un conjunto de Entrenamiento y otro de Validación o Prueba, como es habitual, y después escribirlos de nuevo en tablas temporales de la base de datos, para algunas emocionantes funciones ML de IRIS:

    import numpy as np from matplotlib import pyplot from sklearn.model_selection import train_test_split
    # mantiene, por ejemplo, el 20% = 30 filas como datos de prueba, y el 80% = 120 filas para entrenamiento X = arrayN[:,0:4] y = arrayN[:,4] X_train, X_validation, Y_train, Y_validation = train_test_split(X, y, test_size=0.20, random_state=1, shuffle=True)
    # Hace que el 80% de las filas, escogidas aleatoriamente, estén en el conjunto Entrenamiento labels1 = np.reshape(Y_train,(120,1)) train = np.concatenate([X_train, labels1],axis=-1)
    # Hace que el 20% de las filas, escogidas eleatoriamente, estén en el conjunto Prueba, lTest1 = np.reshape(Y_validation,(30,1)) test = np.concatenate([X_validation, lTest1],axis=-1)
    # Escribe el conjunto de datos de entrenamiento en un dataframe de Pandas dfTrain = pd.DataFrame({'SepalLength':train[:, 0], 'SepalWidth':train[:, 1], 'PetalLength':train[:, 2], 'PetalWidth':train[:, 3], 'Species':train[:, 4]}) dfTrain['Species'].replace(0, 'Iris-setosa', inplace=True) dfTrain['Species'].replace(1, 'Iris-versicolor', inplace=True) dfTrain['Species'].replace(2, 'Iris-virginica', inplace=True)
    # Escribe los datos de pruebas en un dataframe de Pandas dfTest = pd.DataFrame({'SepalLength':test[:, 0], 'SepalWidth':test[:, 1], 'PetalLength':test[:, 2], 'PetalWidth':test[:, 3], 'Species':test[:, 4]}) dfTest['Species'].replace(0, 'Iris-setosa', inplace=True) dfTest['Species'].replace(1, 'Iris-versicolor', inplace=True) dfTest['Species'].replace(2, 'Iris-virginica', inplace=True)
    ### 3. Especifica los nombres de las tablas temporales dtTrain = "TRAIN02" dtTest = "TEST02"
    ### 4. Crea 2 tablas temporales - puedes probar eliminar las tablas temporales y volver a crearlas una y otra vez curs.execute("Create Table %s (%s DOUBLE, %s DOUBLE, %s DOUBLE, %s DOUBLE, %s VARCHAR(100))" %(dtTrain,dfTrain.columns[0],dfTrain.columns[1],dfTrain.columns[2], dfTrain.columns[3], dfTrain.columns[4])) curs.execute("Create Table %s (%s DOUBLE, %s DOUBLE, %s DOUBLE, %s DOUBLE, %s VARCHAR(100))" %(dtTest,dfTest.columns[0],dfTest.columns[1],dfTest.columns[2],dfTest.columns[3],dfTest.columns[4]))
    ### 5. Escribe el conjunto de Entrenamiento y el conjunto de Prueba en las tablas. Se puede intentar borrar cada vez el registro anterior y luego insertarlo otra vez. curs.fast_executemany = True curs.executemany( "INSERT INTO %s (SepalLength, SepalWidth, PetalLength, PetalWidth, Species) VALUES (?, ?, ?, ? ,?)" % dtTrain, list(dfTrain.itertuples(index=False, name=None)) ) curs.executemany( "INSERT INTO %s (SepalLength, SepalWidth, PetalLength, PetalWidth, Species) VALUES (?, ?, ?, ? ,?)" % dtTest, list(dfTest.itertuples(index=False, name=None)) )
    ### 6. Cierra y limpia - ¿si la conexión ya no es necesaria? #curs.close() #conn.close()

    Ahora, si cambiamos a la Consola de Administración de IRIS, o a la Consola del Terminal SQL, deberíamos ver 2 tablas temporales creadas: TRAIN02 con 120 filas y TEST02 con 30 filas.

    Tendré que detenerme aquí, ya que supuestamente este artículo es una nota rápida muy breve.

    4. Advertencias

    • El contenido anterior puede ser modificado o perfeccionado. 

    5. Siguiente

    Simplemente reemplazaremos las secciones 3.3 y 3.4 con PyODBC, PySPark y la API nativa de Python para IRIS, a menos que a alguien no le importe contribuir con una nota rápida - también lo agradeceré.

    0
    0 1496
    Artículo Bernardo Linarez · ago 29, 2019 3m read

    ¡Hola a tod@s!

    El Portal de Administración del Sistema Caché incluye una potente herramienta de consultas en SQL basada en la web, aunque para algunas aplicaciones lo más conveniente es utilizar un cliente dedicado SQL que esté instalado en la PC del usuario.

    SQuirreL SQL es un conocido cliente SQL de código abierto construido en Java, que utiliza JDBC para conectarse a un DBMS. Como tal, podemos configurar SQuirreL para que se conecte a Caché usando el controlador JDBC en Caché.

    Encontrar el controlador JDBC de Caché en archivos JAR

    2
    0 1972