The DreamMon software suite is designed for the analysis and visualization of brain imaging data at the single-trial level using blind source separation and other advanced signal processing technique. Although designed for magnetoencephalography (MEG), it has proven flexible enough to be applied to EEG and other sorts of neuroscience data.
DreamMon is organized as an incoherent set of idiosyncratic programs.
The software is in a pre-alpha state, but we use it to produce lots of scientific papers anyway.
This chapter describes some tricky aspects of running existing software. Necessity of such chapter occurs because of variety of command line parameters and switches present in many programs.
To get more profound information on command line parameters just run
that program with -help.
megtool - main tool to access MEG datamegtool is developed to get low-level access to raw MEG
data files. Next features list describes functionality of
megtool. Features are mentioned in order in which they're done in
megtool (So separating is applied before filtering)
This section gives examples of various ways to use the megtool
program, especially tricky or unusual ways.
The -window option indices the "window of interest" around the
lock event. However, the "before" and "after" lengths in the window may
be negative. So for instance to define the window of interest to be the
period from 20 to 35 samples following the lock, use -window -20,35
The -dump-means f option averages across trials. The output is a
simple time series. It may be worth mentioning that, if the window of
interest around a trial would extend outside the data file (eg before
t=0) that missing data is not included in the mean.
megtool -data 12 -dump-means foo.txt -window 0,100 -lock 2 \
/home/neuro/megdata/ta/ta_trump_raw.raw
That example is stripped down, as it does not include options for
getting sources instead of sensors, ie -W-file W -sources 122
The -response f switch finds the first point in each trial's
window to exceed a threshold. The threshold MUST be supplied, using
the "-response-threshold v" option. To find the first value below some
threshold, start the threshold with a "+", as below.
The file output has one line for each trial in which a response was found. (Rejected trials are not included.) Each line has format described in see responses.
EXAMPLES:
find responses above 75,
megtool -data 12 -window 0,100 -lock 2 -response bar.txt \ -response-thre 75 /home/neuro/megdata/ta/ta_trump_raw.raw
find responses below 53,
megtool -data 12 -window 0,100 -lock 2 -response baz.txt \
-response-thre +53 /home/neuro/megdata/ta/ta_trump_raw.raw
braintw - Probabilistic word typingFOLLOWING TEXT WASN'T FORMATTED PROPERLY. RAW TEXTUAL README FILE
IS INCLUDED
The Braintypewriter project at the Brain and Computation Lab
August, 2001
Overview:
Dependencies:
dict-web1913 (copy web1913.index to directory of installation)
> SDL-1.2
SDL_image
> freetype-2.0 (all available in debian package formt)
additional fonts
Controls:
Joystick left and right to scroll to the left or right of the
letter row. By default, '#' is the termination character
and '<' is the backspace character.
By default, button 1 increases shrinking speed, button 2 decreases
the speed and button 4 exits the program.
Detailed command-line options:
-h The help message.
-s num Shrink speed. num is a float that specifies
for what percentage of the whole screen does the
focus area shrink every event loop. Default value is
0.001.
-b Name of the background image file
-c Clear the joystick event buffer so the program does
not abort prematurely.
-f fn Load color definitions of some or all letters from
file f. See sample config file 'colorconfig' for
detailed syntax.
-t 'c' Specifies char c as the termination character to use
in the letter window. c must appear in quotes.
-a 'c' Specifies c as backspace character to use.
-d num Specifies the window sliding speed when a letter is
picked and we need to shift subwindows up to the top
row. i is an integer value. The bigger the value, the
faster and less smoother the windows slide. The
default value is 10.
-w num Specifies the window width in number of pixels. Default
value is 1280.
-e num Specifies the window height. Default value is 1024.
-x num Controls the speed at which the application runs. It
basically controls the shrink speed. Default value is 4.
-k Show special effects. When enabled, the program will
gradually zoom into child rows when they become
visible. The special effect is here to minimize
interference with the experiment results.
How to run a close-loop live test with braintypewriter:
The setup that is tested to work in the lab is to have 2 machines,
one dedicated to braintypewriter, the other to
sniffer+joycontrol. Remember that sniffer and joycontrol must be
run on the same host to eliminate the network overhead.
The following outlines the operation to be carried out in
order.
1. Hook up the video output on machine 1 to the projector in MEG
chamber.
2. On machine 1:
Run ./braintw
3. On machine 2
Run joycontrol:
meg/control/scripts/run-sniffer-version
The '-G' option in the script tells which host braintypewriter
is running on. It also accepts an IP address.
4. <wait 5 seconds for joycontrol to initialize>
5. Run sniffit as root:
./sniffit -s blood -x -B 10 -v -D -C [-L] [-A n]
The '-s' option specifies packets from this particular host are
to be sniffed. In live test, 'blood' should be replaced by the
MEG server. '-C' has to be used to tell sniffer to check for
the start of transmission. '-L' will tell sniffer to terminate
when the termination string is met. '-A n' activates the thread
to report statistics at n seconds' intervals.
6. Now start the acquisition software to receive data from MEG
machine. You should see some movement on the braintypewriter
screen. If you use the verbose mode in sniffer, it will print
"starting logging" when it sniffed data coming from the MEG
server. Otherwise, you can tell sniffer is not working.
Files:
colorconfig A sample color definition file.
cntxtica - Contextual ICAFOLLOWING TEXT WASN'T FORMATTED PROPERLY. RAW TEXTUAL README FILE
IS INCLUDED
# CVS version control block - do not edit manually
# $RCSfile: README,v $
# $Revision: 1.2 $
# $Date: 2000/10/20 09:00:02 $
# $Source: /home/cvs/meg/cntxtica_s/README,v $
Cntxtica (which stands for contextual independent components analysis for those
of you who are wondering) is a source-separation program. It is currently in
a functional, but extremely slow state.
Here are the possible command line options:
-help this one is a little obvious....
-debug n level of debugging. This outputs
debugging messages to STDOUT. It can
be any number 0-5, 5 being the highest
level of debugging output; 0 being the
lowest. It defaults to 0 (no debug output)
-generate-data generate data internally (for testing purposes)
-test-gradient calculate test gradient
-use_stdin take input from stdin. A really poor
way to do this...on a TODO list to fix
-binary binary data (default: ascii). This one
is a little fussy. At the moment, it
only takes binary data arranged in floats
(no .raw files).
-Nsens n number of sensors. Will default to 122
-Msourc n number of sources. Will also default to 122.
-Tback n depth of time dependency. defaults to 3
-Nouter n number of outer iterations. Defaults to 200
probably excessive, but not by too much
-Logistic_dens Use logistic density function. This is not
actually functioning; I just put it there
to make me look good.
-eta x Learning rate (default: 1e-4)
-ReadTime n sample size to read. defaults to 40000
-TotTime n sample size for computation. defaults to
being equal to ReadTime
-Lsubsets n Number of subsets in data. defaults to 1
-write_debug Output the state of the seperation, including
the regression coefficients for each source
SO-to run it on a typical MEG file, foo.raw, that has about 120000 samples,
you would write
$ megtool -chunk 120000 -data-range 122 -dump_channel - foo.raw | cntxtica
-ReadTime 120000 -use_stdin -Tback 50
Setting Tback to 50 is a somewhat arbitrary number; it should be much more than
the default (3), but how much is up to you.
control - Control suiteFOLLOWING TEXT WASN'T FORMATTED PROPERLY. RAW TEXTUAL README FILE
IS INCLUDED
Instructions on how to operate control project demonstration.
Introduction:
This file has two parts: the first describes how to run the
control software suite, the second describes how to write schemes to
control particle movement.
Part 1 (how to run the control suite):
The control suite is centered around the application
joy-control which acts as a client to any program that supplies
"channel" information. Currently this information must be in 16 bit
integer format. Right now there are three ways to serve the client
joy-control: using create-mouse-fifo, create-alpha-fifo, and sniffer.
Since joy-control is the client you must run it first. This
is done by executing a script file from the meg/control/scripts
directory. The script file contains all necessary command line
switches for joy-control which are specified in detail via the
./joy-control --help command.
1. Using create-mouse-fifo: Once you are running a joy-control
script in one terminal execute the command ./create-mouse-fifo in a
separate terminal on the local host. The script file for joy-control
should look something like this:
exec ../joy-control \
-dimension 2 \
-back linen \
-particles 1 \
-squareColor red,ForestGreen \
-schemeX ../schemes/scheme1.so \
-optionsX 1.0 \
-schemeY ../schemes/scheme1.so \
-optionsY 1.0 \
-graphics 1 \
-fftRate .0001 \
-samples 32\
-windowY 748 \
-windowX 1014 \
-windowZ 500 \
-channels 2
$*
feel free to adjust whatever parameters you would like but the demo is
designed to work with the -dimension, -schemeX, -schemeY, -optionsX,
-optionsY, -graphics, and -channels switches set as they are.
This demo takes channel information (in X and Y) from the
mouse running over a small window generated by create-mouse-fifo. The
scheme switches tell joy-control not to process the channel
information in any special way but to translate the channel
information directly into particle movement.
2. Using create-alpha-fifo: Once you are running a joy-control
script in one terminal execute the command ./create-alpha-fifo in a
separate terminal on a different host if possible (create-alpha-fifo
achieves accurate timing by polling very often and tends to bog down
the fastest of processors). The host running create-alpha-fifo should
also be part of the bcomplab local network since it draws channel
information from a large raw file. create-alpha-fifo expects the
joy-control script to be run on flake but this can easily be changed
by altering the host variable to the desired host name from within
create-alpha-fifo's code. The script file for joy-control should look
something like this:
exec ../joy-control \
-dimension 1 \
-back linen \
-samples 4 \
-particles 1 \
-squareColor red,ForestGreen \
-schemeY ../schemes/scheme9.so \
-optionsY 1.0 \
-graphics 1 \
-fftRate .0001 \
-samples 32\
-windowY 748 \
-windowX 1014 \
-windowZ 500 \
-channels 122
$*
Again, feel free to adjust these parameters as well but the demo is
designed to work with the -schemeY, -optionsY, -graphics, and
-channels switches set as they are.
This demo takes channel information from an actual raw file
created during an unrelated meg experiment. scheme9 is used to move
the particle according to the magnitude of the alpha frequency of
channel 95 (located at the back of the subjects head). The alpha
rhythm is also plotted in a separate window using plotonline (if the
plot is not working then run make in the meg/plotonline directory then
make install).
3. Using sniffer: This application should be run in a
different terminal after the appropriate joy-control script has
already been executed. While the particulars of running sniffer can
be found in Ting Li's documentation the joy-control script file should
look something like this:
exec ../joy-control \
-dimension 2 \
-back linen \
-samples 4 \
-particles 1 \
-squareColor red,ForestGreen \
-schemeX ../schemes/scheme9.so \
-optionsX 1.0 \
-schemeY ../schemes/scheme0.so \
-optionsY 1.0 \
-graphics 1 \
-fftRate .0001 \
-samples 32\
-windowY 748 \
-windowX 1014 \
-windowZ 500 \
-channels 122 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
$*
Here you really should take the liberty of changing as many parameters
as you can to get an idea of joy-control's flexibility. It's a good
idea to change schemes around to see what each will do. Don't forget
to check each particular scheme's documentation before using it
though. Some schemes are outdated and won't run properly with
joy-control's current implementation. Only functional schemes will
actually compile with the makefile in meg/control/schemes so please
use those and whatever schemes you may write yourself.
Part II (how to create new schemes):
What is a scheme?
Schemes are individual files comprising different functions
that dictate how the particle they are assigned to will move. They
are implemented as shared objects and are, therefore, capable of being
compiled separately from joy-control and linked to it dynamically.
Basically, a scheme decides how a given particle will move in
a particular dimension given server side input. For instance, if you
have two particles moving in two dimensions you will have to assign
four schemes in order to fully specify the particles' movement. The
input to a schemes is always the same it basically consists of raw and
processed input from the server. The output from a scheme is sent
though the argument virLoc (the particle dimension's virtual
location). virLoc is given as a float from 0 to 1. The actual
location of a particle is not assigned until the particle is about to
be displayed in joy-control.
What's different about implementing schemes as shared objects?
There is really only one problematic aspect to implementing
schemes as shared objects. Whenever the same scheme is assigned to
different particles and/or dimensions of a given particle, the same
function handle is assigned to both instances. This means that and
global or static variables share the same variable space. For
example, if you were to declare a static variable in the scheme that
is used more than once, all particles using this scheme would modify
the exact same variable.
To get around the problem of "shared variables" we actually
pass in any variables that may differ from one instance of a scheme to
the other. By convention static constants are passed in through the
array options and static variables are passed in through the array var
(with the first argument of options being the size of var). It's
important to realize that truly local variables that are created each
time the function is called do not need to be passed in. Only those
that need to be treated as static.
The biggest drawback to this solution is that since both
options and var are double arrays you can only pass in data in double
format.
Writing a scheme:
Always make sure to #include scheme.h and usually you'll need
to #include "meg/random.h"
Another convention uses the first element of var as a flag
separating the first execution of the function from the others. This
allows the function to initialize all the other elements of var and
write scheme information to the out file descriptor. Typically, the
first few lines of a scheme will look like this:
Please look at original README - was cut due to formatting error.
streamer - records subjects' head movementsFOLLOWING TEXT WASN'T FORMATTED PROPERLY. RAW TEXTUAL README FILE
IS INCLUDED
Recording subjects' head movement
Build:
make
The executable is named streamer.
Important:
Modify config.h according to your machine configuration.
Overview:
Most of the code is borrowed from the streamer program in the
xawtv-3.58 package. The program will do a bit-wise comparison
on two consecutive frames and only record both frames if their
difference exceeds a certain threshold value (to be empirically
determined in the MEG chamber). Capture.c contains most of the
frame grabbing functionality.
Changes were made in streamer.c, capture.h, capture.c.
Command-line options: (obtained from '-h' option)
general options:
-h print this help text
-M n recording threshold
-q quiet operation
-p n use n compression threads [1]
-w seconds wait before grabbing [0]
video options:
-o file video/movie file name
-f format specify video format
-c device specify video4linux device [/dev/video0]
-r fps frame rate [10.000]
-s size specify size [320x240]
-t times number of frames or hh:mm:ss [1]
-b buffers specify # of buffers [16]
-j quality quality for mjpeg or jpeg [75]
-n tvnorm set pal/ntsc/secam
-i input set video source
audio options:
-O file wav file name
-F format specify audio format
-C device specify dsp device [/dev/dsp]
-R rate sample rate [44100]
movie writers:
files - multiple image files
video formats:
ppm 24 bit TrueColor (BE: rgb) [ppm]
pgm 8 bit StaticGray [pgm]
jpeg JPEG (JFIF) [jpeg]
audio formats:
mono8 8bit mono [wav]
mono16 16bit mono (LE) [wav]
stereo 16bit stereo (LE) [wav]
raw - single file, raw video data
video formats:
rgb 24 bit TrueColor (BE: rgb) [raw]
gray 8 bit StaticGray [raw]
422 16 bit YUV 4:2:2 (packed) [raw]
422p 16 bit YUV 4:2:2 (planar) [raw]
4mpeg yuv4mpeg (for mpeg2enc) [yuv]
audio formats:
mono8 8bit mono [wav]
mono16 16bit mono (LE) [wav]
stereo 16bit stereo (LE) [wav]
avi - Microsoft AVI (RIFF) format
video formats:
rgb15 15 bit TrueColor (LE) [avi]
rgb24 24 bit TrueColor (LE: bgr) [avi]
mjpeg MJPEG (AVI) [avi]
jpeg JPEG (JFIF) [avi]
audio formats:
mono8 8bit mono [avi]
mono16 16bit mono (LE) [avi]
stereo 16bit stereo (LE) [avi]
qt - Apple QuickTime format
video formats:
raw 24 bit TrueColor (BE: rgb) [mov]
yuv2 16 bit YUV 4:2:2 (packed) [mov]
yv12 12 bit YUV 4:2:0 (planar) [mov]
jpeg JPEG (JFIF) [mov]
mjpa Motion JPEG-A [mov]
png PNG images [mov]
audio formats:
mono8 8bit mono [mov]
mono16 16bit mono (BE) [mov]
stereo 16bit stereo (BE) [mov]
For example:
./streamer -f mjpeg -o video.avi -t 300 -M 35
The above command will record 300 frames of avi video in motion jpeg
format and the recording threshold is set to 35.
Note that '-t' option is almost always necessary.
Among the above, -M specifies an integer threshold value. When the
average difference(total_difference/(width*height)) between two
frames is more than this value, the program will record both frames.
Output:
The program will save the timestamps for all the frames into a file
named "timestamps" in the following format:
hh:mm:ss,msecond.
msecond indicating how many microseconds have passed since the
current second.
Dependencies:
>X4.0
X4.x-devel
Corresponding codec libraries (avi,quicktime...)
libXv
libdl
Note:
The program has been tested in the Brain and Computation Lab on pus
(Athlon 700, 256MB, Haupauge WinTV, Debian 2.4.6, X4.1). Only
motion jpeg format has been tested.
sniffit - grabs packets from networkFOLLOWING TEXT WASN'T FORMATTED PROPERLY. RAW TEXTUAL README FILE
IS INCLUDED
#Changelog
# May 25,01 Added more notes on packet buffer in the "Buffer
# mechanism" section. Added format of dropout packet
# warning in the "Dropout packet" section.
NOTES
This document explains the general workings of the sniffer program.
Here is a general discription of the whole program:
The sniffit.c basically calls the low-level pcap API to
capture the TCP packets on the network and process these packets by
registering its own packet handler with the pcap functions. To be
more specific, the program basically has an infinite loop, the only
thing in which is the calling of the pcap_dispatch() function, which
captures a single packet, be it TCP,UDP or ICMP,etc, and pass it to
the custom-specified packet handler. The packet handler code is
contained in Control.c file, which reads the packet data into a buffer
and, when the buffer is filled up, assembles the packets in the raw
data format in the right order and sends the assembled data to either
a socket or a harddrive file. Sendpacket.c is a program that reads the
data from the sending unit of sniffer, ie, Control.c, byte swaps the
data if necessary, and sends the data again to another socket. The
program can be made to ouput arbitrary channels.
Other files of interest are:
packet.h Packet structure, header and data buffer.
socket.c A small library by Brian Wiley for socket
manipulations.
sn_defines.h Mainly defines the IPs and port numbers used in the
program, also some TCP/IP related macros.
sn_globle.h All the global variables we need to keep track of,
including some run-time options, sequence number
tracking, etc.
The following is detailed explanation of interesting routines:
The packethandler
The most import function in sniffit.c is packethandler(), which
is called every time a packet comes over the network. First of all,
this function determine the packet type. If it is TCP packet, which
is what we are interested in, it goes ahead and process it, otherwise
it returns DONT_EXAMINE. Then it reads the packet header into the
(struct TCP_header)tcphead. The processing mainly takes place in the
condition (finish<10&&LOGLEVEL==0). One (struct Packet) is used to
store each TCP packet, including the header and actual data. The max
data length is given by (max_packet_size-header_length)=1500-40=1460.
The whole packet is pointed to by (unsigned char *)sp that was passed in.
But we want to skip the header, the size of which is given by
(info.IP_len+info.TCP_len+PROTO_HEAD). Before memcpying the data into
the structure, the program uses IsValid() routine to check if this is
a packet we should be interested in,eg,if the src_ip is the meg
server, and if the src_port is from the communication port on the
server. Also, the routine will not proceed to copy the data until it
sees the signal of acqusition start. The checking is done by
comparing the packet data with a pre-specified string, defined in
sn_defines.h as a macro "start". Similarly, end of aquisition is
characterized by the string defined in sn_defines.h "stop". These two
characteristic strings are obtained by examining the raw dump of TCP
communication between the meg client and server. After the routine
detects the "start" string, it will set the "isstart" flag to be true
and never bothers to check again. Checking for termination works in
pretty much the same way.
NOTICE: Both the header and the actual data passed in are big endian
and therefore it's necessary to do byte swapping when running the
program on a PC. The sendpacket.c program takes care of this translation
before data is sent out to socket.
The buffer mechanism: (in sniffit.c)
The user can specify a buffer size in terms of the number of TCP
packets. This buffer is used to store the packets. When it's filled
up, ProcessData() routine will be called to process the whole buffer.
After the processing is done, the program will start filling the same
buffer again. The reason for using it is we want to check for dropout
or out-of-order packets in the buffer and the buffer is a way to
minimize such problems. A global variable "COUNTER" is maintained to
keep track of the index into the packet buffer. It will be set back to 0
whenever the processing is done.
When the program starts, it will create the buffer by allocating
memory for n packets, where n is the number the user specified on
command line with '-B n'. There is a global pointer (Packet *)packet
pointing to the start of this free memory. packethandler() will keep
copying data sniffed, pointed to by (char*)sp, to the memory address
pointed to by packet[COUNTER], until COUNTER equals n. Then the buffer
will be sent to ProcessData() for assembly, after which COUNTER will
be set to 0 and the program starts filling the piece of memory from the start
again. The sniffed data will only be copied into one of the packet
structure in buffer if the packet actually contains the data we need
so that when the buffer is sent to ProcessData(), it contains all the
"good" data, that is, data that actually contain the channel
information. At the stage of copying data into the packet structure,
the program doesn't check the sequence numbers, that is, the packets
are in whatever order they came in. In ProcessData(), if REORDER
macro is defined, the program will use qsort() to reorder packets
according to their sequence numbers and return an order list of
pointers. However, this way of reordering packets is limited. It can
only sort the packets in the same buffer. If an out-of-order packet
comes way after its normal order and becomes on packet in a different
buffer, then this way wouldn't work.
Actual packet processing:
This is implemented in Control.c file. For each packet in the
buffer, the program simply writes the data as is to the socket, but
adding a strictly incrementing 32-bit integer as the timestamp at
fixed interval. This interval is defined as a constant "386" in the
Control.h file. The number is obtained by (max_num_of_channels*2).
And max_num_of_channels is assumed to be all possible channels,
EEG,MEG,STIM and MISC.
This way, we have the artificial timestamps, which are not contained
in the network traffic.
Duplicate and Out-of-order packet checking:(in Control.c)
Duplicate packet checking can be enabled by use -D DETAIL during
compile time. The Control.c maintains a bucket(called BUCKET) of all
the sequence numbers in the current buffer. If it finds a sequence
number already in the bucket, it reports and error and simply discards
this packet. The out-of-order packet test is implemented by simply
comparing the current sequence number with the last one, and if the
current one is smaller than the last one, then the current one must be
out of order. If the user has enable "REORDER", then program will try
to reorder the packets in the buffer first, by sorting their sequence
numbers, and then process the buffer.
Dropout packet checking:(in Control.c)
Checking for missing packet should always be enabled by defining
"CHECK_MISSING" in the Makefile. The program maintains a variable
that calculates (current_seq_num-last_seq_num-last_packet_length).
This variable should always be 0. Otherwise, there must be dropout
packets, and the number of bytes we are missing is exactly this variable .
Then the program will print a warning to the standard output, giving
both the sequence numbers and the packet length of the current and
last packets, along with the number of missing bytes. The program
does not take any action when such situation occurs.
Whenever the program detects a missing packet, it prints a warning
to the standard error. The format is "Packet loss between a and b at
c, amount: d sample e channel f - sample g channel h i samples",
where a and b are the last packet
processed and current packet, respectively, c the current packet's
index in the buffer, d is the total amount of bytes missing, e and f
and g and h are from which channel in which segment to which channel
in which segment is the data missing. is the number of samples
completely missing.
NOTE: To make sure this checking mechanism works, we should try to
eliminate the data source as much as we can, in other words, this
mechanism works best when there are only packets going from a single
port on a host to a single port on another host. This way, the
sequence numbers of packets from different sources will not mix up and
cause false alarms. Actually, we must have this gurantee for the
checking to work properly.
RealProcess() routine:(in Control.c)
After all the error checking has been done, the program calls this
routine to actually process the data buffer. Its jobs includes
generating binary strings of timestamps and write them to socket at
fixed interval. Two global variables are maintained in this routine:
"index_counter", which is essentially the timestamp and gets incremented
every segment; "ofset", which marks the place to add the first timestamp
in the current packet. We need the variable "ofset" because the
positions of the segments in packets are not fixed. The output will
be directed to a socket on port defined by "com_port" in "sn_defines.h".
Sendpacket.c
This program is just a utility that reads the data from the sniffer
program, performs the byte swapping and formatting(which channels to
output), and sends the resulting data to another socket, on the other
end of which is some signal processing unit.
Test setup:
A. Hardware setup:
First of all, make sure the ethernet interface connected to the
local net is brought up and set to promiscuous mode. This interface
should be assigned an IP of 192.168.100.50 and the netmask should be
255.255.255.255.
Connect this interface card to the LAN hub with a straight ethernet
cable.
The actual meg acquisition can be just noise runs, or with
subjects. It doesn't really matter to sniffer.
B. Software setup:
Before the test, we should avoid running a lot of other processes
on this machine.
The whole program will have two separate executables: sniffit and
sendpacket and a typical live test requires a particular sequence of
operations. NOTICE that "sniffit" assumes all possible channels are
packed in the data, that is, EEG,MEG,STIM and MISC channels. To only
transmit certain type of channels, the constant "INTERVAL" in
Control.h must be modified to correct value. The "all_chan" variable
in sendpacket.c must also be modified to the actual number of channels.
The sniffit has to be run as root. Sendpacket doesn't need to be root.
The correct sequence should be:
1. start the sniffit, and tell it to write to socket(be root first)
2. start sendpacket and tell it to write to socket.
3. start meg acquisition.
If debug messages are enabled, such as LDEBUG and CHECK_MISSING, you
might want to redirect the output of sniffit to a file. The correct
command to start sniffit is:
./sniffit -B 20 -x -s 192.168.100.2 -F eth0 -C
See the README file for detailed explanation of command line options.
One thing to note is we specify only one source for sniffit to sniff,
which is 192.168.100.2, the HP server's IP on the localnet. We should
always use this form for dropout packet checking to work properly. If
you want to get a dump of what sniffit has captured, use "-d filename"
instead of "-x". "-F" should be followed by which ever ethernet
interface hooked up to the local net. When the acquisition is started
on the HP machine, sniffit will report it has identified the start of
the transmission by saying "starting logging". Before the meg is
started, "sendpacket" should be started by doing something like:
./sendpacket --output sock --data-chan 0 --data-range 122
Again, check README for detailed command options. Now start the meg
acquisition.
C. Error checking:
To check whether we have captured the right data, have the sniffit
program create a harddrive dump by using "-d filename" and save the
data of this acquisition on the HP machine. Obtain the .raw file of
the data file on HP and copy it to the host we are running on. Run:
./plot raw_file sniffer_dump 2
This will plot the content of the two files in a window, raw file
in red and sniffer dump in blue. Ignore the tail of the curves. If
the body of the two curves overlap, that is, you can only see one
color showing on the screen, then we have the right data. See README
file for detailed usage on plot.
To simply debug the control loop, there is a way to do test runs
without the meg machine. All we need to do is turn off the packet
validity checking and turn on our own fake machine, which outputs the
sine function of predictable numbers. First, run sniffit like this:
./sniffit -B 20 -x -s server_ip
"server_ip" is the IP of the host running fake meg machine. You
must make sure sniffit and the fake meg run on different hosts,
otherwise sniffit wouldn't be able to sniff anything. Now run fake
meg on a different host:
./meg
On another host, which can be the host on which sniffit is running,
run the cl program:
./cl server_ip
Again, "server_ip" is the IP of fake meg. If the output of cl is not
redirected to a file, you should now see a whole bunch of garbage
bytes showing up on the cl's screen. The sniffit should also begin to
write data to the socket. Now run the sendpacket program on sniffit's host:
./sendpacket --output sock --no_byte_swap --data-chan 0 --data-range 122
The the sendpacket will relay the data to another socket. We disable the
byte swapping calculation here because we are assuming we have little
endian architectures in the lab.
Output of statistics thread:
Output for each time interval will be separated by dash lines. The
following fields will be show:(in the following order)
Time elapsed: number of seconds elapsed since the start of the test.
packets processed: total number of TCP packets processed, also in terms
of how many samples.
packets ignored: packets with different protocols than we are
interested
Traffic: total number of packets sniffed vs. seconds
Processing rate: packets processed vs. seconds, also
samples processed vs. seconds
Number of dropout packets: in number of packets and also in total
number of bytes.
Test result:
All the tests done right now are 30-second noise runs with meg
machine. During the whole process, we have no duplicate, out-of-order
or dropout packets and the data acquired, as shown by plot, is
correct. The sniffit program is also tested for a frequency of 1 kilo
Hz and passed. See BUGS.
Meg test result:
Lab test result:
These tests are conducted in the bcomplab with the fake_meg and
fake_client programs:
fake meg server: tears(K6, 32M)
sniffit and fake meg client: phlegm(Dual PIII 500 CPU, 256M)
Success:
The threaded and sequential versions capture the same data. These
two do not really make a difference in performance, ie, threaded
version fails all the tests that the sequential fails on.
The threaded version of sniffer has no dropout packets when tested
with 300Hz sampling rate for 5 minutes, while joy-control is running
with on-line plotting enabled. When the sampling rate is raised to
600, there is no dropout packets,either.
In the above condition, the threaded sniffer also runs with 1000Hz
sampling rate with no dropout packets, but the statistics thread
cannot be enabled('-A' option).
Throttling on 'sendpacket' works but need a big number like
"--sample-rate 1000" would work.
Tests show that giving a big buffer size will stop dropout packets
when testing against simulated bursting in the lab.
Threaded version has to be used (-D USE_THREAD) and statistics
thread must be disabled. The following command have been tested and
passed 300Hz, 600Hz and 1000Hz sampling rate:
./sniffit -s tears -x -B 130 -C -l 0
The sending pieces uses this command:
./sendpacket --output eat --data-chan 0 --data-range 192 --no-byte-swap
fake_meg:
./fake_meg 300 0
fake_client:
./fake_client tears 0
Giving '-B 130' will also work.
To do a successful test with joy-control, some parameters under
/proc need to be adjusted:
Go to /proc/sys/net/core.
Manually change wmem_default and wmem_max, which should be defaulted
to 65535, to 524287(512k-1). This will increase the read buffer
size of each socket connection. Then run the joy-control and
sniffit with real-time priority enabled. In this case, if we enable
the statistics thread, we have to give '-A' a bigger interval, like
20. So this will work:
./sniffit -s 192.168.100.2 -x -B 20 -l 0 -A 30 -M
./sendpacket --output sock --data-chan 0 --data-range 192 --no-byte-swap --with-control
I had dropout packets when giving 10 for statstics interval. But
the above ran with no problem for more than five minutes, when the
fake sampling rate is 1000 and simulating the bursting problem.
Failure:
When run under 1000 sampling rate with statistics thread enabled,
the program drops a lot of packets.
FOLLOWING TEXT WASN'T FORMATTED PROPERLY. RAW TEXTUAL README FILE
IS INCLUDED
ReadMe
(See working_com for working commands in bcomplab)
1. How to build the programs:
See INSTALL.
Sniffit and sendpacket must run on the same host.
The file sn_defines.h contains system defaults. You should modify
it to suit your own need.
2. Command-line options:
NOTE: sniffit needs the user to be root to run. sendpacket does not
have this requirement.
a) Options for the sniffit program
To force sniffit to check for missing packets, append "-D
CHECK_MISSING" to "CPPFLAGS" field in Makefile and 'make'. To have
Sniffer give out warnings, append "-D DEBUG" to "CPPFLAGS field in
Makefile and 'make'.
-B n Required option. Specifies the buffer size to be used in
the sniffit program. n is the number of TCP packets to
buffer before reordering and assembling raw data in these
packets.
-o fn Tells sniffit to dump raw data to a disk file specified
by fn.
-x Tells sniffit to dump raw data to a socket on the localhost.
In this case, sniffit establishes a socket by opening a
pipe to "tcplisten" on port "com_port", which is
defined in "sn_defines.h". The sendpacket program will
connect to this port to get the raw data. The user must
specify either '-x' or '-o' on the command line to
specify the output mode.
-C Tells sniffit whether to verify the data or not. If this
option is on the command line, whenever a packet is
captured, sniffit will discard those that are either not
from the MEG server, specified by "server_ip" in
"sn_defines.h", or not from the MEG server's
communication port, specified by "f_co_port" in
"sn_defines.h" . Also, if data verification is required,
sniffit will not record data until it has found the
signal of start of transmission, by searching for the
string "200 Logging data" among packets from the server's
control port, specified by "f_ct_port" in
"sn_defines.h". This option should only be turned on
during a live test with the MEG machine. It doesn't work
with the fake raw data.
-s str Tells the program to only listen for packets from a
particular host "str". "str" can be either a host name
or an IP address. This option supports wild card; e.g.,
"192.168.100.¨will process packets from hosts with IP
"192.168.100.xxx".
"¨will process packets from all hosts on the
subnet.
-t str Similar to the above. This tells sniffit to only check
packets destined toward certain host "str".
-P proto Specifies the protocol to be used. Possible options are:
IP,TCP,ICMP,UDP. Sniffit uses TCP by default.
-p port Only checks packets going to port "port".
-F dev Forces sniffit to listen on device dev. dev can be,eg., eth1,
ppp0... To run the program on meg370, it should listen
on NIC on the internal net.
-v Enable debug output.
-l num Enable real-time scheduling, num is the priority number.
Giving a 0 will use the maximum priority allowed.
-D Enable checking for duplicate packets
-r Enable sorting packets within the buffer
-L Enable checking for end of transmission
-A num Create a thread that reports important network statistics
at intervals of 'num' seconds. num must be an integer.
NOTE: Since there will be altogether 3 threads
running(main thread, timer, statistics), the program will
consume a lot of CPU time. Make sure no other
CPU-consuming processes are running, otherwise there will
be dropout packets.
-i num Number of channels contained in a single segment. The
default is all the channels, 193. So if we are using a
different number of channels, be sure to use this option
to specify the number.
-n str Specify the log file name to write the warning messages
into. If this option is not used, error messages will be
written to standard error.
-M Adjust socket send buffer size via the proc file system.
The default size under linux is 64k and this size will be
adjusted to 512k(empirically determined) and the receive
buffer size will remain the same. This is to prevent the
packet loss when the TCP connection has a bursting
problem. Socket buffer size will be restored to its
original value after the program exits.
-h Print the help message.
2. Commands that work:
To do a live test with the MEG machine on meg370 and show the raw data
channel by channel:
first, run sniffit like this:(su to root first)
./sniffit -B 130 -x -s 192.168.100.2 -F eth0 -C -l 0
then, run the sendpacket program on the same host:
./sendpacket --output sock --data-chan 0 --data-range 122
then, start data transmission on the MEG machine;
In this case, sniffit will only start sending data to sendpacket when
it finds the string "200 Logging data" in the incoming packets.
Sendpacket will separate data into channels and dump channels to another
socket.
To do a test run within the lab:
./sniffit -B 20 -x -s
run client:
./sendpacket --output sock --no_byte_swap --data-chan 0
--data-range 122
run the MEG data generator;
The sniffit program can only be terminated by hitting Ctrl-C.
For commands for the plot program, read "Test setup" section of
NOTES.
4. General workings:
See NOTES for detail.
Sniffit only starts sending data when there is a request on the
right port by the sendpacket program.
The sniffit program does not touch the raw data at all. It only
assembles the raw data and send them to the socket as is. The sendpacket
program does the byte swapping on data from the sniffit and encode
them back into binary 16-bit-integer stream. The sendpacket program
doesn't output the timestamp for each slice but can do timestamp
verification if the user wants.
5. Dependencies:
Both programs make use of "tcplisten" and "tcpconnect" to
establish sockets. So make sure you have these utilities in the system.
Also, make sure you have libpcap and bpf(Berkley Packet Filter)
libraries installed in the system.
6. Format of output
The 'sendpacket' program is responsible for outputting data from
sniffer. If you wish to print the data to a socket, 'sendpacket'
will print n 2-byte character strings, each string representing a
value of the type int16_t. n will be the number of output
channels your specify with -data-chan and -data-range.
If you are printing to standard output, the program will output n
integers to stdout, each representing a single channel value. n
is defined the same way as above.
showmeg - GUI for displaying MEG dataIdea behind showmeg was to create a small tool with features as
So now showmeg takes float data from stdin and presents it as a
color image. Palette and other parameters can be changed
dynamically. Sizes of image can be drawn from read data or provided at
the beginning of data stream (Look Usage on showmeg).
Parameters for showmeg can be provided from command line as
well as specified in its GUI (there some parameters which can be
changed just from command line).
Help on all command line parameters can be achieved through invoking
showmeg with -help.
showmeg tries to figure proper sizes if dealing with raw data
without information about sizes. So if we specify either of dimensions
(-[xy]size n) or ratio between them (-ratio n),
showmeg computes the other one depending on size of data
presented.
Here I want to describe just couple of parameters which can be not
clear from small description of -help.
The -input-raw switches whether we're trying to get information
about image from first 3 values which we meet in a
stream. megtool dumps x, y and before(length of
data before event) at the beginning of the image file. So if we get
image from megtool, we can't specify -input-raw because it
will consider then this information as data for displaying.
But if we created some information outside of our suite, like in
Matlab and dumped it to simple ASCII file, we can use showmeg
with this switch to avoid missing first 3 data points.
No GUI will appear. Depending on command line parameters, showmeg
will generate an image and dump it to file with name specified in
-i-file f parameter.
Show data obtained from megtool(see megtool).
megtool -sources 122 -data 27 -window 200,300 -lock 0/1 -gap 2/3/4 \ -sort -W ~neuro/W/ta_el/joint/W -no-convert -i-file - \ ~neuro/W/ta_el/data.raw \ | showmeg -x 400 -colormap -5 -brightness 0.8 -contrast 0.5
run_jade - JADE ICArun_jade idea was adopted from
matlab/gen_utils/decor_ica.m. Both these codes are designed to
implement Independent Component Analysis using JADE
algorithm (for more information can check
http://tsi.enst.fr/icacentral/algos.html).
run_jade was developed to gain some performance
improvement. C implementation gave around 5 times speed up in
comparison with matlab code. As well as matlab's code it reads data
from raw MEG files with help of megtool through
pipeline. This degrades performance a lot, so we will think about way
to unify access to MEG files in our tools suite through some
library.
Algorithm run_jade in nutshell is very straightforward
-corr
parameter present - raw data is not read because it is assumed
precomputed and then filename considered to be a filename for a
file already containing correlation matrices. If -taus
parameter is specified when -taus is provided, then we take
only that matrices which are specified in -taus.
If it needs to read MEG data from .raw file it asks
megtool to do that. That is why there is an optional parameter
-ex_switch x to specify some additional parameters to pass for
megtool. Next step is performed only if no -corr
parameter in command line.
-taus l
parameter specifies user-defined delays. By default next delays
are considered: 1,2:10,11:2:21,22:5:52,100:-2:50. If parameter
-hertz n is specified, then set of delays is scaled assuming
that it was defined to 300Hz sampling rate.
Almost all command line parameters described in Summary. Look also at
examples. One important command line parameter can be -sens n
which changes number of sensors from default 122 to provided value n.
Read all data from file, assumes default number of sensors 122:
run_jade /home/mrgray/misc/backup/at/ta_tp_raw.raw
Read specified amount of data:
run_jade -skip 0 -read 139230 /home/mrgray/misc/backup/at/ta_tp_raw.raw
Previous example with speicified delays:
run_jade -skip 0 -read 139230 -taus 1,2:10,11:2:21,22:5:52 \
/home/mrgray/misc/backup/at/ta_tp_raw.raw
Previous example with specified also thresholds to dump W file:
run_jade -skip 0 -read 139230 -taus 1,2:10,11:2:21,25:5:100 \ -thresh 1e-1,1e-2,1e-3,1e-4,1e-5,1e-6:-1e-7:1e-7,9e-8:-1e-8:1e-8 \ /home/mrgray/misc/backup/at/ta_tp_raw.raw
This chapter describes file formats used some of the DreamMon MEG analysis tools.
Formats of used data files didn't evolve for a long time. Mentioned in
this section data structures defined in megtool/split.h.
| timeslice_rec | .raw Data Structure |
|
This data structure describes single trial in the data. So every
.raw file consists of records of this type.
Here channel is just a pointer to a slice of file/memory with data for all channels at the trial. timestamp keeps timestamp of current trial.
struct timeslice_rec {
u_int32_t timestamp;
u_int16_t channel[1];
} __attribute__ ((packed));
Function |
| timeslice | .raw Data Structure |
Is used just a shortcut (typedef) for struct timeslice_rec
|
Because .raw data file doesn't keep any information about experiment (as number of sensors of each kind, sample rate etc), another data structure became involved.
| rawfile_attributes | .raw Data Structure |
struct rawfile_attributes
{
double samples_sec; /* samples per second */
int n_chan; /* number of channels TOTAL */
int n_meg; /* number of MEG channels */
int n_stim; /* number of STIM channels */
int n_eeg; /* number of EEG channels */
int n_misc; /* number of misc channels */
int rec_size; /* size of each timeslice */
int downsample; /* how much should data be downsampled?*/
};
|
| rawfile_attrib | .raw Data Structure |
Is used just a shortcut (typedef) for struct rawfile_attributes
|
-response command line parameter to megtool (output)
-event-file command line parameter to megtool (input)
Here we mention formats of files which can be generated or fed into megtool.
File contains detected responses. From a megtool.c's point of view
it is a file which is generated with megtool.c and
specific command line parameter -response f where f is a
file name (usual name for a file can be 00x_resp.dat, where x can be a
source number if we work with a single source).
Format of the file is simple, each number in each line has next meaning
1 2 3 4
Times are given as sample numbers, with the first sample considered time 0.
Default name for the file is inputfile.events, where
inputfile is input file with data (like evoked.raw).
Default value can be overriden with -event-file.
First line in a file keeps number of lines with events which follow.
Each line is just couple of numbers
1 2
Numbers for events types varies from project to a project. Some times it
is possible to get minor documentation on that in STIM_LINES
files in the directory of the project.
So in plasticity project
.ncmeg---------------------------------------------------------------------- WARNING:.ncmegformat still is under development, so no caching or storing in.ncmegis done by now. ----------------------------------------------------------------------
Current format is designed under consideration of netMEG file format developed for MEGAN software
For more detailed description of netcdf library you can look at
/usr/doc/netcdf-doc or go to the
netcdf home page
All conventions on names of variables, attributes etc are defined in netcdf/megnetcdf.h.
Global attributes are variable which defined for whole data file to give some additional information about experiment or stored data.
| string Comments | Global Attribute |
| different comments which can come from operator/user/... |
| string DateOfDataAcquisition | Global Attribute |
| date when acquisition was done |
| string DateFileCreated | Global Attribute |
| date when acquisition was done |
| string MontageName | Global Attribute |
| Name of sensor system used |
| string PatientName | Global Attribute |
| Name (can be just some kind of alias) of a patient |
| string netCDFfileType | Global Attribute |
| comments about data acquired (if was averaged etc.) |
| string netCDFfileVersion | Global Attribute |
| version of the file |
| string FiltersUsed | Global Attribute |
| information (comments) if filters were used |
| string OriginalFileName | Global Attribute |
| the name of the main file from which the data was read. Can be .meg file. |
| string OriginalFileDate | Global Attribute |
| Modification time of source file - necessary to figure out if cached data in filtered and sources is valid |
| long SamplingRate | Global Attribute |
| sampling rate of the device where data was acquired (default for MEG machine used was 300 Hz). |
Dimensions are defined to determine structure of other variables. For instance many variables will grow in time, so there is a reason to name a dimension time. Some data will be arranged depending on to which sensor it belongs, so there is a reason to create dimension sensors.
unlimited means that data in this dimension can grow. So if we're
making an experiment we're accumulating data - so dimension dTime
will grow and that is why it must be unlimited. Only single dimension
within a file can be declared as of unlimited size.
| dTime | unlimited |
| Dimension of the time. Each time point is one set of experiment data |
| dSensors | fixed |
| All sensors present in system |
| dSources | fixed |
| All sources separated from raw data. By default (and for now) number of sources is equal to a number of sensors. |
| dStims | fixed |
| Stimuluses which were present during an experiment |
| dCoord | fixed |
| The three Cartesian coordinates XYZ for position of sensors and possibly localized sources |
Most of variables defined in this section based on predefined dimensions (see Dimensions).
short raw (dTime, dSensors)
|
Variables |
| raw data. date when acquisition was done |
float filtered (dTime, dSensors)
|
Variables |
| filtered data. Parameters of the filter used are listed in ???? |
float sources (dTime, dSources)
|
Variables |
| data which was composed by applying unmixing matrix defined by unmixing. |
double unmixing (dSensors, dSources)
|
Variables |
| unmixing matrix which was applied to get sources from raw data |
| string matrixFile | unmixing's Attribute |
| File name (including path) where unmixing matrix was taken from. |
| string matrixFileDate | unmixing's Attribute |
| Date when this unmixing matrix's file was created |
float SensorLocation (dSensors, dCoord)
|
Variables |
| raw data. date when acquisition was done |
.ncmeg.cachedFiles of this format usually are just a temporary files for .ncmeg to
.raw data files. They contains just intermediate computed data for
speeding up the process, to avoid recomputing the same quantities over
and over again, as it happens when we have separating matrix, or doing
different manipulations with filtered data. So as far as parameters for
current data file don't change we have valid cached data. .ncmeg can
also keep all necessary caching data if it was configured for that or it
was explicitly mentioned to don't create .cached file.
So variables in cached data file can be the ones which are missing in
current .ncmeg file.
braintw: braintw
braintypewriter: braintw
cntxtica: cntxtica
create-alpha-fifo: control
create-mouse-fifo: control
joy-control: control
matlab/gen_utils/decor_ica.m: run_jade
megtool: megtool
run-create-alpha-fifo-version: control
run-create-mouse-fifo-version: control
run_jade: run_jade
showmeg: showmeg
sniffit: sniffer
streamer: motion
test-fft: control
testJoy: control
cntxtica_s/: cntxtica
control/: control
joint_diag.[hc]: run_jade
megnetcdf.h: netcdf .ncmeg
megtool.c: events, responses
megtool/: megtool
megtool/megtool.c: events, responses
megtool/read.c: Original .raw
megtool/split.h: Original .raw
motion/: motion
netcdf/megnetcdf.h: netcdf .ncmeg
run_jade.c: run_jade
showmeg/: showmeg
sniffer: sniffer
split.h: Original .raw
yica/: run_jade
dCoord: Dimensions
dSensors: Dimensions
dSources: Dimensions
dStims: Dimensions
dTime: Dimensions
rawfile_attrib: Original .raw
rawfile_attributes: Original .raw
timeslice: Original .raw
timeslice_rec: Original .raw