Skip to content

Groups of scans

Bliss provides the capability to bundle several scans together into a sequence.

Scan sequences

Sequences can be used to group together multiple scans to be run during this sequence. Sub scans have to be added to the sequence before running it. And at the end of the sequence the whole sub scans will be terminated.

The ScanSequence object takes commons keyword arguments like title or scan_info.

It’s a normal scan which can be monitored with blissdata.`

Example

TEST_SESSION [4]: from bliss.scanning.scan_sequence import ScanSequence
             ...: def runner(scan_seq):
             ...:     s1 = loopscan(5, .1, diode, run=False)
             ...:     scan_seq.add(s1)
             ...:     s1.run()
             ...:
             ...:     # do something here ... move motors, open/close shutter
             ...:
             ...:     s2 = loopscan(3, .2, diode, run=False)
             ...:     scan_seq.add_and_run(s2)
             ...:
             ...:     # do more things
             ...:
             ...:     s3 = loopscan(3,.2,diode, run=False)
             ...:     scan_seq.add_and_run(s3)
             ...:
             ...: scan = ScanSequence(runner=runner)
             ...: scan.run()

In the example above we create a function which handle a set of scans (s1 and s2 … note the run=False keyword argument) and add them to the sequence by calling add_and_run (or add to handle the run manually).

Channels attached to sequences

It is possible to publish additional channels that are not part of any of the scans inside the sequence. These channels could e.g. be the result of a calculation based on the data acquired during the sequence.

Example

TEST_SESSION [12]: from bliss.scanning.scan_sequence import ScanSequence
          ...: from bliss.scanning.chain import AcquisitionChannel
          ...: import numpy
          ...: ch1 = AcquisitionChannel("mychannel", float, ())
          ...: ch2 = AcquisitionChannel("sum", float, ())
          ...: def runner(scan_seq):
          ...:     s1=loopscan(5, .1, diode, run=False)
          ...:     s2=loopscan(5, .1, diode, run=False)
          ...:     scan_seq.add_and_run(s1)
          ...:     scan_seq.add_and_run(s2)
          ...:
          ...:     scan_seq.emit('mychannel', [1.1, 2.2, 3.3])
          ...:
          ...:     my_sum = s1.get_data()[diode] + s2.get_data()[diode]
          ...:     scan_seq.emit("sum", my_sum)
          ...: scan = ScanSequence(runner=runner, channels=[ch1, ch2])

In the example above we create a function which handle a set of scans (s1 and s2). We can retreive data from this scans and emit this values to the channels linked to the scan sequence

Sequences (deprecated)

This example still work but should be replaced by ScanSequence (see above)

Sequences can be used to bundle scans no matter if they have already been executed before or if they will be running during the sequence. The only condition: all scans of the sequence must terminate before leaving the context manager provided by the sequence. The Sequences object takes as keyword arguments title and scan_info.

Example

TEST_SESSION [4]: from bliss.scanning.group import Sequence
             ...: seq=Sequence()
             ...: with seq.sequence_context() as scan_seq:
             ...:     s1=loopscan(5,.1,diode,run=False)
             ...:     scan_seq.add(s1)
             ...:     s1.run()
             ...:
             ...:     #do something here ... move motors, open/close shutter
             ...:
             ...:     s2=loopscan(3,.2,diode,run=False)
             ...:     scan_seq.add_and_run(s2)
             ...:
             ...:     #do more things
             ...:
             ...:     s3=loopscan(3,.2,diode)
             ...:     scan_seq.add(s3)

In the example above we prepare scans (s1 and s2 … note the run=False keyword argument) and add them to the sequence by calling add or add_and_run. It is also possible to add a scan that has already terminated (s3). However, when thinking about online data analysis it is advisable to first add the scans to the sequences and run them afterwards (like s1 and s2) as this enables external processes to follow the sequence in real time.

Channels attached to sequences

It is possible to publish additional channels that are not part of any of the scans inside the sequence. These channels could e.g. be the result of a calculation based on the data acquired during the sequence.

Example

TEST_SESSION [12]: from bliss.scanning.group import Sequence
          ...: from bliss.scanning.chain import AcquisitionChannel
          ...: import numpy
          ...: seq=Sequence()
          ...: seq.add_custom_channel(AcquisitionChannel('mychannel',float,()))
          ...: seq.add_custom_channel(AcquisitionChannel('sum',float,()))
          ...: with seq.sequence_context() as scan_seq:
          ...:     s1=loopscan(5,.1,diode,run=False)
          ...:     s2=loopscan(5,.1,diode,run=False)
          ...:     scan_seq.add_and_run(s1)
          ...:     scan_seq.add_and_run(s2)
          ...:
          ...:     seq.custom_channels['mychannel'].emit([1.1,2.2,3.3])
          ...:
          ...:     my_sum = s1.get_data()[diode] + s2.get_data()[diode]
          ...:     seq.custom_channels['sum'].emit(my_sum)