source: specdomain/trunk/src/specdomain/comparison/auto.mac @ 996

Last change on this file since 996 was 996, checked in by jemian, 10 years ago

for comparison against a RoboDoc? build

File size: 48.7 KB
Line 
1"""
2===================
3General Information
4===================
5
6Summary
7=======
8This macro provides a set of definitions which allow for automatic filter
9transmission and exposure time adjustments during experiments.
10
11Description
12===========
13After each count command, the obtained counts are evaluated and checked for
14over-/under-exposure. In case of unsatisfactory count levels, filter
15transmissions and optionally exposure times are adjusted and exposures are
16repeated until a valid exposure is obtained.
17
18Exposure optimization modes
19---------------------------
20Two different modes of operation are available to optimize the count levels
21for each exposure:
22
23- Post-exposure adjustments: Each new exposures is taken with settings that
24  are based on the feedback obtained from the previous one. This mode is
25  based on the assumption that the measured intensity profiles are only
26  gradually changing, and that a satisfactory prediction of the change in
27  the count levels can be obtained in most cases to yield a good exposure.
28  In those cases where the predictions fail and the new exposure falls
29  outside the acceptable limits, the settings are adjusted and the exposure
30  is retaken immediately.
31- Pilot exposure: Each exposure is preceeded by a short pilot exposure,
32  which is used to establish the count levels at the current positions.
33
34Both modes have their relative merits and drawbacks. Post-exposure
35adjustments are riskier in terms of overexposing a detector, since the
36feedback is obtained only after potentially very long exposures. On the
37other hand, they are more efficient in terms of dead-time, especially when
38scanning signals that change only gradually. In this case, it is very
39seldomly necessary to repeat exposures. The pilot exposure mode, in
40contrast, is safer, since it detects potentially harmfully strong signals
41much faster. This comes at the cost of significantly increased dead-times,
42particularly for detectors with longer arming or readout times.
43
44Exposure optimization scheme
45----------------------------
46The filter and exposure time adjustments principles are based on the
47following criteria to formulate an adjustment strategy.  Firstly, it is
48important to note that there are two separate effects which may cause an
49over-exposure of the detector:
50
51#. Paralizing the counter as a result of a count RATE which exceeds the
52   ability of the detector to separate individual photons in time (only for
53   single-photon-counting devices, does not apply to charge-integrating).
54#. Saturating the counter as a result of exceeding the maximum NUMBER OF
55   COUNTS that can be stored in the counter.
56
57The incident photon RATE (case 1) can only be adjusted through the use of
58filters (attenuators), while the integrated NUMBER OF COUNTS is affected
59both by the filter transmission and the integration duration (count time).
60In this implementation, ensuring a valid photon RATE always takes
61precedence over any other adjustment. Once the rate has been optimized
62(keeping it within a given band below the saturation threshold), the
63exposure times may be adjusted. See the next sections below for details.
64
65Filter tramsmission adjustments (RATE)
66----------------------------------------
67The filter adjustment assures a high incident photon rate within a band
68just below the rate limit of the detector. The width of the band is
69defined by the step size in transmission, defined in AUTO_FILTER_FACTOR,
70which is used for each correction. If the count rate is higher than
71AUTO_RATE_LIMIT, the transmission is immediately reduced by
72AUTO_FILTER_FACTOR and the exposure is retaken. If the count rate is
73lower than AUTO_RATE_LIMIT/(2*AUTO_FILTER_FACTOR), the change in
74transmission required to reach a count rate of 0.75*AUTO_RATE_LIMIT is
75calculated, the transmission increased by that factor and the exposure is
76retaken immediately. If the measured count rate falls between these limits,
77no change is applied to the filters. The following scheme illustrates
78this behavior::
79
80  Threshold levels           Actions
81  ----------------           -------
82
83                             - decrease trasmission by AUTO_FILTER_FACTOR
84                             - retake exposure immediately
85  AUTO_RATE_LIMIT---------------------------------------------------------
86   /\
87   || 2*AUTO_FILTER_FACTOR   - leave filters as they are
88   \/
89  ------------------------------------------------------------------------
90                             - calculate change in transmission required to
91                               reach 0.75*AUTO_RATE_LIMIT
92                             - increase trasmission by this factor
93                             - retake exposure immediately
94
95
96Exposure time adjustments (integrated NUMBER OF COUNTS)
97---------------------------------------------------------
98Exposure time adjustments are designed with maximum efficiency in mind.
99The general idea is to attempt to maintain the integrated count level as
100close as possible to the user-defined AUTO_COUNT_TARGET, but to minimize
101the number of re-exposures by accepting exposures which fall into an
102"acceptable" count range, which is defined as any count level between
103the detectors saturation count AUTO_COUNT_HIGH and a user-defined
104lower count level AUTO_COUNT_LOW. If the exposure is within this
105acceptable band, a new count time to reach the target level is
106calculated based on the current exposure, but only applied to the next
107exposure in an attempt to predict a change in the right direction. If the
108current exposure falls outside the acceptable count range, the expsoure
109time is adjusted and the exposure is retaken immediately. Note that
110chosing a small acceptable range will thus result in retaking many
111exposures, hence increasing scan times.
112Count times will be adjusted between user-defined limits AUTO_EXP_LOW and
113AUTO_EXP_HIGH and rounded to a user-defined precision AUTO_COUNT_PREC.
114
115The diagram below outlines the measures taken when the registered maximum
116NUMBER OF COUNTS falls into the various defined ranges::
117
118  Threshold levels           Actions
119  ----------------           -------
120
121                             - reduce exposure time (if > minimum time)
122                             - retake exposure immediately
123  AUTO_COUNT_HIGH---------------------------------------------------------
124                             - reduce exposure time (if > minimum time)
125                             - apply only to next exposure
126  AUTO_COUNT_TARGET-------------------------------------------------------
127                             - increase exposure time (if < maximum time)
128                             - apply only to next exposure
129  AUTO_COUNT_LOW----------------------------------------------------------
130                             - increase exposure time (if < maximum time)
131                             - retake exposure immediately
132
133
134Configuration
135=============
136
137No special configuration is needed to run these macros. Simply load the macro
138file and run ''auto_setup''::
139
140> qdo auto.mac
141> auto_setup
142
143Dependencies
144------------
145
146Dependencies on other macros:
147
148* filter.mac (used to control the attenuators):
149
150  - filter_trans
151  - filter_get_trans()
152  - filter_get_trans_up()
153  - filter_get_mask()
154  - filter_max()
155
156* recount (modified count command used to retake an exposure)
157
158Impact
159------
160The following chained macro definitions are affected by this macro:
161
162* user_prescan_head
163* user_chk_counts (provided in our modified ``count`` command)
164* user_precount
165
166File information
167================
168
169Authors
170-------
171* C.M. Schlepuetz (CS, cschlep),
172  Argonne National Laboratory, cschlep@aps.anl.gov
173* Y. Yang (YY, ysyang),
174  University of Michigan, ysyang@umich.edu
175
176Creation date
177-------------
1782011/02/25
179
180Copyright
181---------
182Copyright 2010 by the above authors (see AUTHOR/AUTHORS)
183
184This program is free software: you can redistribute it and/or modify
185it under the terms of the GNU General Public License as published by
186the Free Software Foundation, either version 3 of the License, or
187(at your option) any later version.
188
189This program is distributed in the hope that it will be useful,
190but WITHOUT ANY WARRANTY; without even the implied warranty of
191MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
192GNU General Public License for more details.
193
194You should have received a copy of the GNU General Public License
195along with this program.  If not, see http://www.gnu.org/licenses/.
196
197Version
198-------
199::
200
201  $Date: 2011-04-11 13:17:13 -0400 (Mon, 11 Apr 2011) $
202  $Author: cschlep $
203  $URL: file:///data/svn/software/spec/trunk/common/auto.mac $
204  $Revision: 25 $
205
206
207Change log
208----------
2092011/02/25 (CS, YY):
210
211- completely reworked previous versions of ``auto.mac`` to produce this new
212  version:
213
214  * improved efficiency
215  * simplified code
216  * new method of scaling the count times (see description above)
217
2182011/04/04 (CS):
219
220- cleaned up code further
221- added and updated documentation
222- added ``auto_setup`` macro
223- added AUTO_AREADETECTOR_VERSION global to track which version of
224  areaDetector is used in ``auto_init_analysis``.
225- added ``auto_on`` and ``auto_off``
226- changed all macro names to lower case and underscore naming convention
227- changed all calls to macros from ``filter.mac`` to lower case and underscore
228  naming conventions.
229
2302011/04/11 (CS):
231
232- changed ``auto_prescan_header``: if AUTO_LEVEL > 1, set the exposure times to
233  the minimum exposure time to start with.
234
2352012/03/29 (CS):
236
237- modified code documentation to be compatible with the ROBODoc
238  documentation generation software.
239- monitor a configurable SPEC counter rather than an EPICS channel for the
240  adjustments. This allows for the monitoring of any arbitrary counter in
241  SPEC, but requires that whatever signal is to be monitored is captured in
242  a SPEC counter during the count process.
243- reworked the setup routines for easier use.
244- removed unnecessary ``auto_init_analysis``
245- removed unnecessary AUTO_AREADETECTOR_VERSION global variable
246- renamed many variables for improved consistency
247
2482012/04/23 (CS):
249
250- fixed a bug where long exposures with valid rate but saturating the
251  counter would result in an infinite loop.
252
2532012/07/06 (CS):
254
255- changed code documentation to be compatible with the new SPEC domain for the
256  SPHINX code documentation suite.
257
258TO DO
259-----
260
261- Extensive testing of the pilot exposure mode
262- complete documentation
263- insert hyperlinks into documentation
264"""
265
266#==============================================================================
267
268#==============================================================================
269# Global variable definitions
270#==============================================================================
271
272  # Save the name of this macro file (Used for the help function).
273  global AUTO_MAC
274         AUTO_MAC = DOFILE
275
276  global AUTO_LEVEL                # Type of adjustments {0,1,2}
277  global AUTO_MODE                 # Adjustment mode (pilot/post-exp){0,1}
278  global AUTO_COUNTER              # Counter to monitor
279  global AUTO_COUNT_RBV            # Counter read back value (measured counts)
280  global AUTO_RETRY_MAX            # Maximum number of retries
281  global AUTO_EXP_LOW              # low exposure time limit
282  global AUTO_EXP_HIGH             # highexposure time limit
283  global AUTO_PILOT_EXPTIME        # exposure time for pilot exposures
284  global AUTO_RATE_LIMIT           # High rate limit
285  global AUTO_COUNT_HIGH           # High count limit
286  global AUTO_COUNT_TARGET         # Target count level
287  global AUTO_COUNT_LOW            # Low count limit
288  global AUTO_FILTER_FACTOR        # Filter transmission factor for adjustments
289  global AUTO_COUNT_PREC           # Count time precision (rounding)
290
291  global AUTO_FILTER_LOCK          # Lock if rate-limited
292  global AUTO_SET_PILOT            # Set pilot exposure time in user_precount
293  global AUTO_ORIG_EXPTIME         # save the original requested count time
294  global AUTO_DEBUG                # debug flag
295
296  # set default values for global variables
297  AUTO_COUNTER = det
298  AUTO_LEVEL = 0
299  AUTO_MODE = 0
300  AUTO_RETRY_MAX = 20
301  AUTO_COUNT_HIGH = 5e5
302  AUTO_RATE_LIMIT =2e5
303  AUTO_COUNT_RBV = 1e6
304  AUTO_COUNT_TARGET = 1e4
305  AUTO_COUNT_LOW = 0.5 * AUTO_COUNT_TARGET
306  AUTO_PILOT_EXPTIME = 0.05
307  AUTO_EXP_LOW = 1
308  AUTO_EXP_HIGH = 10
309  AUTO_FILTER_FACTOR = 5
310  AUTO_COUNT_PREC = 0.01
311  AUTO_FILTER_LOCK = 0
312  AUTO_SET_PILOT = 1
313  AUTO_DEBUG = 0
314
315#==============================================================================
316# Macro command definitions
317#==============================================================================
318
319#------------------------------------------------------------------------------
320# allow for misspelled help commands
321def autohelp 'auto_help'
322
323def auto_help '{
324  """
325  Summary
326  -------
327  Displays the auto help text.
328
329  Usage
330  -----
331  ::
332
333     > auto_help
334
335  .. note:: The help text is generated by simply displaying the text file
336     ``auto_mac.txt``, which should reside in the same directory as
337     ``auto.mac``. If the file does not exist, a generic help text defined in
338     ``auto_help`` is shown.
339  """
340
341  unix (sprintf ("dirname %s", AUTO_MAC), _1)
342  ll = length (_1)
343  if (substr (_1, ll, 1) == "\n") _1 = substr (_1, 1, (ll - 1))
344  file = sprintf ("%s/auto_mac.txt", _1)
345  if (file_info (file, "-e")) {
346    unix (sprintf ("cat %s", file))
347  } else {
348    printf("\nMacros available in file auto.mac ($Revision: 25 $):\n")
349    printf("                           ========"\n)
350    printf("\n")
351    printf("  auto_help          - creates this help text\n")
352    printf("  auto_setup         - setup automatic exposure control\n")
353    printf("  auto_set_mode      - set the auto-adjustment mode\n")
354    printf("  auto_set_level     - activate or deactivate automatic filter\n")
355    printf("                       and exposure setting\n")
356    printf("  auto_on            - turn auto exposure control ON (dialog)\n")
357    printf("  auto_off           - turn auto exposure control OFF\n")
358    printf("  auto_set_exposure  - define the shortest and longest exposure\n")
359    printf("                       time used in case of automatic exposure\n")
360    printf("                       setting\n")
361    printf("  auto_show          - display current auto exposure settings\n")
362    printf("  auto_show_exposure - display current exposure time settings\n")
363  }
364}'
365
366
367#------------------------------------------------------------------------------
368def auto_setup '{
369  """
370  Summary
371  -------
372    Set up the control parameters for the automatic filter and exposure
373    adjustments.
374
375  Description
376  -----------
377    The following parameters can be adjusted to fit the particular needs of an
378    experiment or detector type (global variables holding these parameters and
379    default values are given in brackets):
380
381    * Auto level: the level of automatic adjustments to be performed. Three
382      levels are currently available [AUTO_LEVEL = 0]:
383
384        ===== =================================================================
385        Level Description
386        ===== =================================================================
387        0     No automatic adjustments are made
388        1     Only filters are adjusted, no exposure time adjustments
389        2     Both filters and exposure times are automatically adjusted
390        ===== =================================================================
391
392    * Auto mode: the mode used to calculate/apply the adjustments. Two modes
393      are available [AUTO_MODE = 0]:
394
395        ==== ==================================================================
396        Mode Description
397        ==== ==================================================================
398        0    Post-exposure analysis: exposures are taken at normal settings and
399             analyzed in retrospect. The exposure is only retaken if it is
400             deemed unacceptable. Otherwise, the calculated adjustments are
401             applied only to the next exposure. This mode is faster, but
402             riskier in terms of over-exposing the detector for potentially
403             much longer times.
404        1    Pilot exposure mode: A short pilot exposure is taken before each
405             exposure to determine the correct filter and exposure time
406             settings. This is safer in terms of identifying over-exposures
407             quickly and provides optimized settings for each exposure, but
408             comes at a considerable cost in additional dead time. The pilot
409             exposure time is specified in AUTO_PILOT_EXPTIME.
410        ==== ==================================================================
411
412    * Counter to monitor: the SPEC counter mnemonic or number of the counter
413      used to assess the validity of the exposure. Note that when using area
414      detectors, it is necessary to monitor the count levels per pixel, as this
415      the saturation conditions. In this case, there needs to be a counter
416      configured that is monitoring the maximum count rate of all pixels within
417      the relevant region of interest. [AUTO_COUNTER = det]
418
419    * Count RATE high limit: the maximum count rate (counts per second) on
420      the detector that is acceptable for the experiment. If the measured count
421      rate is higher than this limit, filters will be inserted to lower the
422      rate. [AUTO_RATE_LIMIT = 2.0e5]
423
424    * Target count level: the desired count level for a "perfect" exposure.
425      All adjustments applied to filter and/or count times aim to achieve this
426      level. [AUTO_COUNT_TARGET = 1.0e4]
427
428    * Count level low limit: The lower count limit for an acceptable exposure.
429      If the measured level is below this, filters and exposure times will be
430      adjusted (if possible) and the exposure retaken.
431      [AUTO_COUNT_LOW = 5000]
432
433    * Counter saturation limit: The upper count limit for an acceptable
434      exposure. This should be chosen below the actual saturation level of the
435      detector. If the measured level exceeds the saturation limit, filters and
436      exposure times will be adjusted (if possible) and the exposure is
437      repeated.
438      [AUTO_COUNT_HIGH = 5.0e5]
439
440    * Transmission step: The step in filter transmission to be taken when
441      adjusting the filters. The specified step must be larger than the
442      largest available incremet in transmission values of the experimental
443      setup to ensure that the adjustments can be successful. Ideally, this
444      number is chosen anywhere between 2 and 10, but may need to be higher
445      depending on the available filters. [AUTO_FILTER_FACTOR = 5]
446
447    * Minimum exposure time: Minimum allowable exposure time to be used whith
448      automatic exposure time adjustments. [AUTO_EXP_LOW = 1]
449
450    * Maximum exposure time: Maximum allowable exposure time to be used whith
451      automatic exposure time adjustments. [AUTO_EXP_HIGH = 10]
452
453    * Pilot exposure time: Exposure time for the pilot exposure used in pilot
454      mode. [AUTO_PILOT_EXPTIME = 0.05]
455
456    * Count time precision: Automatically calculated count times will be
457      rounded to this precision. Typically, a value of 0.01 or 0.001 seconds is
458      recommended. [AUTO_COUNT_PREC = 0.01]
459
460    * Maximum number of retries: The maximum number of retries to adjust
461      exposure and filter settings before giving up. This avoids infinite loops
462      due to inconsistent choices of control parameters. [AUTO_RETRY_MAX = 20]
463
464  Usage
465  -----
466  ::
467
468    > auto_setup
469        then answer the questions
470
471  """
472
473  local _setup_numitems, _setup_option, _tmp_option, _str1
474
475  # total number of setup items
476  _setup_numitems = 13
477
478  _clear_screen
479
480  _setup_option = 0
481  _tmp_option = -1
482  while (_tmp_option) {
483      _tmp_option = -1
484      while (_tmp_option < 0 || _tmp_option > _setup_numitems){
485          _auto_print_setup
486          _str1 = sprintf("Enter 1-%d to change the parameters, 0 to quit",\
487            _setup_numitems)
488          _tmp_option = getval(_str1, _setup_option)
489          if(index(_tmp_option, "q") == 1 || index(_tmp_option, "Q") == 1){
490            _tmp_option = 0
491          }
492      }
493      _setup_option = _tmp_option
494      if (_setup_option != 0){
495          _auto_set_option _setup_option
496      }
497      _setup_option = (_tmp_option + 1)%(_setup_numitems + 1)
498  }
499
500  _auto_check_levels
501  _auto_check_exposure
502
503}'
504
505
506#------------------------------------------------------------------------------
507def auto_off '{
508  """
509  Summary
510  -------
511  Turn off any automatic filter and exposure adjustments.
512
513  Usage
514  -----
515  ::
516
517    > auto_off
518
519  .. note:: This command is equivalent to ``auto_set_level 0``
520
521  See also
522  --------
523  auto_set_level, auto_on
524
525  """
526
527  auto_set_level 0
528
529}'
530
531
532#------------------------------------------------------------------------------
533def auto_on '{auto_set_level $*}'
534
535def auto_set_level '{
536  """
537  Summary
538  -------
539  Set the level of automatic filter and exposure adjustments.
540
541  Usage
542  -----
543  ::
544
545    > auto_set_level [<level>]
546    > auto_on [<level>]
547        where <level> can be one of the following:
548          0 - automatic filter and exposure OFF
549          1 - automatic filter ON, automatic exposure OFF
550          2 - automatic filter and exposure ON
551        if <level> is ommitted, the users is asked for input
552
553  Example
554  -------
555  ::
556
557    > auto_set_level
558        then answer the questions in the dialogue
559
560    > auto_on 1
561        turns on automatic filter adjustments (level 1)
562
563  .. note::
564     ``auto_set_level`` and ``auto_on`` are equivalent to each other
565
566  See also
567  --------
568  auto_off
569
570  """
571
572  if ($#>1){
573    eprint "Wrong number or illegal arguments in \'auto_set_level\'"
574    eprint "Usage:"
575    eprint "  auto_set_level <level>"
576    eprint ""
577    eprint "<level> can be:"
578    eprint "0 - OFF"
579    eprint "1 - only automatic filter ON, automatic exposure OFF"
580    eprint "2 - automatic filter and exposure ON"
581    eprint ""
582    exit
583  } else if ($#>0){
584    AUTO_LEVEL = $1
585  } else {
586    printf("Choose auto level:\n")
587    printf("  0 - automatic filter and exposure OFF\n")
588    printf("  1 - only automatic filter ON, automatic exposure OFF\n")
589    printf("  2 - automatic filter and exposure ON\n")
590    AUTO_LEVEL = getval("Auto level", AUTO_LEVEL)
591  }
592
593  # check validity of AUTO_LEVEL
594  if (!((AUTO_LEVEL==0) || (AUTO_LEVEL==1) || (AUTO_LEVEL==2))){
595    eprint "Illegal auto level in \'auto_set_level\'"
596    eprint "Valid levels are:"
597    eprint "  0 - OFF"
598    eprint "  1 - only automatic filter ON, automatic exposure OFF"
599    eprint "  2 - automatic filter and exposure ON"
600    eprint ""
601  }
602
603  #-------------------------------------------
604  # define necessary chained macro definitions
605
606  #--------------------
607  def auto_prescan_head \'
608  #   =================
609    # if automatic filter setting is active start scan with very low
610    # filter transmission
611    if(AUTO_LEVEL > 0){
612      AUTO_ORIG_EXPTIME = COUNT_TIME
613      filter_trans 1e-8
614      if(AUTO_LEVEL > 1){
615        # start with low exposure times
616        COUNT_TIME = AUTO_EXP_LOW
617        _ctime = COUNT_TIME
618      }
619    }
620    # add auto_cleanup to cleanup_once
621    cdef("cleanup_once","auto_cleanup; ", "auto_cleanup_once_key",0x20)
622  \'
623
624  #-----------------------
625  def auto_user_chk_counts \'
626  #   ====================
627    if(AUTO_LEVEL > 0){
628      # automatic filter and exposure setting (if activated)
629      success = _auto_adjust_redo()
630    }
631  \'
632
633  #----------------
634  def auto_precount \'
635  #   =============
636    if(AUTO_LEVEL > 0){
637      if(AUTO_MODE == 1 & AUTO_SET_PILOT == 1){
638        # remember the original exposure time
639        AUTO_ORIG_EXPTIME = COUNT_TIME
640        # set the pilot exposure time
641        COUNT_TIME = AUTO_PILOT_EXPTIME
642        _ctime = COUNT_TIME
643        AUTO_SET_PILOT = 0
644      }
645    }
646  \'
647
648  #---------------
649  def auto_cleanup \'
650  #   ============
651    # drop in filters after finishing, since we do not know where we end up
652    # (center of a peak for dscan?)
653    AUTO_SET_PILOT = 1
654    AUTO_FILTER_LOCK = 0
655    if(AUTO_LEVEL > 0){
656      filter_trans 1e-8
657    }
658    cdef("cleanup_once", "", "auto_cleanup_once_key", "delete")
659  \'
660
661
662  #--------------------------------------------
663  # include necessary chained macro definitions
664  # depending on the current auto-level
665
666  if (AUTO_LEVEL > 0){
667
668    # add auto_prescan_head to user_prescan_head
669    cdef("user_prescan_head", "auto_prescan_head; ", "auto_prescan_head_key",\
670         0x10)
671
672    # add auto_user_chk_counts to user_chk_counts
673    cdef("user_chk_counts", "auto_user_chk_counts; ", \
674         "auto_user_chk_counts_key")
675
676    # add auto_precount to user_precount
677    cdef("user_precount", "auto_precount; ", "auto_precount_key", 0x10)
678
679    # add auto_cleanup to the end of user_scan_tail
680    cdef("user_scan_tail","auto_cleanup; ", \
681         "auto_user_scan_tail_key",0x20)
682
683  }
684
685  #---------------------------------------------
686  # remove unnecessary chained macro definitions
687  # depending on the current auto-level
688
689  # Note: chained macro definitions which are not currently defined
690  #       can be deleted without producing an error.
691
692  if (AUTO_LEVEL < 1) {
693
694    # remove auto_prescan_head from user_prescan_head
695    cdef("user_prescan_head", "", "auto_prescan_head_key", "delete")
696
697    # remove auto_user_chk_counts from user_chk_counts
698    cdef("user_chk_counts", "", "auto_user_chk_counts_key", "delete")
699
700    # remove auto_precount from user_precount
701    cdef("user_precount", "", "auto_precount_key", "delete")
702
703    # remove auto_cleanup from user_scan_tail and cleanup_once
704    cdef("user_scan_tail", "", "auto_user_scan_tail_key", "delete")
705    cdef("cleanup_once", "", "auto_cleanup_once_key", "delete")
706  }
707
708  auto_show
709
710}'
711
712#------------------------------------------------------------------------------
713def auto_set_mode '{
714  """
715  Summary
716  -------
717  Set the acquisition mode to be used for the automatic filter and
718  exposure time adjustments.
719
720  Description
721  -----------
722  Need some more details here...
723
724
725  Usage
726  -----
727  ::
728
729    > auto_set_mode [<mode>]
730        where <mode> must be one of the following:
731          0 - post-exposure analysis
732          1 - pilot exposure mode
733        when called with no arguments, the user is prompted
734
735  Example
736  -------
737  ::
738
739    > auto_set_mode 1
740        use the pilot exposure mode for automatic adjustments.
741
742  See also
743  --------
744  auto, auto_setup
745
746  """
747
748  local _mode
749
750  if ( ($# != 1) && ($# != 0 )) {
751    eprint "Wrong number or illegal arguments in \'auto_set_mode\'"
752    eprint "Usage:"
753    eprint "  auto_set_mode <mode>"
754    exit
755  } else if ($# == 1){
756    _mode = $1
757  } else {
758    _mode = getval("Enter the new auto mode", AUTO_MODE)
759  }
760
761  # check validity of mode
762  if((AUTO_MODE != 0) & (AUTO_MODE !=1)){
763    eprint "ERROR: Illegal value for auto mode (%g)!"
764    printf("  Auto mode is still %d\n", AUTO_MODE)
765    exit
766  } else {
767    AUTO_MODE = _mode
768  }
769
770  auto_show
771
772}'
773
774
775#------------------------------------------------------------------------------
776def auto_set_exposure '{
777  """
778  Summary
779  -------
780  Set the maximum and minimum exposure times used for automatic exposure
781  adjustments.
782
783  Usage
784  -----
785  ::
786
787    > auto_set_exposure [<min> <max>]
788        where <min> is the minimum and <max> the maximum exposure time [s]
789        when called with no arguments, the user is prompted
790
791  Example
792  -------
793  ::
794
795    > auto_set_exposure 1 10
796        sets the minimum exposure time to 1 sec and the maximum to 10 sec.
797
798  """
799
800  if ( ($# != 2) && ($# != 0 )) {
801    eprint "Wrong number or illegal arguments in \'auto_set_exposure\'"
802    eprint "Usage:"
803    eprint "auto_set_exposure [<min> <max>]"
804    eprint "defines the minimum and maximum exposure times in seconds"
805    eprint "(used if auto-level is set to 2  with \'auto_set_level\')"
806  } else if ($# == 2){
807    AUTO_EXP_LOW = $1
808    AUTO_EXP_HIGH = $2
809  } else {
810    AUTO_EXP_LOW = getval("Minimum exposure time [s]", AUTO_EXP_LOW)
811    AUTO_EXP_HIGH = getval("Maximum exposure time [s]", AUTO_EXP_HIGH)
812  }
813
814  _auto_check_exposure
815  auto_show_exposure
816
817}'
818
819
820#------------------------------------------------------------------------------
821def auto_show '{
822  """
823  Summary
824  -------
825  Display the current auto settings.
826
827  Usage
828  -----
829  ::
830
831    > auto_show
832
833  """
834
835  if (AUTO_LEVEL == 0) {
836    printf("Auto-level has been set to %d.\n", AUTO_LEVEL)
837    printf("Automatic filter setting is OFF.\n")
838    printf("Automatic exposure setting is OFF.\n")
839  } else if (AUTO_LEVEL == 1) {
840    printf("Auto-level has been set to %d.\n", AUTO_LEVEL)
841    printf("Automatic filter setting is ON.\n")
842    printf("Automatic exposure setting is OFF.\n")
843  } else  if (AUTO_LEVEL == 2) {
844    printf("Auto-level has been set to %d.\n", AUTO_LEVEL)
845    printf("Automatic filter setting is ON.\n")
846    printf("Automatic exposure setting is ON.\n")
847  } else {
848    AUTO_LEVEL = 0
849    printf("ERROR: Unknown auto-level - resetting to %d", AUTO_LEVEL)
850    printf("Automatic filter setting is OFF.\n")
851    printf("Automatic exposure setting is OFF.\n")
852  }
853
854  if(AUTO_MODE == 0){
855    printf("Auto mode is 0 (post-exposure adjustments)\n")
856  } else if (AUTO_MODE == 1){
857    printf("Auto mode is 1 (pilot exposure)\n")
858  } else {
859    AUTO_MODE = 0
860    printf("ERROR: Unknown auto mode - resetting to %d", AUTO_MODE)
861  }
862
863  if(AUTO_LEVEL>1){
864    auto_show_exposure
865  }
866
867}'
868
869
870#------------------------------------------------------------------------------
871def auto_show_exposure '{
872  """
873  Summary
874  -------
875  Display the current auto-level exposure settings.
876
877  Usage
878  -----
879  ::
880
881    > auto_show_exposure
882
883  """
884
885  printf("Exposure times: minimum = %g s, maximum = %g s\n",\
886         AUTO_EXP_LOW, AUTO_EXP_HIGH)
887
888}'
889
890
891#==============================================================================
892# Internal macros
893#==============================================================================
894
895#------------------------------------------------------------------------------
896def _auto_print_setup '{
897  """
898  Summary
899  -------
900  Prints the configuration options and current values to screen
901
902  .. note::
903     The option numbers must be kept in sync between ``_auto_set_option`` and
904     ``_auto_print_setup``.
905  """
906
907  tty_cntl("ho")  # home cursor on left upper corner of screen
908  tty_cntl("cd")  # clear the rest of the screen
909
910  tty_cntl("so")  # highlight font
911  printf("Auto setup:\n")
912  tty_cntl("se")  # turn off font highlighting
913
914  printf("\n 1)  %40s: %s", "Auto level {0,1,2}", AUTO_LEVEL)
915  if(AUTO_LEVEL == 0) printf(" (no automatic adjustments)")
916  if(AUTO_LEVEL == 1) printf(" (automatic filter adjustments)")
917  if(AUTO_LEVEL == 2) printf(" (automatic filter and exptime adjustments)")
918  printf("\n 2)  %40s: %s", "Auto mode {0,1}", AUTO_MODE)
919  if(AUTO_MODE == 0) printf(" (post-exposure adjustments)")
920  if(AUTO_MODE == 1) printf(" (pilot pre-exposure)")
921  printf("\n 3)  %40s: %s", "Counter to monitor", AUTO_COUNTER)
922  printf("\n 4)  %40s: %s", "Count RATE high limit [cts/s]", AUTO_RATE_LIMIT)
923  printf("\n 5)  %40s: %s", "Target count level [cts]", AUTO_COUNT_TARGET)
924  printf("\n 6)  %40s: %s", "Count level low limit [cts]", AUTO_COUNT_LOW)
925  printf("\n 7)  %40s: %s", "Counter saturation (high) limit [cts]", \
926    AUTO_COUNT_HIGH)
927  printf("\n 8)  %40s: %s", "Transmission step", AUTO_FILTER_FACTOR)
928  printf("\n 9)  %40s: %s", "Minimum exposure time [s]", AUTO_EXP_LOW)
929  printf("\n 10) %40s: %s", "Maximum exposure time [s]", AUTO_EXP_HIGH)
930  printf("\n 11) %40s: %s", "Pilot exposure time [s]", AUTO_PILOT_EXPTIME)
931  printf("\n 12) %40s: %s", "Count time precision [s]", AUTO_COUNT_PREC)
932  printf("\n 13) %40s: %s", "Maximum number of retries", AUTO_RETRY_MAX)
933  printf("\n\n")
934}'
935
936
937#------------------------------------------------------------------------------
938def _auto_set_option '{
939  """
940  Summary
941  -------
942  Sets a new value for a given option
943
944  Description
945  -----------
946  Sets a new value for a given option from the options menu that was created
947  with the _auto_print_setup command.
948
949  .. note::
950     The option numbers must be kept in sync between ``_auto_set_option`` and
951     ``_auto_print_setup``.
952
953  """
954
955  local _input, _dummy, _valid, _numitems
956
957  #----------
958  if ($1==1){
959    auto_set_level
960
961  #----------------
962  } else if ($1==2){
963    auto_set_mode
964
965  #----------------
966  } else if ($1==3){
967
968    show_counters()
969
970    _valid = 0
971    while(!(_valid)){
972      _input = getval("Pleae enter the counter to monitor", AUTO_COUNTER)
973      if(cnt_num(_input)<0){
974        printf("ERROR: Invalid counter (%s)\n", _input)
975      } else {
976        AUTO_COUNTER = cnt_num(_input)
977        _valid = 1
978      }
979    }
980
981  #----------------
982  } else if ($1==4){
983    _valid = 0
984    while(!(_valid)){
985      _input= getval("Upper limit for the counte RATE [cts/sec]", \
986        AUTO_RATE_LIMIT)
987      _numitems = sscanf(_input, "%f", _input)
988      if(_numitems == 1){
989        if(_input > 0) {
990          AUTO_RATE_LIMIT = _input
991          _valid = 1
992        }
993      }
994      if(!(_valid)){
995        printf("ERROR: Invalid input for rate limit (%s)\n", _input)
996      }
997    }
998
999  #----------------
1000  } else if ($1==5){
1001    _valid = 0
1002    while(!(_valid)){
1003      _input= getval("Target count level [cts]", AUTO_COUNT_TARGET)
1004      _numitems = sscanf(_input, "%f", _input)
1005      if(_numitems == 1){
1006        if(_input > 0) {
1007          AUTO_COUNT_TARGET = _input
1008          _valid = 1
1009        }
1010      }
1011      if(!(_valid)){
1012        printf("ERROR: Invalid target count level (%s)\n", _input)
1013      }
1014    }
1015
1016  #----------------
1017  } else if ($1==6){
1018    _valid = 0
1019    while(!(_valid)){
1020      _input= getval("Count level low limit [cts]", AUTO_COUNT_LOW)
1021      _numitems = sscanf(_input, "%f", _input)
1022      if(_numitems == 1){
1023        if(_input > 0) {
1024          AUTO_COUNT_LOW = _input
1025          _valid = 1
1026        }
1027      }
1028      if(!(_valid)){
1029        printf("ERROR: Invalid count level low limit (%s)\n", _input)
1030      }
1031    }
1032
1033  #----------------
1034  } else if ($1==7){
1035    _valid = 0
1036    while(!(_valid)){
1037      _input= getval("Counter saturation (high) limit [cts]", AUTO_COUNT_HIGH)
1038      _numitems = sscanf(_input, "%f", _input)
1039      if(_numitems == 1){
1040        if(_input > 0) {
1041          AUTO_COUNT_HIGH = _input
1042          _valid = 1
1043        }
1044      }
1045      if(!(_valid)){
1046        printf("ERROR: Invalid counter saturation limit (%s)\n", _input)
1047      }
1048    }
1049
1050  #----------------
1051  } else if ($1==8){
1052    _valid = 0
1053    while(!(_valid)){
1054      _input= getval("Transmission step used to adjust filters", \
1055        AUTO_FILTER_FACTOR)
1056      _numitems = sscanf(_input, "%f", _input)
1057      if(_numitems == 1){
1058        if(AUTO_FILTER_FACTOR <= 1.2){
1059          printf("Error: Transmission step factor must be >1.2 !\n")
1060          printf("  (recommended: 4 - 100, must match available filters)\n")
1061        } else if (AUTO_FILTER_FACTOR >= AUTO_RATE_LIMIT){
1062          printf("Error: Transmission step factor must be smaller than\n")
1063          printf("  the maximum count rate (%g)\n", AUTO_RATE_LIMIT)
1064        } else if (AUTO_FILTER_FACTOR >= AUTO_COUNT_HIGH){
1065          printf("Error: Transmission step factor must be smaller than\n")
1066          printf("  the counter saturation limit (%g)\n", AUTO_COUNT_HIGH)
1067        } else {
1068          AUTO_FILTER_FACTOR = _input
1069          _valid = 1
1070        }
1071      }
1072      if(!(_valid)){
1073        printf("ERROR: Invalid transmission step (%s)\n", _input)
1074      }
1075    }
1076
1077  #----------------
1078  } else if ($1==9){
1079    _valid = 0
1080    while(!(_valid)){
1081      _input= getval("Minimum exposure time [s]", AUTO_EXP_LOW)
1082      _numitems = sscanf(_input, "%f", _input)
1083      if(_numitems == 1){
1084        if(_input > 0) {
1085          AUTO_EXP_LOW = _input
1086          _valid = 1
1087        }
1088      }
1089      if(!(_valid)){
1090        printf("ERROR: Invalid minimum exposure time (%s)\n", _input)
1091      }
1092    }
1093
1094  #-----------------
1095  } else if ($1==10){
1096    _valid = 0
1097    while(!(_valid)){
1098      _input= getval("Maximum exposure time [s]", AUTO_EXP_HIGH)
1099      _numitems = sscanf(_input, "%f", _input)
1100      if(_numitems == 1){
1101        if(_input > 0) {
1102          AUTO_EXP_HIGH = _input
1103          _valid = 1
1104        }
1105      }
1106      if(!(_valid)){
1107        printf("ERROR: Invalid maximum exposure time (%s)\n", _input)
1108      }
1109    }
1110
1111
1112  #-----------------
1113  } else if ($1==11){
1114    _valid = 0
1115    while(!(_valid)){
1116      _input= getval("Pilot exposure time [s]", AUTO_PILOT_EXPTIME)
1117      _numitems = sscanf(_input, "%f", _input)
1118      if(_numitems == 1){
1119        if(_input > 0) {
1120          AUTO_PILOT_EXPTIME = _input
1121          _valid = 1
1122        }
1123      }
1124      if(!(_valid)){
1125        printf("ERROR: Invalid pilot exposure time (%s)\n", _input)
1126      }
1127    }
1128
1129  #-----------------
1130  } else if ($1==12){
1131    local _str
1132
1133    _valid = 0
1134    while(!(_valid)){
1135      _str = "Count time rounding precision [s] (e.g.: 0.01; 0=no rounding)"
1136      _input= getval(_str, AUTO_COUNT_PREC)
1137      _numitems = sscanf(_input, "%f", _input)
1138      if(_numitems == 1){
1139        if(_input < 0) {
1140          printf("Count time precision must be >=0 \n")
1141        } else if(_input > 10){
1142          printf("Count time precision must be smaller than 10 sec\n")
1143        } else {
1144          AUTO_COUNT_PREC = _input
1145          _valid = 1
1146        }
1147      }
1148      if(!(_valid)){
1149        printf("ERROR: Invalid count time precision (%s)\n", _input)
1150      }
1151    }
1152
1153  #-----------------
1154  } else if ($1==13){
1155    _valid = 0
1156    while(!(_valid)){
1157      _input= getval("Maximum number of retries", AUTO_RETRY_MAX)
1158      _numitems = sscanf(_input, "%d", _input)
1159      if(_numitems == 1){
1160        if(_input > 100) {
1161          printf("Maximum number of retries must be < 100 !\n")
1162          printf("  (recommended: <30 and >10)\n")
1163        } else if(_input <2) {
1164          printf("Maximum number of retries must be > 2 !\n")
1165          printf("  (recommended: <30 and >10)\n")
1166        } else {
1167          AUTO_RETRY_MAX = int(_input)
1168          _valid = 1
1169        }
1170      }
1171      if(!(_valid)){
1172        printf("ERROR: Invalid pilot exposure time (%s)\n", _input)
1173      }
1174    }
1175  }
1176}'
1177
1178
1179
1180#------------------------------------------------------------------------------
1181def _auto_analyze_exposure '{
1182  """
1183  Summary
1184  -------
1185  Analyze the previous exposure
1186
1187  Description
1188  -----------
1189  This macro retrieves the necessary information to analyze the last exposure
1190  and to initiate adjustments, if necessary. Usually, this step consists only
1191  of retrieving the count value from the monitored SPEC counter, but for more
1192  sophisticated experimental setups, this definition could be overwritten to
1193  include non-standard procedures, such as retrieving counts from EPICS PVs,
1194  etc.
1195
1196  Usage
1197  -----
1198  ::
1199
1200    > _auto_analyze_exposure
1201
1202  """
1203
1204  AUTO_COUNT_RBV = S[AUTO_COUNTER]
1205
1206}'
1207
1208
1209#------------------------------------------------------------------------------
1210def _auto_adjust() '{
1211  """
1212  Summary
1213  -------
1214  Calculate and apply necessary exposure time and filter adjustments.
1215
1216  Description
1217  -----------
1218  The function returns 1 if transmission or exposure time are changed, 0
1219  otherwise.
1220
1221  """
1222
1223  local _auto_adjusted, _count_time, _factor, _transm, _transm_up, _new_transm
1224
1225  # do nothing when auto-level is zero
1226  if (AUTO_LEVEL < 1) {
1227    return(0)
1228  }
1229
1230  # set exposure times to default if they are not defined yet
1231  if (AUTO_EXP_LOW < 0.0000001) {
1232    AUTO_EXP_LOW  =  1
1233  }
1234  if (AUTO_EXP_HIGH < 0.0000001) {
1235    AUTO_EXP_HIGH = 10
1236  }
1237
1238  _auto_adjusted = 0
1239
1240  # record last count time
1241  _count_time = COUNT_TIME
1242
1243  # analyze the exposure in terms of the threshold values
1244  _auto_analyze_exposure
1245
1246  if(AUTO_DEBUG && 0x1){
1247    printf("\n%s\n", date())
1248    printf("Analyzing exposure with exposure time %f s\n", COUNT_TIME)
1249    printf("Obtained count RATE: %f cts/s (saturation limit = %f cts/s)\n",\
1250            AUTO_COUNT_RBV/_count_time, AUTO_RATE_LIMIT)
1251    printf("Obtained count level: %f counts\n", AUTO_COUNT_RBV)
1252    printf("(Target = %f, Hi limit = %f, low limit = %f\n", \
1253            AUTO_COUNT_TARGET, AUTO_COUNT_HIGH, AUTO_COUNT_LOW)
1254  }
1255
1256  #-----------------------------------------
1257  # 1.) filter adjustments if AUTO_LEVEL > 0
1258
1259  if(AUTO_DEBUG && 0x1){
1260    printf("Filter lock is: %d\n", AUTO_FILTER_LOCK)
1261  }
1262
1263  # check if filters are already locked (rate has been adjusted)
1264  if (!(AUTO_FILTER_LOCK)){
1265
1266    # reduce filter transmission if rate is too high
1267    if ( ((AUTO_COUNT_RBV/_count_time) > AUTO_RATE_LIMIT) &\
1268         (filter_get_mask() < filter_max()) ){
1269
1270      if(AUTO_DEBUG && 0x1){
1271        printf("Rate is too high: %f > %f\n", AUTO_COUNT_RBV/_count_time,\
1272                AUTO_RATE_LIMIT)
1273      }
1274
1275      _new_transm = filter_get_trans()/ AUTO_FILTER_FACTOR
1276      filter_trans _new_transm
1277      _auto_adjusted = 1
1278      return(_auto_adjusted)
1279    }
1280
1281    # increase filter transmission if rate is too low
1282    if (((AUTO_COUNT_RBV/_count_time) < \
1283          0.5*AUTO_RATE_LIMIT/AUTO_FILTER_FACTOR) & \
1284          (filter_get_mask() > 0) ){
1285
1286      if(AUTO_DEBUG && 0x1){
1287        printf("Rate is too low: %f < %f\n", AUTO_COUNT_RBV/_count_time, \
1288                0.5*AUTO_RATE_LIMIT/AUTO_FILTER_FACTOR)
1289      }
1290
1291      _transm = filter_get_trans()
1292      if (AUTO_COUNT_RBV > 0){
1293        _factor = (0.75 * AUTO_RATE_LIMIT) / (AUTO_COUNT_RBV/_count_time)
1294      } else {
1295        _factor = (0.75 * AUTO_RATE_LIMIT)
1296      }
1297      # make sure that there is actually a better filter setting available for
1298      # the requested new transmission
1299      _transm_up = filter_get_trans_up()
1300      if(_factor > (_transm_up/_transm)){
1301        _new_transm = _transm * _factor
1302        if(_new_transm > 1){
1303          _new_transm = 1
1304        }
1305        filter_trans _new_transm
1306        _auto_adjusted = 1
1307        return(_auto_adjusted)
1308      } else {
1309        # there is nothing we can do with the filters
1310        AUTO_FILTER_LOCK = 1
1311          if(AUTO_DEBUG && 0x1){
1312            printf("No filter adjustments possible\n")
1313          }
1314      }
1315    }
1316  }
1317
1318  # avoid counter saturation of the detector if AUTO_LEVEL < 2 or the exposure
1319  # time is at AUTO_EXP_LOW
1320  if((AUTO_LEVEL) < 2 | (_count_time <= AUTO_EXP_LOW+1e-7)){
1321    if((AUTO_COUNT_RBV > AUTO_COUNT_HIGH) & \
1322        (filter_get_mask() < filter_max())){
1323
1324      if(AUTO_DEBUG && 0x1){
1325        printf("Rate is ok (%f), but counter is saturating (%f > %f)\n",\
1326                AUTO_COUNT_RBV/_count_time, AUTO_COUNT_RBV, AUTO_COUNT_HIGH)
1327      }
1328
1329      _new_transm = filter_get_trans()/ AUTO_FILTER_FACTOR
1330      filter_trans _new_transm
1331      AUTO_FILTER_LOCK = 1
1332      _auto_adjusted = 1
1333      return(_auto_adjusted)
1334    }
1335  }
1336
1337
1338  #-------------------------------------------------------------------------
1339  # 2.) take real exposure with requested exposure time after pilot exposure
1340  #     if in pilot mode
1341
1342  if(AUTO_LEVEL == 1 && AUTO_MODE == 1){
1343    if(_count_time != AUTO_ORIG_EXPTIME){
1344      if(AUTO_DEBUG && 0x1){
1345        printf("Setting exposure time to %f s\n", AUTO_ORIG_EXPTIME)
1346      }
1347
1348      # set exposure time to requested exposure time to retake the exposure after
1349      # the pilot exposures
1350      AUTO_FILTER_LOCK = 1
1351      COUNT_TIME = AUTO_ORIG_EXPTIME
1352      _ctime = COUNT_TIME
1353      _auto_adjusted = 1
1354      return(_auto_adjusted)
1355    }
1356  }
1357
1358  #-----------------------------------------
1359  # 3.) count time scaling if AUTO_LEVEL > 1
1360
1361  if(AUTO_LEVEL > 1){
1362
1363    # calculate exposure time for next exposure
1364    if (AUTO_COUNT_RBV > 0){
1365      _factor = AUTO_COUNT_TARGET / AUTO_COUNT_RBV
1366    } else {
1367      _factor = 1e3
1368    }
1369    COUNT_TIME = _auto_calc_exposure(_count_time * _factor)
1370    _ctime = COUNT_TIME
1371
1372    if(AUTO_DEBUG && 0x1){
1373        printf("Adjusting exposure time from %f to %f sec\n", _count_time, \
1374                COUNT_TIME)
1375    }
1376
1377    # recount immediately if last exposure time was not within allowed limits
1378    if((_count_time < AUTO_EXP_LOW) | (_count_time > AUTO_EXP_HIGH)){
1379      if(AUTO_DEBUG && 0x1){
1380        printf("Previous exposure outside limits: retake immediately\n")
1381      }
1382      _auto_adjusted = 1
1383      return(_auto_adjusted)
1384    }
1385
1386    # recount immediately if we are saturated or under-exposed
1387    # and count times can still be changed
1388    if((AUTO_COUNT_RBV > AUTO_COUNT_HIGH) & \
1389       (_count_time > AUTO_EXP_LOW)){
1390
1391      if(AUTO_DEBUG && 0x1){
1392        printf("Overexposure: retaking exposure immediately\n")
1393      }
1394      _auto_adjusted = 1
1395      return(_auto_adjusted)
1396    }
1397    if((AUTO_COUNT_RBV < AUTO_COUNT_LOW) & \
1398       (_count_time < AUTO_EXP_HIGH)){
1399
1400      if(AUTO_DEBUG && 0x1){
1401        printf("Underexposure: retaking exposure immediately\n")
1402      }
1403      _auto_adjusted = 1
1404      return(_auto_adjusted)
1405    }
1406
1407    # decrease filter transmission if we are saturated and decreasing the
1408    # exposure time is not possible. Recount immediately
1409    if((AUTO_COUNT_RBV > AUTO_COUNT_HIGH) & \
1410        (_count_time <= AUTO_EXP_LOW+1e-7) & \
1411        (filter_get_mask() < filter_max())){
1412
1413      if(AUTO_DEBUG && 0x1){
1414        printf("Overexposure but cannot decrease exposure time")
1415        printf(" -> reducing filter transmission\n")
1416      }
1417
1418      _new_transm = filter_get_trans()/ AUTO_FILTER_FACTOR
1419      filter_trans _new_transm
1420      _auto_adjusted = 1
1421      return(_auto_adjusted)
1422      AUTO_FILTER_LOCK = 1
1423    }
1424  }
1425
1426  return(_auto_adjusted)
1427}'
1428
1429
1430#------------------------------------------------------------------------------
1431def _auto_check_exposure '{
1432  """
1433  Summary
1434  -------
1435  Make sure the user-entered exposure times are consistent
1436
1437  Usage
1438  -----
1439  ::
1440
1441    > _auto_check_exposure
1442
1443  """
1444
1445  if (AUTO_EXP_LOW >= AUTO_EXP_HIGH) {
1446    AUTO_EXP_LOW  =  1
1447    AUTO_EXP_HIGH = 10
1448    eprint "ERROR: Invalid exposure time values!"
1449    printf("  Minimum (%f) must be less than maximum (%f) exposure time\n",\
1450      AUTO_EXP_LOW, AUTO_EXP_HIGH)
1451    printf("  Setting exposure times to default values:\n")
1452  }
1453}'
1454
1455
1456#------------------------------------------------------------------------------
1457def _auto_check_levels '{
1458  """
1459  Summary
1460  -------
1461  Make sure the user-entered count levels are consistent
1462
1463  Usage
1464  -----
1465  ::
1466
1467    > _auto_check_levels
1468
1469  """
1470
1471  if(AUTO_COUNT_TARGET >= AUTO_COUNT_HIGH){
1472    eprint "ERROR: Invalid count target!"
1473    printf("The count target (%f) must be smaller than ", AUTO_COUNT_TARGET)
1474    printf("the counter saturation limit (%f).\n", AUTO_COUNT_HIGH)
1475    printf("Setting count target to %d counts.\n\n", int(AUTO_COUNT_HIGH/10))
1476    AUTO_COUNT_TARGET = int(AUTO_COUNT_HIGH/10)
1477  }
1478  if(AUTO_COUNT_LOW >= AUTO_COUNT_TARGET) {
1479    eprint "ERROR: Invalid low count limit!"
1480    printf("Low count limit (%f) must be smaller than count target (%f).\n", \
1481      AUTO_COUNT_LOW, AUTO_COUNT_TARGET)
1482    printf("Setting low count limit to %d counts.\n\n", \
1483      int(AUTO_COUNT_TARGET/10))
1484    AUTO_COUNT_LOW = int(AUTO_COUNT_TARGET/10)
1485  }
1486}'
1487
1488
1489#------------------------------------------------------------------------------
1490def _auto_calc_exposure(t) '{
1491  """
1492  Summary
1493  -------
1494  Make sure the requested exposure time is between the min and max values and
1495  round it to the given count time precision.
1496
1497  Usage
1498  -----
1499  ::
1500
1501    > adjusted_time = _auto_calc_exposure(requested_time)
1502
1503  """
1504
1505  # round to given precision
1506  if (AUTO_COUNT_PREC>1e-7){
1507    t = (int(t/AUTO_COUNT_PREC))*AUTO_COUNT_PREC
1508  }
1509
1510  # check if we are inside the limits
1511  if(t > AUTO_EXP_HIGH){
1512    t = AUTO_EXP_HIGH
1513  } else if (t < AUTO_EXP_LOW){
1514    t = AUTO_EXP_LOW
1515  }
1516
1517  return(t)
1518}'
1519
1520
1521#------------------------------------------------------------------------------
1522def _auto_adjust_redo() '{
1523  """
1524  Summary
1525  -------
1526  Determines whether the auto-adjusting has been successful.
1527
1528  Description
1529  -----------
1530  If the current exposure does not meet the required criteria, counting
1531  is repeated until the best possible filter and exposure settings have been
1532  obtained, or a maximum number of retry counts has been reached.
1533  The function returns 1 in case of success, 0 otherwise.
1534
1535  Usage
1536  -----
1537  ::
1538
1539    > success = _auto_adjust_redo()
1540
1541  .. note::
1542     This macro makes use of the ``recount`` macro, which has to be added to SPEC
1543     during the startup procedure.
1544
1545  """
1546
1547  local retryCount
1548  local redo
1549  local _success
1550
1551  _success = 1
1552  AUTO_SET_PILOT = 0
1553
1554  if (AUTO_LEVEL < 1) {
1555    return(_success)
1556  } else {
1557    retryCount = 0
1558    redo = 1
1559    while (redo != 0) {
1560      redo = 0
1561      retryCount++
1562      if (_auto_adjust() != 0) {
1563        if (retryCount <  AUTO_RETRY_MAX) {
1564          redo = 1
1565        } else {
1566          eprint " >> Couldn\'t optimize filter and exposure settings. <<"
1567        }
1568      }
1569      if (redo != 0) {
1570        # repeat exposure
1571        recount COUNT_TIME
1572      } else {
1573        _success = 1
1574        redo = 0
1575      }
1576    }
1577    AUTO_SET_PILOT = 1
1578    AUTO_FILTER_LOCK = 0
1579    return (_success)
1580  }
1581}'
1582
1583#------------------------------------------------------------------------------
1584# define this only if there is no _clear_screen function available yet
1585if (!(whatis("_clear_screen") & 0x2)){
1586  def _clear_screen '{
1587    """
1588    Summary
1589    -------
1590    Clears the terminal screen
1591
1592    Description
1593    -----------
1594    Clears the screen without losing the screen history or messing up the
1595    scrolling capabilities (this has been a problem for certain terminals)
1596    by blanking out the entire height of the screen and returning the cursor to
1597    the top left corner.
1598    """
1599
1600    # update the ROWS and COLS variables in case the terminal has been resized
1601    tty_cntl("resized?")
1602
1603    # print as many newlines as there are ROWS in terminal
1604    cl_text = ""
1605    for (i=0;i<ROWS;i++){
1606      cl_text = cl_text "\n"
1607    }
1608    printf(cl_text)
1609
1610    # move back to the top of the screen and clear to end of the screen
1611    tty_move(0,0)
1612    tty_cntl("cd")
1613
1614  }'
1615}
1616
1617#==============================================================================
1618# End of $Id: $
1619#==============================================================================
Note: See TracBrowser for help on using the repository browser.