esrf

Beamline Instrument Software Support
SPEC Macro documentation: [ Macro Index | BCU Home ]

#%TITLE%  MONOCHK.MAC
#%NAME%
#  Checks monochromator tuning and machine current intensity during scans.
#
#%CATEGORY% Tools
#
#%DESCRIPTION%
# When activated (%B%onmonochk%B%), the mono intensity is monitored and if it goes down below a certain threshold, the on-going scan stops temporarily while a "ghost" scan (line up scan of %B%ghscans.mac%B%) re-align the mono on its maximum of intensity. After what the previous ongoing scan resumes. If it appears that the mono intensity loss is due to a beam loss, the on-going scan stops as well and SPEC waits for the beam is back before realigning the mono and continuing the scan.  
#%SETUP%
#It is possible to adapt the feature to particular needs, by defining 3 user macros :
#%DL%
#%DT%user_scan_mono%DD% called before each ghost line up scan of the mono when the %B%_monochk()%B% has detected it needs to be re-aligned. ("return 0" to skip the line-up and return to %B%chk_beam%B% directly.)
#%DT%user_lineup%DD% called after each re-alignement of the mono.
#%DT%user_beam_is_back%DD% called after beam recovery and before pre-scanning the mono. ("return 1" to skip the pre-scan and return to %B%chk_beam%B% directly.)
#%XDL%
#
#%END%

#%UU% [mon] [mthr] [time] [io] [iothr] [mot] [max] [mag] [steps] [plot] [sleep] [time2] [mag2] [steps2]
#%MDESC% macros initialisation and parameters setting.%BR%
# %PRE%
#[mon]  : mnemonic of the counter that monitors the mono intensity. 
#[mthr] : mono intensity high threshold in percent of maximum of intensity.    
#[time] : integration time for measuring the intensity and scanning the mono.
#[io]   : mnemonic of the counter that monitors the machine current. 
#[iothr]: machine current low threshold in percent of normal current.
#[mot]  : mnemonic of the monochromator motor to be lined up.  
#[max]  : "CEN|COM|PK" line up at what is specified (PK means max of peak).   
#[mag]  : line up scan magnitude.
#[steps]: line up scan number of intervals.
#[plot] : line up scan plot filter number.
#[sleep]: stabilization time after beam is back.
#[TIME2]: integration time for pre-scanning the mono (after beam is back).
#[MAG2] : pre-scan magnitude.
#[STEPS2]:pre-scan number of intervals.

# %PRE%
# If no mnemonic is specified as machine current monitor, the "beam check" activity is disabled. If no motor or no monochromatic beam monitor are specified, the "mono check" activity cannot be activated.

global MCK_LOG
MCK_LOG=1

def monochksetup '{
  global MCK_SCANNINGMONO MCK_WAITINGFORBEAM MCK_MONO_ITER MCK_WAITDELAY 
  global MCK_RATE MCK_BRATE MCK_THRESHOLD MCK_BEAMTHRESHOLD
  global MCK_ANALOG MCK_BANALOG MCK_ON 
  global MCK_PAR  MCK_SETUP_OK 

  cdef ("config_mac","_monochk_chkpar;_monochk_defmac;","monochk")
  cdef ("user_cleanup2","_monochk_cleanup;","monochk")
  cdef ("user_getcounts","_monochk_threshold;","monochk",0x20)

  if (!(whatis("__monochk_ghopt")&2)) rdef __monochk_ghopt ""

  if (!(whatis("user_scan_mono")&2)) rdef user_scan_mono \'#\$*\'
  if (!(whatis("user_beam_is_back")&2)) rdef user_beam_is_back \'#\$*\'
#  if (!(whatis("user_end_monochk")&2)) rdef user_end_monochk \'#\$*\'
  
  setup_tail("monochk")

  if ($#) {

    MCK_PAR["MON"] = "$1"
    MCK_PAR["MTHR"] = $2
    MCK_PAR["TIME"] = $3
    MCK_PAR["IO"] = "$4"
    MCK_PAR["IOTHR"] = $5
    MCK_PAR["MOT"] = "$6"
    MCK_PAR["MAX"] = "$7"
    MCK_PAR["MAG"] = $8
    MCK_PAR["STEPS"] = $9
    MCK_PAR["PLOT"] = $10
    MCK_PAR["SLEEP"] = $11
    MCK_PAR["TIME2"] = $12
    MCK_PAR["MAG2"] = $13
    MCK_PAR["STEPS2"] = $14

    _monochk_chkpar
    _monochk_defmac

 } else {
   menu("MONO CHECK SETUP","_monochk_menu","_monochk_chkpar","_monochk_defmac")
 } 
}
__monochk_ghopt
'

#%IU% 
#%MDESC% %B%setup%B% service. Gets rid of %B%monochk%B% software.

def monochkunsetup '{
  offmonochk
  cdef ("","","monochk","delete")
}'

#%IU%
#%MDESC% Sets default values and checks all the parameters are properly set to allow "mono check" feature activation or not. 

def _monochk_chkpar '{

  local aa

  MCK_SETUP_OK=1  

  if (-1!=(aa=cnt_num(MCK_PAR["MON"]))) MON = aa
  else {
    if (MCK_PAR["MON"])\
      menuerror (sprintf("%s not a configured counter",MCK_PAR["MON"]))
    if (MON>=0) MCK_PAR["MON"] = cnt_mne(MON)
    else {
      MCK_PAR["MON"] = "" 
      MCK_SETUP_OK=0
    }
  }

  if (MCK_PAR["IO"] && -1==cnt_num(MCK_PAR["IO"])) {
    menuerror (sprintf("%s not a configured counter",MCK_PAR["IO"]))
    MCK_PAR["IO"] = ""
  }
  if (MCK_PAR["MOT"] && -1==motor_num(MCK_PAR["MOT"])) {
    menuerror (sprintf("%s not a configured motor",MCK_PAR["MOT"]))
    MCK_PAR["MOT"] = ""
    MCK_SETUP_OK=0
  }

  MCK_PAR["MTHR"] = MCK_PAR["MTHR"]>0 ? MCK_PAR["MTHR"] : 80
  MCK_PAR["IOTHR"] = MCK_PAR["IOTHR"]>0 ? MCK_PAR["IOTHR"] : 10
  MCK_PAR["PLOT"] = MCK_PAR["PLOT"] ? MCK_PAR["PLOT"] : 2
  MCK_PAR["STEPS"] = MCK_PAR["STEPS"] ? MCK_PAR["STEPS"] : 1
  MCK_PAR["TIME"] = MCK_PAR["TIME"] ? MCK_PAR["TIME"] : 1 
  MCK_PAR["TIME2"] = MCK_PAR["TIME2"] ? MCK_PAR["TIME2"] : MCK_PAR["TIME"] 
  MCK_PAR["MAG2"] = MCK_PAR["MAG2"] ? MCK_PAR["MAG2"] : MCK_PAR["MAG"]*10 
  MCK_PAR["STEPS2"] = MCK_PAR["STEPS2"] ? MCK_PAR["STEPS2"] : MCK_PAR["STEPS"] 
  if (MCK_PAR["MAX"]!="CEN" && MCK_PAR["MAX"]!="COM") MCK_PAR["MAX"] = "PK"
}'


#%IU%
#%MDESC% Defines internal macros from the setup parameters. 

def _monochk_defmac '{

  local macro 

  if (MCK_ON && !MCK_SETUP_OK) { 
    offmonochk 
  } 

  macro = ""
  macro = macro "ghlineup "
  macro = macro MCK_PAR["MOT"] " -MCK_PAR[\"MAG\"] MCK_PAR[\"MAG\"]"
  macro = macro " MCK_PAR[\"STEPS\"] MCK_PAR[\"TIME2\"] -MCK_THRESHOLD*0.8\n"
  macro = macro "user_lineup "  MCK_PAR["MOT"] "\n"
  macro = macro "printf(\"" MCK_PAR["MOT"] "  re-tuned at %g degrees\\n\""
  macro = macro ",A[" MCK_PAR["MOT"] "])\n"
		
		  rdef __scan_mono macro

  macro = ""
  macro = macro "ghlineup "
  macro = macro MCK_PAR["MOT"] " -MCK_PAR[\"MAG2\"] MCK_PAR[\"MAG2\"]"
  macro = macro " MCK_PAR[\"STEPS2\"] MCK_PAR[\"TIME2\"] -MCK_THRESHOLD*0.8\n"
  macro = macro "user_lineup "  MCK_PAR["MOT"] "\n"
  macro = macro "printf(\"" MCK_PAR["MOT"] "  pre-tuned at %g degrees\\n\""
  macro = macro ",A[" MCK_PAR["MOT"] "])\n"
		
		  rdef __prescan_mono macro

  macro = sprintf("ghopt peak=%s title=mono_correction plot=%d counters=%s\n"                                ,MCK_PAR["MAX"],MCK_PAR["PLOT"],MCK_PAR["MON"])

		  rdef __monochk_ghopt macro

  if (!MCK_PAR["IO"])  \
		  rdef __monochk_beamlost \'\'
  else \
		  rdef __monochk_beamlost \'beamlost = _monochk_beam ()\'
  

  if (!(whatis("user_lineup")&2)) rdef user_lineup \'#\$*\'
}'

#%IU%
#%MDESC% Cleanup service. Disables mono and beam checking features.

def _monochk_cleanup '{

  _monochk_log ("CLEANUP")
 
  if (!MCK_ON) { offmonochk }
  MCK_SCANNINGMONO=0
  MCK_WAITINGFORBEAM=0
}'

#%IU%
#%MDESC% Setup menu.

def _monochk_menu '{
  local n i str1 str2 n1 n2

  n  = "\n"
  n1 = "%" n
  n2 = "sec." n

  for (str1 = "",i=0;i<COUNTERS;i++) {    str1 = str1 cnt_mne(i) "  "   }
  str2 = str1 "0"

  menuoptval (-44,n,"monitor counter mnemonic",MCK_PAR["MON"])
  menuvarlist ("MCK_PAR[\"MON\"]",str1)

  menuoptval (-45,n1,"intensity high threshold",MCK_PAR["MTHR"])
  menuvargetv ("MCK_PAR[\"MTHR\"]")

  menuoptval (-48,n2,"integration time",MCK_PAR["TIME"])
  menuvargetv ("MCK_PAR[\"TIME\"]")

  menuoptval (-44,n,"machine current counter mnemonic",MCK_PAR["IO"])
  menuvarlist ("MCK_PAR[\"IO\"]",str2)

  menuoptval (-45,n1,"current low threshold",MCK_PAR["IOTHR"])
  menuvargetv ("MCK_PAR[\"IOTHR\"]")

  menuoptval (-48,n2,"sleep time after beam is back",MCK_PAR["SLEEP"])
  menuvargetv ("MCK_PAR[\"SLEEP\"]")

  for (str1 = "",i=0;i<MOTORS;i++) {    str1 = str1 motor_mne(i) "  "   }

  print
  print "( lineup",MCK_PAR["MOT"],-MCK_PAR["MAG"],MCK_PAR["MAG"],                                                        MCK_PAR["STEPS"],MCK_PAR["TIME2"],")"
  print

  menuoptval (-30,n,"mono motor mnemonic",MCK_PAR["MOT"])
  menuvarlist ("MCK_PAR[\"MOT\"]",str1)

  menuoptval (-30,n,"line up at",MCK_PAR["MAX"])
  menuvarlist ("MCK_PAR[\"MAX\"]","COM  CEN  PK")

  menuoptval (-30,n,"scan magnitude",MCK_PAR["MAG"])
  menuvargetv ("MCK_PAR[\"MAG\"]")

  menuoptval (-30,n,"scan intervals",MCK_PAR["STEPS"])
  menuvargetv ("MCK_PAR[\"STEPS\"]")

  menuoptval (-30,n,"scan integration time",MCK_PAR["TIME2"])
  menuvargetv ("MCK_PAR[\"TIME2\"]")

  menuoptval (-30,n,"plot filter",MCK_PAR["PLOT"])
  menuvarlist ("MCK_PAR[\"PLOT\"]","1  2  3  4  5")

  menuoptval (-30,n,"scan magnitude after beam loss",MCK_PAR["MAG2"])
  menuvargetv ("MCK_PAR[\"MAG2\"]")

  menuoptval (-30,n,"scan intervals after beam loss",MCK_PAR["STEPS2"])
  menuvargetv ("MCK_PAR[\"STEPS2\"]")
}'

#%UU% 
#%MDESC% Disables the mono and beam checking features.

def offmonochk '
   MCK_ON = MCK_SCANNINGMONO = 0
   rdef chk_beam "break"
   print "Mono check is OFF."
   _monochk_log("MONO CHK TURNED OFF")
'

#%UU% [counting_interval]
#%MDESC% Enables the mono and beam checking features.%BR%
# Note that the "beam check" is only activated if a machine current monitor has been specified in %B%monochksetup%B%.
#  The macro measures the monitor rate and estimates the type of monitor device (analog or integrating). It uses by default the integration time given at setup.%BR%

def onmonochk '{

  local t m
  t = ($1)
  m = ($2)

  if (!MCK_SETUP_OK) {
      print "Mono check cannot be activated. " 
      tty_cntl("so")
      printf ("monochksetup ")
      tty_cntl("se")
      print "has not been done or has been done wrong." 
      exit
  }

  if (m <= 0){
      count_em (t?t:COUNT)/2
      waitcount
      get_counts
      MCK_RATE = (MON >= 0 && S[sec]!=0)? S[MON]/S[sec] : 0
      if (cnt_num(MCK_PAR["IO"])!=-1)
        MCK_BRATE = (S[sec]!=0)? S[cnt_num(MCK_PAR["IO"])]/S[sec] : 0
      count_em (t?t:COUNT)
      waitcount
      get_counts
      MCK_ANALOG = (MON >= 0 && S[MON] != 0 && S[sec] != 0 &&  \
                    MCK_RATE/(S[MON]/S[sec]) > 1.5)
      if (cnt_num(MCK_PAR["IO"])!=-1)
        MCK_BANALOG = (S[cnt_num(MCK_PAR["IO"])] != 0 && S[sec] != 0 &&  \
                    MCK_BRATE/(S[cnt_num(MCK_PAR["IO"])]/S[sec]) > 1.5)

   } else {
      S[sec] = t
      if (MON >= 0) 
         S[MON] = m
      MCK_ANALOG = ("$3" == "analog")
   }

   _onmonochk
}'

#%IU% 
#%MDESC% Activates the mono and beam checking features. This macro is called
#  from within %B%onmonochk%B%.

def _onmonochk '
   if (MON<0 || !MCK_ANALOG&&S[sec]==0 || MON == sec || \
      (MCK_RATE=MCK_ANALOG?S[MON]:S[MON]/S[sec])<=0 ) {
      rdef chk_beam "break"
      print "ERROR: Mono check not activated. " 
      print "The beam is down or the timer and the monitor are not properly set up." 
      _monochk_log(sprintf("ERROR ACTIVATING MONO CHK %d %d %g %g",MON,sec,S[sec],MCK_RATE))
      exit
   }

   printf("Mono check is ON. ")
   MCK_THRESHOLD = MCK_PAR["MTHR"] / 100 * MCK_RATE
   if (MCK_PAR["IO"]) {
     MCK_BEAMTHRESHOLD = MCK_PAR["IOTHR"] / 100 * MCK_BRATE
     printf("\nMachine current \`%s\` (%s), threshold value: %g\n",  \
          cnt_name(cnt_num(MCK_PAR["IO"])), MCK_PAR["IO"], MCK_BEAMTHRESHOLD)
   }
   if (MCK_ANALOG) {
      printf("Analog monitor \`%s\' (%s), threshold value: %g\n",  \
              cnt_name(MON), cnt_mne(MON), MCK_THRESHOLD)
   } else {
      printf("Integrating monitor \`%s\' (%s), threshold rate: %g/s\n", \
              cnt_name(MON), cnt_mne(MON), MCK_THRESHOLD)
   }
   
   MCK_ON = 1
   rdef chk_beam "if (_monochk ()) break;;"

   _monochk_log(sprintf("ACTIVATING MONO CHK; thresholds: %g %g",MCK_THRESHOLD,MCK_BEAMTHRESHOLD))
'

#%IU% ()
#%MDESC% HERE IS THE CORE OF THE MONO CHECK ACTIVITY, hooked to %B%chk_beam%B% standard macro. It decides what to do in case of intensity loss. It is called after each counting of a scan. If the mono rate goes below its threshold, the macro first check the machine current. If the beam appears to be lost, (current monitor below its threshold), the macro waits till it is back, and then wait for a stabilisation period, before doing a pre scan and then the line-up scan on the mono. Then the foreground scan resumes. If the mono intensity is too low, but the machine current is high enough, the macro lines the mono up on its maximum of intensity before continuing the foreground scan. The thresholds are re-adjusted each time the mono is moved (done by %B%_monochk_threshold%B%).
#%BR%
#It is possible to adapt that "mono check" feature to particular needs, by defining 3 user macros :
#%DL%
#%DT%user_scan_mono%DD% called before each ghost line up scan of the mono when the %B%_monochk()%B% has detected it needs to be re-aligned. ("return 0" to skip the line-up and return to %B%chk_beam%B% directly.)
#%DT%user_lineup%DD% called after each re-alignement of the mono.
#%DT%user_beam_is_back%DD% called after beam recovery and before pre-scanning the mono. ("return 1" to skip the pre-scan and return to %B%chk_beam%B% directly.)
#%XDL%
#
#
def _monochk () '{

  if (!MCK_ON || set_sim(-1)) 
    return (1)

  if (!S[sec] || MON < 0) {
    MCK_RATE = MCK_BRATE = 0
  } else {
    MCK_RATE = MCK_ANALOG? S[MON] : S[MON]/S[sec]
    if (-1!=cnt_num(MCK_PAR["IO"]))   
      MCK_BRATE = MCK_BANALOG? S[cnt_num(MCK_PAR["IO"])] : S[cnt_num(MCK_PAR["IO"])]/S[sec]
  }

  if (!MCK_WAITINGFORBEAM) {
    tty_cntl("md")
    p "_monochk: MCK_RATE = " MCK_RATE ". MCK_THRESHOLD = " MCK_THRESHOLD
    if (MCK_PAR["IO"]) {
      p "_beamchk: current = " MCK_BRATE ". MCK_BEAMTHRESHOLD = " MCK_BEAMTHRESHOLD
    }
    tty_cntl("me")
  }

  _monochk_log(sprintf("MONO CHECKING TIME %g %g %g %g",MCK_RATE,MCK_THRESHOLD,MCK_BRATE,MCK_BEAMTHRESHOLD))

  if (MCK_RATE >= MCK_THRESHOLD) {

    if (MCK_WAITINGFORBEAM) { 
      local duration unit
      
      duration = time()-MCK_WAITDELAY
      if (duration>3600) {
        duration/=3600
        unit = "hour(s)"
      } else if (duration>60) {
        duration/=60
        unit = "minute(s)"
      } else unit = "seconds"    

      printf("Beam back. (been waiting %.2g %s ...) \n",duration,unit)
      printf("Waiting for temperature stabilization...%g sec. \n",                                                                       MCK_PAR["SLEEP"])
      _monochk_log(sprintf("BEAM IS BACK after %g %s",duration,unit))

      sleep (MCK_PAR["SLEEP"])
    }     

#    user_end_monochk

    MCK_WAITINGFORBEAM=0
    MCK_SCANNINGMONO = 0

    return 1

  } else {

    if (!_monochk_beamlost ()) {
      
      if (MCK_SCANNINGMONO) {
        MCK_MONO_ITER++
      } else {
        MCK_MONO_ITER=0
      }
 
      printf("Mono Needs Tuning (%s)\n", date())

      user_scan_mono MCK_PAR["MOT"]

      _monochk_log(sprintf("RESCAN MONO %d",MCK_MONO_ITER))

      if (MCK_MONO_ITER > 4) {
          printf("PANIC, still below criteria. Two many tuning iterations\n")
          printf("Monitor rate : %g, Criteria : %g\n",MCK_RATE,MCK_THRESHOLD)
          if (-1!=cnt_num(MCK_PAR["IO"])) {
            printf("Beam monitor : %g",S[cnt_num(MCK_PAR["IO"])])
            printf(", Beam threshold : %g\n",MCK_BEAMTHRESHOLD)
          }
          else print "Beam might be down..." 
#        exit
          print "Next trial in 5 minutes..."
          sleep(300)
      }

      printf("  Scanning for maximum of intensity ...")
      __scan_mono 
      MCK_SCANNINGMONO=1

      if (MCK_LOG) {
        _monochk_logon
        print "SCAN ARRAY ",GHDATA
        if (GHRES["peak_found"]) {
          print "peak found"
          print MCK_PAR["MAX"],GHRES["peak_pos"]
        } else {
          print "no peak found"
          print "mono back to",GHRES["prev_pos"]
        }
        _monochk_logoff
      }
    }
  }
  return 0
}'

#%IU%
#%MDESC% If the mono was moved and its monitor rate just measured is high enough (at least 80 percent of old threshold), that macro re-adjusts the thresholds. It is hooked to %B%user_getcounts%B%.

def _monochk_threshold '{

  if (MCK_SCANNINGMONO) {
    if (MON>=0 && S[sec]!=0) \
      MCK_RATE=MCK_ANALOG?S[MON]:S[MON]/S[sec]
    else MCK_RATE = 0
    if (cnt_num(MCK_PAR["IO"])>=0 && S[sec]!=0) \
      MCK_BRATE = S[cnt_num(MCK_PAR["IO"])]/S[sec] 
    else MCK_BRATE = 0

    if (MCK_RATE > MCK_THRESHOLD*0.8) {
      MCK_THRESHOLD = MCK_PAR["MTHR"] / 100 * MCK_RATE
      if (MCK_PAR["IO"]) {
        MCK_BEAMTHRESHOLD = MCK_PAR["IOTHR"] / 100 * MCK_BRATE
      }
      _monochk_log(sprintf("THRESHOLDS: %g %g",MCK_THRESHOLD,MCK_BEAMTHRESHOLD))
    }
  }
}'

#%IU% ()
#%MDESC% Checks machine current.

def _monochk_beamlost () '{

  local beamlost
  beamlost = 0
  __monochk_beamlost
  return beamlost
}'


#%IU% ()
#%MDESC% Checks machine current. Called from %B%_monochk_beamlost ()%B%. 

def _monochk_beam () '{

  if (MCK_BRATE < MCK_BEAMTHRESHOLD) {
    if (!MCK_WAITINGFORBEAM) {
      printf("Beam down on %s\n", date())
      printf("Waiting for beam ...\n")
      MCK_WAITDELAY = time()
      _monochk_log("BEAM DOWN")
    }
    MCK_WAITINGFORBEAM=1
    return 1
  } 

  if (MCK_WAITINGFORBEAM) { 
    local duration unit
    duration = time()-MCK_WAITDELAY
    if (duration>3600) {
      duration/=3600
      unit = "hour(s)"
    } else if (duration>60) {
      duration/=60
      unit = "minute(s)"
    } else unit = "seconds"

    printf("Beam back: ")
    printf("been waiting %.2g %s ... \n",duration,unit)
    printf("Waiting for temperature stabilization...%g sec. \n",                                                                          MCK_PAR["SLEEP"])  
    _monochk_log(sprintf("BEAM IS BACK after %g %s",duration,unit))

    user_beam_is_back

    sleep (MCK_PAR["SLEEP"])
    MCK_WAITINGFORBEAM=0

    printf("Doing a prescan on the mono...")
    _monochk_log("PRE SCAN MONO")
    __prescan_mono

    if (MCK_LOG) {
      _monochk_logon
      print "PRE SCAN ARRAY ",GHDATA
      if (GHRES["peak_found"]) {
        print "peak found"
        print MCK_PAR["MAX"],GHRES["peak_pos"]
      } else {
        print "no peak found"
        print "mono back to",GHRES["prev_pos"]
      }
      _monochk_logoff
    }
  }
  return 0
}'

#%IU% (msg)
#%MDESC% Writes message to logfile. Do "MCK_LOG=0" to switch off the logging. File name is e.g. "/tmp/fourc_monochk_Apr1998".
def  _monochk_log (msg) '{
  global MCK_LOGFILE
  local bli n
 
  n=split (date(),bli) 

  MCK_LOGFILE = sprintf ("/tmp/%s_monochk_%s%s",SPEC,bli[1],bli[n-1])

  if (MCK_LOG) {
    _monochk_logon; 
    print "   " msg; 
    _monochk_logoff
  }
}' 

#%IU%
#%MDESC% Sets logfile on.
def   _monochk_logon ' on(MCK_LOGFILE);offt; p "--",SPEC,date()'

#%IU%
#%MDESC% Closes logfile.
def   _monochk_logoff 'ont;close(MCK_LOGFILE);'

#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
# that macro uses %B%ghscans.mac%B%, %B%menu.mac%B% and %B%pseudo.mac%B%.
#%AUTHOR%
# monochk.mac - M.-Claire LAGIER. - 30 th June 1997.
## - May  4 16:41:15 METDST 1998 REV 1.19;
#%TOC%