\documentclass{article}

\usepackage{graphicx}
\usepackage{fancyhdr}

\makeindex{}

\makeatletter
\textheight 625pt
\textwidth 460pt
\oddsidemargin 0pt
\evensidemargin 0pt
\marginparwidth 50pt
\topmargin 0pt
\brokenpenalty=10000

\newcommand{\ie} {{\em i.e.}}
\newcommand{\eg} {{\em e.g.}}
\newcommand{\cf} {cf.}

\newcommand{\gildas}    {\mbox {\bf GILDAS}}
\newcommand{\sic}       {\mbox {\bf SIC}}
\newcommand{\greg}      {\mbox {\bf GREG}}
\newcommand{\otfcal}    {\mbox {\bf OTFCAL}}
\newcommand{\mira}      {\mbox {\bf MIRA}}
\newcommand{\class}     {\mbox {\bf CLASS}}

\newcommand{\analyse}{\texttt{ANALYSE}}
\newcommand{\fit}{\texttt{FIT}}
\newcommand{\fort}{\texttt{F90}}
\newcommand{\plait}{\texttt{PLAIT}}

% Makes fancy headings and footers.
\pagestyle{fancy}

\fancyhf{} % Clears all fields.

\lhead{\scshape \class{} User Section}
\rhead{\scshape \nouppercase{\rightmark}}   %
\fancyfoot[C]{\bfseries \thepage{}}

\renewcommand{\headrulewidth}{0pt}    %
\renewcommand{\footrulewidth}{0pt}    %

\renewcommand{\sectionmark}[1]{%
  \markright{\thesection. \MakeLowercase{#1}}}
\renewcommand{\subsectionmark}[1]{}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}

\title{IRAM Memo 2011-3\\[3\bigskipamount]
  \class{} User Section}
\author{S. Bardeau$^1$, J. Pety$^{1,2}$, S. Guilloteau$^3$\\[0.5cm]
  1. IRAM (Grenoble) \\
  2. LERMA, Observatoire de Paris\\
  3. LAB, Observatoire de Bordeaux}
\date{April, 27$^{th}$ 2015\\
  Version 1.2}

\maketitle

\begin{abstract}
  \class{} is a state-of-the-art
  \gildas{}\footnote{\texttt{http://www.iram.fr/GILDAS}} software for
  reduction and analysis of (sub)--millimeter spectroscopic data.  Up to
  now, the \class{} data format could only describe a predetermined number
  of parameters in the observation headers, these parameters being grouped
  in 17 \emph{sections} (\eg{} the general, spectroscopic or calibration
  sections). However, the possibility to add telescope-specific information
  to the \class{} data format was requested several time. Instead of
  introducing a per-telescope specific and fixed section, we thus decided
  to introduce a new flexible section, named \emph{User Section}.  This
  document describes the functionalities available to the end-users as well
  as the implementation steps which must be developed by the section owner.\\

  Revisions:
  \begin{itemize}
    \item 1.0 (06-jul-2011): first release
    \item 1.1 (15-may-2013): added hook to command {\tt FIND}
    \item 1.2 (27-apr-2015): added support for 2D arrays
  \end{itemize}
\end{abstract}

\newpage{}
\tableofcontents{}

\newpage{}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Basic description and functionalities}

A user section is now part of the \class{} data format. It can be
added to the observations by any external program which is linked with
the \class{} library and which uses the \class{} API.

The user section is composed of a basic owner and data descriptor, and
of a data block. The content and length of the data is controlled by
the section owner, but for a few restrictions described in this
document. The data block is untyped, which means that the standard
\class{} program is not able to understand it natively. Only its owner
is able to do so with the appropriate decoding routines. On the other
hand, the standard \class{} program is able to detect, load and
propagate the User Section when possible. \class{} can also find all
the observations containing a user section. However, users and
programmers should be aware that there are \class{} operations under
which the user section loose its meaning (for example {\tt
AVERAGE}'ing). These operations thus do not propagate the user
function.

More precisely, the User Section can store several user
\emph{subsections}.  Each of these is identified by a unique
\emph{owner} and \emph{title} pair of values. The \class{} library
will properly read and write in the correct subsection as long as the
program has declared properly which one it owns. Each subsection has
its own version number to enable the evolution of the data format
(Note that abuse of the versioning mechanism may slow down operations
on this section).

We also provide code hooks which enable external programs to work on
the user sections when a few usual \class{} commands are called. These
commands are {\tt WRITE}, {\tt GET}, {\tt DUMP}, {\tt SET VARIABLE
USER}, {\tt FIND}.

\section{Adding a user subsection to an observation}

In order to add a new user subsection to an observation, the external
program has first to define a Fortran derived type containing the
data. Scalar, 1D, or 2D-array values of types {\tt INTEGER(4)}, {\tt
  REAL(4)} and {\tt REAL(8)} are supported. Scalar {\tt
  CHARACTER(LEN=*)} strings are also supported, but their length must
be a multiple of 4.
% , else it
% will be truncated to the lower multiple of 4 with a warning when
% trying to add this kind of data to the User Section.
The component names, their number, and their order is defined by the
programmer. The derived type used by the external program does not
need to have a Fortran {\tt sequence} statement: the way its elements
are ordered in memory is also free.\\

The external program can add its user section to an observation in 3
steps:
\begin{enumerate}
\item tell \class{} which subsection it owns thanks to the subroutine
      {\tt class\_user\_owner},
\item declare with {\tt class\_user\_toclass} the subroutine which
      knows how to order and transfer to \class{} the user data,
\item finally send the data to \class{} with the subroutine {\tt
      class\_user\_add} (for a new user subsection) or {\tt
      class\_user\_update} (if the subsection already exists).
\end{enumerate}

The 2 first steps can be done only once, while the last has to be
repeated each time a new user section has to be added. The transfer
subroutine declared at step 2 is mandatory to indicate to \class{}
which elements are present in the data and in which order they have to
be written.

\subsection{Example}

The following program adds a new Usec Section to a \class{}
observation. A more realistic program would open an output file and
write the observation into it. The data here contains dummy values and
names for the example.

\begin{verbatim}
module mytypes
  type :: owner_title_version
    integer(kind=4)   :: datai4
    real(kind=4)      :: datar4
    real(kind=8)      :: datar8
    character(len=4)  :: datac4
  end type owner_title_version
end module mytypes
\end{verbatim}

\begin{verbatim}
program myprog
  use class_types
  use class_api
  use mytypes
  external :: toclass
  type(observation) :: obs
  type(owner_title_version) :: mydata
  integer(kind=4) :: version
  logical :: error
  !
  ! 1) Fill the data
  mydata%datai4 = 111
  mydata%datar4 = 222.
  mydata%datar8 = 333.
  mydata%datac4 = 'ABCD'
  !
  ! 2) Tell Class who I am
  call class_user_owner('OWNER','TITLE')
  !
  ! 3) Declare my transfer subroutine
  call class_user_toclass(toclass)
  !
  ! 4) Fill the User Section in the observation
  version = 1
  error = .false.
  call class_user_add(obs,version,mydata,error)
  if (error)  stop
  !
end program myprog
\end{verbatim}

\begin{verbatim}
subroutine toclass(mydata,version,error)
  use class_api
  use mytypes
  !---------------------------------------------------------------------
  ! Transfer and order the input 'mydata' object to the internal Class
  ! data buffer.
  !---------------------------------------------------------------------
  type(owner_title_version), intent(in)    :: mydata   !
  integer(kind=4),           intent(in)    :: version  ! The version of the data
  logical,                   intent(inout) :: error    ! Logical error flag
  !
  if (version.ne.1) then
    print *,'TOCLASS: Unsupported data version ',version
    error = .true.
    return
  endif
  !
  call class_user_datatoclass(mydata%datai4)
  call class_user_datatoclass(mydata%datar4)
  call class_user_datatoclass(mydata%datar8)
  call class_user_datatoclass(mydata%datac4)
  !
end subroutine toclass
\end{verbatim}

\subsection{Detailed API}

The following subroutines are part of the Class User Section API. The
interface module named {\tt class\_user\_interfaces} MUST be used in
the calling program or subroutines:
\begin{itemize}
\item Declare the owner and title of the User Subsection:
\begin{verbatim}
  subroutine class_user_owner(sowner,stitle)
    character(len=*), intent(in) :: sowner  ! Section owner
    character(len=*), intent(in) :: stitle  ! Section title
\end{verbatim}

\item Declare the user's transfer routine
\begin{verbatim}
subroutine class_user_toclass(usertoclass)
  external :: usertoclass  ! User's 'toclass' subroutine
\end{verbatim}

\item Send a variable to the data buffer in \class{}:
\begin{verbatim}
subroutine class_user_datatoclass(var)
      integer(kind=4),  intent(in) :: var
  OR  real(kind=4),     intent(in) :: var
  OR  real(kind=8),     intent(in) :: var
  OR  character(len=*), intent(in) :: var
\end{verbatim}

\item Add the User Subsection to an observation:
\begin{verbatim}
subroutine class_user_add(obs,sversion,sdata,error)
  type(observation), intent(inout) :: obs       ! Observation
  integer(kind=4),   intent(in)    :: sversion  ! Version number
  type( ),           intent(in)    :: sdata     ! The user data
  logical,           intent(inout) :: error     ! Logical error flag
\end{verbatim}

\item Update the User Subsection in the input observation:
\begin{verbatim}
subroutine class_user_update(obs,sversion,sdata,error)
  type(observation), intent(inout) :: obs       ! Observation
  integer(kind=4),   intent(in)    :: sversion  ! Version number
  type( ),           intent(in)    :: sdata     ! The user data
  logical,           intent(inout) :: error     ! Logical error flag
\end{verbatim}
\end{itemize}

Finally, the calling sequence of the user's transfer routine must be
of the following form:
\begin{verbatim}
subroutine toclass(data,version,error)
  type(  ),        intent(in)    :: data     ! The data to be transfered to Class
  integer(kind=4), intent(in)    :: version  ! The version of the data
  logical,         intent(inout) :: error    ! Logical error flag
\end{verbatim}
The name of this subroutine is to be defined by the user. The data
\emph{type} can be of any kind provided by the user. The purpose of
this routine is to send the {\tt data} elements to \class{} in a given
order. The advantage of this mechanism is to leave \class{} compute
the whole {\tt data} size and store it as its will. The counterpart is
that the order must be then exactly respected in the other parts of
the user code, \eg{} in the reading subroutine {\tt fromclass} defined
hereafter. Furthermore, the \class{} API does not allow to read only
one element in the {\tt data}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Reading a user section from an observation}

When the observation which is read from a file contains a user
section, \class{} will load it entirely (i.e. all the subsections it
may contain). The {\tt data} block of each subsection is loaded ``as
is'' in memory. Nothing more is done at read time.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Adding hooks to the Class commands}

The key point is now: \emph{``How users can access the user subsection
in the context of \class{} commands?''}. Let's take the command {\tt
DUMP} as first example.

\subsection{User hook for command {\tt DUMP}}

The command {\tt DUMP} displays the content of one or all sections of
the R buffer. When \class{} finds a user section to dump, it can
display the information it knows about each subsection. What it can
not do is guessing what the {\tt data} block contains.\\

If the section owner wants to tell \class{} how to {\tt dump} its
subsection, it has to:
\begin{enumerate}
\item tell \class{} which subsection it owns with {\tt
      class\_user\_owner}. This is optional if it has been done
      elsewhere.
\item declare to \class{} with {\tt class\_user\_dump} a subroutine
      which is able to display what is in the {\tt data} block.
\end{enumerate}
If \class{} tries now to {\tt DUMP} the user section, it will loop
over all the subsections it contains. If one matches the owner+title
couple, it will put the {\tt data} block in a specific place, and then
call user's dump subroutine. This subroutine will then just have to
translate back the {\tt data} block to its own data type.\\

This last point must be fulfilled by a subroutine exactly symmetric to
the transfer routine used at write time, i.e. elements should be
reread in the same order they have been written.

\subsubsection{Example}

If no user hooks have been declared, the output of the command {\tt
DUMP /SECTION USER} will be (with the example shown in the previous
section):
\begin{verbatim}
 USER ------------------------------------------------------
  Number of subsections: 1
  User Section #   1
    Owner:         OWNER
    Title:         TITLE
    Version:       1
    Data length:   5
    Data:
      (can not dump)
\end{verbatim}
\class{} claims it is not able to understand the content of the {\tt
data} buffer in the User Subsection.\\

The following subroutines show basically what should be done by the
section owner to allow \class{} to {\tt DUMP} a specific user section:
\begin{verbatim}
subroutine mydump_init
  !----------------------------------------------------------------------
  ! Preliminary declarations
  !----------------------------------------------------------------------
  !
  ! 1) Tell Class who I am
  call class_user_owner('OWNER','TITLE')
  !
  ! 2) Declare my dumping routine
  call class_user_dump(mydump)
  !
  ! Nothing more: return and wait for Class to ask for my User
  ! Subsection dump.
  !
end subroutine mydump_init
\end{verbatim}

\begin{verbatim}
subroutine mydump(version,error)
  use mytypes
  !---------------------------------------------------------------------
  ! Dump to screen my User Subsection
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: version  ! The version of the data
  logical,         intent(inout) :: error    ! Logical error flag
  ! Local
  type(owner_title_version) :: mydata
  !
  call fromclass(mydata,version,error)  ! Read the Class buffer and fill mydata
  if (error)  return
  !
  ! Display to screen
  print *,"     datai4 = ",mydata%datai4
  print *,"     datar4 = ",mydata%datar4
  print *,"     datar8 = ",mydata%datar8
  print *,"     datac4 = ",mydata%datac4
  !
end subroutine mydump
\end{verbatim}

\begin{verbatim}
subroutine fromclass(mydata,version,error)
  use mytypes
  use class_api
  !---------------------------------------------------------------------
  ! Transfer the data values from the Class data buffer to the 'mydata'
  ! instance.
  !---------------------------------------------------------------------
  type(owner_title_version), intent(out)   :: mydata   !
  integer(kind=4),           intent(in)    :: version  ! The version of the data
  logical,                   intent(inout) :: error    ! Logical error flag
  !
  if (version.ne.1) then
    print *,'FROMCLASS: Unsupported data version ',version
    error = .true.
    return
  endif
  !
  call class_user_classtodata(mydata%datai4)
  call class_user_classtodata(mydata%datar4)
  call class_user_classtodata(mydata%datar8)
  call class_user_classtodata(mydata%datac4)
  !
end subroutine fromclass
\end{verbatim}

With these subroutines, \class{} is now able to ask for a translation
of the User Subsection. The output of the command {\tt DUMP /SECTION
USER} will be:
\begin{verbatim}
 USER ------------------------------------------------------
  Number of subsections: 1
  User Section #   1
    Owner:         OWNER
    Title:         TITLE
    Version:       1
    Data length:   5
    Data:
      datai4 =          111
      datar4 =    222.00000
      datar8 =    333.00000000000000
      datac4 = ABCD
\end{verbatim}

\subsubsection{API}

The following subroutines have to be used to declare user's dump
subroutine:

\begin{itemize}
\item Declare the user's dump routine:
\begin{verbatim}
  subroutine class_user_dump(userdump)
    external :: userdump  ! User's 'dump' subroutine
\end{verbatim}
\item Get a variable from the data buffer in \class{}:
\begin{verbatim}
  subroutine class_user_classtodata(var)
        integer(kind=4),  intent(out) :: var
    OR  real(kind=4),     intent(out) :: var
    OR  real(kind=8),     intent(out) :: var
    OR  character(len=*), intent(out) :: var
\end{verbatim}
\end{itemize}

The calling sequence of the user's dump routine must be of the
following form:
\begin{verbatim}
subroutine mydump(version,error)
  integer(kind=4), intent(in)    :: version  ! The version of the data
  logical,         intent(inout) :: error    ! Logical error flag
\end{verbatim}
The name of this subroutine is free.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{User hook for command {\tt SET VARIABLE USER}}

If \class{} knows about a User Subsection owner and title when {\tt
SET VARIABLE USER} is invoked, it can instantiate the SIC variables
which describe the data of this subsection. This is be done if the
associated hook has been defined and declared to \class{}. The steps
to do so are, as usual:
\begin{enumerate}
\item tell \class{} which subsection it owns with {\tt
      class\_user\_owner}. This is optional if it has been done
      elsewhere.
\item declare to \class{} with {\tt class\_user\_setvar} a subroutine
      which is able to instantiate the SIC variables associated to the
      User Subsection.
\end{enumerate}

  The subroutines {\tt class\_user\_def\_inte}, {\tt
class\_user\_def\_real} and {\tt class\_user\_def\_dble} and {\tt
class\_user\_def\_char} will create respectively an integer*4, real*4
and real*8 and character string in {\tt R\%USER\%OWNER\%} (where {\tt
OWNER} is the owner previously declared). The subroutines order must
match the order the data was written in the User Section buffer.

The calling sequence of these subroutines is described in the
following sections. The suffix name of the SIC variable is given as
first argument, e.g. {\tt FOO} for {\tt R\%USER\%OWNER\%FOO}. The
arguments 'ndim' and 'dims' describe the variable dimensions, but only
scalars, 1D, and 2D-arrays are currently supported (ndim=0, 1, or
2). For the character variables, 'strlen' is the string length which
has to be read from the buffer.

  Note that once it has been instantiated, the SIC structure {\tt
R\%USER\%OWNER\%} will be updated each time the data changes
(e.g. after a {\tt GET NEXT}).

\subsubsection{Example}

When \class{} does not know about the User Subsection, it will not
accept to instantiate the SIC structure {\tt R\%USER\%}:
\begin{verbatim}
LAS90> set variable user
E-SETVAR,  No user function set for SET VAR USER
LAS90> exa r%user%
E-EXAMINE,  No such variable R%USER
\end{verbatim}

The following subroutines show basically what should be done by the
section owner to allow \class{} to instantiate SIC variables pointing
to the User Subsection when the command {\tt SET VARIABLE USER} is
invoked.
\begin{verbatim}
subroutine mysetvar_init
  !----------------------------------------------------------------------
  ! Preliminary declarations
  !----------------------------------------------------------------------
  !
  ! 1) Tell Class who I am
  call class_user_owner('OWNER','TITLE')
  !
  ! 2) Declare my instantiation routine
  call class_user_setvar(mysetvar)
  !
  ! Nothing more: return and wait for Class to ask for my User
  ! Subsection instantiation.
  !
end subroutine mysetvar_init
\end{verbatim}

\begin{verbatim}
subroutine mysetvar(version,error)
  use mytypes
  !---------------------------------------------------------------------
  ! Define SIC variables in the structure R%USER%OWNER% which map the
  ! subsection content.
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: version  ! The version of the data
  logical,         intent(inout) :: error    ! Logical error flag
  ! Local
  logical :: error
  integer(kind=4) :: ndim,dims
  !
  error = .false.
  ndim = 0
  call class_user_def_inte('DATAI4',ndim,dims,error)
  call class_user_def_real('DATAR4',ndim,dims,error)
  call class_user_def_dble('DATAR8',ndim,dims,error)
  call class_user_def_strn('DATAC4',ndim,dims,error)
  if (error)  return
  !
end subroutine mysetvar
\end{verbatim}

With these routines, \class{} is now able to instantiate the SIC
variables:
\begin{verbatim}
MYPROG> set variable user
MYPROG> exa r%user%
R%USER%        ! Structure GLOBAL
R%USER%OWNER%DATAC4 = ABCD                     ! Character*4 GLOBAL RO
R%USER%OWNER%DATAR8 =     333.0000000000000    ! Double  GLOBAL RO
R%USER%OWNER%DATAR4 =    222.0000              ! Real    GLOBAL RO
R%USER%OWNER%DATAI4 =          111             ! Integer GLOBAL RO
R%USER%OWNER   ! Structure GLOBAL
\end{verbatim}

\subsubsection{API}

The following subroutines have to be used in order to instantiate SIC
variables in the structure R\%USER\%.

\begin{itemize}
\item Declare the user's subroutine for variables instantiation:
\begin{verbatim}
subroutine class_user_setvar(usersetvar)
  external :: usersetvar
\end{verbatim}
\item Instantiate a SIC variable in {\tt R\%USER\%OWNER\%} (numeric
  types, respectively integer*4, real*4 and real*8). Only scalars
  (ndim=0), 1D (ndim=1), and 2D-arrays (ndim=2) are currently
  supported.
\begin{verbatim}
subroutine class_user_def_inte(suffix,ndim,dims,error)
  character(len=*), intent(in)    :: suffix   ! Component name
  integer(kind=4),  intent(in)    :: ndim     ! Number of dimensions (0=scalar)
  integer(kind=4),  intent(in)    :: dims(4)  ! Dimensions (unused if scalar)
  logical,          intent(inout) :: error    ! Logical error flag
\end{verbatim}
\begin{verbatim}
subroutine class_user_def_real(suffix,ndim,dims,error)
  character(len=*), intent(in)    :: suffix   ! Component name
  integer(kind=4),  intent(in)    :: ndim     ! Number of dimensions (0=scalar)
  integer(kind=4),  intent(in)    :: dims(4)  ! Dimensions (unused if scalar)
  logical,          intent(inout) :: error    ! Logical error flag
\end{verbatim}
\begin{verbatim}
subroutine class_user_def_dble(suffix,ndim,dims,error)
  character(len=*), intent(in)    :: suffix   ! Component name
  integer(kind=4),  intent(in)    :: ndim     ! Number of dimensions (0=scalar)
  integer(kind=4),  intent(in)    :: dims(4)  ! Dimensions (unused if scalar)
  logical,          intent(inout) :: error    ! Logical error flag
\end{verbatim}
\item Instantiate a SIC variable in {\tt R\%USER\%OWNER\%} (scalar
      character strings).
\begin{verbatim}
subroutine class_user_def_char(suffix,lstring,error)
  character(len=*), intent(in)    :: suffix   ! Component name
  integer(kind=4),  intent(in)    :: lstring  ! String length
  logical,          intent(inout) :: error    ! Logical error flag
\end{verbatim}
\end{itemize}

The calling sequence of the user's instantiation routine must be of
the following form:
\begin{verbatim}
subroutine mysetvar(version,error)
  integer(kind=4), intent(in)    :: version  ! The version of the data
  logical,         intent(inout) :: error    ! Logical error flag
\end{verbatim}
The name of this subroutine is free.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{User hook for command {\tt FIND}}

The \class{} command {\tt FIND} allows the user to make a custom
selection from the Input indeX (IX: input file summary), building then
the Current indeX (CX). This is done through the option {\tt
  /USER}. If \class{} knows about a User Subsection owner and title,
then a hook can be executed in order to make a custom search depending
on this User Subsection contents. The basic steps to be done by the
Subsection owner are:
\begin{enumerate}
\item tell \class{} which subsection it owns with {\tt
      class\_user\_owner}. This is optional if it has been done
      elsewhere.
\item declare to \class{} with {\tt class\_user\_find} a subroutine
      which will parse the {\tt FIND /USER} arguments,
\item declare to \class{} with {\tt class\_user\_fix} a subroutine
      which will make the selection depending on the command line
      arguments and the Subsection contents.
\end{enumerate}

\subsubsection{Example}

When \class{} does not know about the User Subsection, it will not
accept to make a custom user selection:
\begin{verbatim}
LAS90> FIND /USER
E-USER_SEC_FIND,  No user function for FIND /USER
\end{verbatim}

The following subroutines show basically what should be done by the
section owner to allow \class{} such custom selections. Note that this
is divided into 2 main steps. The command line parsing is first
called. For efficiency, this is done only once at the beginning of the
command execution. Then \class{} loops on all the observations in the
Input indeX and calls repeatedly the selection subroutine.
\begin{verbatim}
subroutine myfind_init
  !----------------------------------------------------------------------
  ! Preliminary declarations
  !----------------------------------------------------------------------
  !
  ! 1) Tell Class who I am
  call class_user_owner('OWNER','TITLE')
  !
  ! 2) Declare my command line parsing subroutine
  call class_user_find(myfind)
  !
  ! 3) Declare my selection subroutine
  call class_user_fix(myfix)
  !
  ! Nothing more: return and wait for Class to execute FIND /USER.
  !
end subroutine myfind_init
\end{verbatim}

\begin{verbatim}
subroutine myfind(arg,narg,error)
  use gkernel_interfaces
  use mymod
  !---------------------------------------------------------------------
  ! Hook to command:
  !   LAS\FIND /USER [Arg1] ... [ArgN]
  ! Command line parsing: retrieve the arguments given to the option.
  !---------------------------------------------------------------------
  integer(kind=4),  intent(in)    :: narg       ! Number of arguments
  character(len=*), intent(in)    :: arg(narg)  ! Arguments
  logical,          intent(inout) :: error      ! Logical error flag
  ! Local
  integer(kind=4) :: iarg
  !
  ! Here you have to parse and save the selection criteria given to
  ! the command line. We assume here they are saved in a float array
  ! 'mycriteria' provided by the module 'mymod'
  mycriteria(:) = 0.0  ! Initialization
  !
  do iarg=1,narg
    ! Use Gildas kernel parsing subroutines (convert string to REAL*4)
    call sic_math_real(arg(iarg),len(arg(iarg)),mycriteria(iarg),error)
    if (error)  return
  enddo
  !
end subroutine myfind
\end{verbatim}

\begin{verbatim}
subroutine myfix(version,found,error)
  use mymod
  use mytypes
  !---------------------------------------------------------------------
  ! Hook to command:
  !   LAS\FIND /USER
  !  Find or not according the User Subsection contents. Called only if
  ! the observation has a user section and it matches the one
  ! declared here.
  !  NB: 'FIX' stands for "Find in Input indeX"
  !---------------------------------------------------------------------
  integer(kind=4), intent(in)    :: version  ! The version of the data
  logical,         intent(out)   :: found    ! Selected or not selected?
  logical,         intent(inout) :: error    ! Logical error flag
  ! Local
  type(owner_title_version) :: mydata
  !
  call fromclass(mydata,version,error) ! Read the Class buffer and fill mydata
  if (error) return
  !
  ! Use the criteria saved in 'myfind' e.g.
  found = mydata%r4.gt.mycriteria(1) .and. mydata%r8.lt.mycriteria(2)
  !
end subroutine myfix
\end{verbatim}

With these routines, \class{} is now able make a custom search in the
input index:
\begin{verbatim}
MYPROG> find  ! Find everything
I-FIND,  15504 observations found
MYPROG> find /user 1.0 2.0  ! Find with some user selection
I-FIND,  224 observations found
\end{verbatim}
The option {\tt /USER} can be combined with other selection criteria
(e.g. {\tt FIND /SOURCE MYSOURCE /USER 1.0}); as usual the result is
the intersection of all the selections. If {\tt FIND /USER} is invoked
but the User Subsection is absent or is not owned by the program, the
observation is not selected to the Current indeX\footnote{Remember
  that Class provides natively the option FIND /SECTION USER which
  finds all observations providing a User Section, independently from
  any hook.}.

\subsubsection{API}

The following subroutines have to be used to declare user's find
subroutine:

\begin{itemize}
\item Declare the user's dump find routines:
\begin{verbatim}
  subroutine class_user_find(userfind)
    external :: userfind  ! User's 'find' subroutine (command line parsing)
  subroutine class_user_fix(userfix)
    external :: userfix  ! User's 'find' subroutine (selection)
\end{verbatim}
\end{itemize}

The calling sequence of the user's find routines must be of the
following form:
\begin{verbatim}
subroutine userfind(arg,narg,error)
  integer(kind=4),  intent(in)    :: narg       ! Number of arguments
  character(len=*), intent(in)    :: arg(narg)  ! Arguments
  logical,          intent(inout) :: error      ! Logical error flag
\end{verbatim}
\begin{verbatim}
subroutine userfix(version,found,error)
  integer(kind=4), intent(in)    :: version  ! The version of the data
  logical,         intent(out)   :: found    ! Selected or not selected?
  logical,         intent(inout) :: error    ! Logical error flag
\end{verbatim}
The name of these subroutines is free.

%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{API summary}

The table \ref{tbl:hooks:gene} describes the general hooks to be used
in order to read or write the User Section. They have to be considered
as prerequisites before doing anything with this section in \class{}.

\begin{table}[p]
\small
\begin{center}
\caption{General hooks}
\vspace{1ex}
\begin{tabular}{lp{10cm}}

Subroutine               & Purpose \\
\hline
{\tt class\_user\_owner} & declare who is the owner and what is the
                           title of the subsection the hooks can read
                           or write \\
\end{tabular}
\label{tbl:hooks:gene}
\end{center}
\end{table}

 The table \ref{tbl:hooks:writ} describe the hooks to be used when
 adding a User Section to an observation (e.g. before writing it to
 the output file).

\begin{table}[p]
\small
\begin{center}
\caption{Writing hooks}
\vspace{1ex}
\begin{tabular}{lp{10cm}}

Subroutine                     & Purpose \\
\hline
{\tt class\_user\_add}         & add a new user subsection to the input observation \\
{\tt class\_user\_update}      & update a user subsection which already exists \\
{\tt class\_user\_toclass}     & declare the subroutine which will write the data
                                 to the Class internal buffer \\
{\tt class\_user\_datatoclass} & transfer a scalar, 1D, or 2D-array value to the
                                 Class internal buffer (generic subroutine)
\end{tabular}
\label{tbl:hooks:writ}
\end{center}
\end{table}

Finally the table \ref{tbl:hooks:read} summarizes the subroutines
which can be used to declare the hooks to some \class{} commands, plus
some subroutines which are useful for some of them.

\begin{table}[p]
\small
\begin{center}
\caption{Reading hooks}
\vspace{1ex}
\begin{tabular}{lp{10cm}}

Subroutine                     & Purpose \\
\hline
{\tt class\_user\_dump}        & declare the hook for the command {\tt DUMP} \\
{\tt class\_user\_find}        & declare the hook for the command {\tt FIND /USER} (command line parsing) \\
{\tt class\_user\_fix}         & declare the hook for the command {\tt FIND /USER} (selection) \\
{\tt class\_user\_setvar}      & declare the hook for the command {\tt SET VARIABLE USER} \\
\hline
{\tt class\_user\_classtodata} & read a scalar, 1D, or 2D-array value from the Class
                                 internal buffer (generic subroutine)\\
\hline
{\tt class\_user\_def\_inte}   & create an integer*4 SIC variable in the structure
                                 {\tt R\%USER\%OWNER\%} \\
{\tt class\_user\_def\_real}   & create a real*4 SIC variable in the structure
                                 {\tt R\%USER\%OWNER\%} \\
{\tt class\_user\_def\_dble}   & create a real*8 SIC variable in the structure
                                 {\tt R\%USER\%OWNER\%} \\
{\tt class\_user\_def\_char}   & create a character string SIC variable in the structure
                                 {\tt R\%USER\%OWNER\%}
\end{tabular}
\label{tbl:hooks:read}
\end{center}
\end{table}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Extending the standard \class{} capabilities}

The previous sections describe how to write and read a User Section
in/from a \class{} file. This was assumed to be done from an external
program linked to be \class{} library. However, it is also possible to
do this directly from the standard \class{} executable. The key point
is to define all the support subroutines for the User Section in a
binary, dynamically loadable library (say \emph{libowner.so}), linked
to the \class{} library. \emph{libowner.so} must also define a
specific entry point and its associated definition subroutines, as
described in the document named \emph{New package
initialization}\footnote{contact {\tt gildas@iram.fr} for more
information}.

From a standard \class{} session, the command {\tt
SIC$\backslash$IMPORT} can then be used to load the \emph{libowner.so}
library and import the User Section capabilities. Such a session will
look like:
\begin{verbatim}
LAS90> ! First, Class does not know how to read the User Section:
LAS90> DUMP /SECTION USER
 USER ------------------------------------------------------
  Number of subsections: 1
  User Section #   1
    Owner:         OWNER
    Title:         TITLE
    Version:       1
    Data length:   5
    Data:
      (can not dump)
LAS90>
LAS90> ! Load 'libowner.so'
LAS90> SIC\IMPORT OWNER
LAS90>
LAS90> ! Now Class knows how to read it:
LAS90> DUMP /SECTION USER
 USER ------------------------------------------------------
  Number of subsections: 1
  User Section #   1
    Owner:         OWNER
    Title:         TITLE
    Version:       1
    Data length:   5
    Data:
      datai4 =          111
      datar4 =    222.00000
      datar8 =    333.00000000000000
      datac4 = ABCD
LAS90>
\end{verbatim}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Backward compatibility}

Old versions of \class{} (i.e. older than apr11g) will just ignore the
user section, if it exists. This section will be lost in a {\tt
GET}-and-{\tt WRITE} process.

Starting from apr11g, \class{} is able to detect, load and give basic
details about this section. All the user subsections are preserved and
written to the output file, under the restrictions exposed in the next
section.

%%%%%%%%%%%%%%%%%%%%%
\section{Portability}
\label{txt:portability}

The basic behavior of \class{} is that it loads all the user
subsections (if any) at read time, and transfer all of them to the
output file at write time. However, the {\tt data} block of bytes is
untyped in the \class{} data format, so it will make sense to re-read
them if and only if the reading machine has the same endianness (IEEE,
EEEI, etc) than the one used at write time. As a consequence the
following restrictions apply:
\begin{enumerate}
\item at read time, \class{} won't read the user section if the input
      file type is not native (i.e. it has not been written under the
      same architecture we are reading it),
\item at write time, \class{} won't write the user section if the
      output file type is not native (i.e. we reopened for output a
      file first written under another architecture).
\end{enumerate}
However, these restrictions have very low chance to occur, since
nowadays most (all?) of the computers have an IEEE architecture.

%%%%%%%%%%%%%%%%%%
\section{Conclusion}

The \class{} developer team provides some flexibility about the
\class{} data format through a customizable user section
mechanism. This user section can be encoded and decoded only by
external programs linked with the \class{} library and which follows
the \class{} API. This is the responsability of the external programs
to ensure the efficiency of their codes. We recommand to observatory
who would like to use this mechanism to contact us
(\texttt{gildas@iram.fr}) in order to discuss how to maintain the long
term compatibility of their user section.

%%%%%%%%%%%
\clearpage
\newpage
\appendix{}

\section{Implementation details for \class{} developers}

The User Section is added to the \class{} data format. It is defined
in the Fortran source as follows:
\begin{verbatim}
  type user  ! Type for all user subsections
     sequence
     integer(kind=4)          :: n       ! Number of user subsections
     type (user_sub), pointer :: sub(:)  ! Array of subsections
  end type
\end{verbatim}
An object of type {\tt user} is added to the type {\tt observation}
structure in the data format. This {\tt user} object can contain an
arbitrary number of subsections. This allows several user subsections
to exist for the same observation.\\

Then each of these user subsection is described by the following type:
\begin{verbatim}
  type user_sub  ! Type for each user subsection
     sequence
     character(len=12)        :: owner    ! Owner of the subsection
     character(len=12)        :: title    ! Title of the subsection
     integer(kind=4)          :: version  ! Version of the subsection
     integer(kind=4)          :: ndata    ! Length of the data(:) array
     integer(kind=4), pointer :: data(:)  ! Place holder for information
  end type
\end{verbatim}
\begin{itemize}
\item A user subsection is identified by a {\tt owner} and a {\tt
      title}. One owner can have several subsections with each a
      different title. In other words the couple {\tt owner}+{\tt
      title} is considered as a unique identifier for a user
      subsection.
\item The {\tt version} value is a mean for the owner to handle
      several versions of the same subsection (e.g. elements have been
      added in this subsection between two versions).
\item The {\tt data} field is the data itself. It is considered as a
      block of bytes with no direct meaning for \class{}. Only the
      owner is able to decode it.
\item Since the {\tt data} is a dynamic object (i.e. size is not known
      at compilation time), the {\tt ndata} value describes how many
      4-bytes blocks are present in the {\tt data}.
\end{itemize}
Those two types are private to \class{}. They do not have to be known
by the external program.\\

  Finally, this new User Section is different from the other ones in
the \class{} data format since its size is not constant. This implies
some modifications in the subroutines. In particular, a whole copy of
observation to observation ({\tt obsout = obsin}) is forbidden: it
must be done in a specific way, taking care of allocating the pointers
in the user section before the copy. For the same reason, the User
Section is not buffered and must be re-read everytime needed on the
disk (in other words {\tt SET VIRTUAL ON} has no effect).

\end{document}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

