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

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

various things while discussing with Christian

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