- Adding first working version of the McStas SICS connection to cvs

SKIPPED:
	psi/polterwrite.c
This commit is contained in:
koennecke
2005-06-22 07:09:59 +00:00
parent 734577e394
commit ef6c04e6b8
42 changed files with 3268 additions and 18 deletions

View File

@ -92,9 +92,7 @@
if(self->KillPrivate != NULL)
{
self->KillPrivate(self);
} else {
free(self->pData);
}
}
}
free(self);
}

View File

@ -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

View File

@ -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)
{

View File

@ -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,

View File

@ -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:
<ul>
<li><b>hostname</b> The name of the macintosh computer.
<li><b>hostname</b> The name of the instrument computer.
<li><b>port</b> 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.
<li><b>channel</b> 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.
<dt>MakeCounter name mcstas
<dd>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.
<DT>MakeCounter name EL737 host port chan
<DD>This command creates a single
counter name, using an EL737 driver. The counter is at host host, listening

View File

@ -20,6 +20,7 @@ Go to:
<li> Advice about <a href=hwini.htm> hardware </a> configuration.
<li> A description of <a href = command.htm> command </a> initialisation.
<li> Managing the SICS <a href="helpman.htm"> help </a> system.
<li> Connecting SICS to <a href="mcstas.htm">McStas</a> Simulations.
</ul>
</p>
<!latex-on>

View File

@ -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

140
doc/manager/mcstas.htm Normal file
View File

@ -0,0 +1,140 @@
<HTML>
<HEAD>
<TITLE>The McStas SICS Interface</TITLE>
</HEAD>
<BODY>
<H1>The McStas SICS Interface</H1>
<P>
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:
<ul>
<li>A McStas controller module which controls the actual simulation.
<li>A McStas reader which is responsible for reading simulated data into
SICS counters and histogram memories.
<li>Counter and histogram memory drivers which redirect their actions to the
McStas controller module.
</ul>
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:
<dl>
<dt>startmcstas
<dd>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.
<dt>mcstastest pid
<dd>Tests if the McStas simulation is still running.
<dt>mcstasdump pid
<dd>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.
<dt>mcstasstop pid
<dd>Stops the McStas simulation.
<dt>mcstasread
<dd>Reads the McStas simulation output and transfers monitor and histogram memory data
into the appropriate SICS objects.
</dl>
</p>
<h2>McStas Requirements and SICS Requirements</h2>
<p>
In order for the McStas SICS interface to work the McStas simulation has to be configured
in a certain way:
<ul>
<li>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.
<li>McStas must dump its data into a single file: use the <b>-f filename</b> option.
The format must be <b> --format=XML</b>.
<li> 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.
<li>The mcstas simulation executable must be declared with allowexec in order to be able
to start with the Tcl exec command.
</ul>
</p>
<h2>The McStas Reader</h2>
<p>
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: <b>-f filename --format="XML"</b>
This module supports the following commands:
<dl>
<dt>mcreader open filename
<dd>Opens a McStas simulation file for reading.
<dt>mcreader close
<dd>Closes a McStas file after use.
<dt>mcreader insertmon path object monitornumber
<dd>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:
<dl>
<dt>path
<dd>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.
<dt>object
<dd>The counter object into which the monitor is read. This is a limitation, with the
this McStas interface only counters can store monitors.
<dt>monitornumber
<dd>Monitornumber is the monitor channel into which the value is to be stored.
</dl>
<dt>mcreader inserthm path hmobject
<dd>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.
</dl>
</p>
<H2>The McStas Controller</h2>
<p>
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:
<dl>
<dt>mccontrol configure mcstart startscriptname
<dd>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.
<dt>mccontrol configure mcisrunning runtestscriptname
<dd>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.
<dt>mccontrol configure mcdump dumpscriptname
<dd>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.
<dt>mccontrol configure mckill killscript
<dd>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.
<dt>mccontrol configure mccopydata copyscript
<dd>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.
<dt>mccontrol configure update updateintervallinseconds
<dd>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.
<dt>mccontrol configure mcmonfile filename
<dd>This configures the file which mccontrol is going to read in order to watch the
simulation control monitor.
<dt>mccontrol list
<dd>Prints a listing of the configuration parameters.
<dt>mccontrol run scriptkey
<dd>Invokes one of the scripts configure for testing purposes. scripkey can be one of:
mcstart, mcisrunning, mcdump, mckill and mccopydata.
</dl>
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.
</p>
</BODY>
</HTML>

169
doc/user/tasub.htm Normal file
View File

@ -0,0 +1,169 @@
<HTML>
<HEAD>
<TITLE>TASUB: The Triple Axis Calculation Module</TITLE>
</HEAD>
<BODY>
<H1>TASUB: The Triple Axis Calculation Module</H1>
<P>
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.
</P>
<h2>Commands understood by Tasub</h2>
<p>
<h3>Monochromator and Analyzer Parameters
<p>
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:
<ul>
<li>tasub mono
<li>tasub ana
</ul>
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:
<dl>
<dt>dd
<dd>The d-spacing of the reflection used
<dt>ss
<dd>The scattering sense, 1 or -1 are possible.
<dt>hb1
<dd>First parameter for the calculation of the horizontal curvature
<dt>hb2
<dd>Second parameter for the calculation of the horizontal curvature
<dt>vb1
<dd>First parameter for the calculation of the vertical curvature
<dt>vb2
<dd>Second parameter for the calculation of the vertical curvature
</dl>
An example:
<dl>
<dt>tasub mono dd
<dd>will print the current d-spacing of the monochromator
<dt>tasub mono dd 4.3
<dd>Will set the d-spacing of the monochromator to 4.3
</dl>
</p>
<h3>Cell Parameters</h3>
<p>
In order for the UB matrix calculation to work, the cell constants must be known:
<dl>
<dt>tasub cell
<dd>This command prints the current cell parameters.
<dt>tasub cell a b c alpha beta gamma
<dd>This command sets the new cell parameters. All six values must be given.
</dl>
</p>
<h3>Reflection Management</h3>
<p>
In order to calculate a UB matrix a list of reflections must be maintained. This is done
with the commands in this section:
<dl>
<dt>tasub clear
<dd>Clears the reflection list
<dt>tasub listref
<dd>Prints a list of all known reflections.
<dt>tasub del num
<dd>Delete the reflection number num from the list
<dt>tasub addref qh qk ql
<dd>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.
<dt>tasub addref qh qk ql a3 a4 sgu sgl ei ef
<dd>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.
</dl>
</p>
<h3>Calculations</h3>
<p>
This section covers the parameters and commands to use to make the module do calculations
for you.
<dl>
<dt>tasbub const ki | kf
<dd>Sets a parameter to determine if KI or KF is fixed when the energy transfer en is
being driven. Allowed values: ki, kf
<dt>tasub const
<dd>Prints if ki or kf is fixed.
<dt>tasub ss
<dd>Prints the sample scattering sense.
<dt>tasub ss 1 | -1
<dd>Sets the sample scattering sense. Allowed values are either 1 or -1.
<dt>tasub makeub r1 r2
<dd>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.
<dt>tasub listub
<dd>prints the current UB matrix.
<dt>tasub calcang qh qk ql ei ef
<dd>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.
<dt>tasub calcqe a2 a3 a4 sgu sgl a6
<dd>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.
</dl>
</p>
<h3>Virtual Motors</h3>
<p>
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):
<dl>
<dt>qh
<dd>The name of the motor alone will print its current position.
<dt>qh target
<dd>This will print the last requested target position for this virtual motor.
</dl>
</p>
<p>
The virtual motor qm implements <b>powder mode</b>. 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.
</p>
<p>
There is another important command:
<dl>
<dt>tasub update
<dd>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.
</dl>
</p>
<h3>Internal Commands</h3>
<p>
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:
<dl>
<dt>tasub setub ub11 ub12 ub13 ub21 ub22 ub23 ub31 ub32 ub33
<dd>Sets the UB matrix. Nine values are required.
<dt>tasub setnormal n1 n2 n3
<dd>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.
<dt>tasub settarget qh qk ql qm ki kf
<dd>Sets the Q-E target.
<dt>tasub r1 qh qk ql a3 a4 sgu sgl ki kf
<dt>tasub r2 qh qkl ql a3 a4 sgu sgl ki kf
<dd>These commands set the values for the two reflections used for generating the UB
matrix.
</dl>
</p>
</BODY>
</HTML>

View File

@ -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();

View File

@ -49,7 +49,6 @@
#include "HistDriv.i"
#include "histsim.h"
static int iSet = 0;
static HistInt iSetVal = 0;
static HistMode eHistMode;

View File

@ -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;

View File

@ -32,6 +32,7 @@
pHMdata makeHMData(void);
void killHMData(pHMdata self);
void clearHMData(pHMdata self);
int configureHMdata(pHMdata self, pStringDict pOpt,
SConnection *pCon);

View File

@ -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);

View File

@ -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

398
mccontrol.c Normal file
View File

@ -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 <stdio.h>
#include <assert.h>
#include <tcl.h>
#include <time.h>
#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;
}
}

47
mccontrol.h Normal file
View File

@ -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

308
mcreader.c Normal file
View File

@ -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 <assert.h>
#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;
}

28
mcreader.h Normal file
View File

@ -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

222
mcstas.tex Normal file
View File

@ -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}

171
mcstas.w Normal file
View File

@ -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 -------------------------------------------------*/
@<mcconint@>
/*---------------------- function prototypes -------------------------------------------*/
@<mcconproto@>
#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"
@<mcreadint@>
#endif
@}

3
mcstas/dmc/DataNumber Normal file
View File

@ -0,0 +1,3 @@
6
NEVER, EVER modify or delete this file
You'll risk eternal damnation and a reincarnation as a cockroach!|n

141
mcstas/dmc/PSD_monitor.comp Normal file
View File

@ -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; i<nx; i++)
for (j=0; j<ny; j++)
{
PSD_N[i][j] = 0;
PSD_p[i][j] = 0;
PSD_p2[i][j] = 0;
}
totalCount = 0;
currentCount = 0;
%}
TRACE
%{
int i,j;
PROP_Z0;
if (x>xmin && x<xmax && y>ymin && y<ymax)
{
i = floor((x - xmin)*nx/(xmax - xmin));
j = floor((y - ymin)*ny/(ymax - ymin));
PSD_N[i][j]++;
PSD_p[i][j] += p;
PSD_p2[i][j] += p*p;
totalCount++;
currentCount++;
if(dumpCount > 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

8
mcstas/dmc/batch.tcl Normal file
View File

@ -0,0 +1,8 @@
proc SplitReply { text } {
set l [split $text =]
return [lindex $l 1]
}
proc batchrun file {
fileeval [string trim [SplitReply [BatchRoot]]/$file]
}

89
mcstas/dmc/dmc.dic Normal file
View File

@ -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

184
mcstas/dmc/dmc_sics01.instr Normal file
View File

@ -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

84
mcstas/dmc/log.tcl Normal file
View File

@ -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]
}
}

66
mcstas/dmc/mcsupport.tcl Normal file
View File

@ -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 "<NXsimulation name=\"$name\">"
} 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
}

29
mcstas/dmc/na2ca3al2f14.q Normal file
View File

@ -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

108
mcstas/dmc/nxdmc.tcl Normal file
View File

@ -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
}

96
mcstas/dmc/nxsupport.tcl Normal file
View File

@ -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
}

138
mcstas/dmc/vdmc.tcl Normal file
View File

@ -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

156
mcstas/dmc/vdmccom.tcl Normal file
View File

@ -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 "<table BORDER=2>"
append result <tr> <th>Run Number</th> <td> $run </td> </tr>
append result <tr> <th>Title</th> <td> $tit </td> </tr>
append result <tr> <th>User</th> <td> $user </td> </tr>
append result <tr> <th>Sample </th> <td> $sample </td> </tr>
append result <tr> <th>wavelength</th> <td> $lam</td> </tr>
append result <tr> <th>Sample Temperature</th> <td> $tem</td> </tr>
append result <tr> <th>Status</th> <td> $stat</td> </tr>
append result </table>
return $result
}
#------------ install command
catch {Publish wwwsics Spy} msg

217
mcstas/dmc/vdmcstatus.tcl Normal file
View File

@ -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

160
mcstascounter.c Normal file
View File

@ -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 <stdlib.h>
#include <assert.h>
#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;
}

212
mcstashm.c Normal file
View File

@ -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 <stdlib.h>
#include <assert.h>
#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;
}

16
mcstashm.h Normal file
View File

@ -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_

3
napi.c
View File

@ -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 <stdio.h>
#include <stdlib.h>
@ -754,6 +754,7 @@ static NXstatus stepOneUp(NXhandle hfil, char *name)
{
return NX_OK;
}
NXinitgroupdir(hfil);
while(NXgetnextentry(hfil,name2,xclass,&datatype) != NX_EOD)

View File

@ -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;

7
ofac.c
View File

@ -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

View File

@ -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;

View File

@ -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);