#Python

0 Seguidores · 129 Publicaciones

Python es un lenguaje de programación interpretado de alto nivel para propósitos generales de programación. Creado por Guido van Rossum y publicado por primera vez en 1991, Python tiene una filosofía de diseño que hace hincapié en la legibilidad del código, en particular mediante el uso significativo de espacios en blanco.

Sitio oficial.

InterSystems Python Binding Documentatión.

Artículo Luis Angel Pérez Ramos · mar 9, 2023 3m read
   _________ ___ ____  
  |__  /  _ \_ _|  _ \ 
    / /| |_) | || |_) |
   / /_|  __/| ||  __/ 
  /____|_|  |___|_|    

Desde la versión 2021.1, InterSystems IRIS empezó a distribuirse con un runtime de Python en el motor del kernel. Sin embargo, no había forma de instalar paquetes desde dentro de la instancia. La principal ventaja de Python es su enorme ecosistema de paquetes. Con ello en mente, os presento mi proyecto zpip, un empaquetador pip que se puede invocar desde el terminal de iris.

¿Qué es zpip?

zpip es un empaquetador para python pip que permite a los desarrolladores añadir de forma rápida paquetes a una instancia, a través del terminal de InterSystems IRIS.

Características

  • Empaquetador pip de python para InterSystems IRIS
  • Instalación/Desinstalación paquetes python
  • La instalación añade la palabra clave zpip al lenguaje

Instalación de zpip

%SYS> zpm "install zpip"

Lista de tareas

  • API invocable con retorno de estados

Uso de zpip

Todos los comandos* pip están soportados. Sin embargo, cualquier comando interactivo requerirá que uses la versión no-interactiva del comando. Por ejemplo, para desinstalar un package, tendrás que usar -y en el comando para confirmar el proceso.

Instalación de los paquetes python con zpip

// Install multiple packages
// beautiful soup and requests libraries
%SYS> zpip "install requests bs4"

... en acción:

%SYS>zpip "install emoji"

Processing /home/irisowner/.cache/pip/wheels/ae/80/43/3b56e58669d65ea9ebf38b9574074ca248143b61f45e114a6b/emoji-2.1.0-py3-none-any.whl
Installing collected packages: emoji
Successfully installed emoji-2.1.0

%SYS>

Especificación de un directorio de instalación diferente:

// Install to some other python package target
$SYS> zpip "install --target '/durable/iconfig/lib/python' emoji"

Desinstalación de un paquete python

// Requires -y!
%SYS>zpip "uninstall -y emoji"
Found existing installation: emoji 2.1.0
Uninstalling emoji-2.1.0:
  Successfully uninstalled emoji-2.1.0

Otros comandos de pip útiles

lista de paquetes

// List Packages
%SYS> zpip "list"
Package                      Version    
---------------------------- -----------
absl-py                      1.1.0      
argon2-cffi                  21.3.0     
argon2-cffi-bindings         21.2.0     
asttokens                    2.0.5      
astunparse                   1.6.3      
attrs                        21.4.0     
backcall                     0.2.0      
beautifulsoup4               4.11.1     
bleach                       5.0.0      
bs4                          0.0.1   
...

Limitaciones

  • Los comandos interactivos no están soportados.
  • Uso de -y para desinstalar.
  • La búsqueda puede no funcionar dependiendo de la configuración del sistema.
  • Usa la infraestructura pip subyacente del sistema operativo, por lo que la instalación depende de la versión pip del sistema operativo.
1
0 143
Artículo Dmitry Maslennikov · feb 17, 2023 4m read

Os presento mi nuevo proyecto: irissqlcli, REPL (Read-Eval-Print Loop) para InterSystems IRIS SQL.

  • Resaltado de sintaxis
  • Sugerencias (tablas, funciones)
  • +20 formatos de salida
  • Soporte a stdin
  • Salida a ficheros 

Instalación con pip

pipinstallirissqlcli

O se puede ejecutar con docker

dockerrun-itcaretdev/irissqlcliirissqlcliiris://_SYSTEM:SYS@host.docker.internal:1972/USER
1
0 131
Artículo Luis Angel Pérez Ramos · mayo 19, 2023 1m read

¡Hola Comunidad!

Me gustaría presentaros una nueva utilidad para importar CSV a IRIS - ¡csvgenpy!

Instalación

USER>zpm "install csvgenpy"

Uso:

do ##class(shvarov.csvgenpy.csv).Generate("file or url","table","schema")

Ejemplo:

USER>do ##class(shvarov.csvgenpy.csv).Generate("https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv","titanic","data")

Esto creará la tabla y la clase data.titanic en IRIS y a continuación cargará los datos. Podéis probarlo con:

0
0 76
Artículo Ricardo Paiva · abr 20, 2023 2m read

Apache Superset es una moderna plataforma para la visualización y exploración de datos. Superset puede reemplazar o aumentar las herramientas patentadas de business intelligence para muchos equipos. Y se puede integrar con una gran variedad de fuentes de datos.

¡Y ahora es posible utilizarla con InterSystems IRIS!

Hay disponible una demo online que usa IRIS Cloud SQL como fuente de datos.

0
0 621
Artículo Heloisa Paiva · abr 18, 2023 2m read

Introducción

En algunos de mis artículos he hablado de tipos entre IRIS y Python, y está claro que no es tan fácil acceder a objetos de un lado a otro. 

Afortunadamente, el trabajo ya se ha hecho, con la creación de SQLAlchemy-iris, que hace mucho más fácil para Python acceder a los objetos de IRIS, y voy a mostraros cómo funciona.

¡Gracias, @Dmitry Maslennikov!
 

Instalación

Para instalarlo, simplemente abre tu terminal con acceso de administrador y escribe

pip install sqlalchemy-iris

y eso también instalará los pre-requisitos para ti, si fuera necesario.
 

Uso

0
0 1418
Artículo Ricardo Paiva · mar 30, 2023 1m read

Quick Tips: Total Productive Maintenance

Los parámetros nombrados se pueden conseguir con SQLAlchemy :  

from sqlalchemy import create_engine, text,types,engine

_engine = create_engine('iris+emb:///')

with _engine.connect() as conn:
    rs = conn.execute(text("select :some_private_name"), {"some_private_name": 1})
    print(rs.all())

o con api nativa

from sqlalchemy import create_engine, text,types,engine

# set URL for SQLAlchemy
url = engine.url.URL.create('iris', username='SuperUser', password='SYS', host='localhost', port=33782, database='FHIRSERVER')

_engine = create_engine(url)

with _engine.connect() as conn:
    rs = conn.execute(text("select :some_private_name"), {"some_private_name": 1})
    print(rs.all())

requirements.txt

sqlalchemy==1.4.22
sqlalchemy-iris==0.5.0
irissqlcli

Está funcionando hoy, con IRIS 2021.2+

0
0 124
Artículo Jose-Tomas Salvador · oct 6, 2022 6m read

Python se ha convertido en el lenguaje de programación más utilizado del mundo (fuente: https://www.tiobe.com/tiobe-index/) y SQL sigue siendo el líder como lenguaje para las bases de datos. ¿No sería genial que Python y SQL trabajaran juntos para ofrecer nuevas funcionalidades que SQL por sí mismo no puede? Después de todo, Python tiene más de 380.000 librerías publicadas (fuente: https://pypi.org/) con funciones muy interesantes para ampliar las consultas SQL dentro de Python.

En este artículo detallo cómo crear nuevos Procedimientos Almacenados de SQL en la base de datos de InterSystems IRIS usando Embedded Python.

Librerías de Python utilizadas como muestras

En este artículo utilizaré dos librerías muy útiles para cualquiera que trabaje con SQL en IRIS: Geopy y Chronyk.

Geopy es una librería utilizada para aplicar la geocodificación (asignación de coordenadas geográficas a direcciones) a los datos de direcciones. Con ella es posible, a partir del nombre de la calle, obtener el código postal y la dirección completa, en el formato de la oficina de correos. Es muy útil, ya que muchos registros tienen una dirección.

Chronyk se utiliza para procesar fechas y horas mediante el lenguaje humano. Esto es muy útil, porque internamente, tanto para IRIS como para Python, una fecha es un número que representa la cantidad de tiempo que ha transcurrido desde una fecha inicial. Para los humanos, una fecha es el 20 de julio, o ayer, o mañana, o hace dos horas. Chronyk acepta recibir la fecha así y luego la convierte al formato de fecha universal.

Soporte de Python en InterSystems IRIS

Desde la versión 2021.2 es posible utilizar Python para crear métodos de clase, procedimientos almacenados, producciones de interoperabilidad y llamadas nativas entre Python e IRIS (ObjectScript) de forma bidireccional. No conozco ninguna otra plataforma de datos que trabaje tan estrechamente con Python. El requisito para que esto funcione es que Python se instale en la misma máquina física o virtual o contenedor que IRIS. Consulta más detalles en: https://docs.intersystems.com/iris20221/csp/docbook/DocBook.UI.Page.cls?KEY=AFL_epython.

Para instalar Python ejecuta:

# install libraries required for python and pip
RUNapt-get-yupdate\
    &&apt-get-yinstallapt-utils\
    &&apt-getinstall-ybuild-essentialunzippkg-configwget\
    &&apt-getinstall-ypython3-pip  

Soporte de librerías de Python en InterSystems IRIS

Para que InterSystems IRIS pueda utilizar una librería de Python es obligatorio que esté instalada dentro de <installdir>/mgr/python. installdir es la carpeta en la que está instalado IRIS. Para instalar nuevos paquetes ejecuta:

# use pip3 (the python zpm) to install geopy and chronyk packages
RUNpip3install--upgradepipsetuptoolswheel
RUNpip3install--target/usr/irissys/mgr/pythongeopychronyk

Pip3 es el administrador e instalador de paquetes más popular de Python, Pip.

Cómo crear Procedimientos Almacenados en lenguaje de Python

Una de las posibilidades de utilizar Python en InterSystems IRIS es crear Procedimientos Almacenados usando Python.

Hay dos posibilidades:

  1. Crear un Procedimiento Almacenado en Python utilizando la sentencia SQL de crear función o procedimiento
  2. Crear un Método de clase dentro de la clase ObjectScript con las etiquetas sqlProc y language=Python.

Cómo crear un Procedimiento Almacenado en Python utilizando la sentencia SQL de Crear Procedimiento

Según la documentación de InterSystems, también se puede escribir una función SQL o un Procedimiento Almacenado utilizando Python Embebido si se especifica el argumento LANGUAGE PYTHON en la sentencia CREATE, como se muestra a continuación (fuente: https://docs.intersystems.com/iris20221/csp/docbook/DocBook.UI.Page.cls?KEY=AEPYTHON#AEPYTHON_runpython_sql):

CREATE FUNCTION tzconvert(dt TIMESTAMP, tzfrom VARCHAR, tzto VARCHAR)
    RETURNS TIMESTAMP
    LANGUAGE PYTHON
{
    from datetime import datetime
    from dateutil import parser, tz
    d = parser.parse(dt)
    if (tzfrom is not None):
        tzf = tz.gettz(tzfrom)
        d = d.replace(tzinfo = tzf)
    return d.astimezone(tz.gettz(tzto)).strftime("%Y-%m-%d %H:%M:%S")
}

Cuando se ejecuta esta nueva función SQL:

SELECT tzconvert(now(), 'US/Eastern', 'UTC')

La función devuelve algo como:

2022-07-20 15:10:05

Cómo crear el Método de clase dentro de la clase ObjectScript con las etiquetas sqlProc y language=Python

Confieso que este enfoque es mi favorito: crear un método de clase con las etiquetas sqlProc y language=Python.

En mi opinión es más fácil de mantener, está mejor documentado y con una mejor administración de las versiones del código fuente. Para este enfoque he publicado una aplicación de muestra: https://openexchange.intersystems.com/package/Python-IRIS-SQL-Procedures-Sample. La utilizaré para mostrar este segundo enfoque con detalle.

Instalación de la aplicación de muestra

Para instalar la aplicación de muestra, sigue estos pasos:

  1. Clonar/git pull el repositorio en cualquier directorio local: $ git clone https://github.com/yurimarx/iris-sql-python-sample.git
  2. Abrir un terminal de Docker en este directorio y ejecutar: $ docker-compose build
  3. Ejecutar el contenedor de IRIS: $ docker-compose up -d

Otra posibilidad para instalar es utilizar el ZPM:

zpm "install iris-sql-python-sample"

Ejemplos de Procedimientos Almacenamiento usando Python

El primer ejemplo es un Procedimiento Almacenado para administrar la geocodificación de direcciones, consulta el código fuente:

ClassMethodGetFullAddress(StreetAs%String,CityAs%String,StateAs%String)
As%String[Language=python,SqlName=GetFullAddress,SqlProc]
{
    importgeopy.geocoders
    fromgeopy.geocodersimportNominatim
    geopy.geocoders.options.default_timeout =7
    geolocator =Nominatim(user_agent="intersystems_iris")
    location =geolocator.geocode(Street +", " +City +", " +State,country_codes="US")
    returnlocation.address
}

Fíjate que se declaró un Método de clase (dentro de la clase dc.pythonsql.Company) con las etiquetas [ Language = python, SqlProc]. La etiqueta SqlName permite establecer un nombre para el nuevo Procedimiento Almacenado en sentencias SQL. Ve al Portal de administración, Sistema > SQL y ejecuta el siguiente código:

SELECT ID, City, Name, State, Street, Zip, dc_pythonsql.GetFullAddress(Street, City, State) As FullAddress 
FROM dc_pythonsql.Company

Verás estos resultados: Geopy

Ahora las direcciones incompletas regresan como direcciones "completas" (completas y calificadas).

Nota: Si no devuelve nada, ejecuta #class(dc.pythonsql.Company).CreateFiveCompanies(). Creará cinco empresas para utilizar en las pruebas.

Este paquete puede funcionar con los principales servicios de geocodificación abiertos y comerciales. En este ejemplo utilizamos el servicio abierto Nominatim, pero es posible utilizar Bing, Google, ArcGIS y otros. Consulta las posibilidades en https://geopy.readthedocs.io/en/stable/#module-geopy.geocoders.

El segundo ejemplo es un paquete de fecha y hora en formato humanizado, Chronyk. Permite enviar frases como "mañana", "ayer", "dentro de 4 horas", "4 de julio del 2022" y obtener el resultado en formato de fecha universal. Mira la creación del Procedimiento Almacenado:

ClassMethodGetHumanDate(SentenceAs%String)As%String[Language=python,SqlName=GetHumanDate,SqlProc]
{
    fromchronykimportChronyk
    t =Chronyk(Sentence)
    returnt.ctime()
}

Realiza la siguiente llamada en el Portal de administración > Sistema > SQL:

SELECT ID, City, Name, State, Street, Zip, dc_pythonsql.GetHumanDate('yesterday') As Datetime FROM dc_pythonsql.Company

Verás resultados como este: https://raw.githubusercontent.com/yurimarx/iris-sql-python-sample/main/screen2.png

Si quieres simplemente llamar al Procedimiento Almacenado, puedes usar esta sentencia SQL:

select dc_pythonsql.GetHumanDate('yesterday') as Datetime  

Esta librería tiene varias posibilidades de fechas y horas humanizadas, consulta https://github.com/KoffeinFlummi/Chronyk. Así que es fácil crear Procedimientos Almacenados en Python. ¡Disfrútalo!

1
1 764
Artículo Ricardo Paiva · mar 15, 2023 3m read

El SDK nativo para Python de InterSystems es una interfaz ligera para las APIs de InterSystems IRIS, que anteriormente solo estaba disponible mediante ObjectScript.

Estoy especialmente interesado en la capacidad de llamar a los métodos de ObjectScript, a los métodos de clase, para ser más preciso. Esto funciona, y funciona muy bien, pero de manera predeterminada, las llamadas únicamente admiten argumentos escalares: strings, booleanos, enteros y flotantes.

Pero si lo que quieres es:

  • Pasar o devolver estructuras, como diccionarios (dicts) o listas
  • Pasar o devolver streams

Necesitarás escribir algún código adhesivo (glue code) o aprovechar este proyecto (se instala mediante pip install edpy). El paquete edpy te da una estructura sencilla:

call(iris, class_name, method_name, args)

que te permite llamar a cualquier método de ObjectScript y obtener los resultados.

Se importa así:

from edpy import iris

call acepta 4 argumentos necesarios:

  • iris - hace referencia a un objeto de IRIS establecido
  • class_name - la clase de IRIS que debe llamarse
  • method_name - el método de IRIS que debe llamarse
  • args - lista con 0 o más argumentos

Argumentos

Cada argumento puede ser alguno de los siguientes:

  • string (de cualquier longitud, si es mayor que $$$MaxStringLength o 3641144 símbolos, se convertirá automáticamente en un stream)
  • booleano
  • entero
  • flotante
  • dict (se convierte en un objeto dinámico)
  • lista o tupla (se convierte en una matriz dinámica)

Los argumentos de dict, lista y tupla pueden contener otros dicts, listas y tuplas de forma recurrente (mientras dure la memoria).

Valor devuelto

A cambio, esperamos o un objeto/matriz dinámico o una string/stream JSON. En ese caso, edpy primero lo convertiría en un string Python y, si fuera posible, lo interpretaría como un dict o lista Python. De lo contrario, el resultado sería devuelto tal cual.

Eso es todo lo que debemos saber por el momento, pero permíteme dar algunos ejemplos de métodos ObjectScript y cómo llamarlos usando esta función de Python.

Ejemplo 1: Pong

ClassMethod Test(arg1, arg2, arg3) As %DynamicArray
{
    return [(arg1), (arg2), (arg3)]
}

Se llama con:

>>> iris.call(iris_native, "User.Py", "Test", [1, 1.2, "ABC"])
[1, 1.2, 'ABC']

El resultado no es ninguna sorpresa. Los argumentos se vuelven a empaquetar en una matriz y se devuelven.

Ejemplo 2: Propiedades

ClassMethod Test2(arg As %DynamicObject) As %String
{
    return arg.Prop
}

Se llama así:

>>> iris.call(iris_native, "User.Py", "Test2", [{"Prop":123}])
123

Para una invocación más embebida:

>>> iris.call(iris_native, "User.Py", "Test2", [{"Prop":{"Prop2":123}}])
{'Prop2': 123}

No hay ningún problema si una propiedad es demasiado larga: se utilizarán streams para enviarla y/o devolverla a IRIS:

ret = iris.call(iris_native, "User.Py", "Test2", [{"Prop":"A" * 10000000}])
>>> len(ret)
10000000

Si necesitas streams garantizados en el lado de InterSystems IRIS, puedes usar %Get:

set stream = arg.%Get("Prop",,"stream")

Si el stream está codificado en base64, puedes descodificarlo automáticamente mediante:

set stream = arg.%Get("Prop",,"stream<base64")

Ejemplo 3: String o stream

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()
}

Aquí escribimos o un string o un stream para <mgr>test.txt.

>>> iris.call(iris_native, "User.Py", "Test3", ["&#x1f60a;"])
{'status': 1}

Nota: en todos los ejemplos de código "&# x1f642;" se introduce como 😊.

Y si abro el archivo veré un 😊 y no dos ??, de esta forma conservamos el cifrado.

>>> iris.call(iris_native, "User.Py", "Test3", ["&#x1f642;" * 10000000])
{'status': 1}

Por ser breve, omitiré el archivo resultante, pero allí está.

Por último, al pasar dentro un objeto dinámico o una matriz, se puede evitar por completo la dicotomía string/stream, incluso si no sabes si la propiedad sería más corta o más larga que el límite del string. En ese caso, siempre puedes obtener la propiedad de la que dudas como un stream.

Ejemplo 4: Streams de retorno

ClassMethod Test4(arg As %DynamicArray) As %String
{
    return arg.%Get(0)
}

Así es como se ve:

>>> ret = iris.call(iris_native, "User.Py", "Test4", [["&#x1f60a;" * 10000000]])
>>> len(ret)
10000000
>>> ret[:5]
'&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;'

Una cosa más

También hay una función get_iris(ip="localhost", port=1972, namespace="USER", username="_SYSTEM", password="SYS") que te permitirá obtener un objeto funcional de IRIS. Este es un ejemplo completo, por si quieres comprobarlo por ti mismo:

Primero carga la clase User.Py e instala la librería de Phyton edpy:

pip install edpy

Y después en la llamada en 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]])

Conclusión

El SDK nativo para Python es una potente herramienta, que proporciona un acceso completo y sin restricciones a InterSystems IRIS. Espero que este proyecto pueda ahorrarte algo de tiempo cuando preparas las llamadas a InterSystems IRIS. ¿Hay alguna combinación de argumentos que no esté soportada? Si es así, comparte en los comentarios cómo realizas las llamadas.

Enlaces

0
0 112
Artículo Alberto Fuentes · mar 15, 2023 3m read

InterSystems IRIS 2022.2 tiene un SDK nativo para Python (https://docs.intersystems.com/iris20222/csp/docbook/Doc.View.cls?KEY=PA…).

Sabemos cómo recorrer la estructura de datos de un global usando la función $Order de ObjectScript.

SET key=""FOR  {
     SET key=$ORDER(^myglobal(key)) 
     QUIT:key=""WRITE !,^myglobal(key)
   }

¿Cómo hacer lo mismo desde Python usando el SDK nativo de IRIS para Python?

Aquí va un ejemplo directamente en Python:

0
0 152
Artículo Heloisa Paiva · mar 9, 2023 2m read

Por qué he decidido escribir esto

En mi ultimo artículo he hablado de la devolución de valores con Python. Pero la devolución es muy simple, lo que la puede hacer difícil es de lo que voy a hablar hoy: dónde es tratado el valor.
 

Objeto Python en IRIS

Siguiendo el ejemplo del último artículo, tenemos el método:

Class python.returnTest [ Abstract ]
{

ClassMethod returnSomething(pValue... As%String) As%Integer [ Language = python ]
{
	return pValue
}

}
0
0 166
Artículo Heloisa Paiva · feb 22, 2023 2m read

Por qué he decidido escribir esto

En 2022, publiqué un artículo sobre Python Embebido para principiantes. En ese artículo me preguntaron cómo devolver valores con Python. Respondí a la pregunta y, además, me ha parecido interesante escribir un pequeño artículo sobre el tema. Así también espero llegar a más gente con esta publicación.

Situaciones posibles

Hay dos cosas de las que ocuparse cuándo se devuelve un valor con Python. La primera es el tipo que intentas devolver y la segunda es dónde lo devuelves.

0
0 505
Artículo Rubén Larenas · feb 8, 2023 3m read

Python Embedded es una gran herramienta considerando la simpleza y gran cantidad de librerías disponibles, así como una gran comunidad de desarrolladores con toneladas de ejemplos y documentación.

En el siguiente ejemplo les presento una solución para un problema común utilizando Python y ObjectScript.

Un caso de uso muy común es recuperar data desde planillas excel y poblar un objeto persistente en nuestro modelo en IRIS.

para esto utilizaremos pandas, una popular librería Python que nos permite trabajar con DataFrames

0
0 276
Artículo Alberto Fuentes · ene 30, 2023 3m read

OCR DEMO

Esta es una demo de la funcionalidad OCR utilizando la librería pero-ocr de Python.

Utilizaremos la librería en una instancia InterSystems IRIS.

Demo

Este es un ejemplo de los datos de entrada:

input

Y este es el resultado del OCR, donde tenemos la siguiente información:

  • El texto, que está en la etiqueta TextEquiv
  • La confianza de la lectura, presente en el atributo conf de la etiqueta TextEquiv
  • Las coordenadas del texto, que están en la etiqueta Coords
<PcGts xmlns="http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.primaresearch.org/PAGE/gts/pagecontent/2019-07-15/pagecontent.xsd">
  <Metadata>
    <Creator>Pero OCR</Creator>
    <Created>2022-12-13T08:47:12.207893+00:00</Created>
    <LastChange>2022-12-13T08:47:12.207893+00:00</LastChange>
  </Metadata>
  <Page imageFilename="/irisdev/app/misc/in/United_States_Declaration_of_Independence.jpg" imageWidth="3923" imageHeight="4656">
    <TextRegion id="r004">
      <Coords points="977,121 932,121 932,283 1189,277 1178,114 977,121"/>
      <TextLine id="r004-l002" index="0" custom="heights_v2:[123.7,39.0]">
        <Coords points="932,121 932,283 1189,277 1178,114 1130,118 1100,117 1048,121 1019,121 977,121 932,121"/>
        <Baseline points="932,244 977,244 1019,244 1058,244 1100,241 1138,241 1186,238"/>
        <TextEquiv conf="1.000">
          <Unicode>IN</Unicode>
        </TextEquiv>
      </TextLine>
    </TextRegion>
    <TextRegion id="r008">
      <Coords points="1461,107 1241,107 1241,287 2116,290 2549,281 2986,287 3211,277 3203,98 2978,107 2552,101 2114,111 1461,107"/>
      <TextLine id="r008-l001" index="0" custom="heights_v2:[133.8,45.8]">
        <Coords points="1241,107 1241,287 1464,287 1681,284 1896,287 2116,290 2549,281 2986,287 3211,277 3203,98 2978,107 2552,101 2327,107 2114,111 1461,107 1241,107"/>
        <Baseline points="1241,241 1463,241 1682,238 1897,241 2116,244 2331,241 2550,235 2765,238 2984,241 3209,231"/>
        <TextEquiv conf="0.910">
          <Unicode>CONGRESS, JULY 4, 1776.</Unicode>
        </TextEquiv>
      </TextLine>
    </TextRegion>
    <TextRegion id="r001">
      <Coords points="591,452 208,455 209,611 1723,602 2100,608 2855,595 3617,598 3618,442 2855,439 2098,452 1725,446 591,452"/>
      <TextLine id="r001-l003" index="0" custom="heights_v2:[113.8,42.1]">
        <Coords points="208,455 209,611 592,608 968,605 1218,605 1723,602 2100,608 2855,595 3231,595 3617,598 3618,442 2855,439 2477,446 2098,452 1725,446 1346,449 1159,449 591,452 208,455"/>
        <Baseline points="209,569 592,566 968,563 1347,563 1723,559 2100,566 2479,559 2855,553 3231,553 3617,556"/>
        <TextEquiv conf="0.289">
          <Unicode>Dhe unaniwons Declaratton of te Heten maiss States of TNmerica</Unicode>
        </TextEquiv>
      </TextLine>
    </TextRegion>
    <TextRegion id="r000">
      <Coords points="161,3474 161,3539 423,3539 633,3536 958,3468 1354,3472 1764,3581 1944,3571 2246,3730 2653,3718 2718,3633 2855,3608 3238,3557 3514,3554 3739,3462 3762,3397 3761,3333 3735,3139 3743,2696 3730,2177 3735,1920 3723,1727 3736,1341 3717,1014 3724,943 3719,818 3697,693 1012,712 795,776 421,776 183,786 173,848 168,1032 173,2392 160,2713 161,3474"/>
      <TextLine id="r000-l004" index="0" custom="heights_v2:[40.2,18.4]">
        <Coords points="2796,699 2501,703 2205,706 1909,709 1611,709 1460,709 1012,712 1013,771 1315,768 1611,768 1910,768 2206,764 2502,761 2800,758 3096,758 3392,755 3698,752 3697,693 3392,696 3096,699 2802,699 2796,699"/>
        <Baseline points="1013,752 1315,749 1611,749 1910,749 2206,746 2501,743 2800,739 3096,739 3392,736 3697,733"/>
        <TextEquiv conf="0.281">
          <Unicode>hen n lí loune z human venl, i kemu nematy k mpeopě toíohohhehttcal bandí uhích have connechdí tem vith ancthet, andíl</Unicode>
        </TextEquiv>
      </TextLine>
      <TextLine id="r000-l005" index="1" custom="heights_v2:[40.4,19.2]">
        <Coords points="421,776 421,836 794,836 1157,839 1521,839 1884,836 2244,833 2608,829 2971,826 3335,823 3704,813 3703,754 3333,763 2970,767 2607,770 2244,773 1884,776 1520,779 1157,779 795,776 421,776"/>
        <Baseline points="421,817 794,817 1157,820 1521,820 1884,817 2244,813 2608,810 2971,807 3334,804 3704,794"/>
        <TextEquiv conf="0.211">
          <Unicode>o hi ſhwes f he eail, fie rehatal andequal flohon &amp; ufch lhe laav  . kalut and   Aloil ped entilt ttem, a dant rafech to the ofunin o manknd tequies fhat thep</Unicode>
        </TextEquiv>
      </TextLine>
     <!-- Truncated for readme-->
      <TextLine id="r019-l105" index="9" custom="heights_v2:[47.5,21.7]">
        <Coords points="3209,4269 3214,4336 3257,4333 3296,4333 3332,4333 3373,4337 3411,4337 3452,4336 3488,4333 3527,4333 3575,4333 3575,4264 3527,4264 3488,4264 3446,4267 3411,4267 3373,4267 3338,4264 3296,4264 3257,4264 3209,4267 3209,4269"/>
        <Baseline points="3212,4315 3257,4312 3296,4312 3334,4312 3373,4315 3411,4315 3450,4315 3488,4312 3527,4312 3575,4312"/>
        <TextEquiv conf="0.283">
          <Unicode>imuiaa</Unicode>
        </TextEquiv>
      </TextLine>
      <TextLine id="r019-l108" index="10" custom="heights_v2:[40.9,20.2]">
        <Coords points="3198,4406 3251,4409 3294,4409 3339,4412 3394,4415 3398,4354 3343,4351 3298,4348 3251,4348 3202,4345 3198,4406"/>
        <Baseline points="3199,4386 3251,4389 3296,4389 3341,4392 3395,4395"/>
        <TextEquiv conf="0.370">
          <Unicode>Qlver</Unicode>
        </TextEquiv>
      </TextLine>
      <TextLine id="r019-l114" index="11" custom="heights_v2:[39.2,19.1]">
        <Coords points="3181,4469 3225,4466 3263,4466 3305,4466 3327,4466 3352,4465 3386,4462 3424,4462 3472,4462 3472,4404 3424,4404 3386,4404 3341,4407 3305,4407 3263,4407 3225,4407 3177,4411 3181,4469"/>
        <Baseline points="3180,4450 3225,4447 3263,4447 3305,4447 3344,4447 3386,4443 3424,4443 3472,4443"/>
        <TextEquiv conf="0.312">
          <Unicode>Vbalřew/</Unicode>
        </TextEquiv>
      </TextLine>
    </TextRegion>
    <TextRegion id="r020">
      <Coords points="3685,4399 3607,4399 3607,4465 3685,4465 3685,4399"/>
      <TextLine id="r020-l112" index="0" custom="heights_v2:[44.3,21.4]">
        <Coords points="3607,4399 3607,4465 3685,4465 3685,4399 3607,4399"/>
        <Baseline points="3607,4443 3685,4443"/>
        <TextEquiv conf="0.486">
          <Unicode>17.</Unicode>
        </TextEquiv>
      </TextLine>
    </TextRegion>
  </Page>
</PcGts>

Instalación

git clone <this repo>

⚠️ ¡Importante! Esta demo requiere instalar dos modelos (ambos son requeridos)

Para instalar un modelo, descárgalo desde la página de descargas y descomprímelo en el directorio misc/pero-ocr-fix-computation-on-cpu del proyecto:

Después, ejecuta:

docker-compose up

Uso

Coloca cualquier imagen de muestra de la carpeta samples y cópiala en la carpeta misc/in para que sea procesada por el OCR.

Los resultados estarán en la carpeta misc/out.

Verás los archivos xml con los resultados y las imágenes con el texto detectado.

Puedes monitorizar el progreso aquí y accediendo con _SYSTEM y SYS.

Cómo funciona en IRIS

El OCR es un Business Service que analiza todos los ficheros en la carpeta misc/in y pone los resultados en una cola de mensajes.

La cola de mensajes es consumida por una Business Operation que pone los resultados en la carpeta misc/out.

El código está en la carpeta src/python/pero-ocr.

0
1 140
Artículo Kurro Lopez · ene 19, 2023 2m read

Continúo la descripción del trabajo usando el módulo openhl de Python en producción.

Como la versión de IRIS con Python Embebido, aún no ha sido liberada, ya es necesario usarlo en producción ahora. Decidimos hacer una copia de seguridad del servicio para exportar consultas a un archivo xlsx en un servidor aparte, y guardar el resultado de la consulta en un global en una base de datos separada.

Esta base de datos se puso en red, local para el servidor del servicio y remota para el servidor del producto. La comunicación entre el servidor de producto y el servicio fue implementada usando un servicio rest.

Así que: en el servidor en la aplicación del cliente, el usuario pide un informe largo. El informe se genera en segundo plano y se guarda en el global. En la base de datos remota, el servicio rest es llamado con una referencia completa al global como parámetro. El servicio se inicia en segundo plano y exporta un archivo a un fichero Excel y, después, invoca a una llamada al servicio rest con un enlace al archivo generado. Habiendo recibido el mensaje, el servicio en el servidor de producción archiva el fichero Excel y lo envía por email al cliente. Y aquí no debemos olvidar que la base de datos remota y local debe estar protegida por un solo recurso, los privilegios para los cuales se deben asignar al usuario para el que se genera el archivo.

De esta manera, hemos reemplazado %SYS.ZENReportExcelExporter en el servidor de producto. En el futuro, como un desarrollo de esta solución, pensamos reemplazar el envío de archivos por email al panel de enlace de archivos generados por la descarga del usuario independientemente, tras notificación de lectura.

0
0 91
Artículo Nancy Martínez · ene 18, 2023 1m read

En la Comunidad de Desarrolladores hay muchos artículos interesantes que muestran cómo utilizar Jupyter e InterSystems IRIS juntos, y os animo a echarles un vistazo - al final de esta publicación tenéis un enlace a los artículos.

Este es otro de esos artículos. La diferencia con los otros está en la sencillez. ¿Solo quieres iniciar un contenedor en el que Jupyter ya está conectado a una instancia de IRIS? ¡Entonces esto es para ti!

Solo con ejecutar docker-compose up ya podrás acceder a un entorno de trabajo con un par de ejemplos.

No quiero estropear la sencillez, así que probadlo.

login

Más artículos sobre IRIS y Jupyter:

0
0 119
Artículo Ricardo Paiva · ene 18, 2023 4m read

Schematron es un lenguaje de validación basado en reglas para hacer aserciones/afirmaciones sobre la presencia o ausencia de ciertos patrones en documentos XML. Un Schematron se refiere a una colección de una o más reglas que contienen pruebas. Los Schematron están escritos en una forma de XML, lo que los hace relativamente fáciles de inspeccionar, comprender y escribir para todos, incluso los que no son programadores.

0
0 401
Artículo Luis Angel Pérez Ramos · ene 16, 2023 4m read

Motivación

Empecé en este proyecto pensando en cómo permitir que el código Python trabaje de forma natural con el almacenamiento escalable y el eficiente mecanismo de recuperación de datos ofrecido por los globals de IRIS, a través de Python Embebido.

Mi idea inicial era crear algo como un diccionario de implementación de Python usando globals, pero pronto me di cuenta de que antes debía ocuparme de la abstracción de objetos.

Así que empecé creando algunas clases en Python que pudieran envolver objetos Python, almacenando y recuperando sus datos en globals, es decir, serializar y deserializar objetos Python en globals IRIS.

¿Cómo funciona?

Como ObjectScript%DispatchGetProperty(), %DispatchSetProperty() y %DispatchMethod(), Python tiene métodos para delegar las propiedades de los objetos y las llamadas a los métodos.

Cuando haces set o get sobre una propiedad del objeto, el intérprete de Python te permite interceptar esta operación a través de métodos __setattr__(self, name, value) y __getattr(self, name)__.

Podemos comprobarlo con este sencillo ejemplo:

>>> 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
>>> 

Ten en cuenta que los métodos __setattr__() y __getattr()__ fueron llamados indirectamente por las operaciones set y get sobre objetos de la clase Test - que implementa esos métodos. Incluso una propiedad no-declarada, como prop2 en este ejemplo, lanza llamadas hacia ellos.

Ese mecanismo es el nucleo de la prueba de serialización que realicé en mi proyecto python-globals-serializer-example. Con él, se pueden interceptar operaciones set/get y almacenar/recuperar datos desde los globals de IRIS.

Modelo de objetos

Los globals ofrecen una estructura altamente personalizable. Al usar su modelo jerárquico para acceder a la información, que es bastante similar a los objetos JSON y diccionarios Python, podemos almacenar los datos y metadatos de las propiedades de los objetos.

Así es como usé los globals para crear un modelo de objetos sencillo para serializar objetos Python:

Para cada objeto serializado, su nombre de clase es serializado en un nodo etiquetado como “clase”:

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

El primer índice es un número incremental que se usa como referencia de este objeto en el modelo. Así que, en el ejemplo anterior, un objeto de clase employee.SalaryEmployee es almacenado con el valor de referencia 1.

Para propiedades de tipos de datos primitivos, se almacenan su tipo y valor. Por ejemplo:

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

Esa estructura es interpretada como el objeto referido por el índice 1, tiene una propiedad llamada name, con valor igual a ‘me’.

Para referenciar propiedades de tipo objeto el modelo es ligeramente diferente, porque a diferencia de los objetos JSON o los diccionarios Python, los globals están pensados para almacenar solo tipos de datos primitivos. Así que se crea otro nodo “class” para este objeto referenciado y su nodo índice (es decir, su referencia) es almacenado en el nodo propiedad:

^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"

Esas estructuras significan que el objeto 1 tiene una propiedad llamada company, cuyos valores se almacenan en el índice 2 - ten en cuenta el valor para ^test(1,"company","oref").

Proceso de Serialización/Deserialización

Cuando creas un envoltorio para serializar o deserializar objetos Python, necesitas definir el nombre del global que almacena el objeto.

Tras ello, el proceso de serialización se completa cuando se ejecuta una operación set. El método __setattr__() establece el valor y tipo de propiedad en el global definido para almacenar el objeto, usando el modelo de objeto simple explicado anteriormente.

En la dirección contraria, una deserialización es realizada por el método __getattr__, cuando se lleva a cabo una operación get

Para tipos de datos primitivos, este proceso es sencillo: solo coge el valor almacenado en el global y lo devuelve.

Pero para objetos, el proceso necesita instanciar sus tipos de datos de clase y definir todas sus propiedades también, y de esta manera se podría usar un objeto Python recuperado, incluyendo llamadas a sus métodos.

Trabajo futuro

Como comenté al principio de este artículo, este proyecto nació como una simplificación de una manera de permitir que el código Python use el global como un motor de almacenamiento natural, y solo pretende ser una prueba de concepto.

Serializar/deserializar objetos es solo el primer paso para alcanzar este objetivo. Hace falta mucho trabajo para que esta idea madure.

Espero que el artículo os permita entender el propósito de mi trabajo en este proyecto, y puede que os inspire a pensar en nuevas formas de usar los globals de IRIS para que Python esté aún más cerca de IRIS.

0
0 146
Artículo Guillaume Rongier · ene 3, 2023 2m read

ipython-iris-magic

%%iris magic para IPython, puede ejecutar comandos ObjectScript en NoteBooks.

Puede ejecutarse en cualquier Notebook (por ej. Jupyter) y no requiere ninguna configuración especial ni en IRIS ni en el propio Notebook.

Demo

Native Api

image

Python Embebido

image

Como podéis ver, la primera línea carga la "magia", la segunda línea se conecta al servidor y la tercera línea ejecuta el comando ObjectScript.

Esta demo está disponible en example/Notebooks/Demo-Iris-Magic.ipynb.

Para ver la demo en acción, ejecuta los siguientes comandos en el directorio raíz del proyecto:

docker-compose up

A continuación, accede a esta URL: http://127.0.0.1:8888/notebooks/Demo-Iris-Magic.ipynb

Carga la "magia"

%load_ext iris_magic

Conéctate al servidor de IRIS

%%iris iris://superuser:SYS@localhost:1972/USER

Ejecuta comandos Objectscript

%%iris
Set x = 1
Write x

Puedes utilizar la "magia" también para ejecutar queries SQL.

Carga la "magia"

%load_ext sql

/!\ Necesitarás instalar la extensión SQL en primer lugar.

La extensión SQL no forma parte de la instalación estándar de IPython. Puedes instalara con el siguiente comando:

pip install ipython-sql

Conéctate al servidor IRIS

%sql iris://superuser:SYS@localhost:1972/USER

Ejecuta la query SQL

%sql SELECT 1

Instalación

Para poder utilizar esta "magia", debes instalar el paquete ipython-iris-magic.

pip install ipython-iris-magic

Todas las dependencias se instalarán automáticamente.

Uso

%load_ext iris_magic
%%iris iris://superuser:SYS@localhost:1972/USER 
set test = "toto"
zw test

Resultado:

test="toto"
0
0 167
Artículo Yuri Marx · mar 7, 2022 4m read

InterSystems IRIS es una gran plataforma de datos y posee las funcionalidades que demanda el mercado. En este artículo, recojo las 10 mejores:

PuestoFuncionalidad¿Por qué?Más información
1Análisis adaptativoAnalizar los datos empresariales actuales "TAL CUAL" y en tiempo real, con menos esfuerzo de modelado, mayor velocidad de ejecución y soporte para los principales visores analíticos (incluyendo Excel) es un factor clave para la estrategia corporativa de las empresas.

Enlace

2Administrador de APILos activos digitales se consumen mediante la API REST. Se requiere controlar la reutilización, seguridad, consumo, catálogo de activos, ecosistema de desarrolladores y otros aspectos en un punto central. El Administrador de API es la herramienta adecuada para hacerlo. Por ello, todas las empresas tienen o quieren tener un administrador de API.Enlace
3Sharding de la base de datosLa cantidad total de datos creados, capturados, copiados y consumidos a nivel mundial aumenta rápidamente. Hasta 2025, se prevé que la creación de datos a nivel mundial crezca hasta más de 180 zettabytes. En este escenario, es crítico para las empresas poder procesar los datos de forma distribuida (en shards, como hadoop o mongodb), para aumentar y mantener el rendimiento. El otro aspecto importante es que IRIS es 3 veces más rápido que Caché y más rápido que las bases de datos de AWS, en la nube de AWS.

Enlace 1

Enlace 2

4Soporte a PythonPython es el lenguaje más popular para hacer Inteligencia Artificial (IA). Y la IA está en el centro de la estrategia empresarial, porque permite obtener nuevos conocimientos, conseguir más productividad y reducir costes.

Enlace 1

Enlace 2

Enlace 3

5Las APIs nativas (Java, .NET, Node.js, Python) y PEXEn EE. UU. hay casi un millón de ofertas de puestos de trabajo en TI (fuente: https://www.forbes.com/sites/stuartanderson/2021/03/18/over-1-million-job-vacancy-postings-in-computer-occupations-in-us/). Es muy difícil encontrar un desarrollador de ObjectScript. Por eso, es importante ser capaz de utilizar las funcionalidades de IRIS, como la interoperabilidad, con el lenguaje de programación oficial del equipo de desarrolladores (Python, Java, .NET, etc.).

Enlace 1

Enlace 2

Enlace 3

Enlace 4

Enlace 5

Enlace 6

6Interoperabilidad, FHIR y IoT

Las empresas se conectan e intercambian datos constantemente. Los departamentos también deben trabajar conectados seguir procesos con mayor valor estratégico y menor coste. La mejor tecnología para ello son las herramientas de interoperabilidad, especialmente ESB, adaptadores de integración, motores de automatización de procesos empresariales (BPL), herramientas de transformación de datos (DTL) y la adopción de estándares de interoperabilidad del mercado, como FHIR y MQTT/IoT. La interoperabilidad de InterSystems soporta todo esto (para FHIR utiliza IRIS for Health).

Enlace 1

Enlace 2

Enlace 3

7Cloud, Docker y MicroserviciosAhora todo el mundo quiere una arquitectura de microservicios en la nube. Quieren romper los monolitos para crear proyectos más pequeños, menos complejos, menos acoplados, más escalables, reutilizables e independientes. IRIS permite implementar microservicios de datos, aplicaciones y análisis, gracias a la compatibilidad de IRIS con shards, docker, kubernetes, computación distribuida, herramientas DevOps y menor consumo de CPU/memoria (¡IRIS soporta incluso procesadores de ARM!). Pero los microservicios requieren que la gestión de las APIs de los microservicios, usando el Administrador de API, se utilice de forma alineada con las empresas.

Enlace 1

Enlace 2

Enlace 3

Enlace 4

Enlace 5

8Informes integradosLos informes son cruciales para las empresas. El personal operativo y los responsables de la toma de decisiones utilizan los informes para respaldar su trabajo. Además, se entregan muchos informes a los clientes. Pero, con las aplicaciones móviles, y las aplicaciones de microservicios, es necesario habilitar los informes integrados. IRIS Reports soporta todo esto.Enlace
9Soporte para VSCodeVSCode es el IDE más popular e InterSystems IRIS tiene un buen conjunto de herramientas para usarlo.

Enlace 1

Enlace 2

Enlace 3

10Ciencia de DatosLa capacidad de aplicar la ciencia de datos a las solicitudes y respuestas de integración y transacción de datos, utilizando Python, R e IntegratedML (AutoML) permiten que la IA sea inteligente en este momento que requieren las empresas. InterSystems IRIS proporciona IA con Python, R e IntegratedML (AutoML)

Enlace 1

Enlace 2

Enlace 3

1
0 576
Artículo Alberto Fuentes · dic 2, 2022 2m read

Si usáis Python, podéis utilizar el módulo venv para crear un entorno virtual. Este módulo es la manera recomendada de crear y gestionar entornos virtuales.

Un entorno virtual es una herramienta que ayuda a mantener separadas las dependencias requeridas por diferentes proyectos, mediante la creación de entornos virtuales aislados de Python para ellos. Resuelve el dilema “El proyecto X depende de la versión 1.x pero el proyecto Y necesita la 4.x”, y mantiene limpio y manejable el directorio site-packages global.

Así que si trabajáis mucho con Python, como yo, podéis usar el módulo venv para crear un entorno virtual para vuestro proyecto. Esto os permitirá instalar paquetes sin que afecte a la instalación de Python global.

Aquí encontraréis dos alias simples para crear y activar un entorno virtual.

Alias de Python

alias venv="python3 -m venv .venv; source .venv/bin/activate"
alias irisvenv="python3 -m venv .venv; source .venv/bin/activate; pip install https://github.com/grongierisc/iris-embedded-python-wrapper/releases/download/v0.0.1/iris-0.0.1-py3-none-any.whl"

Vamos a profundizar en los detalles de cada alias.

Python venv

El primer alias es uno sencillo. Creará un entorno virtual en el directorio actual y lo activará.

python3 -m venv .venv

Crea un entorno llamado .venv en el directorio actual.

source .venv/bin/activate

Activa el entorno.

InterSystems IRIS venv

El segundo alias es similar al primero excepto que instalará InterSystems IRIS Python wrapper en el entorno virtual.

python3 -m venv .venv

Crea un entorno llamado .venv en el directorio actual

source .venv/bin/activate

Activa el entorno.

pip install https://github.com/grongierisc/iris-embedded-python-wrapper/releases/download/v0.0.1/iris-0.0.1-py3-none-any.whl

Instala el InterSystems IRIS Python wrapper.

Este módulo es un envoltorio alrededor de InterSystems IRIS Embedded Python API. Te permite conectarte a una instancia InterSystems IRIS y ejecutar consultas SQL.

Importante! para que funcione necesitarás tener configurada una variable de entorno llamada IRISINSTALLDIR apuntando al directorio de instalación de IRIS.

export IRISINSTALLDIR=/opt/iris

Conclusión

Espero que os resulte útil este artículo. Si tenéis alguna pregunta o comentario, podéis escribirme en esta misma publicación.

0
1 249
Artículo Ricardo Paiva · nov 21, 2022 8m read

En la primera parte de este artículo he mostrado cómo empezar un nuevo proyecto en Django, y cómo definir nuevos modelos y añadir modelos ya existentes.

En esta publicación, voy a mostrar un Panel de Administración (disponible con la configuración predeterminada) y cómo puede ser útil.

Nota importante: si intentáis reproducir los pasos de este artículo, no funcionará para vosotros. Porque mientras escribía la publicación he realizado varios ajustes en el proyecto django-iris, e incluso en el driver DB-API de InterSystems, para arreglar algunos problemas ahí también, y creo que el driver aún está en desarrollo y habrá un driver más estable en el futuro. Así que vamos a asumir que este artículo solo explica cómo podría ser si tuviéramos todo terminado.

0
1 118
Anuncio Esther Sanchez · nov 15, 2022

¡Hola Comunidad!

Os presentamos la 3ª mesa redonda de la Comunidad - 60 minutos de animada charla (en inglés) sobre el tema: Desarrollando con Python

La idea es juntarse para compartir ideas, experiencias, trucos y consejos. Si tenéis alguna pregunta sobre el tema, podéis escribirla en los comentarios de esta publicación y se responderá y comentará durante la mesa redonda.

🗣 Ponentes: @Guillaume Rongier@Eduard Lebedyuk

📅 Fecha: Miércoles 23 de noviembre
🕑 Hora: 3:00 PM (CET)

➡️Podéis registraros aquí >>


0
0 99
Artículo Ricardo Paiva · oct 20, 2022 2m read

Me gustaría compartir un ejemplo sobre cómo la nueva funcionalidad de Python Embebido en IRIS me ha ayudado en mis rutinas diarias.

Mientras participaba en el proyecto iris-kaggle-socrata-generator con Henrique Dias, tuve que descomprimir conjuntos de datos de Kaggle para poder importarlos.

Conseguí hacerlo fácilmente mediante el uso de la librería zipfile en Python (este código se copió de este 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
}

Fijaos en el modificador del método [Language = python]. Esta funcionalidad se probó en la imagen de IRIS intersystemsdc/iris-ml-community:2021.2.0.617.0-zpm. Consultad la aplicación relacionada en Open Exchange para ver un ejemplo funcionando.

Podéis ver que es un código Python embebido en un método ObjectScript. Así que podéis usarlo en cualquier código ObjectScript. Por ejemplo:

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("There is more than 1 file in the zip file. Using the first one.")
    }
    …
    Return retorno
}

También podéis acceder al código completo aquí.

Recordad que el método de Python Embebido utiliza la librería de Python zipfile y devuelve los resultados del método en un %DynamicArray, utilizado en los métodos de ObjectScript. Esto significa que un objeto creado en un contexto de Python puede ser accedido mediante un contexto de ObjectScript sin problemas.

Aquí podéis consultar más información sobre cómo utilizar Python Embebido.

¡Y eso es todo! Espero que os resulte útil para vuestros proyectos.

0
1 148
Artículo Alberto Fuentes · oct 14, 2022 11m read

Iris-python-template

Proyecto de plantilla con varios códigos Python para ser utilizados con InterSystems IRIS Community Edition con contenedor.

Contenido:

  • Bloc de notas
    • Kernel de Python Embebido
    • Kernel de ObjectScript
    • Kernel de Vanilla Python
  • Python Embebido
    • Ejemplo de código
    • Demostración de Flask
  • API nativas de Python de IRIS
    • Ejemplo de código

Diagrama

2. Índice

3. Instalación

3.1. Docker

El repositorio está dockerizado para que puedas clonar el repositorio a cualquier directorio local

git clone https://github.com/grongierisc/iris-python-template.git

Abre el terminal en este directorio y ejecuta:

docker-compose up -d

y abre después http://localhost:8888/tree para Notebooks

O bien, abre la carpeta clonada en VSCode, inicia docker-compose y abre la URL mediante el menú de VSCode: VsCodeNotebooks

4. Cómo empezar a programar

4.1. Requisitos previos

Asegúrate de tener instalado git y Docker desktop.

Este repositorio está listo para codificarse en VSCode con el plugin de ObjectScript. Instala VSCode,Docker yel plugin de ObjectScripty abre la carpeta en VSCode.

4.1.1. Empezar a programar en ObjectScript

Abre la clase /src/ObjectScript/Embedded/Python.cls e intenta hacer cambios - se compilará en el contenedor Docker IRIS que está funcionando.

4.1.2. Empezar a programar con Python Embebido

La forma más fácil es ejecutar VsCode en el contenedor.

Para adjuntar a un contenedor Docker, selecciona Remote-Containers: Attach to Running Container... en la plantilla de comandos (kbstyle(F1)) o utiliza el Remote Explorer en la barra de actividades y desde la vista Containers, selecciona la acción en línea Attach to Container en el contenedor al que quieras conectarte.

Captura de pantalla del Explorador de contenedores

A continuación, configura tu intérprete de python en /usr/irissys/bin/irispython

PythonInterpreter

4.1.3. Empezar a programar con Notebooks

Abre esta URL: http://localhost:8888/tree

Tienes acceso a tres notebooks diferentes con tres kernels diferentes.

  • Kernel de Python Embebido
  • Kernel de ObjectScript
  • Kernel de Vanilla Python3
Bloc de notas

5. Qué hay dentro del repositorio

5.1. Dockerfile

Un dockerfile que instala algunas dependencias de Python (pip, venv) y Sudo en el contenedor por conveniencia. Después crea el directorio dev y copia en él este repositorio git.

Inicia IRIS e importa los archivos Titanics csv, después activa %Service_CallIn para Python Shell. Utiliza el docker-compose.yml relacionado para configurar fácilmente parámetros adicionales como el número de puerto y dónde asignar claves y carpetas del host.

Este dockerfile termina con la instalación de los requisitos para los módulos de Python.

La última parte es sobre la instalación de Jupyter Notebook y sus kernels.

Utiliza el archivo .env/ para ajustar el dockerfile que se utiliza en docker-compose.

5.2. .vscode/settings.json

Archivo de configuración para poder codificar inmediatamente en VSCode con el plugin VSCode ObjectScript

5.3. .vscode/launch.json

Archivo de configuración si quieres depurar con VSCode ObjectScript

Lee sobre todos los archivos en este artículo

5.4. .vscode/extensions.json

Archivo de recomendación para añadir extensiones si quieres ejecutar VSCode en el contenedor.

Más información aquí

Arquitectura

Esto es muy útil para trabajar con Python Embebido.

5.5. src folder

Esta carpeta está concebida en dos partes, una para el ejemplo de ObjectScript y otra para el código de Python.

5.5.1. src/ObjectScript

Un código diferente que muestra cómo utilizar Python en IRIS.

5.5.1.1. src/ObjectScript/Embedded/Python.cls

Todos los comentarios están en francés para que también puedas mejorar tu nivel de francés.

/// Embedded python example
Class ObjectScript.Embbeded.Python Extends %SwizzleObject
{

/// HelloWorld with a parameter
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
    • Función sencilla para decir "Hola" en Python
    • Utiliza la envoltura OjectScript con la etiqueta [ Language = python ]
  • compare
    • Una función de python que compara una cadena con un regx, si hay una coincidencia entonces la imprime, si no la imprime es que no se encontró ninguna coincidencia
  • compareObjectScript
    • La misma función que la de Python pero en ObjectScript
  • DemoPyhtonToPython
    • Muestra cómo utilizar una función de Python con código de Python envuelto en ObjectScript
set demo = ##class(ObjectScript.Embbeded.Python).%New()

zw demo.DemoPyhtonToPython()
  • DemoPyhtonToObjectScript
    • Una función de Python que muestra cómo llamar a una función de ObjecScript
  • DemoObjectScriptToPython
    • Una función de ObjectScript que muestra cómo llamar a una función de Python

5.5.1.2. src/ObjectScript/Gateway/Python.cls

Una clase de ObjectScript que muestra cómo llamar a un código de Phyton externo con la funcionalidad gateway.

En este ejemplo el código de Python es no ejecutado en el mismo proceso de IRIS.

/// Description
Class Gateway.Python
{

/// Demo of a python gateway to execute python code outside of an iris process.
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

Una pieza diferente del código Python que muestra cómo usar Python Embebido en IRIS.

5.5.2.1. src/Python/embedded/demo.cls

Todos los comentarios están en francés para que también puedas mejorar tu nivel de francés.

import iris

person = iris.cls('Titanic.Table.Passenger')._OpenId(1)

print(person.__dict__)

Primero importa el módulo de IRIS que activa las funciones de Python Embebido. Abre una clase persistente con la función cls del módulo de IRIS. Ten en cuenta que todas las funciones % se sustituyen por _.

Para ejecutar este ejemplo hay que utilizar IRIS Python Shell:

/usr/irissys/bin/irispython /opt/irisapp/src/Python/embedded/demo.py

5.5.2.2. src/Python/native/demo.cls

Muestra cómo utilizar la API nativa en el código de Python.

import irisnative

# create database connection and IRIS instance
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"))

# global
myIris.set("hello","myGlobal")
print(myIris.get("myGlobal"))

Para importar IRISNATIVE, debes instalar las ruedas de las API nativas en tu entorno de Python.

pip3 install /usr/irissys/dev/python/intersystems_irispython-3.2.0-py3-none-any.whl

Entonces puedes ejecutar este código de Python

/usr/bin/python3 /opt/irisapp/src/Python/native/demo.py

Ten en cuenta que en este caso se realiza una conexión a la base de datos de IRIS, esto significa que este código se ejecuta en un subproceso diferente al de IRIS.

5.5.2.3. src/Python/flask

Una demo completa de la combianción entre Python Embebido y el micro framework Flask. Puedes probar este endpoint:

GET http://localhost:4040/api/passengers?currPage=1&pageSize=1
5.5.2.3.1. ¿Cómo funciona?

Para utilizar Python Embebido, usamos irispython como interepretador de Python, y hacemos:

import iris

Justo al principio del archivo.

Entonces podremos ejecutar métodos como:

flaskExample

Como puedes ver, para OBTENER un pasajero con un ID, simplemente ejecutamos una consulta y utilizamos su conjunto de resultados.

También podemos utilizar directamente los objetos de IRIS:

flaskObjectExample

Aquí, utilizamos una consulta SQL para obtener todos los IDs de la tabla, y después recuperamos cada pasajero de la tabla con el método %OpenId() de la clase Titanic.Table.Passenger (ten en cuenta que como % es un carácter ilegal en Python, utilizamos _ como alternativa).

Gracias a Flask, implementamos todas nuestras rutas y métodos de esa manera.

5.5.2.3.2. Lanzamiento del servidor flask

Para lanzar el servidor, usamos gunicornio con irispython.

En el archivo docker-compose, añadimos la siguiente línea:

iris:
  command: -a "sh /opt/irisapp/server_start.sh"

Eso lanzará, después de que se inicie el contenedor (gracias al indicador -a), el siguiente script:

#!/bin/bash

cd ${SRC_PATH}/src/Python/flask

${PYTHON_PATH} -m gunicorn --bind "0.0.0.0:8080" wsgi:app &

exit 1

Con las variables de entorno definidas en el Dockerfile como sigue:

ENV PYTHON_PATH=/usr/irissys/bin/irispython
ENV SRC_PATH=/opt/irisapp/

5.5.3. src/Notebooks

Tres notebooks con tres kernels diferentes:

  • Un kernel de Python3 para ejecutar las API nativas
  • Un kernel de Python Embebido
  • Un kernel de ObjectScript

Se puede acceder a los notebooks aquí: http://localhost:8888/tree

Bloc de notas

5.5.3.1. src/Notebooks/HelloWorldEmbedded.ipynb

Este notebook utiliza el kernel de Python Embebido.

Muestra un ejemplo para abrir y guardar clases persistentes y cómo ejecutar consultas en SQL.

5.5.3.2. src/Notebooks/IrisNative.ipynb

Este notebook utiliza el kernel de Vanila python.

Muestra ejemplo para ejecutar API nativas de IRIS.

5.5.3.3. src/Notebooks/ObjectScript.ipynb

Este notebook utiliza el kernel de ObjectScript.

Muestra un ejemplo para ejecutar el código ObjectSCript y cómo utilizar Python Embebido en ObjectScript.

0
1 356
Artículo Henry Pereira · sep 26, 2021 8m read

https://media.giphy.com/media/Nxu57gIbNuYOQ/giphy.gif

Calma, calma, no estoy promoviendo una guerra contra las máquinas como en las películas de ciencia ficción, para evitar la dominación mundial de Ultron o Skynet. Todavía no, todavía no 🤔

Os invito a retar a las máquinas a través de la creación de un juego muy sencillo usando ObjectScript con Python embebido.

Tengo que deciros que me emocioné mucho con la función de Python integrado en InterSystems IRIS. Es increíble el montón de posibilidades que se abren para crear aplicaciones fantásticas.

Vamos a construir un juego "tres en raya". Las reglas son bastante sencillas y creo que todo el mundo sabe jugar.

Es lo que me salvó del tedio en mi infancia, durante los largos viajes en coche con la familia antes de que los niños tuvieran teléfonos móviles o tabletas. ¡Nada como retar a mis hermanos a jugar unas partidas en el cristal borroso!

Así que... ¡abrochaos el cinturón y vámonos!

Normas

Como he comentado, las reglas son bastante simples:

  • solo 2 jugadores por set
  • se juega por turnos en una cuadrícula de 3x3
  • el jugador humano siempre será la letra X y la computadora la letra O
  • los jugadores solo podrán poner las letras en los espacios vacíos
  • el primero en completar una secuencia de 3 letras iguales en horizontal, o en vertical o en diagonal, es el ganador
  • cuando se ocupen los 9 espacios, será un empate y el final de la partida

https://media4.giphy.com/media/3oriNKQe0D6uQVjcIM/giphy.gif?cid=790b761123702fb0ddd8e14b01746685cc0059bac0bc66e9&rid=giphy.gif&ct=g

Todo el mecanismo y las reglas lo escribiremos en ObjectScript, el mecanismo del jugador de la máquina se escribirá en Python.

Vamos a trabajar

Controlaremos el tablero en un global, en el que cada fila estará en un nodo y cada columna en una pieza.

Nuestro primer método es iniciar el tablero, para que sea fácil iniciaré el global ya con los nodos (filas A, B y C) y con las 3 piezas:

/// Iniciar un juego nuevo
ClassMethod NewGame() As %Status
{
  Set sc = $$$OK
  Kill ^TicTacToe
  Set ^TicTacToe("A") = "^^"
  Set ^TicTacToe("B") = "^^"
  Set ^TicTacToe("C") = "^^"
  Return sc
}

en este momento crearemos un método para añadir las letras en los espacios vacíos, para esto cada jugador dará la ubicación del espacio en el tablero.

Cada fila una letra y cada columna un número, para poner la X en el medio, por ejemplo, pasamos B2 y la letra X al método.

ClassMethod MakeMove(move As %String, player As %String) As %Boolean
{
  Set $Piece(^TicTacToe($Extract(move,1,1)),"^",$Extract(move,2,2)) = player
}

Vamos a comprobar si la coordinación es válida, la forma más simple que veo es usando una expresión regular:

ClassMethod CheckMoveIsValid(move As %String) As %Boolean
{
  Set regex = ##class(%Regex.Matcher).%New("(A|B|C){1}[0-9]{1}")
  Set regex.Text = $ZCONVERT(move,"U")
  Return regex.Locate()
}

Necesitamos garantizar que el espacio seleccionado está vacío.

ClassMethod IsSpaceFree(move As %String) As %Boolean
{
  Quit ($Piece(^TicTacToe($Extract(move,1,1)),"^",$Extract(move,2,2)) = "")
}

¡Muy bien!

Ahora comprobamos si algún jugador ganó el set o si el juego ya está terminado, para esto creemos el método CheckGameResult.

Primero verificamos si hubo algún ganador completando por la horizontal, usaremos una lista con las filas y un simple $ Find resuelve

    Set lines = $ListBuild("A","B","C")
    // Check Horizontal
    For i = 1:1:3 {
      Set line = ^TicTacToe($List(lines, i))
      If (($Find(line,"X^X^X")>0)||($Find(line,"O^O^O")>0)) {
        Return $Piece(^TicTacToe($List(lines, i)),"^", 1)_" won"
      }
    }

Con otro For comprobamos la vertical

For j = 1:1:3 {
      If (($Piece(^TicTacToe($List(lines, 1)),"^",j)'="") &&
        ($Piece(^TicTacToe($List(lines, 1)),"^",j)=$Piece(^TicTacToe($List(lines, 2)),"^",j)) &&
        ($Piece(^TicTacToe($List(lines, 2)),"^",j)=$Piece(^TicTacToe($List(lines, 3)),"^",j))) {
        Return $Piece(^TicTacToe($List(lines, 1)),"^",j)_" won"
      }
    }

para comprobar la diagonal:

    If (($Piece(^TicTacToe($List(lines, 2)),"^",2)'="") &&
      (
        (($Piece(^TicTacToe($List(lines, 1)),"^",1)=$Piece(^TicTacToe($List(lines, 2)),"^",2)) &&
          ($Piece(^TicTacToe($List(lines, 2)),"^",2)=$Piece(^TicTacToe($List(lines, 3)),"^",3)))||
        (($Piece(^TicTacToe($List(lines, 1)),"^",3)=$Piece(^TicTacToe($List(lines, 2)),"^",2)) &&
        ($Piece(^TicTacToe($List(lines, 2)),"^",2)=$Piece(^TicTacToe($List(lines, 3)),"^",1)))
      )) {
      Return ..WhoWon($Piece(^TicTacToe($List(lines, 2)),"^",2))
    }

por fin, comprobamos si hubo un empate

    Set gameStatus = ""
    For i = 1:1:3 {
      For j = 1:1:3 {
        Set:($Piece(^TicTacToe($List(lines, i)),"^",j)="") gameStatus = "Not Done"
      }
    }
    Set:(gameStatus = "") gameStatus = "Draw"

¡Genial!

Es hora de construir la máquina

Vamos a crear a nuestro oponente, necesitamos crear un algoritmo capaz de calcular todos los movimientos disponibles y usar una métrica para saber cuál es el mejor movimiento.

Lo ideal es utilizar un algoritmo de decisión llamado MiniMax (Wikipedia: MiniMax)

https://media3.giphy.com/media/WhTC5v5qQP4yAUvGKz/giphy.gif?cid=ecf05e47cx92yiew8vsig62tjq738xf7hfde0a2ygyfdl0xt&rid=giphy.gif&ct=g

El algoritmo MiniMax es una regla de decisión utilizada en teoría de juegos, teoría de decisiones e inteligencia artificial.

Básicamente, necesitamos saber cómo jugar asumiendo cuáles serán los posibles movimientos del oponente y coger el mejor escenario posible.

En detalle, tomamos la escena actual y comprobamos de forma recurrente el resultado del movimiento de cada jugador. En caso de que la máquina gane el juego, puntuamos con +1, en caso de que pierda, puntuamos con -1 y con 0 si empata.

Si no es el final del juego, abrimos otro árbol con el estado actual del juego. Después de eso, encontramos la jugada con el valor máximo para la máquina y el mínimo para el oponente.

Mira el siguiente gráfico - hay 3 movimientos disponibles: B2, C1 y C3.

Al elegir C1 o C3, el oponente tiene la oportunidad de ganar en el siguiente turno, pero si elige B2 no importa el movimiento que elija el oponente, la máquina gana la partida.

minimaxp

Es como tener la gema del tiempo en nuestras manos e intentar encontrar la mejor línea de tiempo.

https://pa1.narvii.com/7398/463c11d54d8203aac94cda3c906c40efccf5fd77r1-460-184_hq.gif

Convirtiendo a Python

ClassMethod ComputerMove() As %String [ Language = python ]
{
  import iris
  from math import inf as infinity
  computerLetter = "O"
  playerLetter = "X"

  def isBoardFull(board):
    for i in range(0, 8):
      if isSpaceFree(board, i):
        return False
    return True

  def makeMove(board, letter, move):
    board[move] = letter

  def isWinner(brd, let):
    # check horizontals
    if ((brd[0] == brd[1] == brd[2] == let) or \
      (brd[3] == brd[4] == brd[5] == let) or \
      (brd[6] == brd[7] == brd[8] == let)):
        return True
    # check verticals
    if ((brd[0] == brd[3] == brd[6] == let) or \
        (brd[1] == brd[4] == brd[7] == let) or \
        (brd[2] == brd[5] == brd[8] == let)):
        return True
    # check diagonals
    if ((brd[0] == brd[4] == brd[8] == let) or \
        (brd[2] == brd[4] == brd[6] == let)):
        return True
    return False

  def isSpaceFree(board, move):
    #Retorna true se o espaco solicitado esta livre no quadro
    if(board[move] == ''):
      return True
    else:
      return False

  def copyGameState(board):
    dupeBoard = []
    for i in board:
      dupeBoard.append(i)
    return dupeBoard

  def getBestMove(state, player):
    done = "Done" if isBoardFull(state) else ""
    if done == "Done" and isWinner(state, computerLetter): # If Computer won
      return 1
    elif done == "Done" and isWinner(state, playerLetter): # If Human won
      return -1
    elif done == "Done":    # Draw condition
      return 0

    # Minimax Algorithm
    moves = []
    empty_cells = []
    for i in range(0,9):
      if state[i] == '':
        empty_cells.append(i)

    for empty_cell in empty_cells:
      move = {}
      move['index'] = empty_cell
      new_state = copyGameState(state)
      makeMove(new_state, player, empty_cell)

      if player == computerLetter:
          result = getBestMove(new_state, playerLetter)
          move['score'] = result
      else:
          result = getBestMove(new_state, computerLetter)
          move['score'] = result

      moves.append(move)

    # Find best move
    best_move = None
    if player == computerLetter:
        best = -infinity
        for move in moves:
            if move['score'] > best:
                best = move['score']
                best_move = move['index']
    else:
        best = infinity
        for move in moves:
            if move['score'] < best:
                best = move['score']
                best_move = move['index']

    return best_move

  lines = ['A', 'B', 'C']
  game = []
  current_game_state = iris.gref("^TicTacToe")

  for line in lines:
    for cell in current_game_state[line].split("^"):
      game.append(cell)

  cellNumber = getBestMove(game, computerLetter)
  next_move = lines[int(cellNumber/3)]+ str(int(cellNumber%3)+1)
  return next_move
}

Primero, convierto el global en una matriz simple, ignorando columnas y filas, dejándolo plano para facilitar.

En cada movimiento analizado llamamos al método copyGameState que, como su nombre indica, copia el estado del juego en ese momento, donde aplicamos el MiniMax.

El método getBestMove que se llamará repetidamente hasta que finalice el juego encontrando un ganador o un empate.

Primero se mapean los espacios vacíos y verificamos el resultado de cada movimiento, cambiando entre los jugadores.

Los resultados se almacenan en move ['puntuación'] para, después de comprobar todas las posibilidades, encontrar el mejor movimiento.

¡Espero que os haya divertido! Es posible mejorar la inteligencia usando algoritmos como Alpha-Beta Pruning (Wikipedia: AlphaBeta Pruning) o redes neuronales. ¡Solo tened cuidado de no darle vida a Skynet!

https://media4.giphy.com/media/mBpthYTk5rfbZvdtIy/giphy.gif?cid=790b761181bf3c36d85a50b84ced8ac3c6c937987b7b0516&rid=giphy.gif&ct=g

No dudeis en dejar cualquier comentario o pregunta.

¡Esto es todo, amigos!

Código fuente completo: InterSystems Iris version 2021.1.0PYTHON

1
0 866
Artículo Joel Espinoza · oct 28, 2019 5m read

¡Hola a todos!

Hoy instalaremos Jupyter Notebook y vamos a conectarlo con Apache Spark e InterSystems IRIS.

Nota: Los siguientes procedimientos los hice en Ubuntu 18.04 y Python 3.6.5.

Introducción

Si estás buscando un bloc de notas que sea reconocido, difundido ampliamente y muy popular entre los usuarios de Python, en lugar de utilizar Apache Zeppelin, deberías elegir Jupyter notebook. Jupyter notebook es una excelente y muy poderosa herramienta para la "ciencia de datos", que cuenta con una comunidad muy grande, además de muchas funciones y software adicional. Jupyter notebook permite crear y compartir documentos que contienen código en tiempo real, ecuaciones, visualizaciones y texto narrativo. Sus aplicaciones incluyen la limpieza y transformación de los datos, simulaciones numéricas, modelamiento estadístico, visualización de datos, machine learning y muchas funciones más. Y lo más importante, existe una gran comunidad que  ayuda a resolver los problemas que surjan.

1
0 595
Artículo Ricardo Paiva · ago 11, 2022 3m read

Gracias a las últimas mejoras al soporte de Python en IRIS y al continuo trabajo en el soporte a la DB-API de Python por parte de InterSystems, he implementado el soporte de IRIS en el proyecto Django, en el que la DB-API de Python se usa para trabajar con otras bases de datos.

Vamos a probar una sencilla aplicación en Django, que almacena sus datos en IRIS.

todo App

0
1 127
Artículo Muhammad Waseem · jul 28, 2022 4m read

ObjectScript Kernel Logo

Jupyter Notebook es un entorno interactivo formado por celdas que permiten ejecutar código en un gran número de lenguajes de marcado y programación diferentes.

Para hacer esto, Jupyter debe conectarse a un kernel apropiado. No había un Kernel ObjectScript, por lo que decidí crear uno.

Puedes probarlo aquí.

Este es un adelanto de los resultados:

alt text

Jupyter Kernels 101

Hay varias formas de crear un Jupyter Kernel. Decidí hacer un kernel contenedor de Python.

Tenemos que crear una subclase de ipykernel.kernelbase.Kernel e implementar el método do_execute que recibe un código para ser ejecutado en un idioma en particular.

Entonces, la idea general es obtener un fragmento de código ObjectScript, ejecutarlo de alguna manera y devolver los resultados a nuestro cuaderno.

Pero, ¿cómo hacemos eso exactamente? Vamos a tratar de analizarlo un poco más.

Envío de código ObjectScript a IRIS

Para empezar, tenemos que enviar nuestro fragmento de código a IRIS. Aquí es donde la API Nativa de IRIS para Python es necesaria.

Todo lo que tenemos que hacer es importar el paquete irisnative, luego establecer una conexión:

def get_iris_object():
  # Crear conexión con InterSystems IRIS
  connection = irisnative.createConnection('iris', 51773, 'IRISAPP', '_SYSTEM', 'SYS')

  # Crear un objeto de iris
  return irisnative.createIris(connection)

Después de eso, podemos usar la conexión para llamar a las clases que están almacenadas en la base de datos de IRIS.

def execute_code(self, code):
        class_name = "JupyterKernel.CodeExecutor"
        return self.iris.classMethodValue(class_name, "CodeResult", code)

¿Para qué se utilizan esta clase Codes Executor y el método CodeResult?

Vamos a verlo.

Ejecutar código ObjectScript

El propósito de esta clase es ejecutar una línea de código ObjectScript y devolver un objeto JSON con los resultados de la ejecución. Pasamos nuestro código a CodeResult en una variable vstrCommand.

Comenzamos redirigiendo IO a la rutina actual, luego ejecutamos el código pasado a través del comando XECUTE, redirigimos IO de vuelta al original y devolvemos los resultados.

Include %sySystem

Class JupyterKernel.CodeExecutor
{

ClassMethod CodeResult(vstrCommand As %String) As %String [ ProcedureBlock = 0 ]
{
        set tOldIORedirected = ##class(%Device).ReDirectIO()
        set tOldMnemonic = ##class(%Device).GetMnemonicRoutine()
        set tOldIO = $io
        try {
            set str=""
            set status = 1
            //Redirigir IO a la rutina actual: utiliza las etiquetas definidas a continuación
            use $io::("^"_$ZNAME)

            //Habilitar redirección
            do ##class(%Device).ReDirectIO(1)

            XECUTE (vstrCommand)

        } catch ex {
            set str = ex.DisplayString()
            set status = 0
        }

        //Vuelva a la configuración original de redirección/rutina mnemotécnica
        if (tOldMnemonic '= "") {
            use tOldIO::("^"_tOldMnemonic)
        } else {
            use tOldIO
        }
        do ##class(%Device).ReDirectIO(tOldIORedirected)

        quit {"status":(status), "out":(str)}.%ToJSON()

rchr(c)
    quit
rstr(sz,to)
    quit
wchr(s)
    do output($char(s))
    quit
wff()
    do output($char(12))
    quit
wnl()
    do output($char(13,10))
    quit
wstr(s)
    do output(s)
    quit
wtab(s)
    do output($char(9))
    quit
output(s)
    set str = str _ s
    quit
}

}

Mostrar los resultados

Hemos ejecutado una parte del código ObjectScript, ¿y ahora qué? Bueno, tenemos que mostrar los resultados.

Si no hubo excepciones, simplemente mostramos los resultados línea por línea.

Sin embargo, si nuestro fragmento de código aprobado generó una excepción, detenemos la ejecución, mostramos el número de la línea fallida, a sí misma y la excepción generada.

alt text

Lanzamiento de la aplicación

Puedes probar este kernel por ti mismo y aquí te mostramos cómo.

Requisitos previos

Asegúrate de tener git y Docker instalado.

Clonar/extraer el repositorio en cualquier directorio local, por ejemplo, como se muestra a continuación:

$ git clone https://github.com/Vekkby/objectsriptkernel.git

Abre el terminal en este directorio y ejecuta:

$ docker-compose up -d --build

Cómo trabajar con él

Puedes acceder al servidor del notebook desde el navegador usando

localhost:8888

Hay un notebook de muestra llamado 'hello.ipynb' en el directorio 'work'. texto alternativo

0
0 160