- Adding first working version of the McStas SICS connection to cvs
SKIPPED: psi/polterwrite.c
This commit is contained in:
@ -92,9 +92,7 @@
|
|||||||
if(self->KillPrivate != NULL)
|
if(self->KillPrivate != NULL)
|
||||||
{
|
{
|
||||||
self->KillPrivate(self);
|
self->KillPrivate(self);
|
||||||
} else {
|
}
|
||||||
free(self->pData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
@ -81,5 +81,11 @@
|
|||||||
/* PSI Simulation counter, if you have no hardware */
|
/* PSI Simulation counter, if you have no hardware */
|
||||||
/* simcter.c */
|
/* simcter.c */
|
||||||
pCounterDriver NewSIMCounter(char *name, float fVal);
|
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
|
#endif
|
||||||
|
17
counter.c
17
counter.c
@ -529,6 +529,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* test for McStas simulation counter driver
|
||||||
|
*/
|
||||||
|
if(strcmp(argv[2],"mcstas") == 0){
|
||||||
|
pDriv = NewMcStasCounter(argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
if(!pDriv)
|
if(!pDriv)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"ERROR: cannot create requested driver %s",
|
sprintf(pBueffel,"ERROR: cannot create requested driver %s",
|
||||||
@ -666,6 +673,16 @@
|
|||||||
return self->pDriv->lCounts[iNum];
|
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)
|
float GetCountTime(pCounter self,SConnection *pCon)
|
||||||
{
|
{
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
long GetCounts(pCounter self, SConnection *pCon);
|
long GetCounts(pCounter self, SConnection *pCon);
|
||||||
long GetMonitor(pCounter self, int iNum, SConnection *pCon);
|
long GetMonitor(pCounter self, int iNum, SConnection *pCon);
|
||||||
int GetNMonitor(pCounter self);
|
int GetNMonitor(pCounter self);
|
||||||
|
void SetMonitorValue(pCounter self, int index, long value);
|
||||||
float GetCountTime(pCounter self, SConnection *pCon);
|
float GetCountTime(pCounter self, SConnection *pCon);
|
||||||
|
|
||||||
int DoCount(pCounter self,float fPreset, SConnection *pCon,
|
int DoCount(pCounter self,float fPreset, SConnection *pCon,
|
||||||
|
@ -10,13 +10,12 @@ Hardware is configured into the SICS system by executing special hardware
|
|||||||
configuration commands from the server initialisation file. These commands
|
configuration commands from the server initialisation file. These commands
|
||||||
are described here. Much SICS hardware is hooked up to the system via RS-232
|
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
|
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:
|
initialisation the following parameters:
|
||||||
<ul>
|
<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
|
<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
|
listening for requests. It is usually 4000.
|
||||||
port server is running. It is usually 4000.
|
|
||||||
<li><b>channel</b> The number of the RS-232 interface on the Macintosh. 0 is
|
<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,
|
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
|
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
|
at which the counter will generate a random failure for testing error
|
||||||
treatment code. If failrate is less then 0, there are no
|
treatment code. If failrate is less then 0, there are no
|
||||||
failures. This can be used in a instrument simulation server.
|
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
|
<DT>MakeCounter name EL737 host port chan
|
||||||
<DD>This command creates a single
|
<DD>This command creates a single
|
||||||
counter name, using an EL737 driver. The counter is at host host, listening
|
counter name, using an EL737 driver. The counter is at host host, listening
|
||||||
|
@ -20,6 +20,7 @@ Go to:
|
|||||||
<li> Advice about <a href=hwini.htm> hardware </a> configuration.
|
<li> Advice about <a href=hwini.htm> hardware </a> configuration.
|
||||||
<li> A description of <a href = command.htm> command </a> initialisation.
|
<li> A description of <a href = command.htm> command </a> initialisation.
|
||||||
<li> Managing the SICS <a href="helpman.htm"> help </a> system.
|
<li> Managing the SICS <a href="helpman.htm"> help </a> system.
|
||||||
|
<li> Connecting SICS to <a href="mcstas.htm">McStas</a> Simulations.
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
<!latex-on>
|
<!latex-on>
|
||||||
|
@ -47,6 +47,7 @@ which is described elsewhere.
|
|||||||
%html hwini.htm 1
|
%html hwini.htm 1
|
||||||
%html command.htm 1
|
%html command.htm 1
|
||||||
%html helpman.htm 2
|
%html helpman.htm 2
|
||||||
|
%html mcstas.htm 2
|
||||||
%html special.htm 1
|
%html special.htm 1
|
||||||
%html serial.htm 2
|
%html serial.htm 2
|
||||||
%html status.htm 2
|
%html status.htm 2
|
||||||
|
140
doc/manager/mcstas.htm
Normal file
140
doc/manager/mcstas.htm
Normal 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
169
doc/user/tasub.htm
Normal 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>
|
@ -60,6 +60,7 @@
|
|||||||
#include "HistDriv.i"
|
#include "HistDriv.i"
|
||||||
#include "HistMem.i"
|
#include "HistMem.i"
|
||||||
#include "histsim.h"
|
#include "histsim.h"
|
||||||
|
#include "mcstashm.h"
|
||||||
#include "dynstring.h"
|
#include "dynstring.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
@ -442,6 +443,10 @@
|
|||||||
{
|
{
|
||||||
pNew->pDriv = CreateSIMHM(pNew->pOption);
|
pNew->pDriv = CreateSIMHM(pNew->pOption);
|
||||||
}
|
}
|
||||||
|
else if(strcmp(driver,"mcstas") == 0)
|
||||||
|
{
|
||||||
|
pNew->pDriv = NewMcStasHM(pNew->pOption);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
site = getSite();
|
site = getSite();
|
||||||
|
@ -49,7 +49,6 @@
|
|||||||
#include "HistDriv.i"
|
#include "HistDriv.i"
|
||||||
#include "histsim.h"
|
#include "histsim.h"
|
||||||
|
|
||||||
|
|
||||||
static int iSet = 0;
|
static int iSet = 0;
|
||||||
static HistInt iSetVal = 0;
|
static HistInt iSetVal = 0;
|
||||||
static HistMode eHistMode;
|
static HistMode eHistMode;
|
||||||
|
13
hmdata.c
13
hmdata.c
@ -37,6 +37,19 @@ void killHMData(pHMdata self){
|
|||||||
}
|
}
|
||||||
free(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){
|
static int resizeBuffer(pHMdata self){
|
||||||
long size;
|
long size;
|
||||||
|
1
hmdata.h
1
hmdata.h
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
pHMdata makeHMData(void);
|
pHMdata makeHMData(void);
|
||||||
void killHMData(pHMdata self);
|
void killHMData(pHMdata self);
|
||||||
|
void clearHMData(pHMdata self);
|
||||||
|
|
||||||
int configureHMdata(pHMdata self, pStringDict pOpt,
|
int configureHMdata(pHMdata self, pStringDict pOpt,
|
||||||
SConnection *pCon);
|
SConnection *pCon);
|
||||||
|
1
hmdata.w
1
hmdata.w
@ -28,6 +28,7 @@ The following functions work on this data structure:
|
|||||||
@d hmdatfunc @{
|
@d hmdatfunc @{
|
||||||
pHMdata makeHMData(void);
|
pHMdata makeHMData(void);
|
||||||
void killHMData(pHMdata self);
|
void killHMData(pHMdata self);
|
||||||
|
void clearHMData(pHMdata self);
|
||||||
|
|
||||||
int configureHMdata(pHMdata self, pStringDict pOpt,
|
int configureHMdata(pHMdata self, pStringDict pOpt,
|
||||||
SConnection *pCon);
|
SConnection *pCon);
|
||||||
|
5
make_gen
5
make_gen
@ -27,8 +27,9 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
|||||||
synchronize.o definealias.o oscillate.o tasdrive.o \
|
synchronize.o definealias.o oscillate.o tasdrive.o \
|
||||||
hmcontrol.o userscan.o rs232controller.o lomax.o tasscanub.o \
|
hmcontrol.o userscan.o rs232controller.o lomax.o tasscanub.o \
|
||||||
fourlib.o motreg.o motreglist.o anticollider.o nxdataset.o \
|
fourlib.o motreg.o motreglist.o anticollider.o nxdataset.o \
|
||||||
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) \
|
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\
|
||||||
hmdata.o nxscript.o tclintimpl.o sicsdata.o
|
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
|
||||||
|
mcstashm.o
|
||||||
|
|
||||||
MOTOROBJ = motor.o simdriv.o
|
MOTOROBJ = motor.o simdriv.o
|
||||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||||
|
398
mccontrol.c
Normal file
398
mccontrol.c
Normal 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
47
mccontrol.h
Normal 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
308
mcreader.c
Normal 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
28
mcreader.h
Normal 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
222
mcstas.tex
Normal 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
171
mcstas.w
Normal 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
3
mcstas/dmc/DataNumber
Normal 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
141
mcstas/dmc/PSD_monitor.comp
Normal 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
8
mcstas/dmc/batch.tcl
Normal 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
89
mcstas/dmc/dmc.dic
Normal 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
184
mcstas/dmc/dmc_sics01.instr
Normal 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
84
mcstas/dmc/log.tcl
Normal 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
66
mcstas/dmc/mcsupport.tcl
Normal 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
29
mcstas/dmc/na2ca3al2f14.q
Normal 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
108
mcstas/dmc/nxdmc.tcl
Normal 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
96
mcstas/dmc/nxsupport.tcl
Normal 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
138
mcstas/dmc/vdmc.tcl
Normal 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
156
mcstas/dmc/vdmccom.tcl
Normal 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
217
mcstas/dmc/vdmcstatus.tcl
Normal 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
160
mcstascounter.c
Normal 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
212
mcstashm.c
Normal 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
16
mcstashm.h
Normal 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
3
napi.c
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
----------------------------------------------------------------------------*/
|
----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static const char* rscid = "$Id: napi.c,v 1.10 2005/05/27 11:58:05 koennecke Exp $"; /* Revision interted by CVS */
|
static const char* rscid = "$Id: napi.c,v 1.11 2005/06/22 07:10:00 koennecke Exp $"; /* Revision interted by CVS */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -754,6 +754,7 @@ static NXstatus stepOneUp(NXhandle hfil, char *name)
|
|||||||
{
|
{
|
||||||
return NX_OK;
|
return NX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NXinitgroupdir(hfil);
|
NXinitgroupdir(hfil);
|
||||||
while(NXgetnextentry(hfil,name2,xclass,&datatype) != NX_EOD)
|
while(NXgetnextentry(hfil,name2,xclass,&datatype) != NX_EOD)
|
||||||
|
@ -154,8 +154,9 @@ CreateSocketAdress(
|
|||||||
i = sizeof(struct linger);
|
i = sizeof(struct linger);
|
||||||
lili.l_onoff = 1;
|
lili.l_onoff = 1;
|
||||||
lili.l_linger = 1;
|
lili.l_linger = 1;
|
||||||
|
/*
|
||||||
setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i);
|
setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i);
|
||||||
|
*/
|
||||||
pRes->iType = PORT;
|
pRes->iType = PORT;
|
||||||
pRes->lMagic = NETMAGIC;
|
pRes->lMagic = NETMAGIC;
|
||||||
return pRes;
|
return pRes;
|
||||||
|
7
ofac.c
7
ofac.c
@ -112,6 +112,8 @@
|
|||||||
#include "ubcalc.h"
|
#include "ubcalc.h"
|
||||||
#include "tasub.h"
|
#include "tasub.h"
|
||||||
#include "tasscanub.h"
|
#include "tasscanub.h"
|
||||||
|
#include "mcreader.h"
|
||||||
|
#include "mccontrol.h"
|
||||||
/*----------------------- Server options creation -------------------------*/
|
/*----------------------- Server options creation -------------------------*/
|
||||||
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
@ -303,6 +305,10 @@
|
|||||||
TasUBFactory,NULL,NULL);
|
TasUBFactory,NULL,NULL);
|
||||||
AddCommand(pInter,"MakeTasScan",
|
AddCommand(pInter,"MakeTasScan",
|
||||||
TASUBScanFactory,NULL,NULL);
|
TASUBScanFactory,NULL,NULL);
|
||||||
|
AddCommand(pInter,"MakeMcStasReader",
|
||||||
|
McStasReaderFactory,NULL,NULL);
|
||||||
|
AddCommand(pInter,"MakeMcStasController",
|
||||||
|
McStasControllerFactory,NULL,NULL);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -368,6 +374,7 @@
|
|||||||
RemoveCommand(pSics,"MakeUBCalc");
|
RemoveCommand(pSics,"MakeUBCalc");
|
||||||
RemoveCommand(pSics,"MakeTasUB");
|
RemoveCommand(pSics,"MakeTasUB");
|
||||||
RemoveCommand(pSics,"MakeTasScan");
|
RemoveCommand(pSics,"MakeTasScan");
|
||||||
|
RemoveCommand(pSics,"MakemcStasReader");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
remove site specific installation commands
|
remove site specific installation commands
|
||||||
|
10
tasscanub.c
10
tasscanub.c
@ -333,13 +333,13 @@ static int TASUBHeader(pScanData self)
|
|||||||
pTAS->ub->cell.beta,
|
pTAS->ub->cell.beta,
|
||||||
pTAS->ub->cell.gamma);
|
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",
|
fprintf(self->fd,"PARAM: AX=%8.4f, AY=%8.4f, AZ=%8.4f\n",
|
||||||
r.qe.qh,
|
r.qe.qh,
|
||||||
r.qe.qk,
|
r.qe.qk,
|
||||||
r.qe.ql);
|
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",
|
fprintf(self->fd,"PARAM: BX=%8.4f, BY=%8.4f, BZ=%8.4f\n",
|
||||||
r.qe.qh,
|
r.qe.qh,
|
||||||
r.qe.qk,
|
r.qe.qk,
|
||||||
@ -857,7 +857,7 @@ static void ParseOutput(pTASdata pTAS, SConnection *pCon)
|
|||||||
/*
|
/*
|
||||||
get a copy of output
|
get a copy of output
|
||||||
*/
|
*/
|
||||||
pText = (char *)malloc(strlen(GetVarText("output"))*sizeof(char));
|
pText = (char *)malloc((strlen(GetVarText("output"))+1)*sizeof(char));
|
||||||
if(!pText)
|
if(!pText)
|
||||||
{
|
{
|
||||||
SCWrite(pCon,"WARNING: out of memory while parsing output variable",
|
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
|
write orienting reflections
|
||||||
*/
|
*/
|
||||||
snprintf(pBueffel,255,"%s_vec1",argv[3]);
|
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[0] = r.qe.qh;
|
||||||
v[1] = r.qe.qk;
|
v[1] = r.qe.qk;
|
||||||
v[2] = r.qe.ql;
|
v[2] = r.qe.ql;
|
||||||
@ -1038,7 +1038,7 @@ static void TASUBDump(pTASdata self, SicsInterp *pSics, SConnection *pCon,
|
|||||||
SCWrite(pCon,pBueffel,eWarning);
|
SCWrite(pCon,pBueffel,eWarning);
|
||||||
}
|
}
|
||||||
snprintf(pBueffel,255,"%s_vec2",argv[3]);
|
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[0] = r.qe.qh;
|
||||||
v[1] = r.qe.qk;
|
v[1] = r.qe.qk;
|
||||||
v[2] = r.qe.ql;
|
v[2] = r.qe.ql;
|
||||||
|
@ -397,6 +397,7 @@ int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe,
|
|||||||
|
|
||||||
angles->sgl = Asind(-R[2][0]);
|
angles->sgl = Asind(-R[2][0]);
|
||||||
if(ABS(angles->sgl -90.) < .5){
|
if(ABS(angles->sgl -90.) < .5){
|
||||||
|
mat_free(R);
|
||||||
return BADUBORQ;
|
return BADUBORQ;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -419,6 +420,7 @@ int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe,
|
|||||||
|
|
||||||
QC = tasReflectionToQC(qe,UB);
|
QC = tasReflectionToQC(qe,UB);
|
||||||
if(QC == NULL){
|
if(QC == NULL){
|
||||||
|
mat_free(R);
|
||||||
return UBNOMEMORY;
|
return UBNOMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,6 +428,8 @@ int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe,
|
|||||||
q = 2.*PI*vectorLength(QC);
|
q = 2.*PI*vectorLength(QC);
|
||||||
cos2t = (qe.ki*qe.ki + qe.kf*qe.kf - q*q)/(2. * ABS(qe.ki) * ABS(qe.kf));
|
cos2t = (qe.ki*qe.ki + qe.kf*qe.kf - q*q)/(2. * ABS(qe.ki) * ABS(qe.kf));
|
||||||
if(ABS(cos2t) > 1.){
|
if(ABS(cos2t) > 1.){
|
||||||
|
mat_free(R);
|
||||||
|
killVector(QC);
|
||||||
return TRIANGLENOTCLOSED;
|
return TRIANGLENOTCLOSED;
|
||||||
}
|
}
|
||||||
angles->sample_two_theta = ss*Acosd(cos2t);
|
angles->sample_two_theta = ss*Acosd(cos2t);
|
||||||
|
Reference in New Issue
Block a user