Añadir semántica a un croissant
Un archivo RoboCroissant indica qué archivos tiene una base de conocimiento y qué columnas contienen. Esta habilidad añade qué significan los datos: qué columnas juntas describen un gen o una enfermedad, qué afirma una fila, qué prefijo de identificador usan los ids de una columna, qué representan los códigos. Lo escribe en un nuevo croissant usando constructos de Croissant 1.1, y registra por qué se hizo cada afirmación.
Produces un plan (JSON, por layout), los scripts lo aplican y verifican. No editas el croissant manualmente.
Entradas y salidas
- Entrada: un croissant (
croissant.jsonocroissant.json.gz) y un directorio de salida, más el archivosemantics_answers.jsonde los mantenedores junto al croissant, si existe. - Salida, en el directorio de salida:
semantics_plan.json— el plan (formato:reference/plan-format.md)croissant.semantic.json(o.json.gzsi la entrada estaba comprimida con gzip) — el resultadocheck_report.md— salida decheck.py(ycheck_report.load_errors.txt, errores completos de mlcroissant, cuando los registros no se pudieron cargar)notes.md— decisiones, layouts omitidos y por qué, y preguntas para los mantenedores de la base de conocimiento
El croissant de entrada nunca se modifica. Coloca las descargas, scripts auxiliares y otros trabajos temporales en OUT/work/, no en otro lugar.
Scripts
Todos en scripts/, se ejecutan directamente (son archivos uv run --script e instalan sus propias dependencias). Usa --help en cualquiera de ellos.
| Script | Uso |
|---|---|
inventory.py CROISSANT [--layout ID] [--json F] [--common-columns] | Lista layouts (conjuntos de columnas distintos), los más grandes primero; describe las columnas de un layout, los conjuntos de registros y archivos; lista las columnas que comparten la mayoría de los conjuntos de registros |
sample.py CROISSANT --layout ID | Lee filas reales de tres de los archivos del layout; muestra los valores de ejemplo de cada columna y su forma (CURIEs y sus prefijos, ids simples, listas, códigos) |
dialects.py list/show/detect/read | Formatos de archivo conocidos (VCF, GAF, MITAB, CTD, ...) como dialectos computables; cuál lee los archivos de un layout; lee registros usando solo lo que un croissant dice sobre el archivo |
vocab.py class/slot/search/associations/prefix/identify/term/ols/infores | Busca clases y slots de Biolink (con sugerencias de aproximación), clases de asociación para un par sujeto/objeto, prefijos de identificador (Biolink + Bioregistry), qué prefijos se ajustan a ids simples, términos de ontología por id o texto, e ids infores para nombres de fuente |
apply_plan.py CROISSANT PLAN OUT | Escribe el plan en un nuevo croissant |
check.py CROISSANT PLAN OUT --report R --load-records | --plan-only primero: términos, prefijos, dialectos y unidades en segundos. Luego la verificación completa: verifica términos, prefijos, códigos y dialectos contra Biolink y los datos muestreados, ejecuta el validador MLCommons, lee algunos registros a través de mlcroissant (de las primeras líneas de cada archivo, no de descargas completas), y reporta cobertura |
Flujo de trabajo
-
Exploración. Si hay un
semantics_answers.jsonjunto al croissant, léelo primero: contiene las respuestas de los mantenedores de la base de conocimiento a preguntas anteriores (ver "Respuestas del mantenedor" más abajo). No hagas esas preguntas de nuevo;apply_plan.pyycheck.pyaplican las respuestas a tu plan automáticamente. Luegoinventory.py CROISSANT. Anota la base de conocimiento (nombre, descripción, url en el croissant) y cómo se distribuyen los conjuntos de registros entre los layouts. Las bases de conocimiento grandes tienen cientos de layouts; trabaja desde la parte superior de la lista.Encuentra el id infores propio de la base de conocimiento ahora (
vocab.py infores NAME; prueba su nombre completo, su acrónimo y su url) y establécela comoinforesdel plan. Identifica el recurso cuyos archivos son estos, y los constructores de grafos lo citan como la fuente de todo lo leído de ellos: sin él, la etapa de transformación no construirá la base de conocimiento en absoluto. Cuando coincidan varias entradas, elige la del recurso que publica estos archivos, no un servicio que los re-sirve (infores:reactome, noinfores:automat-reactome).check.pylo compara con lo que dice el resto de tu plan: un único agregador o constanteprovided_bytambién nombra la base de conocimiento (los ortólogos de HCOP son agregados porinfores:hgnc), y una discrepancia es una advertencia a resolver.Cuando ninguna coincida, propón una:
infores:y el nombre corto de la base de conocimiento en minúsculas unido por guiones (infores:bioplex,infores:expression-atlas), con"infores_proposed": trueen el plan. Luego escribe su entrada de catálogo convocab.py infores-entry CROISSANT --id infores:NAME, añadiendo--knowledge-levely--agent-typecuando la documentación los haga claros, y colócala ennotes.mdbajo un encabezado Id infores a registrar, cerca del principio. Di allí que el usuario debe registrarlo con un pull request al registro infores (el comando imprime dónde), y que el id puede cambiar en la revisión.check.pymantiene una advertencia sobre un id propuesto hasta que esté registrado; no lo expliques. -
Elige los layouts a realizar. Apunta a los layouts que cubren la mayoría de los conjuntos de registros y el contenido central (asociaciones y las tablas de entidades principales) — típicamente los 5 a 15 principales, o hasta que los layouts restantes sean menores (archivos tipo readme, logs, recuentos por versión). Si hay muchos layouts pequeños (
inventory.pylo dirá), los conjuntos de registros probablemente comparten columnas centrales: usainventory.py --common-columnsy planifica esas columnas una vez conmatch.has_columns. Todo lo que omitas va en la listaskippeddel plan con una razón. Hacer menos layouts bien es mejor que muchos mal. -
Para cada layout, mira los datos antes de decidir nada.
inventory.py CROISSANT --layout IDpara columnas, descripciones y nombres de archivo. Una columna marcadaMIXEDtiene diferentes tipos atómicos en diferentes conjuntos de registros (el pipeline los infiere por archivo); decide su tipo a partir de los datos y estableceatomic.- Para tablas,
dialects.py detect CROISSANT --layout IDencuentra cómo están escritos los archivos (líneas de comentario, cabecera o ninguna, delimitador) entre formatos conocidos. Los formatos conocidos (VCF, GAF, MITAB) tienen especificaciones publicadas; confía en ellas en lugar de redescubrir el formato. Si nada encaja, describe el dialecto en línea (reference/dialects.md). Luego muestra con--dialect NAMEpara que las filas se lean como dice el formato, no como se adivina. sample.py CROISSANT --layout IDpara valores reales. Lee tres archivos del layout (el de nombre más reciente, el más grande, el más pequeño), porque un solo archivo — a menudo una instantánea antigua o un subconjunto filtrado — puede ocultar valores (marcadores de posiciónN/A, valores de código adicionales, otros tipos de id).--files Nmuestra más de ellos;--record-set IDmuestra un archivo en particular. Si el muestreo falla (un archivo enorme, un archivo comprimido, un conjunto de archivos), dilo en elbasisdel plan y baja la confianza.- Para columnas de código (tipos, evidencia, relaciones, fuentes), una muestra omite valores raros.
sample.py CROISSANT --record-set ID --profile COL1,COL2lee el archivo completo y cuenta cada valor distinto; repite--record-setpara sumar varios archivos. Traza el mapa desde el perfil, no desde la muestra. - Sé amable con los servidores de la base de conocimiento. Ejecuta un comando de muestreo o verificación a la vez por base de conocimiento, nunca muchos en paralelo: los hosts bloquean ráfagas con un desafío de bot, y entonces cada solicitud posterior falla. Los scripts espacian sus propias solicitudes y almacenan en caché las descargas (en
~/.cache/croissant-semantics/downloads;--refreshdescarga de nuevo), por lo que volver a ejecutar es barato (una copia almacenada bajo un--max-mbmayor sirve una más pequeña). Si un script reporta un desafío de bot o un HTTP 403, deja de muestrear ese host, no intentes sortearlo, y di ennotes.mdqué verificaciones no pudieron ejecutarse. Los scripts entonces rechazan ese host durante una hora, entre ejecuciones, y trabajan desde archivos en caché. - Las hojas de cálculo (xlsx y xls heredado), bases de datos SQLite y archivos parquet también se muestrean y perfilan: la hoja o tabla es aquella con la que termina el nombre del conjunto de registros ("archivo.xlsx — Hoja1", "archivo.xlsx: Hoja1"), y el muestreo falla en lugar de adivinar cuando no puede determinarlo. Se leen completos, así que aumenta
--max-mbsi es necesario (también encheck.py). mlcroissant no puede leer hojas de cálculo o bases de datos, por lo que sus registros no se cargan. - Los archivos XML, RDF (Turtle, RDF/XML, OWL), FASTA y otros que no son tablas no se pueden muestrear: los scripts lo dicen. Si un layout es importante, verifica sus ids con un pequeño script en
OUT/work/(uv run --with rdflibpara RDF; transmite XML conxml.etree.ElementTree.iterparse), y di cómo ennotes.md. Sus campos normalmente no tienenextract, por lo que ninguna herramienta puede leerlos: un problema del generador a reportar. --profilecon--layoutperfila--filesconjuntos de registros del layout (por defecto 3, oall) en lugar de nombrar cada uno con--record-set.--prefixescuenta el prefijo o etiqueta de cada valor, para todas las columnas perfiladas o solo las listadas (--prefixes COL1,COL2);--by COLtabula cruzadamente contra otra columna (con qué tipos de objeto ocurre cada código);--split SEPcuenta los elementos de celdas de lista;--per-fileperfila cada conjunto de registros por separado (para verificar que los ids son únicos por archivo);--stop-mb Ndetiene cada archivo después de N MB, para archivos de muchos GB (los recuentos entonces cubren solo el inicio; en un archivo ordenado por especie o id eso puede ser solo un grupo, así que dilo).- Perfila las columnas de id de los layouts principales (
--profile COL --shapes) antes de confiar en ellas: la verificación de datos lee las primeras filas de unos pocos archivos, por lo que una columna cuyas filas posteriores carecen de id, o contienen otra familia de id, la pasa. Varias bases de conocimiento tenían entre un 20 y un 30 % de filas sin id después de cientos de filas que todas tenían uno. - Una entrada
match.has_columnsque cubre muchos layouts es muestreada porcheck.pysolo en unos pocos de sus archivos. Muestrea los layouts que abarca que difieren (--record-set-name,--files) antes de confiar en ella. - Los scripts usan el almacén de certificados del sistema operativo. Si las descargas aún fallan con un error de certificado, repórtalo con la salida; no desactives la verificación.
- Si la documentación está detrás de una verificación de bot ("verifica que eres humano", un desafío de Cloudflare o ALTCHA), no intentes sortearlo; planifica a partir de datos y nombres, y limita la confianza a
mediumpara significados que solo la documentación podría confirmar. La procedencia del croissant puede citar páginas que desde entonces se han puesto detrás de una verificación: cita solo lo que pudiste leer. - En un archivo enorme, las primeras filas pueden no ser representativas (el archivo
genes_diseasesde 3 GB de CTD comienza con miles de filas inferidas). Perfila un archivo más pequeño del mismo layout (el subconjunto curado) en lugar de transmitir todo. - Para elegir conjuntos de registros por nombre, usa
--record-set-name REGEX(en lugar de--layout) en lugar de construir una lista de argumentos--record-seten el shell (zsh no divide variables en palabras).--per-filemuestra cada archivo muestreado por separado, para layouts cuyos archivos difieren (un tipo de id por archivo). - La verificación de datos lee las primeras filas de unos pocos archivos. Las filas posteriores de una columna pueden diferir (nodos en blanco después de 200 IRIs, un código raro): confirma las formas de id y los códigos con
--profile, que lee archivos completos. inventory.pylista los archivos de documentación enviados con los datos (README.pdf dentro de un zip, un diccionario de datos) después de los layouts. Lee los relevantes:sample.py CROISSANT --dump FILEimprime un archivo como texto,--member NAMEun miembro de un archivo comprimido (un zip se lee completo, así que aumenta--max-mbpara uno grande) (lista los miembros de un zip cuando el nombre es incorrecto),--sheet NAMEuna hoja de una hoja de cálculo.sample.pymarca columnas cuyo tipo declarado no se ajusta a los valores (una columnasc:Integerque contiene27152464|29518214) y archivos cuyas filas son más anchas o más estrechas que la cabecera. Ambos suelen ser problemas del pipeline: corrige los tipos conatomic, y repórtalos.- Cuando los scripts no pueden leer una fuente, obtén los archivos tú mismo (uno a la vez, en
OUT/work/) y apunta los scripts a ellos con--url-map OLD=file:///abs/path/para que sus verificaciones aún se ejecuten, en lugar de escribir tus propios perfiladores. Las descargas se almacenan en caché, y~/.cache/croissant-semantics/downloads/index.tsvasigna cada archivo en caché a su URL. - Si los "nombres de columna" de un layout son realmente datos (sin fila de cabecera, por lo que el pipeline tomó la primera fila de datos como nombres, y cada archivo se convirtió en su propio layout), sáltalo y repórtalo en
notes.mdcomo un problema del pipeline. - Si las URLs de los datos ya no existen (HTTP 404), la base de conocimiento probablemente ha pasado a una versión más reciente. Encuentra las URLs actuales desde su página de descarga y pasa
--url-map OLD=NEWasample.pyycheck.py(por ejemplo,--url-map 202607=202610). Cuando ha cambiado más que la versión (otra ruta o nombre de archivo), asigna URLs completas, un--url-map OLD_URL=NEW_URLpor archivo. Cuando las URLs mismas contienen=(cadenas de consulta), escribeOLD=>NEW. Dilo ennotes.md; también es un problema del pipeline. Una URL de endpoint SPARQL que devuelve JSON donde el croissant describe una tabla normalmente necesita&format=csv(otext/csv) asignado. - Archivos comprimidos: se muestrean los miembros de archivos zip y tar. Un zip se descarga completo (hasta
--max-mb); un tar se transmite hasta que se encuentra el miembro, por lo que un miembro profundamente anidado dentro de un tar enorme puede exceder--max-mb. Un archivo que falla una vez no se intenta de nuevo, y el muestreo se detiene después de fallos repetidos. Si es necesario, extrae un miembro enOUT/work/tú mismo, y registra qué verificaste y cómo ennotes.md. - Si los datos necesitan un inicio de sesión o clave API (HTTP 401/403, o el
conditionsOfAccessdel croissant lo dice), no busques credenciales. Planifica solo a partir de la documentación y los nombres de columna:sourceesdocumentationoagent,confidencecomo máximomedium, ynotes.mddice que no se verificó nada contra los datos. - Busca un diccionario de datos (también llamado