source: trunk/bindings/swig/nxinter.tex @ 1822

Revision 211, 15.6 KB checked in by nexus, 9 years ago (diff)
  • Fixed a bug which caused foreign HDF-5's not to be read properly
  • Fixed a bug in NXgetnextentry which prevented reinitialising searches and nested searches.
  • Adapted the jnexus stuff to NAPI-2.0
  • Added the swig interface to NeXus to the source tree
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1\documentclass[12pt,a4paper]{article}
2%%\usepackage[dvips]{graphics}
3%%\usepackage{epsf}
4\setlength{\textheight}{24cm}
5\setlength{\textwidth}{16cm}
6\setlength{\headheight}{0cm}
7\setlength{\headsep}{0cm}
8\setlength{\topmargin}{0cm}
9\setlength{\oddsidemargin}{0cm}
10\setlength{\evensidemargin}{0cm}
11\setlength{\hoffset}{0cm}
12\setlength{\marginparwidth}{0cm}
13
14\begin{document}
15
16\begin{center}
17{\large NeXus--SWIG Interface}\\
18Mark Koennecke\\
19Laboratory for Neutron Scattering\\
20Paul Scherrer Institute\\
21CH--5232 Villigen--PSI\\
22Switzerland\\
23Mark.Koennecke@psi.ch\\
24November 2002\\
25\end{center}
26
27
28\section{Introduction}
29This is a description of the SWIG interface to the NeXus--API. NeXus
30is a proposal for a common data format for synchrotron and neutron
31diffraction data. NeXus uses HDF, the Hierachical Data Format, from
32the National Center for Super Computing Applications (NCSA) as its
33physical file format. NeXus files are accessed through a NeXus--API
34which sits between application programs and the HDF--libraries and
35then the files themselves. For more information on NeXus see:\\
36\centerline{http://lns00.psi.ch/NeXus}
37
38SWIG is the Simplified Wrapper and Interface Generator. This is a
39software tool which creates the necessary wrapper code needed to access a
40given ANSI--C or C++ library  from a variety of scripting languages
41including: Tcl, Java, Perl, Phyton, scheme etc. For more information
42about SWIG see:\\
43\centerline{http://www.swig.org}
44
45This now is the description of the SWIG interface to the
46NeXus--API. This document is intended for users who are familiar with
47the NeXus--API. The meaning of the functions is the same as for the
48ANSI--C NeXus--API, only function signatures may have changed. Please
49refer to the NeXus--API documentation for further reference.
50
51
52\section{General Remarks}
53When interfacing an API like NeXus to a scripting language
54a couple of issues have to be handled:
55\begin{description}
56\item[pointers] The NeXus--API uses pointers extensively. Fortunately
57SWIG provides a means for encapsulating pointers in a script language.
58\item[memory management] Most scripting language have some kind of
59automatic variable management or garbage collection. Interfaces
60generated with SWIG however still use the C memory management. This
61imples that if you call C--routines which allocate memory you should
62not forget to free the memory again after you are done. Otherwise you
63may end up with a system out of memory due to memory leakage.
64\item[datasets] NeXus works on possibly large datasets which may have
65different number types. Support for handling large arrays misses in
66many scripting languages. Therefore this interface system provides its
67own implementation of datasets.
68\item[return values] Some functions of the NeXus--API return more then
69one value through the call by reference mechanism. These functions had
70to be wrapped such that all necessary return values are passed back
71into the scripting language.
72\end{description} 
73
74Necessarily the generated interface will look slightly different in
75each target scripting language. For instance the constant NXACC\_READ
76is referred to as:
77\begin{verbatim}
78$NXACC_READ
79\end{verbatim} in Tcl. In scheme this looks like:
80\begin{verbatim}
81(nxacc-read)
82\end{verbatim} 
83Functions also follow the calling conventions of the target
84language. An example in Tcl and scheme:
85\begin{description}
86\item[Tcl] \verb+ set fd [nx_open ``nxinter.hdf'' $NXACC\_READ] +
87\item[mzScheme] (define fd (nx-open ``nxinter.hdf'' (nxacc-read)))
88\end{description}
89The actual mapping generated for a target scripting language by SWIG
90can be found by studying SWIG's documentation or through browsing the
91generated wrapper file for your interface. All examples in the
92reference below are given in Tcl syntax.
93
94SWIG goes a long way to help in the creation of scripting language
95interfaces. The user still has to master the process of compiling and
96linking a scripting language extension and loading it into the target
97interpreter. Examples for this are provided in the SWIG package. 
98
99
100\section{The Dataset Interface}
101The dataset interface brings multidimensional datasets  to the
102scripting language. This is necessary because many scripting languages
103do not have a good support for multi dimensional arrays of numbers.
104If a scripting language supports
105multidimensional  arrays, another extension could be written which
106transfers such data efficiently, either directly from the NeXus file
107or using the NeXus dataset as an intermediary.
108Currently no such optimisations are provided. 
109
110There usually is a number type associated with a NeXus dataset. In
111order to save effort and for simplification the NeXus number types
112were used. The names are self explaining, if more information about
113the meaning of these types is required, please consult the NeXus
114documentation. The types provided are (in Tcl syntax):
115\begin{verbatim} 
116$NX_FLOAT32
117$NX_FLOAT64
118$NX_INT8 
119$NX_UINT8   
120$NX_INT16
121$NX_UINT16
122$NX_INT32
123$NX_UINT32
124$NX_CHAR
125\end{verbatim}
126
127For notational convenience a symbol {\bf nxdsPtr} is now
128introduced. This symbol stands for a pointer to a NeXus dataset
129wrapped according to the scripting languages conventions. 
130
131
132The dataset interface consists of the following functions. Tcl syntax
133is assumed for this description.
134
135{\bf nxdsPtr create\_nxds rank type dim0 dim1 dim2 dim3 dim4 dim5 dim6}
136creates a NeXus dataset with the specified rank and type and the
137dimensions given as dim0 - dim6. If you do not need so many
138dimensions, leave the surplus ones out, this sytem will replace the
139values with zeros. The interface can be easily extended to support
140more then 7 dimensions if required. 
141
142{\bf nxdsPtr create\_text\_nxds textdata} convenience function which
143wraps textdata into a NeXus dataset.
144
145{\bf drop\_nxds nxdsPtr} use this function to dispose of datasets which
146are no longer needed.  Do this, otherwise memory leaks occur!
147
148
149{\bf get\_nxds\_rank nxdsPtr} returns the rank of the dataset.
150
151{\bf get\_nxds\_type nxdsPtr} returns the data type of the datset as an
152integer.
153
154{\bf get\_nxds\_dim nxdsPtr which} returns the dimension of the dataset
155in dimension which.
156
157{\bf get\_nxds\_value nxdsPtr  dim0 dim1 dim2 dim3 dim4 dim5 dim6}
158returns  the value of the dataset at the index specified by dim0 -
159dim6. Again, leave out unneccessary indexes.
160
161{\bf get\_nxds\_text nxdsPtr} convenience function which returns the
162content of the dataset as a text string. his works only if the dataset
163has rank 1 and is of type NX\_CHAR, NX\_INT8 or NX\_UINT8.
164
165{\bf put\_nxds\_value nxdsPtr val dim0 dim1 dim2 dim3 dim4 dim5 dim6}
166sets the value of the dataset at the cell denoted by dim0 -dim6 to the
167value val. Again, you may omit surplu indexes.
168
169                   
170\section{The NeXus--API Interface}
171
172\subsection{Notation}
173After opening them, NeXus files are referred to through a
174handle. This handle is denoted through the symbol {nxFil} in the next
175sections.
176
177There is another symbol {\bf nxSuccess} which stands for an
178integer. This is 1 if the function returned with success and 0 in case
179of a failure. If a function returns a pointer, failure is indicated
180through the NULL pointer. The encoding of the NULL pointer varies
181between scripting languages.
182
183
184\subsection{Error Handling}
185Most NeXus-API functions return 1 on success and 0 in case of an
186error. The exception are those functions which return a pointer. These
187return a NULL pointer in case of an error. In each case more
188information about the problem can be obtained by calling:
189{\bf nx\_getlasterror} This call returns a string describing the last
190NeXus error found.
191
192\subsection{File Creation accessCode Constants}
193The meanings of the constants are as described in the NeXus--API
194documentation.
195\begin{verbatim}
196$NXACC_READ
197$NXACC_RDWR
198$NXACC_CREATE
199$NXACC_CREATE4
200$NXACC_CREATE5
201\end{verbatim}
202
203
204
205\subsection{Opening and Closing of Files} 
206{nxFil nx\_open filename accessCode} opens the NeXus file filename. The
207accessCodes must be one of the constants given above. Returns a new
208handle in the case of a success, NULL in case of failure.
209
210{\bf nxFil nx\_flush nxFil} flushes a NeXus file.
211
212{\bf nx\_close nxFil} closes a NeXus file, The handle nxFil is useless
213after this. his call is necessary, especially when writing files.
214
215
216\subsection{Group Operations}
217{\bf nxSuccess nx\_makegroup nxFil name nxclass}
218
219{\bf nxSuccess nx\_opengroup nxFil name nxclass}
220
221{\bf nxSuccess nx\_closegroup nxFil}
222
223{\bf nxMulti nx\_getnextentry nxFil separatorChar} performs group
224directory searches. nxMulti is a string containing name and NeXus
225class of the group item separated by the character given as
226separatorChar. If the search ends, NULL is returned. 
227
228{\bf nxSuccess nx\_initgroupdir nxFil}
229 
230{nxPtr nx\_getgroupID nxFil} returns a pointer to a structure needed
231for linking.
232
233
234\subsection{Dataset Handling}
235
236{\bf nxSuccess nx\_makedata nxFil  name rank type dimDs}
237makes a new dataset. The dimensions are described through the NeXus
238dataset dimDs.
239 
240{\bf nxSuccess nx\_compmakedata nxFil  name rank type dimDs bufds}
241as above, but for compressed datasets. The HDF--5 buffering size is
242specified through the NeXus dataset bufDs.
243
244{\bf nx\_opendata nxFil name}
245
246{\bf nx\_closedata nxFil}
247
248{\bf nx\_putslab nxFil nxdsPtr  startDs}  slabbed data writing. The
249data comes from the NeXus dataset nxdsPtr. The start point from the
250NeXus dataset startDS. The size of the dataset to write is the size of
251nxdsPtr. 
252
253{\bf nxdsPtr nx\_getslab nxFil startDs sizeDs} reads a slab. startDS
254and sizeDs are two NeXus datasets describing the slab to read. The
255data is returned as a NeXus dataset. Do not forget to drop this
256dataset once you are done with the data!
257
258{\bf nxdsPtr nx\_getds nxFil} reads dataset name. This convenience
259function opens the dataset, allocates a NeXus dataset of appropriate
260type and size for you and closes the SDS again.
261
262{\bf nxSuccess nx\_putds nxFil  name nxdsPtr} writes the dataset
263nxdsPtr to the file as name at the current position in the
264hierarchy. Same convenience fatures as above.
265
266{\bf nxdsPtr nx\_getdata nxFil} normal NeXus getdata but returns a
267NeXus dataset.
268
269{\bf nxSuccess nx\_putdata nxFil nxdsPtr} normal NeXus putdata. Data is
270taken from the NeXus dataset nxdsPtr.
271
272{\bf nxdsPtr nx\_getinfo nxFil} returns the current datasets type, rank
273and dimensions in a one dimensional NeXus dataset.
274
275{\bf ptr nx\_getdataID nxFil} retrieves link pointer for linking.
276
277\subsection{Attributes}
278{\bf nxText nx\_getnextattr nxFil  separatorChar}reads the next entry
279of attribute directory. nxText then contains then name, length and
280type of the attribute formatted as a string and separated by the
281character separatorChar.
282
283{\bf nxSuccess nx\_putattr nxFil name nxdsPtr} writes an attribute name
284from the NeXus dataset nxdsPtr.
285
286{\bf nxdsPtr nx\_getattr nxFil name type length} reads an attribute
287into a dataset. The data type and the length of the attribute have to
288specified.
289
290\subsection{Making Links}
291{bf nxSuccess nx\_makelink nxFil nxLink}  makes a link. nxLink is one
292of the pointers returned from the nx\_getgroupID or nx\_getdataID
293functions.
294
295\section{Example}
296As an example for the usage of the API see the API test program
297documented below:
298\begin{verbatim}
299#-------------------------------------------------------------------------
300# Test program for the nxinter interface. Also example usage.
301#
302# copyright: GPL
303#
304# Mark Koennecke, October 2002
305#------------------------------------------------------------------------
306
307#load ./nxinter.so
308
309#------------- testing dataset interface
310set ds [create_nxds 2 $NX_FLOAT32 3 3]
311
312put_nxds_value $ds 1 0 0
313put_nxds_value $ds 1 1 1
314put_nxds_value $ds 1 2 2
315
316puts stdout "Testing dataset interface "
317puts stdout [format "rank = %d" [get_nxds_rank $ds]]
318puts stdout [format "type = %d" [get_nxds_type $ds]]
319puts stdout [format "dim1 = %d" [get_nxds_dim $ds 1]]
320
321proc printDS {ds} {
322for {set i 0} {$i < 3} {incr i} {
323    puts stdout " "
324    for {set j 0} {$j < 3} {incr j} {
325        puts -nonewline stdout [format " %f" [get_nxds_value $ds $i $j]]
326    }
327}
328puts stdout "     "
329}
330
331printDS $ds
332puts stdout "Hmmmmmmmhhh....... seems OK"
333
334#-------------- prepare a dimension dataset 
335set dimds [create_nxds 1 $NX_INT32 2]
336put_nxds_value $dimds 3 0
337put_nxds_value $dimds 3 1
338
339#--------- prepare slabbing slabber dimensions
340set start [create_nxds 1 $NX_INT32 2]
341put_nxds_value $start 0 0
342put_nxds_value $start 0 1
343
344
345#----------------------------------- write tests
346puts stdout "Testing writing ..........."
347
348set fd [nx_open "nxinter.hdf" $NXACC_CREATE5]
349puts stdout [format "Opening file worked: %s" $fd]
350
351#---------- write an attribute.....
352set tds [create_text_nxds "Rosa Waschmaschinen sind hip"]
353puts stdout [format "Writing SuperDuper = %s" [get_nxds_text $tds]]
354puts stdout [format "Writing attribute results in: %d " \
355        [nx_putattr $fd "SuperDuper" $tds]]
356drop_nxds $tds
357
358#----------- making groups....
359set status [nx_makegroup $fd fish NXentry]
360if {$status == 1} {
361    puts stdout "Creating vGroup worked"
362}
363
364set status [nx_opengroup $fd fish NXentry]
365if {$status == 1} {
366    puts stdout "Opening vGroup worked"
367}
368
369set lnk [nx_getgroupID $fd]
370puts stdout [format "groupID determined to: %s" $lnk]
371
372#------------ writing tata
373puts stdout "Test Writing data....."
374puts stdout [nx_makedata $fd "fish" 2 $NX_FLOAT32 $dimds]
375puts stdout [nx_opendata $fd "fish"]
376puts stdout [nx_putdata $fd $ds]
377set lnk [nx_getdataID $fd]
378puts stdout $lnk
379puts stdout [nx_closedata $fd]
380
381#--------------- testing slabbed tata writing
382puts stdout "Testing  writing in slabs"
383put_nxds_value $dimds 6 0
384puts stdout [format "Dimensions for slab test: %f, %f"  \
385        [get_nxds_value $dimds 0] [get_nxds_value $dimds 1]]
386 
387puts stdout [nx_makedata $fd "fish2" 2 $NX_FLOAT32 $dimds]
388puts stdout [nx_opendata $fd "fish2"]
389puts stdout [nx_putslab  $fd $ds $start]
390put_nxds_value $start 3 0
391puts stdout [nx_putslab  $fd $ds $start]
392puts stdout [nx_closedata $fd]
393puts stdout "Finished Writing Slabs........."
394
395puts stdout [format "Linking = %d" [nx_makelink $fd $lnk]]
396
397set status [nx_closegroup $fd]
398if {$status == 1} {
399    puts stdout "Closing vGroup worked"
400}
401
402
403nx_close $fd
404puts stdout "Closed file"
405#---------------- finished writing tests
406
407
408#---------------- trying to read
409puts stdout "Testing Reading files"
410
411set fd [nx_open "nxinter.hdf" $NXACC_READ]
412puts stdout "Opening file for reading worked"
413
414set run 1
415
416#----------------- printing group content
417puts stdout "Group directory listing"
418while {$run == 1} {
419    set entry [nx_getnextentry $fd / ]
420    if { [string length $entry] < 2 } {
421        set run 0
422    } else {
423        puts stdout $entry
424    }
425}
426#--------- printing attributes
427puts stdout "Attributes"
428set run 1
429while {$run == 1} {
430    set entry [nx_getnextattr $fd / ]
431    puts stdout $entry
432    if { [string length $entry] < 2 } {
433        set run 0
434    } 
435}
436
437set rds [nx_getattr $fd "SuperDuper" $NX_CHAR 30]
438puts stdout $rds
439if {[string compare $rds NULL] != 0} {
440    puts stdout [format "SuperDuper = %s" [get_nxds_text $rds]]
441}
442drop_nxds $rds
443
444#---------------- reading tata
445puts stdout [nx_opengroup $fd fish NXentry]
446puts stdout [nx_opendata $fd "fish"]
447set rds [nx_getdata $fd]
448puts stdout $rds
449
450puts stdout "Read data should be a 3x3 unity matrix"
451printDS $rds
452
453puts stdout [nx_closedata $fd]
454
455#----------- reading slabbed data
456puts stdout "Testing slabbed reading......"
457puts stdout [nx_opendata $fd "fish2"]
458set ids [nx_getinfo $fd]
459puts stdout [format "fish2: type %f, rank %f, d1 %f, d2 %f" \
460        [get_nxds_value $ids 0] [get_nxds_value $ids 1] \
461        [get_nxds_value $ids 2] [get_nxds_value $ids 3]]
462drop_nxds $ids
463
464put_nxds_value $dimds 3 0
465set r1 [nx_getslab $fd $start $dimds]
466printDS $r1
467put_nxds_value $start 0 0
468set r2 [nx_getslab $fd $start $dimds]
469printDS $r2
470puts stdout [nx_closedata $fd]
471
472puts stdout [nx_closegroup $fd]
473puts stdout [nx_close $fd]
474
475#--------------- dropping datasets: do not forget!!!
476drop_nxds $ds
477drop_nxds $rds
478drop_nxds $dimds
479\end{verbatim}
480\end{document}
Note: See TracBrowser for help on using the repository browser.