From ef6c04e6b8c88617e34e96e8466df0e430f4ac6a Mon Sep 17 00:00:00 2001
From: koennecke
Date: Wed, 22 Jun 2005 07:09:59 +0000
Subject: [PATCH] - Adding first working version of the McStas SICS connection
to cvs
SKIPPED:
psi/polterwrite.c
---
countdriv.c | 4 +-
countdriv.h | 8 +-
counter.c | 17 ++
counter.h | 1 +
doc/manager/hwini.htm | 11 +-
doc/manager/inifile.htm | 1 +
doc/manager/managerman | 1 +
doc/manager/mcstas.htm | 140 +++++++++++++
doc/user/tasub.htm | 169 +++++++++++++++
histmem.c | 5 +
histsim.c | 1 -
hmdata.c | 13 ++
hmdata.h | 1 +
hmdata.w | 1 +
make_gen | 5 +-
mccontrol.c | 398 ++++++++++++++++++++++++++++++++++++
mccontrol.h | 47 +++++
mcreader.c | 308 ++++++++++++++++++++++++++++
mcreader.h | 28 +++
mcstas.tex | 222 ++++++++++++++++++++
mcstas.w | 171 ++++++++++++++++
mcstas/dmc/DataNumber | 3 +
mcstas/dmc/PSD_monitor.comp | 141 +++++++++++++
mcstas/dmc/batch.tcl | 8 +
mcstas/dmc/dmc.dic | 89 ++++++++
mcstas/dmc/dmc_sics01.instr | 184 +++++++++++++++++
mcstas/dmc/log.tcl | 84 ++++++++
mcstas/dmc/mcsupport.tcl | 66 ++++++
mcstas/dmc/na2ca3al2f14.q | 29 +++
mcstas/dmc/nxdmc.tcl | 108 ++++++++++
mcstas/dmc/nxsupport.tcl | 96 +++++++++
mcstas/dmc/vdmc.tcl | 138 +++++++++++++
mcstas/dmc/vdmccom.tcl | 156 ++++++++++++++
mcstas/dmc/vdmcstatus.tcl | 217 ++++++++++++++++++++
mcstascounter.c | 160 +++++++++++++++
mcstashm.c | 212 +++++++++++++++++++
mcstashm.h | 16 ++
napi.c | 3 +-
network.c | 3 +-
ofac.c | 7 +
tasscanub.c | 10 +-
tasublib.c | 4 +
42 files changed, 3268 insertions(+), 18 deletions(-)
create mode 100644 doc/manager/mcstas.htm
create mode 100644 doc/user/tasub.htm
create mode 100644 mccontrol.c
create mode 100644 mccontrol.h
create mode 100644 mcreader.c
create mode 100644 mcreader.h
create mode 100644 mcstas.tex
create mode 100644 mcstas.w
create mode 100644 mcstas/dmc/DataNumber
create mode 100644 mcstas/dmc/PSD_monitor.comp
create mode 100644 mcstas/dmc/batch.tcl
create mode 100644 mcstas/dmc/dmc.dic
create mode 100644 mcstas/dmc/dmc_sics01.instr
create mode 100644 mcstas/dmc/log.tcl
create mode 100644 mcstas/dmc/mcsupport.tcl
create mode 100644 mcstas/dmc/na2ca3al2f14.q
create mode 100644 mcstas/dmc/nxdmc.tcl
create mode 100644 mcstas/dmc/nxsupport.tcl
create mode 100644 mcstas/dmc/vdmc.tcl
create mode 100644 mcstas/dmc/vdmccom.tcl
create mode 100644 mcstas/dmc/vdmcstatus.tcl
create mode 100644 mcstascounter.c
create mode 100644 mcstashm.c
create mode 100644 mcstashm.h
diff --git a/countdriv.c b/countdriv.c
index 1bbe47f5..2bf0d535 100644
--- a/countdriv.c
+++ b/countdriv.c
@@ -92,9 +92,7 @@
if(self->KillPrivate != NULL)
{
self->KillPrivate(self);
- } else {
- free(self->pData);
- }
+ }
}
free(self);
}
diff --git a/countdriv.h b/countdriv.h
index 79986609..4bb86fed 100644
--- a/countdriv.h
+++ b/countdriv.h
@@ -81,5 +81,11 @@
/* PSI Simulation counter, if you have no hardware */
/* simcter.c */
pCounterDriver NewSIMCounter(char *name, float fVal);
- void KillSIMCounter(pCounterDriver self);
+ void KillSIMCounter(pCounterDriver self);
+
+ /*
+ * McStas simulation counter driver
+ * file: mcstascounter.c
+ */
+ pCounterDriver NewMcStasCounter(char *name);
#endif
diff --git a/counter.c b/counter.c
index 3fc88a8f..731b9da7 100644
--- a/counter.c
+++ b/counter.c
@@ -529,6 +529,13 @@
}
}
+ /*
+ * test for McStas simulation counter driver
+ */
+ if(strcmp(argv[2],"mcstas") == 0){
+ pDriv = NewMcStasCounter(argv[1]);
+ }
+
if(!pDriv)
{
sprintf(pBueffel,"ERROR: cannot create requested driver %s",
@@ -666,6 +673,16 @@
return self->pDriv->lCounts[iNum];
}
}
+ /*-----------------------------------------------------------------------*/
+ void SetMonitorValue(pCounter self, int index, long value)
+ {
+ assert(self);
+
+ if(index >= 0 && index < self->pDriv->iNoOfMonitors)
+ {
+ self->pDriv->lCounts[index] = value;
+ }
+ }
/*------------------------------------------------------------------------*/
float GetCountTime(pCounter self,SConnection *pCon)
{
diff --git a/counter.h b/counter.h
index a91e8241..9c84f64c 100644
--- a/counter.h
+++ b/counter.h
@@ -42,6 +42,7 @@
long GetCounts(pCounter self, SConnection *pCon);
long GetMonitor(pCounter self, int iNum, SConnection *pCon);
int GetNMonitor(pCounter self);
+ void SetMonitorValue(pCounter self, int index, long value);
float GetCountTime(pCounter self, SConnection *pCon);
int DoCount(pCounter self,float fPreset, SConnection *pCon,
diff --git a/doc/manager/hwini.htm b/doc/manager/hwini.htm
index ac53ad8e..e0c92029 100644
--- a/doc/manager/hwini.htm
+++ b/doc/manager/hwini.htm
@@ -10,13 +10,12 @@ Hardware is configured into the SICS system by executing special hardware
configuration commands from the server initialisation file. These commands
are described here. Much SICS hardware is hooked up to the system via RS-232
interfaces. The SICS server communicates with such devices through a serial
-port server program running on a Macintosh PC. All such devices require on
+port server program running on the instrument computer All such devices require on
initialisation the following parameters:
-- hostname The name of the macintosh computer.
+
- hostname The name of the instrument computer.
- port The port number where the serial port server program is
-listening for requests. It is given on the Macintosh screen when the serial
-port server is running. It is usually 4000.
+listening for requests. It is usually 4000.
- channel The number of the RS-232 interface on the Macintosh. 0 is
the standard Macintosh modem port, 1 is the standard Macintosh printer port,
2 is the first connector on the interface extension box. This leads to much
@@ -146,6 +145,10 @@ accessible as object name. Failrate is the per centage of invocations
at which the counter will generate a random failure for testing error
treatment code. If failrate is less then 0, there are no
failures. This can be used in a instrument simulation server.
+
- MakeCounter name mcstas
+
- Creates a counter which interoperates with a McStas simulation. Please note,
+ that the McStas module mccontrol must have been initialized before this initialization
+ can work.
- MakeCounter name EL737 host port chan
- This command creates a single
counter name, using an EL737 driver. The counter is at host host, listening
diff --git a/doc/manager/inifile.htm b/doc/manager/inifile.htm
index b0a43c68..d88f7807 100644
--- a/doc/manager/inifile.htm
+++ b/doc/manager/inifile.htm
@@ -20,6 +20,7 @@ Go to:
- Advice about hardware configuration.
- A description of command initialisation.
- Managing the SICS help system.
+
- Connecting SICS to McStas Simulations.
diff --git a/doc/manager/managerman b/doc/manager/managerman
index 4a47cedd..8791bf4c 100644
--- a/doc/manager/managerman
+++ b/doc/manager/managerman
@@ -47,6 +47,7 @@ which is described elsewhere.
%html hwini.htm 1
%html command.htm 1
%html helpman.htm 2
+%html mcstas.htm 2
%html special.htm 1
%html serial.htm 2
%html status.htm 2
diff --git a/doc/manager/mcstas.htm b/doc/manager/mcstas.htm
new file mode 100644
index 00000000..bb4acd7f
--- /dev/null
+++ b/doc/manager/mcstas.htm
@@ -0,0 +1,140 @@
+
+
+The McStas SICS Interface
+
+
+The McStas SICS Interface
+
+It is useful to drive a simulation of an instrument with the same interface as is used at
+the original instruments. One of the better packages for performing simulations of neutron
+scattering instruments, including samples, is McStas. This section describes SICS
+interface to McStas simulations. The interface consists of three parts:
+
+- A McStas controller module which controls the actual simulation.
+
- A McStas reader which is responsible for reading simulated data into
+ SICS counters and histogram memories.
+
- Counter and histogram memory drivers which redirect their actions to the
+ McStas controller module.
+
+The general ideas is that all parameters are handled through the normal SICS simulation
+ drivers. The counting operations, however, are linked with the McStas simulation. In order
+ to be portable, many aspects are controlled by scripts. These scripts are configured at the
+ McStas Controller. Several scripts must be defined:
+
+- startmcstas
+
- This script will be invoked when counting starts and has to collect the necessary
+ settings from SICS, construct a McStas command line and start the simulation. As a return
+ value this script has to return the PID of the started mcstat process.
+
- mcstastest pid
+
- Tests if the McStas simulation is still running.
+
- mcstasdump pid
+
- Has to send a signal to McStas which causes it to dump its data without terminating.
+ Current versions of McStas do this on receiving the USR2 signal.
+
- mcstasstop pid
+
- Stops the McStas simulation.
+
- mcstasread
+
- Reads the McStas simulation output and transfers monitor and histogram memory data
+ into the appropriate SICS objects.
+
+
+McStas Requirements and SICS Requirements
+
+In order for the McStas SICS interface to work the McStas simulation has to be configured
+in a certain way:
+
+- All parameters which have to pass between SICS and McStas have to be declared as
+ simulation parameters in the DEFINE INSTRUMENT section of the instrument definition file.
+ Alternatively SICS can write the data to be passed to McStas into a file. But then this
+ file must be read in the INITIALIZE section of the instrument definition and values must
+ be assigned to the appropriate McStas variables.
+
- McStas must dump its data into a single file: use the -f filename option.
+ The format must be --format=XML.
+
- In order to count on monitor, a modified PSD_monitor component MUST be used in the
+ simulation. This component writes the collected total counts into a file. This file is
+ the read by SICS in order to determine the control monitor. Evaluating the McStas XML dump \
+ file each time proved to be to inaccurate. The name of the file containing the monitor
+ must be configured through: mccontrol configure mcmonfile name-of-file.
+
- The mcstas simulation executable must be declared with allowexec in order to be able
+ to start with the Tcl exec command.
+
+
+The McStas Reader
+
+In order to enable trasnfer from McStas result files into SICS objects a reader object is
+needed. This module supports only XML formatted McStas files, with the output dumped into
+one file. The McStas options to achieve this are: -f filename --format="XML"
+This module supports the following commands:
+
+- mcreader open filename
+
- Opens a McStas simulation file for reading.
+
- mcreader close
+
- Closes a McStas file after use.
+
- mcreader insertmon path object monitornumber
+
- This transfers a monitor value from a previously opened McStas file into a SICS
+monitor field. The McStas field read is the values tag belonging to the component. The
+parameters:
+
+- path
+
- The path to the correct values field in the simulation file. The format is the same
+as the path format for NXopenpath in the NeXus-API (which will internally be used). For
+groups, the name attribute is used a path component.
+
- object
+
- The counter object into which the monitor is read. This is a limitation, with the
+ this McStas interface only counters can store monitors.
+
- monitornumber
+
- Monitornumber is the monitor channel into which the value is to be stored.
+
+ - mcreader inserthm path hmobject
+
- Inserts array data stored under path in the histogram memory array of hmobject which
+ must be a valid SICS histogram memory object. The path is the same as given for insertmon,
+ but of course the data part of the detector must be addressed.
+
+
+The McStas Controller
+
+The actual control of the "counting" operation of the McStas simulation is done by the
+ McStas controller module in SICS. Internally this module implements the routines for
+ counting virtual neutrons. Towards the SICS interpreter, an interface is exhibited which
+ allows to configure and test the McStas controller. The McStas Controller delegates many
+ tasks to script procedures written in SICS's internal Tcl scripting language. This is done
+ in order to achieve a degree of generality for various types of instruments and in order
+ to allow easier adaption to differing demands. This is the SICS interface implemented:
+
+ - mccontrol configure mcstart startscriptname
+
- Configures the script which starts the McStas simulation. Startscriptname is the name
+ of a Tcl procedure which collects the necessary information from SICS, builds a command
+line and finally starts the simulation. This script is expected to return either an error or
+ the PID of the started process. Startscriptname will be called with the parameters mode and
+ preset which represent the counting characteristics.
+
- mccontrol configure mcisrunning runtestscriptname
+
- Configures the name of a script which tests if the McStas process is still running.
+ Runtestscriptname is called with the PID as a parameter. This returns 0 in the case the
+ McStas simulation was stopped or 1 if it is still running.
+
- mccontrol configure mcdump dumpscriptname
+
- Configures the name of the script which causes McStas to dump intermediate results.
+ The script will be called with the PID of the started McStas process as a parameter.
+
- mccontrol configure mckill killscript
+
- Configure the name of a procedure which kills the current McStas simulation
+ process. KillScript will be called with the PID of the McStas simulation as a parameter.
+
- mccontrol configure mccopydata copyscript
+
- This configures the name of a script which has the task to read the results of
+ a McStas simulation and assign values to SICS monitors and histogram memories.
+
- mccontrol configure update updateintervallinseconds
+
- This configures the minimum time between McStas dumps in seconds. The idea is that
+ SICS buffers values during a simulation run and does not interrupt the McStas process to
+ often.
+
- mccontrol configure mcmonfile filename
+
- This configures the file which mccontrol is going to read in order to watch the
+ simulation control monitor.
+
- mccontrol list
+
- Prints a listing of the configuration parameters.
+
- mccontrol run scriptkey
+
- Invokes one of the scripts configure for testing purposes. scripkey can be one of:
+ mcstart, mcisrunning, mcdump, mckill and mccopydata.
+
+Standard scripts for many of the script routines required are provided for the unix
+ environment in the file mcsupport.tcl. Please note, that all system executables called
+ from scripts must be registrered with SICS using the allowexec command.
+
+
+
diff --git a/doc/user/tasub.htm b/doc/user/tasub.htm
new file mode 100644
index 00000000..0e2f618e
--- /dev/null
+++ b/doc/user/tasub.htm
@@ -0,0 +1,169 @@
+
+
+TASUB: The Triple Axis Calculation Module
+
+
+TASUB: The Triple Axis Calculation Module
+
+On a triple axis instrument the parameters incoming energy, Q-position in 3D and
+ analyzed energy have to be changed frequently. These calculations are the task of
+ the TASUB module. This module uses the calculus described by M. Lumsden, J. L.
+ Roberston and M. Yethiraj in J. Appl. Cryst. (2005), 38, 405-411. The special feauture of
+ this algorithm is that the tilt cradles of the sample table are used to help during
+ alignment and in order to drive out of plane (within the limits of the tilt cradles).
+ For alignment, two reflections must be located and their angles and Q-E parameters
+ entered into the module. Then a UB matrix can be calculated. With a UB matrix, the
+ Q-E variables ei, ki, ef, kf, en, qh, qk and ql can be driven as virtual motors in
+ SICS.
+
+Commands understood by Tasub
+
+
Monochromator and Analyzer Parameters
+
+Incident and scattered energies are defined by monochromator crystals. In order for the
+ calculations to work, some parameters need to be configured. Monochromator and analyzer
+ parameters can be accessed with the prefixes:
+
+The parameter syntax used is as usual: giving only the parameter name queries the value,
+ giving the parameter plus a value sets the parameter to the new value. The following
+ parameters are supported:
+
+- dd
+
- The d-spacing of the reflection used
+
- ss
+
- The scattering sense, 1 or -1 are possible.
+
- hb1
+
- First parameter for the calculation of the horizontal curvature
+
- hb2
+
- Second parameter for the calculation of the horizontal curvature
+
- vb1
+
- First parameter for the calculation of the vertical curvature
+
- vb2
+
- Second parameter for the calculation of the vertical curvature
+
+An example:
+
+- tasub mono dd
+
- will print the current d-spacing of the monochromator
+
- tasub mono dd 4.3
+
- Will set the d-spacing of the monochromator to 4.3
+
+
+Cell Parameters
+
+In order for the UB matrix calculation to work, the cell constants must be known:
+
+- tasub cell
+
- This command prints the current cell parameters.
+
- tasub cell a b c alpha beta gamma
+
- This command sets the new cell parameters. All six values must be given.
+
+
+Reflection Management
+
+In order to calculate a UB matrix a list of reflections must be maintained. This is done
+ with the commands in this section:
+
+ - tasub clear
+
- Clears the reflection list
+
- tasub listref
+
- Prints a list of all known reflections.
+
- tasub del num
+
- Delete the reflection number num from the list
+
- tasub addref qh qk ql
+
- Adds a reflection to the list. The indices of the reflections are given. The angles
+ and energy values are read from the motors. Use this command only when the instrument is
+ positioned right on a reflection.
+
- tasub addref qh qk ql a3 a4 sgu sgl ei ef
+
- Add a new reflection to the list. Besides the indices all angles are given:
+ a3, the sample rotation, a4, sample two theta, sgu, upper tilt cradle, sgl, lower tilt
+ cradle and incoming energey ei and outgoing energy ef.
+
+
+Calculations
+
+This section covers the parameters and commands to use to make the module do calculations
+ for you.
+
+- tasbub const ki | kf
+
- Sets a parameter to determine if KI or KF is fixed when the energy transfer en is
+ being driven. Allowed values: ki, kf
+
- tasub const
+
- Prints if ki or kf is fixed.
+
- tasub ss
+
- Prints the sample scattering sense.
+
- tasub ss 1 | -1
+
- Sets the sample scattering sense. Allowed values are either 1 or -1.
+
- tasub makeub r1 r2
+
- Calculate a new UB matrix from the current cell constants and the entries r1 and r2 in
+ the reflection list. r1 and r2 are integer numbers. This command will not only print the
+ new UB matrix but also the results of various back and forth calculations performed with
+ the new UB matrix. This can be inspected in order to check the new UB. WARNING: The calculation
+ will go wrong if the scattering sense at the sample has changed since the reflections used
+ for the UB matrix determination have been entered.
+
- tasub listub
+
- prints the current UB matrix.
+
- tasub calcang qh qk ql ei ef
+
- Will calculate new angles for the Q-E position specified. The angles will be
+ printed in the order: monochromator two theta, sample rotation, sample two theta,
+ lower tilt cradle, upper tilt cradle and analyzer two theta.
+
- tasub calcqe a2 a3 a4 sgu sgl a6
+
- Calculates and prints the Q-E position from the angles given: a2 = monochromator
+ two theta, a3 = sample rotation, a4 = sample tow theta, sgu = upper tilt cradle, sgl =
+ lower tilt cradle and a6 = analyzer two theta. The Q-E position is printed in the sequence:
+ qh, qk, ql, ei, ef.
+
+
+Virtual Motors
+
+The tasub module also installs the following virtual motors into SICS: ei, ki, qh, qk, ql,
+ en, ef, kf and qm. All these motors can be used in SICS drive, run or scan commands like real
+ motors. Driving them triggers a recalculation of angles and the drives the real motors to
+ appropriate values. The virtual motors have a very limited command set
+ (shown at the example of qh):
+
+ - qh
+
- The name of the motor alone will print its current position.
+
- qh target
+
- This will print the last requested target position for this virtual motor.
+
+
+
+The virtual motor qm implements powder mode. In this mode, only the sample two theta
+ and energy motors will be driven, sample rotation and tilt cradles will be left at their
+ respective positions. THis is commonly used to analyze the energy transfer of powder samples.
+
+
+There is another important command:
+
+- tasub update
+
- This command will force a recalculation of the current Q-E position for the virtual
+motors from angles. Normally tasub will take care of this. However, if any of the angle
+motors are moved directly or manualy, this command might be required. The SICS dr
+ wrapper command, however, even takes care of this.
+
+
+Internal Commands
+
+The tasub module supports some more commands which are used by SICS in order to restore
+ the tasub configuration between instantiations of SICS. These commands are documented here
+ for the sake of completeness:
+
+ - tasub setub ub11 ub12 ub13 ub21 ub22 ub23 ub31 ub32 ub33
+
- Sets the UB matrix. Nine values are required.
+
- tasub setnormal n1 n2 n3
+
- This command sets the plane normal which is required in calculations. Normally this
+ plane normal is automatically generated during the calculation of the UB matrix.
+
- tasub settarget qh qk ql qm ki kf
+
- Sets the Q-E target.
+
- tasub r1 qh qk ql a3 a4 sgu sgl ki kf
+
- tasub r2 qh qkl ql a3 a4 sgu sgl ki kf
+
- These commands set the values for the two reflections used for generating the UB
+ matrix.
+
+
+
+
diff --git a/histmem.c b/histmem.c
index db0d79ef..331af5c4 100644
--- a/histmem.c
+++ b/histmem.c
@@ -60,6 +60,7 @@
#include "HistDriv.i"
#include "HistMem.i"
#include "histsim.h"
+#include "mcstashm.h"
#include "dynstring.h"
#include "event.h"
#include "status.h"
@@ -442,6 +443,10 @@
{
pNew->pDriv = CreateSIMHM(pNew->pOption);
}
+ else if(strcmp(driver,"mcstas") == 0)
+ {
+ pNew->pDriv = NewMcStasHM(pNew->pOption);
+ }
else
{
site = getSite();
diff --git a/histsim.c b/histsim.c
index d3bca918..0d085a1e 100644
--- a/histsim.c
+++ b/histsim.c
@@ -49,7 +49,6 @@
#include "HistDriv.i"
#include "histsim.h"
-
static int iSet = 0;
static HistInt iSetVal = 0;
static HistMode eHistMode;
diff --git a/hmdata.c b/hmdata.c
index c55117d5..a57c373b 100644
--- a/hmdata.c
+++ b/hmdata.c
@@ -37,6 +37,19 @@ void killHMData(pHMdata self){
}
free(self);
}
+/*---------------------------------------------------------------------*/
+void clearHMData(pHMdata self){
+ long size;
+ int i;
+ size = 1;
+ for(i = 0; i < self->rank; i++){
+ size *= self->iDim[i];
+ }
+ if(self->tofMode){
+ size *= self->nTimeChan;
+ }
+ memset(self->localBuffer,0,size*sizeof(HistInt));
+}
/*----------------------------------------------------------------------*/
static int resizeBuffer(pHMdata self){
long size;
diff --git a/hmdata.h b/hmdata.h
index 6823d3b0..c7f9f097 100644
--- a/hmdata.h
+++ b/hmdata.h
@@ -32,6 +32,7 @@
pHMdata makeHMData(void);
void killHMData(pHMdata self);
+ void clearHMData(pHMdata self);
int configureHMdata(pHMdata self, pStringDict pOpt,
SConnection *pCon);
diff --git a/hmdata.w b/hmdata.w
index 14c44c9d..bdce46fe 100644
--- a/hmdata.w
+++ b/hmdata.w
@@ -28,6 +28,7 @@ The following functions work on this data structure:
@d hmdatfunc @{
pHMdata makeHMData(void);
void killHMData(pHMdata self);
+ void clearHMData(pHMdata self);
int configureHMdata(pHMdata self, pStringDict pOpt,
SConnection *pCon);
diff --git a/make_gen b/make_gen
index f04b3d15..8ae8a77e 100644
--- a/make_gen
+++ b/make_gen
@@ -27,8 +27,9 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
synchronize.o definealias.o oscillate.o tasdrive.o \
hmcontrol.o userscan.o rs232controller.o lomax.o tasscanub.o \
fourlib.o motreg.o motreglist.o anticollider.o nxdataset.o \
- s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) \
- hmdata.o nxscript.o tclintimpl.o sicsdata.o
+ s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\
+ hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
+ mcstashm.o
MOTOROBJ = motor.o simdriv.o
COUNTEROBJ = countdriv.o simcter.o counter.o
diff --git a/mccontrol.c b/mccontrol.c
new file mode 100644
index 00000000..da079f73
--- /dev/null
+++ b/mccontrol.c
@@ -0,0 +1,398 @@
+ /*----------------------------------------------------------------------------
+ McStas simulation to SICS controller module mplementation file. For more details
+ see mcstas.tex.
+
+ copyright: see file COPYRIGHT
+
+ Mark Koennecke, June 2005
+-----------------------------------------------------------------------------*/
+#include
+#include
+#include
+#include
+#include "stringdict.h"
+#include "mccontrol.h"
+/*========================= life and death ==================================*/
+static void KillMcStasController(void *pData){
+ pMcStasController self = (pMcStasController)pData;
+ if(self == NULL){
+ return;
+ }
+ if(self->pDes != NULL){
+ DeleteDescriptor(self->pDes);
+ }
+ if(self->scripts != NULL){
+ DeleteStringDict(self->scripts);
+ }
+ free(self);
+}
+/*---------------------------------------------------------------------------*/
+int McStasControllerFactory(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]){
+ pMcStasController pNew = NULL;
+
+ pNew = (pMcStasController)malloc(sizeof(McStasController));
+ if(pNew == NULL){
+ SCWrite(pCon,"ERROR: out of memory creating McStasController",
+ eError);
+ return 0;
+ }
+ memset(pNew,0,sizeof(McStasController));
+
+ pNew->pDes = CreateDescriptor("McStasController");
+ pNew->scripts = CreateStringDict();
+ if(pNew->pDes == NULL || pNew->scripts == NULL){
+ SCWrite(pCon,"ERROR: out of memory creating McStasController",
+ eError);
+ free(pNew);
+ return 0;
+ }
+ StringDictAddPair(pNew->scripts,"mcstart","UNDEFINED");
+ StringDictAddPair(pNew->scripts,"mcisrunning","UNDEFINED");
+ StringDictAddPair(pNew->scripts,"mcdump","UNDEFINED");
+ StringDictAddPair(pNew->scripts,"mckill","UNDEFINED");
+ StringDictAddPair(pNew->scripts,"mccopydata","UNDEFINED");
+ StringDictAddPair(pNew->scripts,"mcmonfile","UNDEFINED");
+ pNew->pid = -1;
+
+ return AddCommand(pSics,"mccontrol",
+ McStasControllerWrapper,
+ KillMcStasController,
+ pNew);
+}
+/*====================== interpreter interface ============================*/
+static int configureController(pMcStasController self, SConnection *pCon,
+ int argc, char *argv[]){
+ char pBueffel[256];
+
+ if(argc < 4){
+ SCWrite(pCon,
+ "ERRROR: insufficient number of arguments to mccontrol configure",
+ eError);
+ return 0;
+ }
+ strtolower(argv[2]);
+ if(strcmp(argv[2],"update") == 0){
+ self->updateIntervall = atoi(argv[3]);
+ SCSendOK(pCon);
+ return 1;
+ }
+ if(!StringDictExists(self->scripts,argv[2])){
+ snprintf(pBueffel,255,"ERROR: scriptkey %s does not exist",argv[2]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+ StringDictUpdate(self->scripts,argv[2],argv[3]);
+ SCSendOK(pCon);
+ return 1;
+}
+/*------------------------------------------------------------------------*/
+static void listConfiguration(pMcStasController self, SConnection *pCon){
+ Tcl_DString txt;
+ char pLine[256];
+ char pScript[131];
+
+ Tcl_DStringInit(&txt);
+ StringDictGet(self->scripts,"mcstart",pScript,131);
+ snprintf(pLine,255,"mccontrol.mcstart = %s\n",pScript);
+ Tcl_DStringAppend(&txt,pLine,-1);
+ StringDictGet(self->scripts,"mcisrunning",pScript,131);
+ snprintf(pLine,255,"mccontrol.mcisrunning = %s\n",pScript);
+ Tcl_DStringAppend(&txt,pLine,-1);
+ StringDictGet(self->scripts,"mcdump",pScript,131);
+ snprintf(pLine,255,"mccontrol.mcdump = %s\n",pScript);
+ Tcl_DStringAppend(&txt,pLine,-1);
+ StringDictGet(self->scripts,"mckill",pScript,131);
+ snprintf(pLine,255,"mccontrol.mckill = %s\n",pScript);
+ Tcl_DStringAppend(&txt,pLine,-1);
+ StringDictGet(self->scripts,"mccopydata",pScript,131);
+ snprintf(pLine,255,"mccontrol.mccopydata = %s\n",pScript);
+ Tcl_DStringAppend(&txt,pLine,-1);
+ StringDictGet(self->scripts,"mcmonfile",pScript,131);
+ snprintf(pLine,255,"mccontrol.mcmonfile = %s\n",pScript);
+ Tcl_DStringAppend(&txt,pLine,-1);
+ snprintf(pLine,255,"mccontrol.updateintervall = %d\n",
+ self->updateIntervall);
+ Tcl_DStringAppend(&txt,pLine,-1);
+ snprintf(pLine,255,"mccontrol.pid = %d", self->pid);
+ Tcl_DStringAppend(&txt,pLine,-1);
+
+ SCWrite(pCon,Tcl_DStringValue(&txt),eValue);
+ Tcl_DStringFree(&txt);
+}
+/*--------------------------------------------------------------------------*/
+static int invokeScript(pMcStasController self, char *name, SicsInterp *pSics,
+ char *result, int resultLen){
+ char pCommand[256], pScript[132], pMode[10];
+ Tcl_Interp *pTcl;
+ int status;
+
+ if(!StringDictGet(self->scripts,name,pScript,131)){
+ strncpy(result,"ERROR: script not found",resultLen);
+ return 0;
+ }
+
+ if(strcmp(name,"mccopydata") == 0){
+ snprintf(pCommand,255,"%s",pScript);
+ }else if(strcmp(name,"mcstart") == 0){
+ if(self->mode == eTimer){
+ strcpy(pMode,"timer");
+ }else {
+ strcpy(pMode,"monitor");
+ }
+ snprintf(pCommand,255,"%s %s %f", pScript,pMode,self->fPreset);
+ } else {
+ snprintf(pCommand,255,"%s %d",pScript,self->pid);
+ }
+
+ pTcl = InterpGetTcl(pSics);
+ status = Tcl_Eval(pTcl,pCommand);
+ strncpy(result, pTcl->result, resultLen);
+ if(status == TCL_OK){
+ return 1;
+ } else {
+ return 0;
+ }
+}
+/*------------------------------------------------------------------------*/
+static int runScript(pMcStasController self, SConnection *pCon,
+ SicsInterp *pSics, int argc, char *argv[]){
+ char pResult[256];
+ int status;
+
+ if(argc < 3){
+ SCWrite(pCon,
+ "ERRROR: insufficient number of arguments to mccontrol run",
+ eError);
+ return 0;
+ }
+ status = invokeScript(self,argv[2],pSics,pResult,255);
+ if(status == 1){
+ SCWrite(pCon,pResult,eValue);
+ return 1;
+ } else {
+ SCWrite(pCon,pResult,eError);
+ return 0;
+ }
+}
+/*------------------------------------------------------------------------*/
+static int start(pMcStasController self, SConnection *pCon){
+ int status;
+
+ status = McStasStart(self,eTimer,1000.);
+ if(status != OKOK){
+ SCWrite(pCon,self->errorText,eError);
+ return 0;
+ }
+ SCSendOK(pCon);
+ return 1;
+}
+/*-------------------------------------------------------------------------*/
+int McStasControllerWrapper(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]){
+ pMcStasController self = NULL;
+ char pBueffel[255];
+
+ self = (pMcStasController)pData;
+ assert(self);
+ if(argc < 2) {
+ SCWrite(pCon,"ERROR: insufficient number of arguments to mccontrol",
+ eError);
+ return 0;
+ }
+ strtolower(argv[1]);
+ if(strcmp(argv[1],"configure") == 0){
+ return configureController(self,pCon,argc,argv);
+ } else if(strcmp(argv[1],"list") == 0){
+ listConfiguration(self,pCon);
+ return 1;
+ } else if(strcmp(argv[1],"run") == 0){
+ return runScript(self,pCon,pSics,argc,argv);
+ } else if(strcmp(argv[1],"start") == 0){
+ return start(self,pCon);
+ } else {
+ snprintf(pBueffel,255,"ERROR: subcommand %s to mccontrol unknown",
+ argv[1]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+ return 0;
+}
+/*========================== the actual action functions =================*/
+int McStasStart(pMcStasController self, CounterMode mode, float fPreset){
+ char pResult[256];
+ int status;
+ FILE *fd = NULL;
+
+ self->fPreset = fPreset;
+ self->mode = mode;
+ /**
+ * make sure that the monitor file has only a 0 in it...
+ */
+ if(!StringDictGet(self->scripts,"mcmonfile",pResult,255)){
+ strncpy(self->errorText,"Misconfiguration: no monfile",255);
+ return HWFault;
+ }
+ fd = fopen(pResult,"w");
+ if(fd == NULL){
+ strncpy(self->errorText,"Failed to access monitor file",255);
+ return HWFault;
+ }
+ fprintf(fd,"0\n");
+ fclose(fd);
+
+ /*
+ * invoke start script
+ */
+ status = invokeScript(self,"mcstart",pServ->pSics,pResult,255);
+ if(status == 0){
+ strncpy(self->errorText,pResult,255);
+ return HWFault;
+ }
+
+ /*
+ * some general initializations ..
+ */
+ self->pid = atoi(pResult);
+ self->startTime = time(NULL);
+ self->lastUpdate = self->startTime - self->updateIntervall;
+ return OKOK;
+}
+/*------------------------------------------------------------------------*/
+static long readMonFile(pMcStasController self){
+ char pResult[256];
+ FILE *fd = NULL;
+ long monValue = -1;
+
+ if(!StringDictGet(self->scripts,"mcmonfile",pResult,255)){
+ return -1;
+ }
+ fd = fopen(pResult,"r");
+ if(fd != NULL){
+ fscanf(fd,"%ld", &monValue);
+ fclose(fd);
+ }
+ return monValue;
+}
+/*------------------------------------------------------------------------*/
+int McStasStatus(pMcStasController self, float *fControl){
+ char pResult[256];
+ long monValue;
+ int status, i;
+
+ status = invokeScript(self,"mcisrunning",pServ->pSics,pResult, 255);
+ if(status == 0){
+ strncpy(self->errorText,pResult,255);
+ return HWFault;
+ }
+ status = atoi(pResult);
+ /*
+ * handle timer mode
+ */
+ if(status == 1 && self->mode == eTimer &&
+ time(NULL) >= self->startTime + (int)self->fPreset){
+ McStasStop(self);
+ return HWBusy;
+ } else {
+ *fControl = time(NULL) - self->startTime;
+ }
+ /*
+ * handle monitor mode
+ */
+ if(status == 1 && self->mode == ePreset){
+ monValue = -1;
+ /*
+ * try to read the monfile up to three times. Problems reading it
+ * can be synchronisation problems with McStas
+ */
+ for(i = 0, monValue = -1; i < 3; i++){
+ monValue = readMonFile(self);
+ if(monValue >= 0){
+ break;
+ }
+ }
+ if(monValue < 0){
+ strncpy(self->errorText,"Failed to read monitor file",255);
+ return HWFault;
+ }
+ *fControl = (float)monValue;
+ if(monValue >= (long)self->fPreset){
+ McStasStop(self);
+ }
+ }
+
+ if(status == 1){
+ return HWBusy;
+ } else {
+ self->stopTime = time(NULL);
+ self->pid = -1;
+ return HWIdle;
+ }
+}
+/*-------------------------------------------------------------------------*/
+int McStasStop(pMcStasController self){
+ char pResult[256];
+ invokeScript(self,"mckill",pServ->pSics,pResult, 255);
+ self->lastUpdate = time(NULL) - 3*self->updateIntervall;
+ return 1;
+}
+/*-------------------------------------------------------------------------*/
+int McStasTransferData(pMcStasController self){
+ char pResult[256];
+ int status;
+
+ /*
+ * prevent to frequent requests
+ */
+ if(self->lastUpdate + self->updateIntervall > time(NULL)){
+ return OKOK;
+ }
+
+ if(self->pid >= 0){
+ status = invokeScript(self,"mcdump",pServ->pSics,pResult, 255);
+ if(status == 0){
+ strncpy(self->errorText,pResult,255);
+ return HWFault;
+ }
+ }
+
+ status = invokeScript(self,"mccopydata",pServ->pSics,pResult, 255);
+ if(status == 0){
+ strncpy(self->errorText,pResult,255);
+ return HWFault;
+ }
+ self->lastUpdate = time(NULL);
+ return OKOK;
+}
+/*-------------------------------------------------------------------------*/
+int McStasGetError(pMcStasController self, char *error, int errLen){
+ strncpy(error,self->errorText,errLen);
+ return 1;
+}
+/*-------------------------------------------------------------------------*/
+int McStasFix(pMcStasController self){
+ /*
+ * if the monitor file cannot be read, this may be caused by
+ * a conflict of mCstas writing while we are reading. let us
+ * retry...
+ */
+ if(strstr(self->errorText,"monitor") != NULL){
+ return COREDO;
+ }
+ /*
+ * you have to edit the scripts to fix anything which is going wrong here.
+ * But make sure the simulation is stopped.
+ */
+ McStasStop(self);
+ self->stopTime = time(NULL);
+ self->pid = -1;
+ return COTERM;
+}
+/*-------------------------------------------------------------------------*/
+float McStasGetTime(pMcStasController self){
+ if(self->pid < 0){
+ return (float)(self->stopTime - self->startTime);
+ } else {
+ return (float)time(NULL) - self->startTime;
+ }
+}
diff --git a/mccontrol.h b/mccontrol.h
new file mode 100644
index 00000000..66b3a6b8
--- /dev/null
+++ b/mccontrol.h
@@ -0,0 +1,47 @@
+
+ /*--------------------------------------------------------------------------------------
+ McSas simulation to SICS controller module header file. For more details see
+ mcstas.tex.
+
+ copyright: see file COPYRIGHT
+
+ Mark Koennecke, June 2005
+----------------------------------------------------------------------------------------*/
+#ifndef MCSTASCONTROL
+#define MCSTASCONTROL
+#include "sics.h"
+#include "countdriv.h"
+#include "stringdict.h"
+/*--------------------- data structure -------------------------------------------------*/
+
+ typedef struct{
+ pObjectDescriptor pDes;
+ pStringDict scripts;
+ int updateIntervall;
+ int pid;
+ int lastError;
+ char errorText[256];
+ CounterMode mode;
+ float fPreset;
+ time_t lastUpdate;
+ time_t startTime;
+ time_t stopTime;
+ }McStasController, *pMcStasController;
+
+/*---------------------- function prototypes -------------------------------------------*/
+
+ int McStasControllerFactory(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]);
+ int McStasControllerWrapper(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]);
+
+ int McStasStart(pMcStasController self, CounterMode mode, float fPreset);
+ int McStasStatus(pMcStasController self,float *fControl);
+ int McStasStop(pMcStasController self);
+ int McStasTransferData(pMcStasController self);
+ int McStasGetError(pMcStasController self, char *error, int errLen);
+ int McStasFix(pMcStasController self);
+ float McStasGetTime(pMcStasController self);
+
+#endif
+
diff --git a/mcreader.c b/mcreader.c
new file mode 100644
index 00000000..96b5e19d
--- /dev/null
+++ b/mcreader.c
@@ -0,0 +1,308 @@
+/*-----------------------------------------------------------------------------
+ Implementation file for the McStas reader module. This module helps
+ transferring McStasresult data into SICS counters and histogram memories.
+
+ copyright: see file COPYRIGHT
+
+ Mark Koennecke, June 2005
+-----------------------------------------------------------------------------*/
+#include
+#include "mcreader.h"
+#include "counter.h"
+#include "HistMem.h"
+/*-------------------------------------------------------------------------*/
+static void KillMcReader(void *pData){
+ pMcStasReader self = (pMcStasReader)pData;
+ if(self == NULL){
+ return;
+ }
+ if(self->pDes){
+ DeleteDescriptor(self->pDes);
+ }
+ if(self->handle != NULL){
+ NXclose(&self->handle);
+ }
+ free(self);
+}
+/*--------------------------------------------------------------------------*/
+int McStasReaderFactory(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]){
+ pMcStasReader pNew = NULL;
+
+ pNew = (pMcStasReader)malloc(sizeof(McStasReader));
+ if(pNew == NULL){
+ SCWrite(pCon,"ERROR: out of memory creating McStasReader",eError);
+ return 0;
+ }
+ memset(pNew,0,sizeof(McStasReader));
+
+ pNew->pDes = CreateDescriptor("McStasReader");
+ if(pNew->pDes == NULL){
+ SCWrite(pCon,"ERROR: out of memory creating McStasReader",eError);
+ free(pNew);
+ return 0;
+ }
+ return AddCommand(pSics,"mcreader",
+ McStasReaderWrapper,
+ KillMcReader,
+ pNew);
+}
+/*==================== interpreter interface ===============================*/
+static void MCReportError(void *pData, char *txt){
+ pMcStasReader self = NULL;
+
+ self = (pMcStasReader)pData;
+ if(self != NULL){
+ strncpy(self->nexusError,txt,1024);
+ } else {
+ printf(
+"ERROR: NeXus error in McStasReader without McStasReader data structure: %s\n",
+ txt);
+ }
+}
+/*-------------------------------------------------------------------------*/
+static int openMcStasFile(pMcStasReader self, SConnection *pCon,
+ int argc, char *argv[]){
+ int status;
+ char pBueffel[512];
+
+ if(argc < 3){
+ SCWrite(pCon,"ERROR: need filename argument for opening file",
+ eError);
+ }
+ /*
+ * be nice to users: if file still open, close it
+ */
+ if(self->handle != NULL){
+ NXclose(&self->handle);
+ self->handle = NULL;
+ }
+ /**
+ * open the file
+ */
+ NXMSetError(self,MCReportError);
+ status = NXopen((const char*)argv[2],NXACC_READ,&self->handle);
+ if(status != NX_OK){
+ snprintf(pBueffel,511,"ERROR: NeXus reported %s",
+ self->nexusError);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+ SCSendOK(pCon);
+ return 1;
+}
+/*--------------------------------------------------------------------------*/
+static int closeMcStasFile(pMcStasReader self, SConnection *pCon){
+ if(self->handle != NULL){
+ NXclose(&self->handle);
+ self->handle = NULL;
+ }
+ SCSendOK(pCon);
+ return 1;
+}
+/*-------------------------------------------------------------------*/
+static char *getNextMCNumber(char *pStart, char pNumber[80]){
+ int charCount = 0;
+ pNumber[0] = '\0';
+
+ /* advance to first digit */
+ while(isspace(*pStart) && *pStart != '\0'){
+ pStart++;
+ }
+ if(*pStart == '\0'){
+ return NULL;
+ }
+
+ /* copy */
+ while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){
+ pNumber[charCount] = *pStart;
+ pStart++;
+ charCount++;
+ }
+ pNumber[charCount] = '\0';
+ return pStart;
+}
+/*--------------------------------------------------------------------------*/
+static int insertMonitor(pMcStasReader self, SConnection *pCon,
+ SicsInterp *pSics, int argc, char *argv[]){
+ char pBueffel[512], *pPtr, pNumber[80];
+ pCounter pCount = NULL;
+ int status, mon, monValue, type, rank, iDim[NX_MAXRANK];
+
+ if(argc < 5){
+ SCWrite(pCon,\
+ "ERROR: insufficient number of arguments to mcreader insertmon",
+ eError);
+ return 0;
+ }
+ if(self->handle == NULL){
+ SCWrite(pCon,"ERROR: no file open to read data from",eError);
+ return 0;
+ }
+ pCount = FindCommandData(pSics,argv[3],"SingleCounter");
+ if(pCount == NULL){
+ snprintf(pBueffel,511,
+ "ERROR: %s is no counter object",
+ argv[3]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+ mon = atoi(argv[4]);
+
+ status = NXopenpath(self->handle,argv[2]);
+ if(status != NX_OK){
+ snprintf(pBueffel,511,"ERROR: Nexus error %s while opening %s",
+ self->nexusError, argv[2]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+
+ status = NXgetinfo(self->handle,&rank,iDim,&type);
+ if(status != NX_OK){
+ snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s",
+ self->nexusError, argv[2]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+ if(rank != 1 || type != NX_CHAR || iDim[0] > 511){
+ snprintf(pBueffel,511,"ERROR: %s is no valid monitor data",
+ argv[2]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+
+ status = NXgetdata(self->handle,pBueffel);
+ if(status != NX_OK){
+ snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s",
+ self->nexusError, argv[2]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+
+ /*
+ * the monitor value we want is the third value in the values field
+ */
+ pPtr = pBueffel;
+ memset(pNumber,0,80*sizeof(char));
+ pPtr = getNextMCNumber(pPtr,pNumber);
+ pPtr = getNextMCNumber(pPtr,pNumber);
+ pPtr = getNextMCNumber(pPtr,pNumber);
+ monValue = atoi(pNumber);
+
+ if(pCount != NULL){
+ SetMonitorValue(pCount,mon,(long)monValue);
+ }
+ SCSendOK(pCon);
+ return 1;
+}
+/*--------------------------------------------------------------------------*/
+static int insertHM(pMcStasReader self, SConnection *pCon,
+ SicsInterp *pSics, int argc, char *argv[]){
+ char pBueffel[512], *pPtr, pNumber[80], *pData = NULL;
+ pHistMem pHM = NULL;
+ int status, type, rank, iDim[NX_MAXRANK];
+ int length, i;
+ HistInt *lData = NULL;
+
+ if(argc < 4){
+ SCWrite(pCon,\
+ "ERROR: insufficient number of arguments to mcreader inserthm",
+ eError);
+ return 0;
+ }
+ if(self->handle == NULL){
+ SCWrite(pCon,"ERROR: no file open to read data from",eError);
+ return 0;
+ }
+ pHM = FindCommandData(pSics,argv[3],"HistMem");
+ if(pHM == NULL){
+ snprintf(pBueffel,511,
+ "ERROR: %s is no histogram memory object",
+ argv[3]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+
+ status = NXopenpath(self->handle,argv[2]);
+ if(status != NX_OK){
+ snprintf(pBueffel,511,"ERROR: Nexus error %s while opening %s",
+ self->nexusError, argv[2]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+
+ status = NXgetinfo(self->handle,&rank,iDim,&type);
+ if(status != NX_OK){
+ snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s",
+ self->nexusError, argv[2]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+
+ pData = (char *)malloc(iDim[0]*sizeof(char));
+ if(pData == NULL){
+ SCWrite(pCon,"ERROR: out of memory in mcreader inserthm",eError);
+ return 0;
+ }
+ memset(pData,0,iDim[0]*sizeof(char));
+
+ status = NXgetdata(self->handle,pData);
+ if(status != NX_OK){
+ snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s",
+ self->nexusError, argv[2]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+
+ length = GetHistLength(pHM);
+ lData = (HistInt *)malloc(length*sizeof(HistInt));
+ if(lData== NULL){
+ SCWrite(pCon,"ERROR: out of memory in mcreader inserthm",eError);
+ free(pData);
+ return 0;
+ }
+ memset(lData,0,length*sizeof(HistInt));
+
+ pPtr = pData;
+ for(i = 0; i < length && pPtr != NULL; i++){
+ pPtr = getNextMCNumber(pPtr,pNumber);
+ lData[i] = atoi(pNumber);
+ }
+
+ SetHistogram(pHM,pCon,0,0,length,lData);
+ free(pData);
+ free(lData);
+ SCSendOK(pCon);
+ return 1;
+}
+/*--------------------------------------------------------------------------*/
+int McStasReaderWrapper(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]){
+ pMcStasReader self = NULL;
+ char pBueffel[512];
+
+ self = (pMcStasReader)pData;
+ assert(self != NULL);
+
+ if(argc < 2){
+ SCWrite(pCon,"ERROR: insufficient number of arguments to mcreader",
+ eError);
+ return 0;
+ }
+ strtolower(argv[1]);
+ if(strcmp(argv[1],"open") == 0){
+ return openMcStasFile(self, pCon, argc, argv);
+ } else if(strcmp(argv[1],"close") == 0){
+ return closeMcStasFile(self,pCon);
+ } else if(strcmp(argv[1],"insertmon") == 0){
+ return insertMonitor(self,pCon, pSics,argc,argv);
+ } else if(strcmp(argv[1],"inserthm") == 0){
+ return insertHM(self,pCon, pSics,argc,argv);
+ } else {
+ snprintf(pBueffel,511,"ERROR: invalid subcommand %s to %s",
+ argv[1],argv[0]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+ return 1;
+}
diff --git a/mcreader.h b/mcreader.h
new file mode 100644
index 00000000..8a057535
--- /dev/null
+++ b/mcreader.h
@@ -0,0 +1,28 @@
+
+ /*---------------------------------------------------------------------------------
+ Header file for the McStas reader module. This module helps transferring McStas
+ result data into SICS counters and histogram memories.
+
+ copyright: see file COPYRIGHT
+
+ Mark Koennecke, June 2005
+-------------------------------------------------------------------------------------*/
+#ifndef MCSTASREADER
+#define MCSTASREADER
+#include "sics.h"
+#include "napi.h"
+
+typedef struct {
+ pObjectDescriptor pDes;
+ NXhandle handle;
+ char nexusError[1024];
+ }McStasReader, *pMcStasReader;
+/*-----------------------------------------------------------------------------*/
+ int McStasReaderFactory(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]);
+ int McStasReaderWrapper(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]);
+
+#endif
+
+
\ No newline at end of file
diff --git a/mcstas.tex b/mcstas.tex
new file mode 100644
index 00000000..0a5e8f6a
--- /dev/null
+++ b/mcstas.tex
@@ -0,0 +1,222 @@
+\subsection{McStas Integration}
+It is useful to drive a simulation of an instrument with the same interface as is used at
+the original instruments. One of the better packages for performing simulations of neutron
+scattering instruments, including samples, is McStas. This section describes SICS
+interface to McStas simulations. The interface consists of three parts:
+\begin{itemize}
+\item A McStas controller module which controls the actual simulation.
+\item A McStas reader which is responsible for reading simulated data into
+ SICS counters and histogram memories.
+ \item Counter and histogram memory drivers which redirect their actions to the
+ McStas controller module.
+\end{itemize}
+The general ideas is that all parameters are handled through the normal SICS simulation
+ drivers. The counting operations, however, are linked with the McStas simulation.
+
+\subsubsection{McStas Requirements and SICS Requirements}
+In order for the McStas SICS interface to work the McStas simulation has to be configured
+in a certain way:
+\begin{itemize}
+\item All parameters which have to pass between SICS and McStas have to be declared as
+ simulation parameters in the DEFINE INSTRUMENT section of the instrument definition file.
+ Alternatively SICS can write the data to be passed to McStas into a file. But then this
+ file must be read in the INITIALIZE section of the instrument definition and values must
+ be assigned to the appropriate McStas variables.
+ \item McStas must dump its data into a single file: use the {\it -f filename} option.
+ The format must be {\it --format=\"XML\"}.
+\end{itemize}
+
+\subsubsection{The McStas Controller}
+The connection to the McStas simulation could have been implemented in the counter,
+HM drivers alone. However, these two implementations would share so much code that it
+deemed advisable to separate this logic into a separate module. The McStas controller is
+ basically implementing the Countable SICS interface plus some necessary parameters. In order
+ to be as general as possible many operations of the McStas controller are offloaded to
+ Tcl scripts in order to achieve support for different types of instruments.
+ The following operations will be performed at the various steps:
+ \begin{description}
+ \item[Start Counting] A script will be called which collects the settings parameters from SICS and
+ builds a command line for the McStas simulation. The simulation will then be started. A note
+ is made of the PID of the McStas process.
+ \item[Status Requests]First thing, status checking maps to running a script which decides
+ if the McStas process is still running. Else it is finished. Count control depends
+ on the counting mode:
+\begin{description}
+\item[timer mode] Timer mode is handled in SICS internally. The simulation is started with a
+ generous number of neutron generations and stopped when the time limit has been reached.
+ \item[monitor mode] In monitor mode, the control monitor of McStas is read at regular
+ intervalls. Counting is interrupted when the preset monitor has been exceeded.
+\end{description}
+\item[Stopping] Interrupting the simulation is achived by sending the TERM signal to the
+ McStas process.
+ \item[Data Transfer] Data transfer happens by calling a script which is supposed to use
+ the McStas reader for transferring simulation data into SICS counters and histogram
+ memories. In order to read data during the runtime of the simulation, the signal USR2
+ is sent to the McStas process. This causes McStas to dump a data file. In order for this
+ not to happen to frequently, an update intervall is maintained.
+ \end{description}
+
+
+ In order to do its job the McStas controller needs the following data structure:
+ \begin{flushleft} \small
+\begin{minipage}{\linewidth} \label{scrap1}
+$\langle$mcconint {\footnotesize ?}$\rangle\equiv$
+\vspace{-1ex}
+\begin{list}{}{} \item
+\mbox{}\verb@@\\
+\mbox{}\verb@ typedef struct{@\\
+\mbox{}\verb@ pObjectDescriptor pDes;@\\
+\mbox{}\verb@ pStringDict scripts;@\\
+\mbox{}\verb@ int updateIntervall;@\\
+\mbox{}\verb@ int pid;@\\
+\mbox{}\verb@ int lastError;@\\
+\mbox{}\verb@ char errorText[256];@\\
+\mbox{}\verb@ CounterMode mode;@\\
+\mbox{}\verb@ float fPreset;@\\
+\mbox{}\verb@ time_t lastUpdate;@\\
+\mbox{}\verb@ time_t startTime;@\\
+\mbox{}\verb@ time_t stopTime;@\\
+\mbox{}\verb@ }McStasController, *pMcStasController;@\\
+\mbox{}\verb@ @$\diamond$
+\end{list}
+\vspace{-1ex}
+\footnotesize\addtolength{\baselineskip}{-1ex}
+\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
+\item Macro referenced in scrap ?.
+\end{list}
+\end{minipage}\\[4ex]
+\end{flushleft}
+The fields are:
+ \begin{description}
+ \item[pDes] The usual SICS object descriptor.
+ \item[scripts] A dictionary holding the keys and values for all the scripts required.
+ \item[updateIntervall] The minimum time to leave between updates.
+ \item[pid] The PID of the McStas process. Is negative if the simulation is not running.
+ \item[lastError] The last error code.
+ \item[mode] The count mode.
+ \item[fPreset] The preset value.
+ \item[lastUpdate] The time of the last update.
+ \item[startTime] The starting time of the counting operation.
+ \item[stopTime] The time when counting finished
+ \end{description}
+
+ The prototypes for the McStas controller are:
+ \begin{flushleft} \small
+\begin{minipage}{\linewidth} \label{scrap2}
+$\langle$mcconproto {\footnotesize ?}$\rangle\equiv$
+\vspace{-1ex}
+\begin{list}{}{} \item
+\mbox{}\verb@@\\
+\mbox{}\verb@ int McStasControllerFactory(SConnection *pCon, SicsInterp *pSics, @\\
+\mbox{}\verb@ void *pData, int argc, char *argv[]);@\\
+\mbox{}\verb@ int McStasControllerWrapper(SConnection *pCon, SicsInterp *pSics, @\\
+\mbox{}\verb@ void *pData, int argc, char *argv[]);@\\
+\mbox{}\verb@@\\
+\mbox{}\verb@ int McStasStart(pMcStasController self, CounterMode mode, float fPreset);@\\
+\mbox{}\verb@ int McStasStatus(pMcStasController self,float *fControl);@\\
+\mbox{}\verb@ int McStasStop(pMcStasController self);@\\
+\mbox{}\verb@ int McStasTransferData(pMcStasController self); @\\
+\mbox{}\verb@ int McStasGetError(pMcStasController self, char *error, int errLen);@\\
+\mbox{}\verb@ int McStasFix(pMcStasController self);@\\
+\mbox{}\verb@ float McStasGetTime(pMcStasController self);@\\
+\mbox{}\verb@ @$\diamond$
+\end{list}
+\vspace{-1ex}
+\footnotesize\addtolength{\baselineskip}{-1ex}
+\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
+\item Macro referenced in scrap ?.
+\end{list}
+\end{minipage}\\[4ex]
+\end{flushleft}
+The functions implement the interpreter interface to SICS and the required raw functions
+ for implementing the countable interface.
+
+
+\subsubsection{The McStas Reader}
+A means is needed to map McStas detectors and monitors to SICS monitors and histogram
+memories. This is the purpose of the McStas reader. The McStas reader uses the NeXus-XML
+ API in order to traverse the XML hierarchy. Due to problems with the XML format
+ written by McStas all data is treated as text. The McStas reader decodes this and assigns the data
+ to counter or HM monitors or HM arrays. Most of this modules operation is in the
+ interpreter interface. Thus the signature of this module looks like this:
+ \begin{flushleft} \small
+\begin{minipage}{\linewidth} \label{scrap3}
+$\langle$mcreadint {\footnotesize ?}$\rangle\equiv$
+\vspace{-1ex}
+\begin{list}{}{} \item
+\mbox{}\verb@@\\
+\mbox{}\verb@typedef struct {@\\
+\mbox{}\verb@ pObjectDescriptor pDes;@\\
+\mbox{}\verb@ NXhandle handle;@\\
+\mbox{}\verb@ char nexusError[1024];@\\
+\mbox{}\verb@ }McStasReader, *pMcStasReader;@\\
+\mbox{}\verb@/*-----------------------------------------------------------------------------*/@\\
+\mbox{}\verb@ int McStasReaderFactory(SConnection *pCon, SicsInterp *pSics, @\\
+\mbox{}\verb@ void *pData, int argc, char *argv[]);@\\
+\mbox{}\verb@ int McStasReaderWrapper(SConnection *pCon, SicsInterp *pSics, @\\
+\mbox{}\verb@ void *pData, int argc, char *argv[]); @\\
+\mbox{}\verb@ @$\diamond$
+\end{list}
+\vspace{-1ex}
+\footnotesize\addtolength{\baselineskip}{-1ex}
+\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
+\item Macro referenced in scrap ?.
+\end{list}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft} \small
+\begin{minipage}{\linewidth} \label{scrap4}
+\verb@"mccontrol.h"@ {\footnotesize ? }$\equiv$
+\vspace{-1ex}
+\begin{list}{}{} \item
+\mbox{}\verb@@\\
+\mbox{}\verb@ /*--------------------------------------------------------------------------------------@\\
+\mbox{}\verb@ McSas simulation to SICS controller module header file. For more details see @\\
+\mbox{}\verb@ mcstas.tex. @\\
+\mbox{}\verb@@\\
+\mbox{}\verb@ copyright: see file COPYRIGHT@\\
+\mbox{}\verb@ @\\
+\mbox{}\verb@ Mark Koennecke, June 2005@\\
+\mbox{}\verb@----------------------------------------------------------------------------------------*/@\\
+\mbox{}\verb@#ifndef MCSTASCONTROL@\\
+\mbox{}\verb@#define MCSTASCONTROL@\\
+\mbox{}\verb@#include "sics.h"@\\
+\mbox{}\verb@#include "countdriv.h"@\\
+\mbox{}\verb@#include "stringdict.h"@\\
+\mbox{}\verb@/*--------------------- data structure -------------------------------------------------*/@\\
+\mbox{}\verb@@$\langle$mcconint {\footnotesize ?}$\rangle$\verb@@\\
+\mbox{}\verb@/*---------------------- function prototypes -------------------------------------------*/@\\
+\mbox{}\verb@@$\langle$mcconproto {\footnotesize ?}$\rangle$\verb@@\\
+\mbox{}\verb@#endif@\\
+\mbox{}\verb@@\\
+\mbox{}\verb@@$\diamond$
+\end{list}
+\vspace{-2ex}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft} \small
+\begin{minipage}{\linewidth} \label{scrap5}
+\verb@"mcreader.h"@ {\footnotesize ? }$\equiv$
+\vspace{-1ex}
+\begin{list}{}{} \item
+\mbox{}\verb@@\\
+\mbox{}\verb@ /*---------------------------------------------------------------------------------@\\
+\mbox{}\verb@ Header file for the McStas reader module. This module helps transferring McStas@\\
+\mbox{}\verb@ result data into SICS counters and histogram memories.@\\
+\mbox{}\verb@@\\
+\mbox{}\verb@ copyright: see file COPYRIGHT@\\
+\mbox{}\verb@@\\
+\mbox{}\verb@ Mark Koennecke, June 2005@\\
+\mbox{}\verb@-------------------------------------------------------------------------------------*/@\\
+\mbox{}\verb@#ifndef MCSTASREADER @\\
+\mbox{}\verb@#define MCSTASREADER@\\
+\mbox{}\verb@#include "sics.h"@\\
+\mbox{}\verb@#include "napi.h"@\\
+\mbox{}\verb@@$\langle$mcreadint {\footnotesize ?}$\rangle$\verb@@\\
+\mbox{}\verb@#endif@\\
+\mbox{}\verb@@\\
+\mbox{}\verb@ @$\diamond$
+\end{list}
+\vspace{-2ex}
+\end{minipage}\\[4ex]
+\end{flushleft}
diff --git a/mcstas.w b/mcstas.w
new file mode 100644
index 00000000..acd8ef30
--- /dev/null
+++ b/mcstas.w
@@ -0,0 +1,171 @@
+\subsection{McStas Integration}
+It is useful to drive a simulation of an instrument with the same interface as is used at
+the original instruments. One of the better packages for performing simulations of neutron
+scattering instruments, including samples, is McStas. This section describes SICS
+interface to McStas simulations. The interface consists of three parts:
+\begin{itemize}
+\item A McStas controller module which controls the actual simulation.
+\item A McStas reader which is responsible for reading simulated data into
+ SICS counters and histogram memories.
+ \item Counter and histogram memory drivers which redirect their actions to the
+ McStas controller module.
+\end{itemize}
+The general ideas is that all parameters are handled through the normal SICS simulation
+ drivers. The counting operations, however, are linked with the McStas simulation.
+
+\subsubsection{McStas Requirements and SICS Requirements}
+In order for the McStas SICS interface to work the McStas simulation has to be configured
+in a certain way:
+\begin{itemize}
+\item All parameters which have to pass between SICS and McStas have to be declared as
+ simulation parameters in the DEFINE INSTRUMENT section of the instrument definition file.
+ Alternatively SICS can write the data to be passed to McStas into a file. But then this
+ file must be read in the INITIALIZE section of the instrument definition and values must
+ be assigned to the appropriate McStas variables.
+ \item McStas must dump its data into a single file: use the {\it -f filename} option.
+ The format must be {\it --format=\"XML\"}.
+\item In order to count on monitor, a modified PSD_monitor component MUST be used in the
+ simulation. This component writes the collected total counts into a file. This file is
+ the read by SICS in order to determine the control monitor. Evaluating the McStas XML dump \
+ file each time proved to be to inaccurate.
+\end{itemize}
+
+\subsubsection{The McStas Controller}
+The connection to the McStas simulation could have been implemented in the counter,
+HM drivers alone. However, these two implementations would share so much code that it
+deemed advisable to separate this logic into a separate module. The McStas controller is
+ basically implementing the Countable SICS interface plus some necessary parameters. In order
+ to be as general as possible many operations of the McStas controller are offloaded to
+ Tcl scripts in order to achieve support for different types of instruments.
+ The following operations will be performed at the various steps:
+ \begin{description}
+ \item[Start Counting] A script will be called which collects the settings parameters from SICS and
+ builds a command line for the McStas simulation. The simulation will then be started. A note
+ is made of the PID of the McStas process.
+ \item[Status Requests]First thing, status checking maps to running a script which decides
+ if the McStas process is still running. Else it is finished. Count control depends
+ on the counting mode:
+\begin{description}
+\item[timer mode] Timer mode is handled in SICS internally. The simulation is started with a
+ generous number of neutron generations and stopped when the time limit has been reached.
+ \item[monitor mode] In monitor mode, the control monitor of McStas is read at regular
+ intervalls. Counting is interrupted when the preset monitor has been exceeded.
+\end{description}
+\item[Stopping] Interrupting the simulation is achived by sending the TERM signal to the
+ McStas process.
+ \item[Data Transfer] Data transfer happens by calling a script which is supposed to use
+ the McStas reader for transferring simulation data into SICS counters and histogram
+ memories. In order to read data during the runtime of the simulation, the signal USR2
+ is sent to the McStas process. This causes McStas to dump a data file. In order for this
+ not to happen to frequently, an update intervall is maintained.
+ \end{description}
+
+
+ In order to do its job the McStas controller needs the following data structure:
+ @d mcconint @{
+ typedef struct{
+ pObjectDescriptor pDes;
+ pStringDict scripts;
+ int updateIntervall;
+ int pid;
+ int lastError;
+ char errorText[256];
+ CounterMode mode;
+ float fPreset;
+ time_t lastUpdate;
+ time_t startTime;
+ time_t stopTime;
+ }McStasController, *pMcStasController;
+ @}
+ The fields are:
+ \begin{description}
+ \item[pDes] The usual SICS object descriptor.
+ \item[scripts] A dictionary holding the keys and values for all the scripts required.
+ \item[updateIntervall] The minimum time to leave between updates.
+ \item[pid] The PID of the McStas process. Is negative if the simulation is not running.
+ \item[lastError] The last error code.
+ \item[mode] The count mode.
+ \item[fPreset] The preset value.
+ \item[lastUpdate] The time of the last update.
+ \item[startTime] The starting time of the counting operation.
+ \item[stopTime] The time when counting finished
+ \end{description}
+
+ The prototypes for the McStas controller are:
+ @d mcconproto @{
+ int McStasControllerFactory(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]);
+ int McStasControllerWrapper(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]);
+
+ int McStasStart(pMcStasController self, CounterMode mode, float fPreset);
+ int McStasStatus(pMcStasController self,float *fControl);
+ int McStasStop(pMcStasController self);
+ int McStasTransferData(pMcStasController self);
+ int McStasGetError(pMcStasController self, char *error, int errLen);
+ int McStasFix(pMcStasController self);
+ float McStasGetTime(pMcStasController self);
+ @}
+ The functions implement the interpreter interface to SICS and the required raw functions
+ for implementing the countable interface.
+
+
+\subsubsection{The McStas Reader}
+A means is needed to map McStas detectors and monitors to SICS monitors and histogram
+memories. This is the purpose of the McStas reader. The McStas reader uses the NeXus-XML
+ API in order to traverse the XML hierarchy. Due to problems with the XML format
+ written by McStas all data is treated as text. The McStas reader decodes this and assigns the data
+ to counter or HM monitors or HM arrays. Most of this modules operation is in the
+ interpreter interface. Thus the signature of this module looks like this:
+ @d mcreadint @{
+typedef struct {
+ pObjectDescriptor pDes;
+ NXhandle handle;
+ char nexusError[1024];
+ }McStasReader, *pMcStasReader;
+/*-----------------------------------------------------------------------------*/
+ int McStasReaderFactory(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]);
+ int McStasReaderWrapper(SConnection *pCon, SicsInterp *pSics,
+ void *pData, int argc, char *argv[]);
+ @}
+
+ @o mccontrol.h @{
+ /*--------------------------------------------------------------------------------------
+ McSas simulation to SICS controller module header file. For more details see
+ mcstas.tex.
+
+ copyright: see file COPYRIGHT
+
+ Mark Koennecke, June 2005
+----------------------------------------------------------------------------------------*/
+#ifndef MCSTASCONTROL
+#define MCSTASCONTROL
+#include "sics.h"
+#include "countdriv.h"
+#include "stringdict.h"
+/*--------------------- data structure -------------------------------------------------*/
+@
+/*---------------------- function prototypes -------------------------------------------*/
+@
+#endif
+
+@}
+
+ @o mcreader.h @{
+ /*---------------------------------------------------------------------------------
+ Header file for the McStas reader module. This module helps transferring McStas
+ result data into SICS counters and histogram memories.
+
+ copyright: see file COPYRIGHT
+
+ Mark Koennecke, June 2005
+-------------------------------------------------------------------------------------*/
+#ifndef MCSTASREADER
+#define MCSTASREADER
+#include "sics.h"
+#include "napi.h"
+@
+#endif
+
+ @}
\ No newline at end of file
diff --git a/mcstas/dmc/DataNumber b/mcstas/dmc/DataNumber
new file mode 100644
index 00000000..c8093d83
--- /dev/null
+++ b/mcstas/dmc/DataNumber
@@ -0,0 +1,3 @@
+ 6
+NEVER, EVER modify or delete this file
+You'll risk eternal damnation and a reincarnation as a cockroach!|n
\ No newline at end of file
diff --git a/mcstas/dmc/PSD_monitor.comp b/mcstas/dmc/PSD_monitor.comp
new file mode 100644
index 00000000..cb72e484
--- /dev/null
+++ b/mcstas/dmc/PSD_monitor.comp
@@ -0,0 +1,141 @@
+/*******************************************************************************
+*
+* McStas, neutron ray-tracing package
+* Copyright 1997-2002, All rights reserved
+* Risoe National Laboratory, Roskilde, Denmark
+* Institut Laue Langevin, Grenoble, France
+*
+* Component: PSD_monitor
+*
+* %I
+* Written by: Kim Lefmann
+* Date: Feb 3, 1998
+* Version: $Revision: 1.1 $
+* Origin: Risoe
+* Release: McStas 1.6
+*
+* Hacked by to dump the total number of neutrons any dumpCount
+* neutrons into a very simple one line file. This is needed to stay in control
+* for virtual instruments.
+*
+* Mark Koennecke, June 2005
+*
+* Position-sensitive monitor.
+*
+* %D
+* An (n times m) pixel PSD monitor. This component may also be used as a beam
+* detector.
+*
+* Example: PSD_monitor(xmin=-0.1, xmax=0.1, ymin=-0.1, ymax=0.1,
+ nx=90, ny=90, filename="Output.psd")
+*
+* %P
+* INPUT PARAMETERS:
+*
+* xmin: Lower x bound of detector opening (m)
+* xmax: Upper x bound of detector opening (m)
+* ymin: Lower y bound of detector opening (m)
+* ymax: Upper y bound of detector opening (m)
+* nx: Number of pixel columns (1)
+* ny: Number of pixel rows (1)
+* filename: Name of file in which to store the detector image (text)
+* controlfile: A file to which the total number of neutrons detected is dumped
+* any dumpCount counts.
+* dumpCount: The number of counst after which a controlfile is written. A negative
+* value switches the feauture off.
+* OUTPUT PARAMETERS:
+*
+* PSD_N: Array of neutron counts
+* PSD_p: Array of neutron weight counts
+* PSD_p2: Array of second moments
+* totalCounts: The total number of counts in the detector
+* currentCount: The current counter since the last dump.
+*
+* %E
+*******************************************************************************/
+
+
+DEFINE COMPONENT PSD_monitor
+DEFINITION PARAMETERS (nx=90, ny=90, filename, controlfile="mon01.dat")
+SETTING PARAMETERS (xmin, xmax, ymin, ymax, int dumpCount = -1.)
+OUTPUT PARAMETERS (PSD_N, PSD_p, PSD_p2, totalCount, currentCount)
+STATE PARAMETERS (x,y,z,vx,vy,vz,t,s1,s2,p)
+
+SHARE
+%{
+ void dumpTotal(char *ffilename, long totalCounts){
+ FILE *fd = NULL;
+
+ fd = fopen(ffilename,"w");
+ if(fd != NULL){
+ fprintf(fd,"%ld\n",totalCounts);
+ fclose(fd);
+ }
+ }
+%}
+
+DECLARE
+ %{
+ long totalCount, currentCount;
+ double PSD_N[nx][ny];
+ double PSD_p[nx][ny];
+ double PSD_p2[nx][ny];
+ %}
+INITIALIZE
+ %{
+ int i,j;
+
+ for (i=0; ixmin && xymin && y 0 && currentCount > dumpCount){
+ dumpTotal(controlfile,totalCount);
+ currentCount = 0;
+ }
+ SCATTER;
+ }
+ %}
+SAVE
+ %{
+ DETECTOR_OUT_2D(
+ "PSD monitor",
+ "X position [cm]",
+ "Y position [cm]",
+ xmin*100.0, xmax*100.0, ymin*100.0, ymax*100.0,
+ nx, ny,
+ &PSD_N[0][0],&PSD_p[0][0],&PSD_p2[0][0],
+ filename);
+ %}
+
+MCDISPLAY
+%{
+ magnify("xy");
+ multiline(5, (double)xmin, (double)ymin, 0.0,
+ (double)xmax, (double)ymin, 0.0,
+ (double)xmax, (double)ymax, 0.0,
+ (double)xmin, (double)ymax, 0.0,
+ (double)xmin, (double)ymin, 0.0);
+%}
+
+END
diff --git a/mcstas/dmc/batch.tcl b/mcstas/dmc/batch.tcl
new file mode 100644
index 00000000..afd1af2e
--- /dev/null
+++ b/mcstas/dmc/batch.tcl
@@ -0,0 +1,8 @@
+proc SplitReply { text } {
+ set l [split $text =]
+ return [lindex $l 1]
+}
+
+proc batchrun file {
+ fileeval [string trim [SplitReply [BatchRoot]]/$file]
+}
diff --git a/mcstas/dmc/dmc.dic b/mcstas/dmc/dmc.dic
new file mode 100644
index 00000000..abbeaa4f
--- /dev/null
+++ b/mcstas/dmc/dmc.dic
@@ -0,0 +1,89 @@
+##NXDICT-1.0
+#----------------------------------------------------------------------------
+# NeXus dictionary file for the SINQ instrument DMC and HRPT
+#
+# DO NOT EDIT WHEN YOU DO NOT KNOW WHAT YOU ARE DOING!
+# This file determines the placement of data items in the Powder NeXus
+# data file. Your data may not be readable if this file is messed up.
+#
+# Mark Koennecke, May 2004
+#----------------------------------------------------------------------------
+inst=DMC
+detector=DMC-BF3-Detector
+noofdetectors=400
+#---------- NXentry level
+etitle=/entry1,NXentry/SDS title -type DFNT_CHAR -rank 1
+estart=/entry1,NXentry/SDS start_time -type DFNT_CHAR -rank 1
+eend=/entry1,NXentry/SDS end_time -type DFNT_CHAR -rank 1
+#----------------- NXinstrument
+iname=/entry1,NXentry/$(inst),NXinstrument/SDS name -type DFNT_CHAR \
+ -rank 1 -dim {132}
+#----------------- NXsource
+sname=/entry1,NXentry/$(inst),NXinstrument/SINQ,NXsource/SDS name \
+ -type DFNT_CHAR -rank 1
+stype=/entry1,NXentry/$(inst),NXinstrument/SINQ,NXsource/SDS type \
+ -type DFNT_CHAR -rank 1
+#-------------- Monochromator
+mname=/entry1,NXentry/$(inst),NXinstrument/Monochromator,NXcrystal/SDS type \
+ -type DFNT_CHAR -rank 1
+mtheta=/entry1,NXentry/$(inst),NXinstrument/Monochromator,NXcrystal/SDS \
+ theta
+mttheta=/entry1,NXentry/$(inst),NXinstrument/Monochromator,NXcrystal/SDS \
+ two_theta
+mlambda=/entry1,NXentry/$(inst),NXinstrument/Monochromator,NXcrystal/SDS \
+ lambda -attr {units,Angstroem}
+mdd=/entry1,NXentry/$(inst),NXinstrument/Monochromator,NXcrystal/SDS \
+ d_spacing -attr {units,Angstroem}
+mcurve=/entry1,NXentry/$(inst),NXinstrument/Monochromator,NXcrystal/SDS \
+ curvature
+monox=/entry1,NXentry/$(inst),NXinstrument/Monochromator,NXcrystal/SDS \
+ x_translation
+monoy=/entry1,NXentry/$(inst),NXinstrument/Monochromator,NXcrystal/SDS \
+ y_translation
+mchi=/entry1,NXentry/$(inst),NXinstrument/Monochromator,NXcrystal/SDS \
+ chi
+mphi=/entry1,NXentry/$(inst),NXinstrument/Monochromator,NXcrystal/SDS \
+ phi
+#------------- counter
+cter_mode=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ CounterMode -type DFNT_CHAR -rank 1 -dim {30}
+cter_preset=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ Preset -type NX_INT32
+cter_time=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ time
+
+cter_01=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ Monitor -type DFNT_INT32 -attr {units,counts}
+cter_00=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ beam_monitor -type DFNT_INT32 -attr {units,counts}
+cter_04=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ proton_monitor -type DFNT_INT32 -attr {units,counts}
+#-------------- detector bank
+dtheta=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ two_theta -rank 1 -dim {$(noofdetectors)} -attr {axis,1} \
+ -attr {units,degree}
+dcounts=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ counts -type DFNT_INT32 -LZW -rank 1 -dim {$(noofdetectors)} \
+ -attr {signal,1}
+dthst=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ two_theta_start -attr {units,degree}
+dtstep=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ Step -attr {units,degree}
+dtnstep=/entry1,NXentry/$(inst),NXinstrument/$(detector),NXpsd/SDS \
+ no_of_steps -type NX_INT32
+#--------------- Sample
+saname=/entry1,NXentry/sample,NXsample/SDS sample_name -type DFNT_CHAR \
+ -rank 1
+devname=/entry1,NXentry/sample,NXsample/SDS device_name -type DFNT_CHAR \
+ -rank 1
+stemp=/entry1,NXentry/sample,NXsample/SDS sample_temperature -attr {units,K}
+smean=/entry1,NXentry/sample,NXsample/SDS temperature_mean -attr {units,K}
+stddev=/entry1,NXentry/sample,NXsample/SDS temperature_stddev -attr {units,K}
+mfield=/entry1,NXentry/sample,NXsample/SDS magfield -attr {units,T}
+saangle=/entry1,NXentry/sample,NXsample/SDS sample_table_rotation \
+ -attr {units,degree}
+smur=/entry1,NXentry/sample,NXsample/SDS sample_mur \
+ -attr {units,degree}
+#----------------NXdata ------------------------------------------------
+dana=/entry1,NXentry/data1,NXdata/NXVGROUP
+
diff --git a/mcstas/dmc/dmc_sics01.instr b/mcstas/dmc/dmc_sics01.instr
new file mode 100644
index 00000000..59b08c23
--- /dev/null
+++ b/mcstas/dmc/dmc_sics01.instr
@@ -0,0 +1,184 @@
+DEFINE INSTRUMENT DMC_diff(TKOFF,lambda,char *samplefile, char *monfile)
+DECLARE
+%{
+double mono_q = 1.87;
+double OMA;
+double RV;
+double y_mono = 0.025;
+double NV = 5;
+double d_phi_0;
+double TKOFF;
+double sample_radius = 0.005;
+double sample_height = 0.03;
+double lambda;
+double ldiff=0.5;
+char *samplefile;
+%}
+
+INITIALIZE
+%{
+OMA = TKOFF/2;
+RV = fabs(2*2.82*sin(DEG2RAD*OMA));
+%}
+
+TRACE
+
+COMPONENT source_arm = Arm()
+AT (0, 0, 0) ABSOLUTE
+
+/* values for guide side window RNR12 */
+COMPONENT csource = Source_gen(
+ radius = 0.08,xw = 0.02, yh = 0.12, dist = 1.5,
+ Lambda0 = lambda, dLambda = ldiff,
+ T1=150.42,I1=5.98e11,
+ T2=37.23,I2=5.637e11,T3=14.9,I3=0.962e11)
+AT (0,0,0) RELATIVE source_arm ROTATED (0,0,0) RELATIVE source_arm
+
+/* guide segment 1, m=2, 4.66 m */
+ COMPONENT guide1 = Guide(w1=0.02, h1=0.12, w2=0.02, h2=0.12,
+ l=4.66, R0=0.995, Qc=0.0217, alpha = 5.76,
+ m = 2.0, W = 0.0033)
+ AT (0,0,1.5) RELATIVE source_arm ROTATED (0,0,0) RELATIVE source_arm
+
+/* guide segment 2, curved, m=2, 24.5 m */
+COMPONENT guide2 = Bender(
+ w = 0.02, h = 0.12, r = 3612, R0a = 0.995, Qca = 0.0217,
+ alphaa = 5.76, ma = 2, Wa = 0.0033, R0i = 0.995, Qci = 0.0217,
+ alphai = 5.76, mi = 2, Wi = 0.0033, R0s = 0.995, Qcs = 0.0217,
+ alphas = 5.76, ms = 2, Ws = 0.0033, l = 24.5)
+ AT (0,0,6.16) RELATIVE source_arm ROTATED (0,0,0) RELATIVE source_arm
+
+/* bunker wall, m=2, 3.0 m */
+ COMPONENT bunker = Guide(
+ w1=0.02, h1=.12, w2=0.02, h2=.12,
+ l=3.0, R0=0.995, Qc=0.0217, alpha = 5.76,
+ m = 2.0, W = 0.0033)
+ AT (0,0,30.66) RELATIVE source_arm ROTATED (0,0,0) RELATIVE source_arm
+
+/* guide segment 3, m=2, 8.84 m */
+
+ COMPONENT guide3 = Guide(
+ w1=0.02, h1=.12, w2=0.02, h2=.12,
+ l=8.84, R0=0.995,Qc=0.0217, alpha = 5.76,
+ m = 2.0, W = 0.0033)
+ AT (0,0,33.66) RELATIVE source_arm ROTATED (0,0,0) RELATIVE source_arm
+
+/* guide exit at 42.5 m - measured flux 2.46 10e8 cm-2 s-1 mA-1 */
+
+COMPONENT in_slit = Slit(
+ xmin = -0.01, xmax=0.01 , ymin = -0.06, ymax = 0.06)
+ AT (0,0,42.5) RELATIVE source_arm ROTATED (0,0,0) RELATIVE source_arm
+
+/* Monochromator description */
+
+COMPONENT sma = Arm() /* source - monochromator arm */
+AT (0, 0, 43.15) RELATIVE source_arm ROTATED (0,OMA,0) RELATIVE source_arm
+
+
+COMPONENT foc_mono = Monochromator_2foc(
+ zwidth = 0.05, yheight = 0.025, gap = 0.0005, NH = 1, NV = 5,
+ mosaich = 38, mosaicv = 38, r0 = 0.7, Q = 1.8857, RV = RV,
+ RH = 0)
+AT (0, 0, 0) RELATIVE sma
+
+COMPONENT msa = Arm() /* monochromator - sample arm */
+ AT (0, 0, 0) RELATIVE sma ROTATED (0, TKOFF, 0) RELATIVE source_arm
+
+COMPONENT out1_slit = Slit(
+ xmin=-0.01, xmax=0.01, ymin=-0.06, ymax=0.06)
+ AT (0,0,0.2) RELATIVE msa ROTATED (0,0,0) RELATIVE msa
+
+COMPONENT Amoin_slit = Slit(
+ xmin=-0.01, xmax=0.01, ymin=-0.06, ymax=0.06)
+ AT (0,0,0.325) RELATIVE msa ROTATED (0,0,0) RELATIVE msa
+
+COMPONENT Bmoin_slit = Slit(
+ xmin=-0.01, xmax=0.01, ymin=-0.06, ymax=0.06)
+ AT (0,0,0.525) RELATIVE msa ROTATED (0,0,0) RELATIVE msa
+
+COMPONENT out2_slit = Slit(
+ xmin=-0.01, xmax=0.01, ymin=-0.06, ymax=0.06)
+ AT (0,0,0.65) RELATIVE msa ROTATED (0,0,0) RELATIVE msa
+
+COMPONENT PSD_sample = PSD_monitor(
+ xmin=-0.05, xmax=0.05, ymin=-0.07, ymax=0.07,
+ nx=80, ny=80, filename="PSD_sample.dat",controlfile=monfile, dumpCount=500)
+ AT ( 0, 0, 1.5) RELATIVE msa
+
+COMPONENT sa_arm = Arm()
+ AT (0, 0, 2.82) RELATIVE msa
+ ROTATED (0, 0, 0) RELATIVE msa
+
+COMPONENT sample = PowderN (
+ d_phi0=40,radius=sample_radius, h=sample_height,
+ pack=1, Vc=1076.98, reflections = samplefile,
+ sigma_a=0.2, target_index=+4)
+ AT ( 0, 0, 0) RELATIVE sa_arm
+
+COMPONENT sda = Arm() /* sample-detector arm */
+ AT (0, 0, 0) RELATIVE sa_arm ROTATED (0, -93.8, 0) RELATIVE sa_arm
+
+COMPONENT Det9 = Monitor_nD(
+ xwidth=3.0,yheight=0.09,
+ options="banana theta limits [19 99] bins=400, file=det9.dat")
+AT (0,0,0) RELATIVE sa_arm
+ROTATED (0, 0, 180) RELATIVE sa_arm
+
+END
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mcstas/dmc/log.tcl b/mcstas/dmc/log.tcl
new file mode 100644
index 00000000..fa70cf2a
--- /dev/null
+++ b/mcstas/dmc/log.tcl
@@ -0,0 +1,84 @@
+#-----------------------------------------------------------------------------
+# This file implements a LogBook facility for SICS.
+# Usage:
+# LogBook - lists the current status
+# LogBook filename - sets the logbook file name
+# LogBook on - starts logging, creates new file
+# LogBook off - closes log file
+#
+# Mark Koennecke, June 1997, initially developed for SANS
+# works using one procedure and an array for data. All internal procedures
+# start with cli
+#----------------------------------------------------------------------------
+
+set cliArray(file) default.log
+set cliArray(status) off
+set cliArray(number) 0
+#---------------------------------------------------------------------------
+proc cliList { } {
+ global cliArray
+# ClientPut [format " LogBook file: %s\n" $cliArray(file)]
+# ClientPut [format " Logging: %s " $cliArray(status)] ]
+ append res [format " LogBook file: %s\n" $cliArray(file)] \
+ [format " Logging: %s " $cliArray(status)]
+ return $res
+}
+#-------------------------------------------------------------------------
+proc cliLogOn { } {
+ global cliArray
+ set cmd [list config File $cliArray(file)]
+ set ret [catch {eval $cmd} msg]
+ if { $ret != 0 } {
+ error $msg
+ } else {
+ set l [ split $msg = ]
+ set cliArray(number) [lindex $l 1]
+ set cliArray(status) on
+ }
+}
+#--------------------------------------------------------------------------
+proc cliLogOff { } {
+ global cliArray
+ set cmd [list config close $cliArray(number)]
+ set ret [catch {eval $cmd} msg]
+ if { $ret != 0 } {
+ error $msg
+ } else {
+ set cliArray(status) off
+ }
+}
+#-------------------------------------------------------------------------
+proc logbook args {
+ global cliArray
+#---- first case: a listing
+ if { [llength $args] == 0} {
+ return [cliList]
+ }
+#---- there must be an argument
+ set argument [lindex $args 0]
+#---- on/ off
+ if {[string compare "on" $argument] == 0} {
+ set ret [catch {cliLogOn} msg]
+ if { $ret != 0 } {
+ error $msg
+ } else {
+ ClientPut OK
+ }
+ } elseif {[string compare "off" $argument] == 0} {
+ set ret [catch {cliLogOff} msg]
+ if { $ret != 0 } {
+ error $msg
+ } else {
+ ClientPut OK
+ }
+ } elseif {[string compare "file" $argument] >= 0} {
+ if {[llength $args] < 1} {
+ error "ERROR: nor filename specified for LogBook"
+ }
+ set cliArray(file) [lindex $args 1]
+ } elseif {[string compare "no" $argument] == 0} {
+ ClientPut $cliArray(number)
+ } else {
+ error [format "ERROR: unknown argument %s to LogBook" $argument]
+ }
+}
diff --git a/mcstas/dmc/mcsupport.tcl b/mcstas/dmc/mcsupport.tcl
new file mode 100644
index 00000000..582c0a5a
--- /dev/null
+++ b/mcstas/dmc/mcsupport.tcl
@@ -0,0 +1,66 @@
+#-------------------------------------------------------------------
+# These are a couple of Tcl function which help with the interface
+# between SICS and McStas
+#
+# Mark Koennecke, June 2005
+#--------------------------------------------------------------------
+# washsimfile fixes the evil NXsimulation name ="./dmc.xml" thing in
+# the XML file. Path separators in name attributes throw off
+# NXopenpath
+#--------------------------------------------------------------------
+proc washsimfile {name} {
+ set oriname $name
+ set in [open $name "r"]
+ set name [file tail $name]
+ set out [open /tmp/$name "w"]
+ while { [gets $in line] >= 0} {
+ if { [string first "NXsimulation name=" $line] > 0} {
+ puts $out ""
+ } else {
+ puts $out $line
+ }
+ }
+ close $in
+ close $out
+ file copy -force /tmp/$name $oriname
+ file delete /tmp/$name
+}
+#---------------------------------------------------------------------
+# When McStas dumps or is killed we need to give McStas some time to
+# dump its data. Otherwise we observe that data reading fails.
+# mcwaittime is used for this. Increase if you see problems
+#--------------------------------------------------------------------
+set mcwaittime 7
+#----------------------------------------------------------------------
+proc mcstasdump {pid} {
+ global mcwaittime
+ catch {eval exec /usr/bin/kill -USR2 $pid}
+ wait $mcwaittime
+}
+#-----------------------------------------------------------------------
+proc mcstasisrunning {pid} {
+ set ret [catch {eval exec /bin/ps --pid $pid} msg]
+ if {$ret == 0} {
+ return 1
+ } else {
+ return 0;
+ }
+}
+#-----------------------------------------------------------------------
+proc mcstaskill {pid} {
+ global mcwaittime
+ catch {eval exec /usr/bin/kill -TERM $pid}
+ wait $mcwaittime
+}
+#-----------------------------------------------------------------------
+proc mcinstall {} {
+ allowexec /usr/bin/kill
+ allowexec /bin/ps
+ Publish mcstasdump User
+ Publish mcstasisrunning User
+ Publish mcstaskill User
+ mccontrol configure mcdump mcstasdump
+ mccontrol configure mckill mcstaskill
+ mccontrol configure mcisrunning mcstasisrunning
+ mccontrol configure update 300
+}
diff --git a/mcstas/dmc/na2ca3al2f14.q b/mcstas/dmc/na2ca3al2f14.q
new file mode 100644
index 00000000..7646bee9
--- /dev/null
+++ b/mcstas/dmc/na2ca3al2f14.q
@@ -0,0 +1,29 @@
+// mult Q(hkl) F2 DW w
+12 0.8669 0.81 1 0
+6 1.2259 16.0 1 0
+24 1.5015 9.0 1 0
+12 1.7338 40.96 1 0
+12 1.9384 7.84 1 0
+12 1.9384 0.64 1 0
+8 2.1234 26.01 1 0
+24 2.2936 5.29 1 0
+24 2.2936 10.24 1 0
+6 2.4519 62.41 1 0
+24 2.601 38.44 1 0
+12 2.601 0.81 1 0
+12 2.7413 56.25 1 0
+12 2.7413 60.84 1 0
+24 2.8751 161.29 1 0
+24 3.003 4.41 1 0
+24 3.1256 108.16 1 0
+12 3.1256 1.96 1 0
+12 3.1256 18.49 1 0
+24 3.1256 51.84 1 0
+24 3.3574 116.64 1 0
+24 3.3574 53.29 1 0
+12 3.4675 256.0 1 0
+12 3.5743 28.09 1 0
+12 3.5743 0.81 1 0
+24 3.5743 4.0 1 0
+24 3.6779 39.69 1 0
+6 3.6779 33.64 1 0
diff --git a/mcstas/dmc/nxdmc.tcl b/mcstas/dmc/nxdmc.tcl
new file mode 100644
index 00000000..272fa0a9
--- /dev/null
+++ b/mcstas/dmc/nxdmc.tcl
@@ -0,0 +1,108 @@
+#--------------------------------------------------------------------------
+# NeXus file writing for DMC
+#
+# This is the scripted version using nxscript
+#
+# Mark Koennecke, May 2004
+#---------------------------------------------------------------------------
+
+proc storeMonochromator {} {
+ nxscript puttext mname "Pyrolithic Graphite 002"
+ writeFloatVar mtheta OmegaM
+ writeFloatVar mttheta TwoThetaM
+ writeFloatVar mlambda lambda
+ writeFloatVar mcurve CurveM
+ writeFloatVar monox MonoX
+ writeFloatVar monoy MonoY
+ writeFloatVar mchi MonoChi
+ writeFloatVar mphi MonoPhi
+ set dd [SplitReply [mono dd]]
+ set dd [string trim $dd]
+ set ret [catch {expr $dd * 1.0} msg]
+ if {$ret != 0} {
+ clientput "ERROR: failed to read monochromator d spacing"
+ } else {
+ nxscript putfloat mdd $dd
+ }
+}
+#------------------------------------------------------------------------
+proc storeSample {} {
+ writeTextVar saname sample
+ writeFloatVar saangle Table
+ set ret [catch {set temp [SplitReply [temperature]]} msg]
+ if {$ret == 0} {
+ nxscript putfloat stemp $temp
+ set dname [string trim [SplitReply [temperature driver]]]
+ if {"$dname" == "tecs"} {
+ set dname [SplitReply [temperature device]]
+ }
+ nxscript puttext devname $dname
+ set ret [catch {temperature log getmean} msg]
+ if {$ret == 0} {
+ set l [split $msg =]
+ set stddev [string trim [lindex $l 2]]
+ set l2 [split [string trim [lindex $l 1]]]
+ set mean [string trim [lindex $l2 0]]
+ nxscript putfloat smean $mean
+ nxscript putfloat stddev $stddev
+ }
+ }
+ writeFloatVar smur sample_mur
+ set ret [catch {set mtemp [SplitReply [magfield]]} msg]
+ if {$ret == 0} {
+ nxscript putfloat mfield $mtemp
+ }
+}
+#---------------------------------------------------------------------
+proc storeDetector {ndet stepwidth} {
+ nxscript udpatedictvar noofdetectors $ndet
+ set start [string trim [SplitReply [TwoThetaD]]]
+ for {set i 0} { $i < $ndet} {incr i} {
+ set th($i) [expr $start + $i * $stepwidth]
+ }
+ nxscript putfloat dthst $start
+ nxscript putfloat dtstep $stepwidth
+ nxscript putint dtnstep [string trim $ndet]
+ nxscript putarray dtheta th 400
+ nxscript puthm dcounts banana
+}
+#----------------------------------------------------------------------
+proc makeLinks {} {
+ nxscript makelink dana dcounts
+ nxscript makelink dana dtheta
+ nxscript makelink dana dthst
+ nxscript makelink dana dtstep
+ nxscript makelink dana dtnstep
+ nxscript makelink dana mlambda
+ }
+#-------------------------------------------------------------------------
+# store DMC data
+#-------------------------------------------------------------------------
+proc storedata {} {
+ global home
+ set fil [newFileName]
+ clientput "Opening $fil for writing"
+ nxscript create4 $fil $home/dmc.dic
+
+ writeStandardAttributes $fil
+ writeTextVar etitle title
+ nxscript puttext estart [sicstime]
+ nxscript puttext iname "DMC at SINQ"
+ nxscript puttext sname "SINQ"
+ nxscript puttext stype "Continuous flux spallation source"
+
+ nxscript updatedictvar inst DMC
+ nxscript updatedictvar detector "DMC-BF3-Detector"
+
+ storeMonochromator
+
+ storeSample
+
+ nxscript putcounter cter counter
+
+ storeDetector 400 .2
+
+ makeLinks
+
+ nxscript close
+}
diff --git a/mcstas/dmc/nxsupport.tcl b/mcstas/dmc/nxsupport.tcl
new file mode 100644
index 00000000..29157c01
--- /dev/null
+++ b/mcstas/dmc/nxsupport.tcl
@@ -0,0 +1,96 @@
+#===========================================================================
+# Support routines for scripting NeXus files with nxscript.
+#
+# Mark Koennecke, February 2003
+# Mark Koennecke, January 2004
+#==========================================================================
+proc makeFileName args {
+ sicsdatanumber incr
+ set num [SplitReply [sicsdatanumber]]
+ set p [string trim [SplitReply [sicsdatapath]]]
+ set pre [string trim [SplitReply [sicsdataprefix]]]
+ set po [string trim [SplitReply [sicsdatapostfix]]]
+ return [format "%s%s%5.5d2003%s" $p $pre $num $po]
+}
+#==========================================================================
+# new version, attending to the new 1000 grouping logic
+proc newFileName args {
+ set ret [catch {nxscript makefilename} msg]
+ if {$ret != 0} {
+ clientput "ERROR: Misconfiguration of file writing variables"
+ clientput "Defaulting filename to emergency.hdf"
+ set fil emergency.hdf
+ } else {
+ set fil $msg
+ }
+ return $fil
+}
+#==========================================================================
+proc writeFloatVar {alias var} {
+ set ret [catch {set val [SplitReply [$var]]} val]
+ if { $ret != 0} {
+ clientput [format "ERROR: failed to read %s, %s" $var $val]
+ return
+ } else {
+ set val [string trim $val]
+ set ret [catch {expr $val * 1.0} val]
+ if { $ret == 0} {
+ nxscript putfloat $alias [expr $val * 1.0 ]
+ } else {
+ clientput "ERROR: bad value $val when reading $var"
+ }
+ }
+}
+#==========================================================================
+proc writeIntVar {alias var} {
+ set ret [catch {set val [SplitReply [$var]]} val]
+ if { $ret != 0} {
+ clientput [format "ERROR: failed to read %s, %s" $var $val]
+ return
+ } else {
+ set val [string trim $val]
+ set ret [catch {expr $val * 1.0} val]
+ if { $ret == 0} {
+ nxscript putint $alias [expr int($val * 1.0) ]
+ } else {
+ clientput "ERROR: bad value $val when reading $var"
+ }
+ }
+}
+#=========================================================================
+proc writeTextVar {alias var} {
+ set ret [catch {$var} val]
+ if { $ret != 0} {
+ clientput [format "ERROR: failed to read %s" $var]
+ return
+ } else {
+ set index [string first = $val]
+ if {$index >= 0} {
+ set txt [string trim [string range $val [expr $index + 1] end]]
+ nxscript puttext $alias $txt
+ } else {
+ clientput [format "ERROR: failed to read %s" $var]
+ }
+ }
+}
+#========================================================================
+proc writeTextAttribute {attName var} {
+ set ret [catch {set val [SplitReply [$var]]} val]
+ if { $ret != 0} {
+ clientput [format "ERROR: failed to read %s" $var]
+ return
+ } else {
+ nxscript putglobal $attName [string trim $val]
+ }
+}
+#=======================================================================
+proc writeStandardAttributes {fileName} {
+ nxscript putglobal file_name $fileName
+ nxscript putglobal file_time [sicstime]
+ writeTextAttribute instrument instrument
+ writeTextAttribute owner user
+ writeTextAttribute owner_telephone_number phone
+ writeTextAttribute owner_fax_number fax
+ writeTextAttribute owner_email email
+ writeTextAttribute owner_address adress
+}
diff --git a/mcstas/dmc/vdmc.tcl b/mcstas/dmc/vdmc.tcl
new file mode 100644
index 00000000..87a10d2d
--- /dev/null
+++ b/mcstas/dmc/vdmc.tcl
@@ -0,0 +1,138 @@
+# --------------------------------------------------------------------------
+# Initialization script for a virtual DMC instrument using a McStas
+# simulationas a data source
+#
+# Dr. Mark Koennecke, June 2005
+#---------------------------------------------------------------------------
+# O P T I O N S
+
+set home $env(HOME)/src/workspace/sics/mcstas/dmc
+
+#--------------------------------- first all the server options are set
+#ServerOption RedirectFile $home/stdcdmc
+ServerOption ReadTimeOut 0
+ServerOption AcceptTimeOut 0
+ServerOption ReadUserPasswdTimeout 500000
+ServerOption LogFileBaseName "$home/vdmclog"
+ServerOption LogFileDir $home/
+ServerOption ServerPort 2911
+ServerOption statusfile $home/vdmcstatus.tcl
+ServerOption InterruptPort 3007
+ServerOption TelnetPort 1301
+ServerOption TelWord sicslogin
+#---------------------------------------------------------------------------
+# U S E R S
+SicsUser lnsmanager lnsSICSlns 1
+SicsUser Manager Manager 1
+SicsUser user looser 2
+SicsUser Spy 007 1
+#--------------------------------------------------------------------------
+# D E V I C E S : M O T O R S
+#---------------------------------------------------------------------------
+ClientPut "Installing Motors"
+Motor OmegaM SIM 0 120 -.1 2.
+Motor TwoThetaM SIM 30 100 -.1 1.
+Motor MonoX SIM -30 30 -.1 3.0
+Motor MonoY SIM -30 30 -.1 3.0
+Motor CurveM SIM 0 20 -.1 3.0
+Motor MonoPhi SIM -30 30 -.1 3.0
+Motor MonoChi SIM -30 30 -.1 3.0
+
+# sample Table
+Motor Table SIM -180 360 -.1 2.
+Motor TwoThetaD SIM -10 120 -.1 1.
+#-------------------------------------------------------------
+# Monochromator
+#-------------------------------------------------------------
+MakeMono Mono "PG-002" OmegaM TwoThetaM CurveM
+Mono DD 3.3537
+Mono vk1 -0.025942
+Mono vk2 5.351660
+# Syntax MakeWaveLength name MonochromatorToUse
+MakeWaveLength lambda Mono
+#--------------------------------------------------------------------------
+# Configure Detector
+# NOTE: the McStas objects have to be created first, otherwise
+# the initialisation will fail.
+#--------------------------------------------------------------------------
+MakeMcStasReader
+MakeMcStasController
+allowexec $home/dmc_sics01
+
+ClientPut "Installing counter"
+MakeCounter counter mcstas
+counter SetExponent 1
+MakeHM banana mcstas
+banana configure HistMode Normal
+banana configure OverFlowMode Ceil
+banana configure Rank 1
+banana configure dim0 400
+banana configure BinWidth 4
+banana preset 100.
+banana CountMode Timer
+banana configure Counter counter
+banana configure init 0
+banana init
+banana exponent 3
+#-------------------------------------------------------------------------
+# Aliases
+#-------------------------------------------------------------------------
+SicsAlias OmegaM A1
+SicsAlias TwoThetaM A2
+SicsAlias Table A3
+SicsAlias TwoThetaD A4
+SicsAlias MonoX A5
+SicsAlias MonoY A6
+SicsAlias MonoPhi A7
+SicsAlias MonoChi A8
+SicsAlias CurveM A9
+DefineAlias TT temperature
+#--------------------------------------------------------------------------
+# V A R I A B L E S
+
+# now a few general variables are created
+# Syntax: VarMake name type access
+# type can be one of: Text, Int, Float
+#access can be one of: Internal, Mugger, User, Spy
+#-----------------------------------------------------------------------------
+VarMake SicsDataPath Text Internal
+SicsDataPath "$home/"
+SicsDataPath lock
+VarMake DetStepWidth Float Internal
+DetStepWidth 0.2
+DetStepWidth lock
+VarMake Instrument Text Internal
+Instrument "Virtual DMC driven by McStas"
+Instrument lock
+VarMake Title Text User
+VarMake User Text User
+VarMake Collimation Text User
+VarMake Sample Text User
+Sample Kellerit
+VarMake comment1 Text User
+VarMake comment2 Text User
+VarMake comment3 Text User
+VarMake starttime Text User
+starttime ""
+VarMake SicsDataPrefix Text Internal
+SicsDataPrefix vdmc
+#--------- make data number
+MakeDataNumber SicsDataNumber $home/DataNumber
+VarMake SicsDataPostFix Text Internal
+SicsDataPostFix ".hdf"
+VarMake Adress Text User
+VarMake phone Text User
+VarMake fax Text User
+VarMake email Text User
+VarMake sample_mur Float User
+#--------------------------------------------------------------------------
+# P R O C E D U R E S
+#--------------------------------------------------------------------------
+MakeDrive
+MakeBatchManager
+MakeNXScript
+#-------------------- initialize scripted commands
+source $home/vdmccom.tcl
+#-------------------- configure commandlog
+commandlog auto
+commandlog intervall 5
diff --git a/mcstas/dmc/vdmccom.tcl b/mcstas/dmc/vdmccom.tcl
new file mode 100644
index 00000000..fe106fb1
--- /dev/null
+++ b/mcstas/dmc/vdmccom.tcl
@@ -0,0 +1,156 @@
+#----------------------------------------------------------------------------
+# VDMC instrument special scripted commands
+#
+# Mark Koennecke, June 2005
+#---------------------------------------------------------------------------
+source $home/mcsupport.tcl
+
+if { [info exists vdmcinit] == 0 } {
+ set vdmcinit 1
+ Publish LogBook Spy
+ Publish count User
+ Publish Repeat User
+ Publish storedmcdata User
+ Publish rundmcsim User
+ Publish copydmcdata User
+ mcinstall
+}
+source $home/log.tcl
+source $home/nxsupport.tcl
+source $home/nxdmc.tcl
+#------------------------------------------------------------------------
+proc SplitReply { text } {
+ set l [split $text =]
+ return [lindex $l 1]
+}
+#-----------------------------------------------------------------------
+# Scripts required for controlling McStas simulations
+#-----------------------------------------------------------------------
+proc rundmcsim {mode preset} {
+ global home
+ append command $home/dmc_sics01 " -f $home/dmc.xml --format=\"XML\""
+ append command " -n 9e15 "
+ append command " lambda=[string trim [SplitReply [lambda]]]"
+ append command " TKOFF=[string trim [SplitReply [TwoThetaM]]]"
+ append command " samplefile=$home/[string trim [SplitReply [sample]]].q"
+ append command " monfile=$home/monfile "
+ append command " >& $home/dmc.log &"
+ clientput "Starting McStas.. "
+ set ret [catch {eval exec $command} msg]
+ if {$ret != 0} {
+ error $msg
+ } else {
+ return $msg
+ }
+}
+#------------------------------------------------------------------------
+proc copydmcdata { } {
+ global home
+ set mcversion "McStas 1.8 - Mar. 05, 2004"
+ washsimfile $home/dmc.xml
+ mcreader open $home/dmc.xml
+ mcreader insertmon \
+ "/$mcversion/DMC_diff/dmc.xml/PSD_sample/PSD_sample.dat/values" \
+ counter 1
+ mcreader inserthm \
+ "/$mcversion/DMC_diff/dmc.xml/Det9/det9.dat/data" banana
+ mcreader close
+}
+#--------------------------------------------------------------------------
+mccontrol configure mcstart rundmcsim
+mccontrol configure mccopydata copydmcdata
+mccontrol configure update 60
+mccontrol configure mcmonfile $home/monfile
+#--------------------------------------------------------------------------
+# A count command for VDMC
+# All arguments are optional. The current values will be used if not
+# specified
+# Dr. Mark Koennecke, Juli 1997
+#--------------------------------------------------------------------------
+proc count { {mode NULL } { preset NULL } } {
+ starttime [sicstime]
+ catch {temperature log clear} msg
+#----- deal with mode
+ set mode2 [string toupper $mode]
+ set mode3 [string trim $mode2]
+ set mc [string index $mode2 0]
+ if { [string compare $mc T] == 0 } {
+ banana CountMode Timer
+ } elseif { [string compare $mc M] == 0 } {
+ banana CountMode Monitor
+ }
+#------ deal with preset
+ if { [string compare $preset NULL] != 0 } {
+ banana preset $preset
+ }
+#------ prepare a count message
+ set a [banana preset]
+ set aa [SplitReply $a]
+ set b [banana CountMode]
+ set bb [SplitReply $b]
+ ClientPut [format " Starting counting in %s mode with a preset of %s" \
+ $bb $aa]
+#------- count
+ banana InitVal 0
+ wait 1
+ banana count
+ set ret [catch {Success} msg]
+#------- StoreData
+ storedata
+ if { $ret != 0 } {
+ error [format "Counting ended with error"]
+ }
+}
+#---------------- Repeat -----------------------------------------------
+proc repeat { num {mode NULL} {preset NULL} } {
+ for { set i 0 } { $i < $num } { incr i } {
+ set ret [catch {count $mode $preset} msg]
+ if {$ret != 0} {
+ error "Counting ended with error"
+ }
+ }
+}
+#------------------------------------------------------------------------
+# This implements the wwwsics command which generates a listing of
+# important experiment parameters in html format for the SICS WWW Status
+# application. This version is for the powder diffractometers DMC and
+# HRPT.
+#
+# Mark Koennecke, March 2000
+#------------------------------------------------------------------------
+proc wwwsics {} {
+#----- get all the data we need
+ set user [GetNum [user]]
+ set sample [GetNum [sample]]
+ set tit [GetNum [title]]
+ set ret [catch {lambda} msg]
+ if {$ret != 0 } {
+ set lam Undetermined
+ } else {
+ set lam [GetNum $msg]
+ }
+ set ret [catch {temperature} msg]
+ if {$ret != 0 } {
+ set tem Undetermined
+ } else {
+ set tem [GetNum $msg]
+ }
+ set run [GetNum [sicsdatanumber]]
+ catch {incr run} msg
+ set stat [GetNum [status]]
+#------- html format the reply
+ append result ""
+ append result Run Number | $run |
+ append result Title | $tit |
+ append result User | $user |
+ append result Sample | $sample |
+ append result wavelength | $lam |
+ append result Sample Temperature | $tem |
+ append result Status | $stat |
+ append result
+ return $result
+}
+
+#------------ install command
+catch {Publish wwwsics Spy} msg
+
diff --git a/mcstas/dmc/vdmcstatus.tcl b/mcstas/dmc/vdmcstatus.tcl
new file mode 100644
index 00000000..db4bda9c
--- /dev/null
+++ b/mcstas/dmc/vdmcstatus.tcl
@@ -0,0 +1,217 @@
+exe batchpath ./
+exe syspath ./
+sample_mur 0.000000
+sample_mur setAccess 2
+email UNKNOWN
+email setAccess 2
+fax UNKNOWN
+fax setAccess 2
+phone UNKNOWN
+phone setAccess 2
+adress UNKNOWN
+adress setAccess 2
+sicsdatapostfix .hdf
+sicsdatapostfix setAccess 0
+sicsdataprefix powder
+sicsdataprefix setAccess 0
+starttime 2005-06-21 14:21:44
+starttime setAccess 2
+comment3 UNKNOWN
+comment3 setAccess 2
+comment2 UNKNOWN
+comment2 setAccess 2
+comment1 UNKNOWN
+comment1 setAccess 2
+sample na2ca3al2f14
+sample setAccess 2
+collimation UNKNOWN
+collimation setAccess 2
+user UNKNOWN
+user setAccess 2
+title UNKNOWN
+title setAccess 2
+# Motor a9
+a9 sign 1.000000
+a9 SoftZero 0.000000
+a9 SoftLowerLim 0.000000
+a9 SoftUpperLim 20.000000
+a9 Fixed -1.000000
+a9 InterruptMode 0.000000
+a9 precision 0.010000
+a9 AccessCode 2.000000
+a9 movecount 10.000000
+# Motor a8
+a8 sign 1.000000
+a8 SoftZero 0.000000
+a8 SoftLowerLim -30.000000
+a8 SoftUpperLim 30.000000
+a8 Fixed -1.000000
+a8 InterruptMode 0.000000
+a8 precision 0.010000
+a8 AccessCode 2.000000
+a8 movecount 10.000000
+# Motor a7
+a7 sign 1.000000
+a7 SoftZero 0.000000
+a7 SoftLowerLim -30.000000
+a7 SoftUpperLim 30.000000
+a7 Fixed -1.000000
+a7 InterruptMode 0.000000
+a7 precision 0.010000
+a7 AccessCode 2.000000
+a7 movecount 10.000000
+# Motor a6
+a6 sign 1.000000
+a6 SoftZero 0.000000
+a6 SoftLowerLim -30.000000
+a6 SoftUpperLim 30.000000
+a6 Fixed -1.000000
+a6 InterruptMode 0.000000
+a6 precision 0.010000
+a6 AccessCode 2.000000
+a6 movecount 10.000000
+# Motor a5
+a5 sign 1.000000
+a5 SoftZero 0.000000
+a5 SoftLowerLim -30.000000
+a5 SoftUpperLim 30.000000
+a5 Fixed -1.000000
+a5 InterruptMode 0.000000
+a5 precision 0.010000
+a5 AccessCode 2.000000
+a5 movecount 10.000000
+# Motor a4
+a4 sign 1.000000
+a4 SoftZero 0.000000
+a4 SoftLowerLim -10.000000
+a4 SoftUpperLim 120.000000
+a4 Fixed -1.000000
+a4 InterruptMode 0.000000
+a4 precision 0.010000
+a4 AccessCode 2.000000
+a4 movecount 10.000000
+# Motor a3
+a3 sign 1.000000
+a3 SoftZero 0.000000
+a3 SoftLowerLim -180.000000
+a3 SoftUpperLim 360.000000
+a3 Fixed -1.000000
+a3 InterruptMode 0.000000
+a3 precision 0.010000
+a3 AccessCode 2.000000
+a3 movecount 10.000000
+# Motor a2
+a2 sign 1.000000
+a2 SoftZero 0.000000
+a2 SoftLowerLim 30.000000
+a2 SoftUpperLim 100.000000
+a2 Fixed -1.000000
+a2 InterruptMode 0.000000
+a2 precision 0.010000
+a2 AccessCode 2.000000
+a2 movecount 10.000000
+# Motor a1
+a1 sign 1.000000
+a1 SoftZero 0.000000
+a1 SoftLowerLim 0.000000
+a1 SoftUpperLim 120.000000
+a1 Fixed -1.000000
+a1 InterruptMode 0.000000
+a1 precision 0.010000
+a1 AccessCode 2.000000
+a1 movecount 10.000000
+banana CountMode timer
+banana preset 180.000000
+# Counter counter
+counter SetPreset 180.000000
+counter SetMode Timer
+# Motor twothetad
+twothetad sign 1.000000
+twothetad SoftZero 0.000000
+twothetad SoftLowerLim -10.000000
+twothetad SoftUpperLim 120.000000
+twothetad Fixed -1.000000
+twothetad InterruptMode 0.000000
+twothetad precision 0.010000
+twothetad AccessCode 2.000000
+twothetad movecount 10.000000
+# Motor table
+table sign 1.000000
+table SoftZero 0.000000
+table SoftLowerLim -180.000000
+table SoftUpperLim 360.000000
+table Fixed -1.000000
+table InterruptMode 0.000000
+table precision 0.010000
+table AccessCode 2.000000
+table movecount 10.000000
+# Motor monochi
+monochi sign 1.000000
+monochi SoftZero 0.000000
+monochi SoftLowerLim -30.000000
+monochi SoftUpperLim 30.000000
+monochi Fixed -1.000000
+monochi InterruptMode 0.000000
+monochi precision 0.010000
+monochi AccessCode 2.000000
+monochi movecount 10.000000
+# Motor monophi
+monophi sign 1.000000
+monophi SoftZero 0.000000
+monophi SoftLowerLim -30.000000
+monophi SoftUpperLim 30.000000
+monophi Fixed -1.000000
+monophi InterruptMode 0.000000
+monophi precision 0.010000
+monophi AccessCode 2.000000
+monophi movecount 10.000000
+# Motor curvem
+curvem sign 1.000000
+curvem SoftZero 0.000000
+curvem SoftLowerLim 0.000000
+curvem SoftUpperLim 20.000000
+curvem Fixed -1.000000
+curvem InterruptMode 0.000000
+curvem precision 0.010000
+curvem AccessCode 2.000000
+curvem movecount 10.000000
+# Motor monoy
+monoy sign 1.000000
+monoy SoftZero 0.000000
+monoy SoftLowerLim -30.000000
+monoy SoftUpperLim 30.000000
+monoy Fixed -1.000000
+monoy InterruptMode 0.000000
+monoy precision 0.010000
+monoy AccessCode 2.000000
+monoy movecount 10.000000
+# Motor monox
+monox sign 1.000000
+monox SoftZero 0.000000
+monox SoftLowerLim -30.000000
+monox SoftUpperLim 30.000000
+monox Fixed -1.000000
+monox InterruptMode 0.000000
+monox precision 0.010000
+monox AccessCode 2.000000
+monox movecount 10.000000
+# Motor twothetam
+twothetam sign 1.000000
+twothetam SoftZero 0.000000
+twothetam SoftLowerLim 30.000000
+twothetam SoftUpperLim 100.000000
+twothetam Fixed -1.000000
+twothetam InterruptMode 0.000000
+twothetam precision 0.010000
+twothetam AccessCode 2.000000
+twothetam movecount 10.000000
+# Motor omegam
+omegam sign 1.000000
+omegam SoftZero 0.000000
+omegam SoftLowerLim 0.000000
+omegam SoftUpperLim 120.000000
+omegam Fixed -1.000000
+omegam InterruptMode 0.000000
+omegam precision 0.010000
+omegam AccessCode 2.000000
+omegam movecount 10.000000
diff --git a/mcstascounter.c b/mcstascounter.c
new file mode 100644
index 00000000..e7f07269
--- /dev/null
+++ b/mcstascounter.c
@@ -0,0 +1,160 @@
+/*----------------------------------------------------------------------------
+ This is a counter driver which wraps the McStas controller into a
+ counter driver.
+
+ copyright: see file COPYRIGHT
+
+ Mark Koennecke, June 2005
+-----------------------------------------------------------------------------*/
+#include
+#include
+#include "sics.h"
+#include "countdriv.h"
+#include "mccontrol.h"
+/*-------------------------------------------------------------------------*/
+#define SCRIPTERROR -110
+#define NOTIMPLEMENTED -111
+/*====================== interface functions ==============================*/
+static int McStatus(struct __COUNTER *self, float *fControl){
+ int status;
+ pMcStasController pMcStas = NULL;
+
+ pMcStas = (pMcStasController)self->pData;
+
+ status = McStasStatus(pMcStas,fControl);
+ if(status == HWFault){
+ self->iErrorCode = SCRIPTERROR;
+ return status;
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------*/
+static int McStart(struct __COUNTER *self){
+ int status;
+ pMcStasController pMcStas = NULL;
+
+ pMcStas = (pMcStasController)self->pData;
+
+ memset(self->lCounts,0,MAXCOUNT*sizeof(long));
+ status = McStasStart(pMcStas,self->eMode,self->fPreset);
+ if(status == HWFault){
+ self->iErrorCode = SCRIPTERROR;
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------*/
+static int McPause(struct __COUNTER *self){
+ self->iErrorCode = NOTIMPLEMENTED;
+ return HWFault;
+}
+/*--------------------------------------------------------------------------*/
+static int McContinue(struct __COUNTER *self){
+ self->iErrorCode = NOTIMPLEMENTED;
+ return HWFault;
+}
+/*--------------------------------------------------------------------------*/
+static int McHalt(struct __COUNTER *self){
+ int status;
+ pMcStasController pMcStas = NULL;
+
+ pMcStas = (pMcStasController)self->pData;
+
+ status = McStasStop(pMcStas);
+ if(status == HWFault){
+ self->iErrorCode = SCRIPTERROR;
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------*/
+static int McReadValues(struct __COUNTER *self){
+ int status;
+ pMcStasController pMcStas = NULL;
+
+ pMcStas = (pMcStasController)self->pData;
+
+ status = McStasTransferData(pMcStas);
+ if(status == HWFault){
+ self->iErrorCode = SCRIPTERROR;
+ }
+ return status;
+}
+/*--------------------------------------------------------------------------*/
+static int McGetError(struct __COUNTER *self, int *iCode, char *error,
+ int iErrLen){
+ pMcStasController pMcStas = NULL;
+ pMcStas = (pMcStasController)self->pData;
+
+ switch(self->iErrorCode){
+ case SCRIPTERROR:
+ McStasGetError(pMcStas,error,iErrLen);
+ break;
+ case NOTIMPLEMENTED:
+ strncpy(error,"Feauture not implemented",iErrLen);
+ break;
+ default:
+ strncpy(error,"Unknown error code in McStas Driver",iErrLen);
+ break;
+ }
+ return 1;
+}
+/*------------------------------------------------------------------------*/
+static int McTryAndFixIt(struct __COUNTER *self, int iCode){
+ int status;
+ pMcStasController pMcStas = NULL;
+
+ pMcStas = (pMcStasController)self->pData;
+
+ status = McStasFix(pMcStas);
+ return status;
+}
+/*------------------------------------------------------------------------*/
+static int McSet(struct __COUNTER *self, char *name, int iCter, float FVal){
+ return 1;
+}
+/*------------------------------------------------------------------------*/
+static int McGet(struct __COUNTER *self, char *name, int iCter, float *fVal){
+ *fVal = 25.99;
+ return 1;
+}
+/*-------------------------------------------------------------------------*/
+static int McSend(struct __COUNTER *self, char *pText,
+ char *pReply, int iReplyLen){
+ strncpy(pReply,"WARNING: McStas simulation cannot be sent anything",
+ iReplyLen);
+ return 1;
+}
+/*-------------------------------------------------------------------------*/
+pCounterDriver NewMcStasCounter(char *name){
+ pMcStasController pMcStas = NULL;
+ pCounterDriver pNew = NULL;
+
+ /*
+ * cannot do it without a McStas Controller
+ */
+ pMcStas = FindCommandData(pServ->pSics,"mccontrol","McStasController");
+ if(pMcStas == NULL){
+ return NULL;
+ }
+
+ pNew = CreateCounterDriver(name,"McStas");
+ if(pNew == NULL){
+ return NULL;
+ }
+ pNew->iNoOfMonitors = 10;
+ pNew->pData = pMcStas;
+
+ pNew->GetStatus = McStatus;
+ pNew->Start = McStart;
+ pNew->Halt = McHalt;
+ pNew->ReadValues = McReadValues;
+ pNew->GetError = McGetError;
+ pNew->TryAndFixIt = McTryAndFixIt;
+ pNew->Pause = McPause;
+ pNew->Continue = McContinue;
+ pNew->Set = McSet;
+ pNew->Get = McGet;
+ pNew->Send = McSend;
+ pNew->KillPrivate = NULL;
+
+ return pNew;
+}
diff --git a/mcstashm.c b/mcstashm.c
new file mode 100644
index 00000000..9f9fa0c4
--- /dev/null
+++ b/mcstashm.c
@@ -0,0 +1,212 @@
+/*--------------------------------------------------------------------------
+ This is a driver for a histogram memory which is meant to interoperate
+ with a McStas simulation. For reasons of lazyness the control of counting
+ operations is delegated to a single counter object and this driver only
+ provides data space and means to access and copy data. This driver also
+ works without a counter connected in order to support multi HM control via
+ the hmcontrol module.
+
+ copyright: see file COPYRIGHT
+
+ Mark Koennecke, June 2005
+ -------------------------------------------------------------------------*/
+#include
+#include
+#include "sics.h"
+#include "counter.h"
+#include "stringdict.h"
+#include "HistDriv.i"
+/*================= operator functions ====================================*/
+static int McHMConfigure(pHistDriver self, SConnection *pCon,
+ pStringDict pOpt, SicsInterp *pSics){
+ char counterName[80];
+ char pError[256];
+
+ if(StringDictGet(pOpt,"counter",counterName,79) == 1){
+ self->pPriv = FindCommandData(pSics,counterName,"SingleCounter");
+ if(self->pPriv == NULL){
+ snprintf(pError,255,
+ "ERROR: tried to configure counter but %s not found",
+ counterName);
+ SCWrite(pCon,pError,eError);
+ return 0;
+ }
+ }
+ self->iReconfig = 0;
+ return configureHMdata(self->data,pOpt,pCon);
+}
+/*-------------------------------------------------------------------------*/
+static int McHMStart(pHistDriver self, SConnection *pCon){
+ pCounter pCount = NULL;
+
+ /*
+ * clear data
+ */
+ clearHMData(self->data);
+ /*
+ * if there is a counter, make him start
+ */
+ pCount = (pCounter)self->pPriv;
+ if(pCount != NULL){
+ pCount->pDriv->eMode = self->eCount;
+ pCount->pDriv->fPreset = self->fCountPreset;
+ return pCount->pCountInt->StartCount(pCount,pCon);
+ } else {
+ return 1;
+ }
+}
+/*------------------------------------------------------------------------*/
+static int McHMHalt(pHistDriver self){
+ pCounter pCount = NULL;
+
+ pCount = (pCounter)self->pPriv;
+ if(pCount != NULL){
+ return pCount->pCountInt->Halt(pCount);
+ } else {
+ return 1;
+ }
+}
+/*-------------------------------------------------------------------------*/
+static int McHMCountStatus(pHistDriver self, SConnection *pCon){
+ pCounter pCount = NULL;
+
+ pCount = (pCounter)self->pPriv;
+ if(pCount != NULL){
+ return pCount->pCountInt->CheckCountStatus(pCount,pCon);
+ } else {
+ return HWIdle;
+ }
+}
+/*------------------------------------------------------------------------*/
+static int McHMGetError(pHistDriver self, int *iCode, char *error, int errLen){
+ pCounter pCount = NULL;
+
+ pCount = (pCounter)self->pPriv;
+ if(pCount != NULL){
+ return pCount->pDriv->GetError(pCount->pDriv,iCode, error, errLen);
+ } else {
+ *iCode = -1000;
+ strncpy(error,"Feature not implemented in McStasHM",errLen);
+ return 1;
+ }
+}
+/*-------------------------------------------------------------------------*/
+static int McHMFixIt(pHistDriver self, int iCode){
+ pCounter pCount = NULL;
+
+ pCount = (pCounter)self->pPriv;
+ if(pCount != NULL){
+ return pCount->pDriv->TryAndFixIt(pCount->pDriv,iCode);
+ } else {
+ return COTERM;
+ }
+}
+/*-----------------------------------------------------------------------*/
+static int McHMGetData(pHistDriver self, SConnection *pCon){
+ pCounter pCount = NULL;
+
+ pCount = (pCounter)self->pPriv;
+ if(pCount != NULL){
+ return pCount->pCountInt->TransferData(pCount,pCon);
+ } else {
+ return 1;
+ }
+}
+/*-----------------------------------------------------------------------*/
+static int McHMGetHistogram(pHistDriver self, SConnection *pCon,
+ int bank, int start, int end, HistInt *pData){
+ /*
+ * normally this would update HM data from the actual histogram mmeory.
+ * With the McStas simulation, the updated values for the hiistogram
+ * mmeory data are pushed through SetHistogram. Thus this routine has
+ * to do nothing.
+ */
+ return 1;
+}
+/*-------------------------------------------------------------------------*/
+static int McHMSetHistogram(pHistDriver self, SConnection *pCon,
+ int bank, int start, int end,
+ HistInt *pData){
+ int i, count = 0;
+ HistInt *hmData;
+
+ assert(bank == 0);
+
+ hmData = self->data->localBuffer;
+ for(i = start; i < end; i++, count++){
+ hmData[i] = pData[count];
+ }
+ return 1;
+}
+/*-------------------------------------------------------------------------*/
+static long McHMMonitor(pHistDriver self, int i, SConnection *pCon){
+ pCounter pCount = NULL;
+
+ pCount = (pCounter)self->pPriv;
+ if(pCount != NULL){
+ return GetMonitor(pCount,i,pCon);
+ } else {
+ return 0L;
+ }
+}
+/*-------------------------------------------------------------------------*/
+static float McHMGetTime(pHistDriver self, SConnection *pCon){
+ pCounter pCount = NULL;
+
+ pCount = (pCounter)self->pPriv;
+ if(pCount != NULL){
+ return GetCountTime(pCount,pCon);;
+ } else {
+ return -999.99;
+ }
+}
+/*--------------------------------------------------------------------------*/
+static int McHMPreset(pHistDriver self, SConnection *pCon, HistInt *val){
+ int i;
+ long length;
+ HistInt *data;
+
+ length = getHMDataLength(self->data);
+ data = self->data->localBuffer;
+ for(i = 0; i < length; i++){
+ data[i] = val;
+ }
+ return 1;
+}
+/*------------------------------------------------------------------------*/
+static int McHMPause(pHistDriver self, SConnection *pCon){
+ return HWFault;
+}
+/*-----------------------------------------------------------------------*/
+static int McHMContinue(pHistDriver self, SConnection *pCon){
+ return HWFault;
+}
+/*========================== the actual creation function ================*/
+pHistDriver NewMcStasHM(pStringDict pOpt){
+ pHistDriver pNew = NULL;
+
+ pNew = CreateHistDriver(pOpt);
+ if(pNew == NULL){
+ return NULL;
+ }
+ pNew->Configure = McHMConfigure;
+ pNew->Start = McHMStart;
+ pNew->Halt = McHMHalt;
+ pNew->GetCountStatus = McHMCountStatus;
+ pNew->GetError = McHMGetError;
+ pNew->TryAndFixIt = McHMFixIt;
+ pNew->GetData = McHMGetData;
+ pNew->GetHistogram = McHMGetHistogram;
+ pNew->SetHistogram = McHMSetHistogram;
+ pNew->GetMonitor = McHMMonitor;
+ pNew->GetTime = McHMGetTime;
+ pNew->Preset = McHMPreset;
+ pNew->FreePrivate = NULL;
+ pNew->Pause = McHMPause;
+ pNew->Continue = McHMContinue;
+ StringDictAddPair(pOpt,"counter","UNKNOWN");
+ StringDictUpdate(pOpt,"update","10");
+
+ return pNew;
+}
+
diff --git a/mcstashm.h b/mcstashm.h
new file mode 100644
index 00000000..4596448e
--- /dev/null
+++ b/mcstashm.h
@@ -0,0 +1,16 @@
+/*--------------------------------------------------------------------------
+ This is a driver for a histogram memory which is meant to interoperate
+ with a McStas simulation. For reasons of lazyness the control of counting
+ operations is delegated to a single counter object and this driver only
+ provides data space and means to access and copy data. This driver also
+ works without a counter connected in order to support multi HM control via
+ the hmcontrol module.
+
+ copyright: see file COPYRIGHT
+
+ Mark Koennecke, June 2005
+ -------------------------------------------------------------------------*/
+#ifndef _MCSTASHM_H_
+#define _MCSTASHM_H_
+ pHistDriver NewMcStasHM(pStringDict pOpt);
+#endif //_MCSTASHM_H_
diff --git a/napi.c b/napi.c
index 98777341..60673de8 100644
--- a/napi.c
+++ b/napi.c
@@ -23,7 +23,7 @@
----------------------------------------------------------------------------*/
-static const char* rscid = "$Id: napi.c,v 1.10 2005/05/27 11:58:05 koennecke Exp $"; /* Revision interted by CVS */
+static const char* rscid = "$Id: napi.c,v 1.11 2005/06/22 07:10:00 koennecke Exp $"; /* Revision interted by CVS */
#include
#include
@@ -754,6 +754,7 @@ static NXstatus stepOneUp(NXhandle hfil, char *name)
{
return NX_OK;
}
+
NXinitgroupdir(hfil);
while(NXgetnextentry(hfil,name2,xclass,&datatype) != NX_EOD)
diff --git a/network.c b/network.c
index d2ec21bb..e6b0e7ca 100644
--- a/network.c
+++ b/network.c
@@ -154,8 +154,9 @@ CreateSocketAdress(
i = sizeof(struct linger);
lili.l_onoff = 1;
lili.l_linger = 1;
+ /*
setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i);
-
+ */
pRes->iType = PORT;
pRes->lMagic = NETMAGIC;
return pRes;
diff --git a/ofac.c b/ofac.c
index 6f38ed8b..a1124076 100644
--- a/ofac.c
+++ b/ofac.c
@@ -112,6 +112,8 @@
#include "ubcalc.h"
#include "tasub.h"
#include "tasscanub.h"
+#include "mcreader.h"
+#include "mccontrol.h"
/*----------------------- Server options creation -------------------------*/
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
@@ -303,6 +305,10 @@
TasUBFactory,NULL,NULL);
AddCommand(pInter,"MakeTasScan",
TASUBScanFactory,NULL,NULL);
+ AddCommand(pInter,"MakeMcStasReader",
+ McStasReaderFactory,NULL,NULL);
+ AddCommand(pInter,"MakeMcStasController",
+ McStasControllerFactory,NULL,NULL);
/*
@@ -368,6 +374,7 @@
RemoveCommand(pSics,"MakeUBCalc");
RemoveCommand(pSics,"MakeTasUB");
RemoveCommand(pSics,"MakeTasScan");
+ RemoveCommand(pSics,"MakemcStasReader");
/*
remove site specific installation commands
diff --git a/tasscanub.c b/tasscanub.c
index 73263930..cf700a69 100644
--- a/tasscanub.c
+++ b/tasscanub.c
@@ -333,13 +333,13 @@ static int TASUBHeader(pScanData self)
pTAS->ub->cell.beta,
pTAS->ub->cell.gamma);
- findReflection(pTAS->ub->reflectionList,pTAS->ub->r1 - 1,&r);
+ r = pTAS->ub->r1;
fprintf(self->fd,"PARAM: AX=%8.4f, AY=%8.4f, AZ=%8.4f\n",
r.qe.qh,
r.qe.qk,
r.qe.ql);
- findReflection(pTAS->ub->reflectionList,pTAS->ub->r2 - 1,&r);
+ r = pTAS->ub->r2;
fprintf(self->fd,"PARAM: BX=%8.4f, BY=%8.4f, BZ=%8.4f\n",
r.qe.qh,
r.qe.qk,
@@ -857,7 +857,7 @@ static void ParseOutput(pTASdata pTAS, SConnection *pCon)
/*
get a copy of output
*/
- pText = (char *)malloc(strlen(GetVarText("output"))*sizeof(char));
+ pText = (char *)malloc((strlen(GetVarText("output"))+1)*sizeof(char));
if(!pText)
{
SCWrite(pCon,"WARNING: out of memory while parsing output variable",
@@ -1028,7 +1028,7 @@ static void TASUBDump(pTASdata self, SicsInterp *pSics, SConnection *pCon,
write orienting reflections
*/
snprintf(pBueffel,255,"%s_vec1",argv[3]);
- findReflection(self->ub->reflectionList, self->ub->r1,&r);
+ r = self->ub->r1;
v[0] = r.qe.qh;
v[1] = r.qe.qk;
v[2] = r.qe.ql;
@@ -1038,7 +1038,7 @@ static void TASUBDump(pTASdata self, SicsInterp *pSics, SConnection *pCon,
SCWrite(pCon,pBueffel,eWarning);
}
snprintf(pBueffel,255,"%s_vec2",argv[3]);
- findReflection(self->ub->reflectionList, self->ub->r2,&r);
+ r = self->ub->r2;
v[0] = r.qe.qh;
v[1] = r.qe.qk;
v[2] = r.qe.ql;
diff --git a/tasublib.c b/tasublib.c
index 20efc6f0..783851eb 100644
--- a/tasublib.c
+++ b/tasublib.c
@@ -397,6 +397,7 @@ int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe,
angles->sgl = Asind(-R[2][0]);
if(ABS(angles->sgl -90.) < .5){
+ mat_free(R);
return BADUBORQ;
}
/*
@@ -419,6 +420,7 @@ int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe,
QC = tasReflectionToQC(qe,UB);
if(QC == NULL){
+ mat_free(R);
return UBNOMEMORY;
}
@@ -426,6 +428,8 @@ int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe,
q = 2.*PI*vectorLength(QC);
cos2t = (qe.ki*qe.ki + qe.kf*qe.kf - q*q)/(2. * ABS(qe.ki) * ABS(qe.kf));
if(ABS(cos2t) > 1.){
+ mat_free(R);
+ killVector(QC);
return TRIANGLENOTCLOSED;
}
angles->sample_two_theta = ss*Acosd(cos2t);