2 ;;; Copyright (c) 2008, by A.J. Rossini <blindglobe@gmail.com>
3 ;;; See COPYRIGHT file for any additional restrictions (BSD license).
4 ;;; Since 1991, ANSI was finally finished. Edited for ANSI Common Lisp.
6 ;;; Time-stamp: <2009-12-21 12:58:29 tony>
7 ;;; Creation: <2008-09-03 08:10:00 tony>
9 ;;; Author: AJ Rossini <blindglobe@gmail.com>
10 ;;; Copyright: (c)2007--2009, AJ Rossini. GPLv2
11 ;;; Purpose: base structures for importing data into CLS
13 ;;; What is this talk of 'release'? Klingons do not make software
14 ;;; 'releases'. Our software 'escapes', leaving a bloody trail of
15 ;;; designers and quality assurance people in its wake.
17 (in-package :cls-data
)
21 ;; We can read 2 types of data -- those which are non-lisp-native
22 ;; data, and those which are lisp-native (lisp-enabled, an extension
23 ;; of lisp-serialized, i.e. data as program as data thingy's).
25 ;; of the non-native, there could be raw sources (ascii file formats),
26 ;; xml sources (xml -> lisp, possible with some preprocessing.
28 ;;; Reading from DSV files:
30 ;;; consider either the cybertyggyr-dsv package, or the rsm.string
31 ;;; package. Decision: RSM.STRING
32 ;;; The latter seems to actually work a bit at what we need to
33 ;;; acccomplish, is better licensed (i.e. BSD-style) and is now
34 ;;; implemented through filename.dsv->dataframe
36 (defparameter *lisp-stat-data-external-source-formats
*
37 '(dsv xml
;; ex of text-based (UTF, ASCII, or similar) formats
38 sql
;; ex of RDBMS call
39 fcs affy
)) ;; ex of binary formats
41 (defparameter *lisp-stat-data-import-referencing-type
*
42 '(lisp-data-structure reference lisp-function
))
44 (defgeneric data-import
(source source-format referencing-type
)
45 (:documentation
"read data from stream srce, in format srce-frmt;
46 return a reftype, which could be a
47 lisp-data-structure, a reference to such, or a lisp
48 function which can be evaluated to generate
51 (defgeneric data-export
(data target-format target-referencing-type
)
52 (:documentation
"write data from stream srce, in format srce-frmt;
53 return a reftype, which could be a
54 lisp-data-structure, a reference to such, or a lisp
55 function which can be evaluated to generate
59 ;;; Related to data file reading
62 (defun count-file-columns (fname)
64 Returns the number of lisp items on the first nonblank line of file FNAME."
65 (with-open-file (f fname
)
67 (let ((line (do ((line (read-line f
) (read-line f
)))
68 ((or (null line
) (< 0 (length line
))) line
))))
70 (with-input-from-string (s line
)
71 (do ((n 0 (+ n
1)) (eof (gensym)))
72 ((eq eof
(read s nil eof
)) n
))))))))
74 (if (not (fboundp 'open-file-dialog
))
76 (defun open-file-dialog () ;; why?(&optional set)
77 (get-string-dialog "Enter a data file name:"))
79 (defun open-file-dialog () ;; why? (&optional set)
80 (error "You must provide a file name explicitly")))
83 ;;; General modification approaches.
85 (defgeneric importData
(source featureList
)
86 (:documentation
"command to get data into CLS. Specific methods
87 will need to handle pathnames, internal data structures, and
88 external services such as DBMS's. We would like to be able to do
90 (importData MyPathName '(:formattype 'csvString))
91 (importData '(sqlConnection :server host.domain.net :port 666)
96 (defun pathname-example (name)
97 (let ((my-path (parse-namestring name
)))
98 (values (pathname-name my-path
:case
:common
)
99 (pathname-name my-path
:case
:local
))))
101 (defvar sourceTypes
(list 'csv
'lisp
'tsv
'special
)
102 "list of possible symbols.
104 Thsees are used to specify source formats that might be supported for
105 input. CSV and TSV are standard, LISP refers to forms, and SPECIAL
106 refers to a FUNCTION which parses as appropriately.")
110 (defmethod importData ((fileHandle pathname
)
111 (fmt list
)) ;sourceTypes))
112 "File-based input for data.
114 (importData (parse-namestring 'path/to/file')
117 (importData myPathName (list :format 'lisp))
119 (let* ((fmtType (getf fmt
:format
))
120 (newData (getDataAsLists fileHandle fmtType
)))
125 ('special
(let ((parserFcn (getf fmt
:special-parser
)))))
126 (:default
(error "no standard default importData format")))))
129 (defmethod importData ((ds array
) (fmt list
))
130 "mapping arrays into CLS data.")
133 (defmethod importData ((dsSpec DBMSandSQLextract
)
135 "mapping DBMS into CLS data.")
141 (defun filename.dsv-
>dataframe
(filename &optional
144 (docstring "This is an amusing dataframe array")
145 (arraystorage-object 'dataframe-array
))
146 "Reads the DSV file FILENAME and returns a dataframe-array object.
147 By default, the delimiter is a ',' which can be changed.
148 FIXME: could read first 2 lines, and logically guess if the first is variable name or not."
149 (let ((csv-file-data (rsm.string
:file-
>number-table
152 (let ((var-name-list (if varnameheader
154 (make-labels "V" (length (car csv-file-data
)))))
155 (data-list (listoflist:listoflist-
>array
(cdr csv-file-data
))))
156 (make-instance arraystorage-object
; 'dataframe-array, but all DF-likes have the following attrs
158 :var-labels var-name-list