spec

Software for Diffraction

3.6. - Counting Macros



ct [time]               # Count, then show_cnts
count [time]            # Count for time
show_cnts               # Count, then display results
uct [time]              # Updated counting


When time is positive, counting is to seconds. When time is negative, counting is to monitor counts. If the counting macros are invoked without an argument, the count time used is that contained in the global variable COUNT.

Counting in spec combines timing generators and scalers. Three scaler channels are normally used in the standard macros. The first channel takes an accurate clock input (normally at 1 KHz), the second takes the monitor input, and the third takes the detector.

The scaler channels identifying the various inputs are determined by the values of the global constants, sec, mon and det. Their default values are 0, 1 and 2, respectively, matching the recommended hardware cabling. If you do not connect your counting sources to the default scaler channels, you must explicitly assign new values to sec, mon and det for the standard counting macros to work properly.

The additional global variables MON and DET are then set to the channels that are to be treated as the monitor and detector for particular scans, normally mon and det. If, while doing a line-up scan of a motor on which the monitor is mounted, you would want the monitor counts to be plotted as a function of the motor position, enter DET=mon before doing the scan. Do not forget to reassign DET=det at the end of the scan.

The global variable COUNT is set to a default count time (normally 1 second). If the macro ct is invoked without arguments, counting will last for the duration given by COUNT.
# A user calls "ct" to count for some interval and display results
def ct '{
      rdef cleanup \'
              undef cleanup
              onp; show_cnts; offp
      \'
      waitmove
      count_em $*
      waitcount
      undef cleanup
      onp; show_cnts; offp
}'

# "count" is the basic macro to count to monitor or to time.
# It runs the clock and reads the scalers.
def count '{
      waitmove
      if ($1) for (;;) {
              count_em $1
              waitcount
              get_counts
              chk_beam
      }
      if (S[sec] && MON >= 0)
              MON_RATE = S[MON]/S[sec]
}'
# The macro "show_cnts" reads the scalers and displays the results.
def show_cnts '{
      local   i

      get_counts
      printf("\n%s\n\n", date())
      for (i=0;i<COUNTERS;i++)
              if (cnt_name(i) != "unused")
                      printf("%12s = %g%s\n", cnt_name(i), S[i], \
                 i != sec && S[sec]? sprintf(" (%g/s)", S[i] / S[sec]):")
}'


Updated counting is done with the uct macro,
def uct '{
      waitmove
      count_em $*
      if (chk_count) {
              local i
              printf("\n")
              for (i=0;i<COUNTERS;i++)
                      if (cnt_name(i) != "unused")
                              printf("%12.12s ",cnt_name(i))
              printf("\n")
              while (chk_count) {
                      get_counts
                      for (i=0;i<COUNTERS;i++)
                              if (cnt_name(i) != "unused")
                                      printf("%12g ",S[i])
                      printf("\r")
                      sleep(UPDATE)
              }
              get_counts
              for (i=0;i<COUNTERS;i++)
                      if (cnt_name(i) != "unused")
                              printf("%12g ",S[i])
              printf("\n")
      }
}'