r11103: 2006 umls updates
[umlisp.git] / parse-rrf.lisp
1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: umlisp -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:     parse-2002.lisp
6 ;;;; Purpose:  Parsing and SQL insertion routines for UMLisp which may
7 ;;;;           change from year to year
8 ;;;; Author:   Kevin M. Rosenberg
9 ;;;; Created:  Apr 2000
10 ;;;;
11 ;;;; $Id$
12 ;;;;
13 ;;;; This file, part of UMLisp, is
14 ;;;;    Copyright (c) 2000-2006 by Kevin M. Rosenberg, M.D.
15 ;;;;
16 ;;;; UMLisp users are granted the rights to distribute and use this software
17 ;;;; as governed by the terms of the GNU General Public License.
18 ;;;; *************************************************************************
19
20 (in-package #:umlisp)
21
22 ;;; Pre-read data for custom fields into hash tables
23 (defvar *preparse-hash-init?* nil)
24
25 (eval-when (:compile-toplevel :load-toplevel :execute)
26 (let ((pfstr-hash nil)      ;; Preferred concept strings by CUI
27       (cui-lrl-hash nil)    ;; LRL by CUI
28       (lui-lrl-hash nil)    ;; LRL by LUI
29       (sui-lrl-hash nil)    ;; LRL by SUI
30       (cuisui-lrl-hash nil) ;; LRL by CUISUI
31       (sab-srl-hash nil))   ;; SRL by SAB
32
33   (defun make-preparse-hash-table ()
34     (if sui-lrl-hash
35         (progn
36           (clrhash pfstr-hash)
37           (clrhash cui-lrl-hash)
38           (clrhash lui-lrl-hash)
39           (clrhash sui-lrl-hash)
40           (clrhash cuisui-lrl-hash)
41           (clrhash sab-srl-hash))
42       (setf
43           pfstr-hash (make-hash-table :size 800000)
44           cui-lrl-hash (make-hash-table :size 800000)
45           lui-lrl-hash (make-hash-table :size 1500000)
46           sui-lrl-hash (make-hash-table :size 1500000)
47           cuisui-lrl-hash (make-hash-table :size 1800000)
48           sab-srl-hash (make-hash-table :size 100 :test 'equal))))
49
50   (defun ensure-preparse (&optional (force-read nil))
51     (when (and *preparse-hash-init?* (not force-read))
52       (return-from ensure-preparse 'already-done))
53     (make-preparse-hash-table)
54     (with-umls-file (line "MRCONSO.RRF")
55       (let ((cui (parse-ui (nth 0 line)))
56             (lui (parse-ui (nth 3 line)))
57             (sui (parse-ui (nth 5 line)))
58             (sab (nth 11 line))
59             (srl (parse-integer (nth 15 line))))
60         (unless (gethash cui pfstr-hash)  ;; if haven't stored pfstr for cui
61             (if (and (string-equal (nth 1 line) "ENG") ; LAT
62                      (string-equal (nth 2 line) "P") ; ts
63                      (string-equal (nth 4 line) "PF")) ; stt
64               (setf (gethash cui pfstr-hash) (nth 14 line))))
65         (set-lrl-hash cui srl cui-lrl-hash)
66         (set-lrl-hash lui srl lui-lrl-hash)
67         (set-lrl-hash sui srl sui-lrl-hash)
68         (set-lrl-hash (make-cuisui cui sui) srl cuisui-lrl-hash)
69         (multiple-value-bind (val found) (gethash sab sab-srl-hash)
70           (declare (ignore val))
71           (unless found
72             (setf (gethash sab sab-srl-hash) srl)))))
73     (setq *preparse-hash-init?* t)
74     t)
75
76   (defun pfstr-hash (cui) (gethash cui pfstr-hash))
77   (defun cui-lrl (cui)    (gethash cui cui-lrl-hash))
78   (defun lui-lrl (lui)    (gethash lui lui-lrl-hash))
79   (defun sui-lrl (sui)    (gethash sui sui-lrl-hash))
80   (defun sab-srl (sab)    (aif (gethash sab sab-srl-hash) it 0))
81   (defun cuisui-lrl (cuisui) (gethash cuisui cuisui-lrl-hash))
82
83 )) ;; closure
84
85 (defun set-lrl-hash (key lrl hash)
86   "Set the least restrictive level in hash table"
87   (multiple-value-bind (hash-lrl found) (gethash key hash)
88     (if (or (not found) (< lrl hash-lrl))
89         (setf (gethash key hash) lrl))))
90
91 ;; UMLS file and column structures
92 ;;; SQL datatypes symbols
93 ;;; sql-u - Unique identifier
94 ;;; sql-s - Small integer (16-bit)
95 ;;; sql-i - Integer (32-bit)
96 ;;; sql-l - Big integer (64-bit)
97 ;;; sql-f - Floating point
98 ;;; sql-c - Character data
99
100 (defparameter +col-datatypes+
101     '(("AV" sql-f) ("BTS" sql-i) ("CLS" sql-i) ("COF" sql-i) ("CUI1" sql-u)
102       ("AUI" sql-u) ("AUI1" sql-u) ("AUI2" sql-u) ("PCUI" sql-u)
103       ("PLUI" sql-u) ("PAUI" sql-u)
104       ("CUI2" sql-u) ("CUI" sql-u) ("CXN" sql-s) ("FR" sql-i) ("LRL" sql-s)
105       ("LUI" sql-u) ("MAX" sql-s) ("MIN" sql-s) ("RANK" sql-s) ("REF" sql-c)
106       ("RNK" sql-s) ("RWS" sql-i) ("SRL" sql-s) ("SUI" sql-u) ("TUI" sql-u)
107       ("MAPRANK" sql-s)
108       ;;; Custom columns
109       ("KCUISUI" sql-l) ("KCUILUI" sql-l) ("KCUILRL" sql-i) ("KLUILRL" sql-i)
110       ("KSUILRL" sql-i)
111       ("KSRL" sql-i) ("KLRL" sql-i)
112       ;;; LEX columns
113       ("EUI" sql-u) ("EUI2" sql-u)
114       ;;; Semantic net columns
115       ("UI" sql-u) ("UI2" sql-u) ("UI3" sql-u)
116       ;; New fields for 2002AD
117       ("RCUI" sql-u) ("VCUI" sql-u) ("CFR" sql-i) ("TFR" sql-i)
118       ;; New fields for 2004AA
119       ("MAPSETCUI" sql-u)
120       )
121     "SQL data types for each non-string column")
122
123 (defparameter +custom-tables+
124     nil
125   #+ignore
126   '(("KCON" "SELECT CUI,STR FROM MRCONSO WHERE STT='PF' AND TS='P' AND ISPREF='Y' AND LAT='ENG'"))
127   "Custom tables to create")
128
129 (defparameter +custom-cols+
130     '(#+nil ("MRCONSO.RRF" "KPFSTR" "TEXT"
131              (slot-value (find-ucol "STR" "MRCONSO.RRF") 'max)
132              (lambda (x) (pfstr-hash (parse-ui (nth 0 x)))))
133       ;; Set to 1 if term is prefered term for english
134       ("MRCONSO.RRF" "KPFENG" "TINYINT" 0
135        (lambda (x)  (if (and (string-equal (nth 1 x) "ENG") ; LAT
136                              (string-equal (nth 2 x) "P") ; ts
137                              (string-equal (nth 4 x) "PF")) ; stt
138                       "1"
139                       "0")))
140       ("MRCONSO.RRF" "KCUISUI" "BIGINT" 0
141        (lambda (x) (write-to-string (make-cuisui (parse-ui (nth 0 x)) (parse-ui (nth 5 x))))))
142       ("MRCONSO.RRF" "KCUILUI" "BIGINT" 0
143        (lambda (x) (write-to-string (make-cuilui (parse-ui (nth 0 x)) (parse-ui (nth 3 x))))))
144       ("MRCONSO.RRF" "KCUILRL" "SMALLINT" 0
145        (lambda (x) (write-to-string (lui-lrl (parse-ui (nth 0 x))))))
146       ("MRCONSO.RRF" "KLUILRL" "SMALLINT" 0
147        (lambda (x) (write-to-string (lui-lrl (parse-ui (nth 3 x))))))
148       ("MRCONSO.RRF" "KSUILRL" "SMALLINT" 0
149        (lambda (x) (write-to-string (sui-lrl (parse-ui (nth 5 x))))))
150       ("MRSTY.RRF" "KLRL" "SMALLINT" 0
151        (lambda (x) (write-to-string (cui-lrl (parse-ui (nth 0 x))))))
152       ("MRCOC.RRF" "KLRL" "SMALLINT" 0
153        (lambda (x) (write-to-string
154                     (max (cui-lrl (parse-ui (nth 0 x)))
155                          (kmrcl:aif (cui-lrl (parse-ui (nth 1 x))) kmrcl::it 0)))))
156       ("MRSAT.RRF" "KSRL" "SMALLINT" 0
157        (lambda (x) (write-to-string (sab-srl (nth 9 x)))))
158       ("MRREL.RRF" "KSRL" "SMALLINT" 0
159        (lambda (x) (write-to-string (sab-srl (nth 10 x)))))
160       ("MRRANK.RRF" "KSRL" "SMALLINT" 0
161        (lambda (x) (write-to-string (sab-srl (nth 1 x)))))
162       ("MRDEF.RRF" "KSRL" "SMALLINT" 0
163        (lambda (x) (write-to-string (sab-srl (nth 4 x)))))
164       #+nil  ("MRCXT.RRF" "KSRL" "SMALLINT" 0 (lambda (x) (write-to-string (sab-srl (nth 2 x)))))
165       ("MRXW_ENG.RRF" "KLRL" "SMALLINT" 0
166        (lambda (x) (write-to-string (cuisui-lrl (make-cuisui
167                                                  (parse-ui (nth 2 x))
168                                                  (parse-ui (nth 4 x)))))))
169       ("MRXW_NONENG.RRF" "KLRL" "SMALLINT" 0
170        (lambda (x) (write-to-string (cuisui-lrl (make-cuisui
171                                                  (parse-ui (nth 2 x))
172                                                  (parse-ui (nth 4 x)))))))
173       ("MRXNW_ENG.RRF" "KLRL" "SMALLINT" 0
174        (lambda (x) (write-to-string (cuisui-lrl (make-cuisui
175                                                  (parse-ui (nth 2 x))
176                                                  (parse-ui (nth 4 x)))))))
177       ("MRXNS_ENG.RRF" "KLRL" "SMALLINT" 0
178        (lambda (x) (write-to-string (cuisui-lrl (make-cuisui
179                                                  (parse-ui (nth 2 x))
180                                                  (parse-ui (nth 4 x)))))))
181
182       ;; FIXME: For MRREF and MRCOC, add lookups to KPFSTR2 using new MRCONSO index KPFENG
183
184       #+nil  ("MRREL.RRF" "KPFSTR2" "TEXT" 1024 (lambda (x) (pfstr-hash (parse-ui (nth 4 x)))))
185       #+nil  ("MRCOC.RRF" "KPFSTR2" "TEXT" 1024 (lambda (x) (pfstr-hash (parse-ui (nth 2 x)))))
186       #+use-mrctx  ("MRCXT.RRF" "KCUISUI" "BIGINT" 0 (lambda (x) (write-to-string (make-cuisui (parse-ui (nth 0 x)) (parse-ui (nth 1 x))))))
187       ("MRSAT.RRF" "KCUILUI" "BIGINT" 0
188        (lambda (x) (write-to-string (make-cuilui (parse-ui (nth 0 x)) (parse-ui (nth 1 x))))))
189       ("MRSAT.RRF" "KCUISUI" "BIGINT" 0
190        (lambda (x) (write-to-string (make-cuisui (parse-ui (nth 0 x)) (parse-ui (nth 2 x))))))
191       ("MRXW_ENG.RRF" "KCUISUI" "BIGINT" 0
192        (lambda (x) (write-to-string (make-cuisui (parse-ui (nth 2 x)) (parse-ui (nth 4 x))))))
193       ("MRXNW_ENG.RRF" "KCUISUI" "BIGINT" 0
194        (lambda (x) (write-to-string (make-cuisui (parse-ui (nth 2 x)) (parse-ui (nth 4 x))))))
195       ("MRXNS_ENG.RRF" "KCUISUI" "BIGINT" 0
196        (lambda (x) (write-to-string (make-cuisui (parse-ui (nth 2 x)) (parse-ui (nth 4 x))))))
197       ("MRXW_NONENG.RRF" "LAT" "VARCHAR" 3 (lambda (x) (nth 0 x)))
198       ("MRXW_NONENG.RRF" "WD"  "VARCHAR" 200  (lambda (x) (nth 1 x)))
199       ("MRXW_NONENG.RRF" "CUI" "INTEGER" 0 (lambda (x) (write-to-string (parse-ui (nth 2 x)))))
200       ("MRXW_NONENG.RRF" "LUI" "INTEGER" 0 (lambda (x) (write-to-string (parse-ui (nth 3 x)))))
201       ("MRXW_NONENG.RRF" "SUI" "INTEGER" 0 (lambda (x) (write-to-string (parse-ui (nth 4 x)))))
202       ("MRXW_NONENG.RRF" "KCUISUI" "BIGINT" 0
203        (lambda (x) (write-to-string (make-cuisui (parse-ui (nth 2 x)) (parse-ui (nth 4 x)))))))
204   "Custom columns to create.(filename, col, sqltype, value-func).")
205
206 (defparameter +index-cols+
207     '(("CUI1" "MRCOC") ("CUI" "MRCONSO") ("LUI" "MRCONSO")
208       ("SRL" "MRCONSO") ("AUI" "MRCONSO") ("KPFENG" "MRCONSO")
209       ("SUI" "MRCONSO") ("CUI" "MRDEF")
210       ("CUI1" "MRREL") ("CUI" "MRSAT") ("LUI" "MRSAT") ("SUI" "MRSAT")
211       ("CUI" "MRSTY")
212       ("TUI" "MRSTY") ("CUI" "MRXNS_ENG")
213       ;; ("CUI" "MRCXT") ("KCUISUI" "MRCXT") ("KSRL" "MRCXT")
214       ("AUI" "MRHIER") ("PTR" "MRHIER") ("CUI" "MRHIER") ("CXN" "MRHIER") ("RELA" "MRHIER") ("PAUI" "MRHIER")
215       ("SAB" "MRHIER")
216       #+ignore ("NSTR" "MRXNS_ENG" 10)
217       ("CUI" "MRXNW_ENG") ("NWD" "MRXNW_ENG") ("WD" "MRXW_ENG")
218       ("KCUISUI" "MRCONSO") ("KCUILUI" "MRCONSO") ("KCUILRL" "MRCONSO")
219       ("KLUILRL" "MRCONSO")
220       ("KCUISUI" "MRSAT")  ("KCUILUI" "MRSAT")
221       ("KCUISUI" "MRXW_ENG") ("KCUISUI" "MRXNW_ENG")
222       ("KCUISUI" "MRXNS_ENG") ("KCUISUI" "MRXW_NONENG")
223       ("KSRL" "MRDEF") ("KSRL" "MRRANK")
224       ("KSRL" "MRREL") ("KSRL" "MRSAT") ("KLRL" "MRCOC")
225       ("KLRL" "MRSTY") ("KLRL" "MRXW_ENG") ("KLRL" "MRXNW_ENG")
226       ("KLRL" "MRXNS_ENG") ("KLRL" "MRXW_NONENG")
227       ;; LEX indices
228       ("EUI" "LRABR") ("EUI2" "LRABR") ("EUI" "LRAGR") ("EUI" "LRCMP") ("EUI" "LRMOD")
229       ("EUI" "LRNOM") ("EUI2" "LRNOM") ("EUI" "LRPRN") ("EUI" "LRPRP") ("EUI" "LRSPL")
230       ("EUI" "LRTRM") ("EUI" "LRTYP") ("EUI" "LRWD") ("WRD" "LRWD")
231       ("BAS" "LRABR")
232       ;; Semantic NET indices
233       ("UI" "SRSTRE1") ("UI2" "SRSTRE1") ("UI3" "SRSTRE1")
234       ("STY_RL" "SRDEF") ("RT" "SRDEF") ("STY_RL" "SRSTR") ("STY_RL2" "SRSTR")
235       ("RL" "SRSTR")
236
237       ("SRL" "MRSAB") ("RSAB" "MRSAB") ("VSAB" "MRSAB") ("RCUI" "MRSAB")
238       ("VCUI" "MRSAB") ("LAT" "MRSAB") ("MAPSETCUI" "MRMAP")  ("MAPSETCUI" "MRSMAP")
239       ("CUI" "MRHIER"))
240   "Columns in files to index")
241
242
243 (defparameter +custom-index-cols+
244   nil
245   #+ignore
246   '(("CUI" "KCON") ("LRL" "KCON"))
247   "Indexes to custom tables")
248
249 ;; File & Column functions
250
251 (defun gen-ucols ()
252   (add-ucols (gen-ucols-meta))
253   (add-ucols (gen-ucols-custom))
254   (add-ucols (gen-ucols-generic "LRFLD"))
255   (add-ucols (gen-ucols-generic "SRFLD")))
256
257 (defun gen-ucols-meta ()
258 "Initialize all umls columns"
259   (let ((cols '()))
260     (with-umls-file (line "MRCOLS.RRF")
261       (destructuring-bind (col des ref min av max fil dty) line
262         (push (make-ucol col des ref (parse-integer min) (read-from-string av)
263                          (parse-integer max) fil dty)
264               cols)))
265     (nreverse cols)))
266
267 (defun gen-ucols-custom ()
268 "Initialize umls columns for custom columns"
269   (loop for customcol in +custom-cols+
270         collect
271         (make-ucol (nth 1 customcol) "" 0 0 0 (eval (nth 3 customcol))
272                    (nth 0 customcol) nil :sqltype (canonicalize-column-type (nth 2 customcol))
273                    :custom-value-fun (nth 4 customcol))))
274
275 (defun gen-ucols-generic (col-filename)
276 "Initialize for generic (LEX/NET) columns"
277   (let ((cols '()))
278     (with-umls-file (line col-filename)
279       (destructuring-bind (nam des ref fil) line
280         (setq nam (escape-column-name nam))
281         (dolist (file (delimited-string-to-list fil #\,))
282           (push
283            (make-ucol nam des ref nil nil nil file nil)
284            cols))))
285     (nreverse cols)))
286
287
288 (defun gen-ufiles ()
289   (add-ufiles (gen-ufiles-generic "MRFILES.RRF" "META"))
290   (add-ufiles (gen-ufiles-generic "LRFIL" "LEX"))
291   (add-ufiles (gen-ufiles-generic "SRFIL" "NET"))
292   ;; needs to come last
293   (add-ufiles (gen-ufiles-custom)))
294
295
296 (defun gen-ufiles-generic (files-filename dir)
297 "Initialize all LEX file structures"
298   (let ((files '()))
299     (with-umls-file (line files-filename)
300       (destructuring-bind (fil des fmt cls rws bts) line
301         (push (make-ufile
302                dir fil des
303                (parse-integer cls)
304                (parse-integer rws) (parse-integer bts)
305                (concatenate 'list (umls-field-string-to-list fmt)
306                             (custom-colnames-for-filename fil)))
307               files)))
308     (nreverse files)))
309
310 (defun gen-ufiles-custom ()
311   (make-ufile "META" "MRXW_NONENG.RRF" "Custom NonEnglish Index"
312               5 0 0 (fields (find-ufile "MRXW_ENG.RRF"))))
313
314
315