esrf

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

#%TITLE% monoscan.mac
#%NAME% 
#   Macros to perform monochromator scan with the MUSST card
#%END%

#%UU% [[remote_spec] mono_motmne mono_type [mono_ds] [mca_ds] [velocity_reduction_factor] cnt [en_motmne] nb_val [monoenc_cnt]
#%MDESC% Setup the monoscan with the parameters:%BR%
# - %B%remote_spec%B% name (e.g.id29:oh) %BR%
# - %B%mono_motmne%B% mono motor mnemonic%BR%
# - %B%mono_type%B% accepted values - micos or maxe%BR%
# - %B%mono_ds%B% device name if micos type (e.g. id29/micos/1)%BR%
# - %B%mca_ds%B% device name if mca detector used (e.g id29/mca/0)%BR%
# - %B%velocity_reduction_factor%B% if needed%BR%
# - %B%cnt%B% counter mnemonic or mca ROI mnemonic%BR%
# - %B%en_motmne%B% energy motor mnemonic%BR%
# - %B%nb_val%B% values per scan point
# - %B%monoenc_cnt%B% mono encoder counter mnemonuc
def monoscan_setup '{
global MONOSCAN
local pars nb pars1 nbp npars

  nb = 0
  if ($# > 0) {
    npars = split("$*",pars)
    nbp = split (pars[0], pars1, ":")
    if (nbp == 2) {
      MONOSCAN["remote_spec"] = pars[0]
      nb++
    } else
      MONOSCAN["remote_spec"] = ""
    MONOSCAN["mono_motmne"] = pars[nb]
    MONOSCAN["mono_type"] = pars[1+nb]
    if (MONOSCAN["mono_type"] == "micos") {
      MONOSCAN["mono_ds"] =  pars[2+nb]
      nb++
    } else {
      MONOSCAN["mono_type"] = "maxe"
      MONOSCAN["mono_ds"] = ""
    }
    nbp = split (pars[2+nb], pars1, "/")
    if (nbp == 3) {
      MONOSCAN["det_type"] = "mca"
      MONOSCAN["mca_ds"] = pars[2+nb]
      MONOSCAN["cnt"] = AE_MCAROI[0]
      nb++
    } else {
      MONOSCAN["det_type"] = "other"
      MONOSCAN["mca_ds"] = ""
      MONOSCAN["cnt"] = ""
    }
    if (fabs(pars[2+nb]) != 0)
      MONOSCAN["velocity_reduction_factor"] = pars[2+nb]
    else {
      MONOSCAN["velocity_reduction_factor"] = 150
      nb--
    }
    MONOSCAN["cnt"] = pars[3+nb]
    if (npars == 5) {
      MONOSCAN["en_motmne"] = ""
      MONOSCAN["nb_val"] = pars[4+nb]
    } else {
      MONOSCAN["en_motmne"] = pars[4+nb]
      MONOSCAN["nb_val"] = pars[5+nb]
    }
    if (npars > 6)
      MONOSCAN["monoenc_cnt"] = pars[npars-1]
  } else {
    MONOSCAN["remote_spec"] = \
	getval("spec remote version (e.g.id29:oh or none)", \
	MONOSCAN["remote_spec"])
    nbp = split (MONOSCAN["remote_spec"], pars1,":")
    if (nbp != 2)
      MONOSCAN["remote_spec"] = ""
    MONOSCAN["mono_motmne"] = getval("mono motor mnemonic", \
	MONOSCAN["mono_motmne"]) 
    MONOSCAN["mono_type"] = getval("mono controller type (micos or maxe) ", \
	MONOSCAN["mono_type"])    
    if (MONOSCAN["mono_type"] == "micos") {
      MONOSCAN["mono_ds"] = getval("mono device server (e.g. id29/micos/1)", \
	MONOSCAN["mono_ds"])
    } else {
      MONOSCAN["mono_ds"] = ""
    }
    MONOSCAN["det_type"] = getval("detector type (mca or other):", \
	MONOSCAN["det_type"])
    if (MONOSCAN["det_type"] == "mca") {
      MONOSCAN["mca_ds"] = getval("Mca device name (e.g. id29/mca/0)", \
	MONOSCAN["mca_ds"])
    } else {
      MONOSCAN["det_type"] = ""
      MONOSCAN["mca_ds"] = ""
    }
    MONOSCAN["velocity_reduction_factor"] = \
	getval("Monoscan velocity reduction factor",\
	MONOSCAN["velocity_reduction_factor"])
    MONOSCAN["cnt"] = getval("counter mnemonic", MONOSCAN["cnt"])
    MONOSCAN["en_motmne"] = getval("energy motor mnemonic", \
	MONOSCAN["en_motmne"])
    MONOSCAN["nb_val"] = getval ("number of values per scan point", \
	MONOSCAN["nb_val"])
    if (yesno ("do you want to set energy encoder counter mnemonic",0))
      MONOSCAN["monoenc_cnt"] = getval ("energy encoder counter mnemonic", \
	MONOSCAN["monoenc_cnt"])
    else
      MONOSCAN["monoenc_cnt"] = ""

  }
  if (MONOSCAN["mca_ds"] == "")
    MONOSCAN["det_type"] = "other"

  if (MONOSCAN["remote_spec"] == "") 
    MONOSCAN["remote_spec"] = "none"

  if ((MONOSCAN["en_motmne"] == "") || \
	(MONOSCAN["en_motmne"] == 0))
    MONOSCAN["en_motmne"] = "energy"

  if (MONOSCAN["velocity_reduction_factor"] == "" || \
	MONOSCAN["velocity_reduction_factor"] == 0)
    MONOSCAN["velocity_reduction_factor"] = 150

  if (MONOSCAN["nb_val"] == "" || MONOSCAN["nb_val"] == 0)
    MONOSCAN["nb_val"] = 3

  MONOSCAN["en_motnum"] =  motor_num(MONOSCAN["en_motmne"])
  if (MONOSCAN["en_motnum"] == -1)
    eprintf("Wrong energy motor %s, setup not done\n", MONOSCAN["en_motmne"])

  if ((MONOSCAN["cnt"] == "") || MONOSCAN["cnt"] == 0)
    eprintf("No counter mnemonic, setup not done\n")

  if (MONOSCAN["remote_spec"] != "none") {
    if (remote_stat(MONOSCAN["remote_spec"]) == 0) {
      eprintf ("No connection to %s, aborted\n", MONOSCAN["remote_spec"])
      MONOSCAN["remote"] = -1
      exit
    } else
      MONOSCAN["remote"] = 0
  }

  MONOSCAN["mono_motnum"] = _monoscan_getmotnum(MONOSCAN["mono_motmne"])
  if (MONOSCAN["mono_motnum"] == -1)
    eprintf("Wrong mono motor %s, setup not done\n", MONOSCAN["mono_motmne"])

}'

#%IU% (mne)
#%MDESC% Get the motor number for %B%mne%B% motor.
def _monoscan_getmotnum(mne) '{
local motn mot_par

  if (MONOSCAN["remote_spec"] == "none") {
    motn = motor_num(mne)
  } else {
    if (MONOSCAN["remote"] == -1)
      motn = -1
    else {
      mot_par = sprintf("motor_num(%s)", mne)
      motn = remote_eval(MONOSCAN["remote_spec"], mot_par)
    }
  }
  return(motn)
}'

#%IU% ()
#%MDESC% Get the step size for the "mono" motor.
def monoscan_getstep() '{
local mono_par
global MONOSCAN[]

  if (MONOSCAN["mono_step"] != "")
    return (fabs(counter_par(MONOSCAN["monoenc_cnt"],"scale")))

  if (MONOSCAN["remote_spec"] == "none") {
    MONOSCAN["mono_step"] = \
	motor_par(MONOSCAN["mono_motmne"], "step_size")
  } else {
    if (MONOSCAN["remote"] == -1)
      MONOSCAN["mono_step"] = 0
    else {
      mono_par = \
	sprintf("motor_par(%s,\"step_size\")", MONOSCAN["mono_motmne"])
      MONOSCAN["mono_step"] = remote_eval(MONOSCAN["remote_spec"], mono_par)
    }
  }
  MONOSCAN["mono_step"] = fabs(MONOSCAN["mono_step"])
  local_monoscan_getstep()
  if (MONOSCAN["debug"])
    printf ("Monochromator stepsize = %d\n", MONOSCAN["mono_step"])
  if (MONOSCAN["mono_step"] == 0) {
    eprintf("invalid stepsize for mono\n")
    exit
  }
}'

#%UU% 
#%MDESC% Cleanup procedure executed at the end of the scan of ^C interruption.
def monoscan_cleanup '{
  monoscan_setvelocity MONOSCAN["mono_vel"]
  musst_comm("ABORT")
  if (MONOSCAN["mca_ds"]) {
    esrf_io(MONOSCAN["mca_ds"], "DevMcaStopAcq")
    musst_comm("CH RONTEC STOP")
  } else
    musst_comm("CH CH1 STOP")
}'

#%UU% velocity
#%MDESC% Set the "mono" motor velocity.
def monoscan_setvelocity '{
local vel

  vel = $1
  if (vel == 0) {
    eprintf ("Cannot set %s velocity to 0, exiting\n", MONOSCAN["mono_motmne"])
    exit
  }
  printf("  - setting %s velocity to %f\n", MONOSCAN["mono_motmne"], vel)

  if (MONOSCAN["mono_ds"] != "") {
    esrf_io(MONOSCAN["mono_ds"], "DevSetVelocity", vel)
  } else {
    _monoscan_setvel(vel)
  }
}'

#%IU% (vel)
#%MDESC% Set the "mono" motor velocity to %B%vel%B%.
def _monoscan_setvel(vel) '{
local mono_par

  if (MONOSCAN["remote_spec"] == "none") {
    motor_par(MONOSCAN["mono_motmne"], "velocity", vel)
  } else {
    if (MONOSCAN["remote"] == -1) {
      eprintf ("No connection to remote host, setvelocity aborted\n")
      exit
    } else {
      mono_par = sprintf("motor_par(%s,\"velocity\", %f)", \
	MONOSCAN["mono_motmne"], vel)
      remote_eval(MONOSCAN["remote_spec"], mono_par)
    }
  }  
}'

#%UU% ()
#%MDESC% Get the "mono" motor velocity.
def monoscan_getvelocity() '{

  if (MONOSCAN["mono_ds"]) {
    MONOSCAN["mono_vel"] = esrf_io(MONOSCAN["mono_ds"], "DevReadVelocity")
  } else {
    _monoscan_getvel()
  }
}'

#%IU% ()
#%MDESC% Get the "mono" motor velocity.
def _monoscan_getvel() '{
local mono_par

  if (MONOSCAN["remote_spec"] == "none") {
    MONOSCAN["mono_vel"] = motor_par(MONOSCAN["mono_motmne"], "velocity")
  } else {
    if (MONOSCAN["remote"] == -1)
      MONOSCAN["mono_vel"] = 0
    else {
      mono_par = sprintf("motor_par(%s,\"velocity\")", MONOSCAN["mono_motmne"])
      MONOSCAN["mono_vel"] = remote_eval(MONOSCAN["remote_spec"], mono_par)
    }
  }
  if (MONOSCAN["mono_vel"] == 0) {
    eprintf("invalid velocity for mono\n")
    exit
  }
}'

#%IU% ()
#%MDESC% Get the monochromator constant to conver energy to angle.
def _monoscan_getconst() '{
local c

  if (MONOSCAN["remote_spec"] == "none") {
    c = hc_over_e / (2 * g_mo_d)
  } else {
    if (MONOSCAN["remote"] == -1)
      c = -1
    else
      c = remote_eval(MONOSCAN["remote_spec"], "hc_over_e / (2 * g_mo_d)")
  }
  return(c)
}'

#%IU% (pos)
#%MDESC% Return the "mono" motor dial position, correspondig to %B%pos%B% user
#position.
def _monoscan_getdial(pos) '{
local dd mono_par
  if (MONOSCAN["remote_spec"] == "none") {
    dd = dial(MONOSCAN["mono_motmne"],pos)
  } else {
    if (MONOSCAN["remote"] == -1)
      dd = -1
    else {
      mono_par = sprintf("dial(%s,%g)",MONOSCAN["mono_motmne"], pos)
      dd = remote_eval(MONOSCAN["remote_spec"], mono_par)
    }
  }
  return(dd)
}'

#%IU% ()
#%MDESC% Return the "mono" motor user position.
def _monoscan_getpos() '{
local dd
  if (MONOSCAN["remote_spec"] == "none") {
    get_angles
    dd = A[MONOSCAN["mono_motnum"]]
  } else {
    if (MONOSCAN["remote"] == -1) {
      eprintf ("Cannot get mono position, abort\n")
      exit
    } else {
      remote_eval(MONOSCAN["remote_spec"], "get_angles")
      mono_par = sprintf("dial(%s,A[%d])", MONOSCAN["mono_motmne"], \
	  MONOSCAN["mono_motnum"])
      dd = remote_eval(MONOSCAN["remote_spec"], mono_par)
    }
  }
  return(dd)
}'

#%IU% (startE, endE, nb_pts)
#%MDESC% Do the monoscan form energy %B%startE%B% to energy %B%endE%B%, for
#%B%nb_pts%B% points.
def _monoscan(startE, endE, nb_pts,l_speed) '{
monoscan__debug_start
monoscan__debug "_monoscan"
local c startA endA deltaA
local startD endD
local accdelta tmpA
local mono_angle sign offset
local pts_acq old_pts_acq
local n i j stat
local myarr

local double array mdat_temp[100000][MONOSCAN["nb_val"]]
shared double array mdat[nb_pts][MONOSCAN["nb_val"]]

  #saving original velocity
  monoscan_getvelocity()

  #get the mono motorstep
  monoscan_getstep()

  cdef("cleanup_once","monoscan_cleanup\n","monoscan")

  #prepare the MCA if needed
  if (MONOSCAN["mca_ds"]) {
    if (esrf_io(MONOSCAN["mca_ds"], "DevMcaStopAcq") == -1)
      return(-1)
    esrf_io(MONOSCAN["mca_ds"], "DevMcaClearMemory")
    esrf_io(MONOSCAN["mca_ds"], "DevMcaSelectTimeMode",1)
    myarr[0]=0
    myarr[1]=0
    esrf_io(MONOSCAN["mca_ds"], "DevMcaPresetTime",myarr)
    myarr[0]=1
    esrf_io(MONOSCAN["mca_ds"], "DevMcaSelectStopMode",myarr)
  }

  if (MONOSCAN["debug"])
    printf("  - Converting energies to mono angles\n")

  #get the energy/angle constant
  c = _monoscan_getconst()

  startA = deg(asin(c/startE))
  endA = deg(asin(c/endE))
  deltaA = fabs(endA-startA)/nb_pts

  printf("      User Angle Positions:\n")
  printf("      start: %f, end: %f, step: %f\n", startA, endA, deltaA)
  printf("      we expect %d points!:\n", nb_pts)

  #get the dial positions for the MUSST
  startD = _monoscan_getdial(startA)
  endD = _monoscan_getdial(endA)
  printf("      Dial Angle Positions:\n")
  printf("      start: %f, end: %f\n", startD, endD)

  #set offset to start before and stop after the initial positions
  #thus we ignore the acceleratiom/decceleration points
  if (startE <= endE)
    accdelta = -0.05
  else
    accdelta = 0.05
  waitmove; get_angles

  tmpA =  deg(asin(c/startE)) - accdelta
  startE = hc_over_e/(2 * g_mo_d * sin(rad(tmpA)))
  tmpA =  deg(asin(c/endE)) + accdelta
  endE = hc_over_e/(2 * g_mo_d * sin(rad(tmpA)))
  printf("  - Moving to start energy (%f) keV\n", startE)
  A[MONOSCAN["en_motnum"]] = startE
  move_em; waitmove; get_angles
  monoscan__debug "waitmove/get_angles"
  
  mono_angle = _monoscan_getpos()
  printf("  - Mono is currently at %f\n", mono_angle)

  printf("  - Initializing the MUSST\n")
  musstmonoscan_init(mono_angle)
  monoscan__debug "musstmonoscan_init"
  musstmonoscan(startD, endD, deltaA)

  monoscan__debug "musstmonoscan started"
  sign = ((endD - startD) / (endA - startA)) > 0 ? 1: -1
  offset = endA - (endD*sign)

  if (l_speed > 0)
    monoscan_setvelocity l_speed

  #start MCA if needed
  if (MONOSCAN["mca_ds"]) {
    printf("  - Starting Fluorescence detector\n")
    if (esrf_io(MONOSCAN["mca_ds"], "DevMcaStartAcq") == -1)
      return(-1)
  }

  monoscan__debug "Launching the monoscan", startE, endE
  printf("  - Launching the monoscan\n")
  printf("  - Moving to end energy (%f) keV\n", endE)
  A[MONOSCAN["en_motnum"]] = endE
  move_em

  HEADING = sprintf("monoscan %g %g %d %f", startE, endE, nb_pts, deltaA)
  SCAN_N = savestdheader(DATAFILE, 0x02|0x01|0x04, SCAN_N)

  local scan_desc[]
  scan_desc["counter"]=python_repr(MONOSCAN["cnt"])
  scan_desc["motor"]=python_repr("energy")
  scan_desc["nb_motors"]=python_repr(1) 
  scan_desc["title"]=python_repr(HEADING)
  scan_desc["type"]=python_repr(1|(1<<8))
  scan_desc["xlabel"]=python_repr("energy")
  scan_desc["ylabel"]=python_repr("MCA counts")
  _SC_NEWSCAN=python_repr(scan_desc)

  monoscan__debug "open(DATAFILE)"
  open(DATAFILE)
  fprintf(DATAFILE, "#N %d\n", array_op("cols", mdat_temp))
  fprintf(DATAFILE, sprintf("#L Energy  %s\n", MONOSCAN["cnt"]))

  pts_acq = 0; n=0
  old_pts_acq = 0
  while (1) {
    get_angles
    monoscan__debug "Mono position", A[MONOSCAN["en_motnum"]]
    old_pts_acq = pts_acq
    sleep(0.5)
    pts_acq = musstmonoscan_progress()
    printf ("_________________> %d\n", pts_acq)
    monoscan__debug "_________________>", pts_acq

    if (old_pts_acq != pts_acq) {
      printf(".")
      n = musst_getdata(MUSST_AUX["default"], pts_acq, \
		MONOSCAN["nb_val"], mdat_temp)
      if (n != pts_acq) { 
        eprintf("   ERROR: could not retrieve scan data from MUSST\n")
      } else {
        monoscan__debug "start calculation"
        #0=time, 1=position; 2=detector(i0); 3=i1
        if (pts_acq > nb_pts)
          pts_acq = nb_pts
        for (i=old_pts_acq; i<pts_acq; i++) {
           for (j=0; j<MONOSCAN["nb_val"]; j++)
             mdat[i][j]=mdat_temp[i][j]

          #position in degrees
          mdat[i][1] /= MONOSCAN["mono_step"]
          #position in energy
          s = sin(rad((mdat[i][1] * sign) + offset + MONOSCAN["offset"]))
          mdat[i][1] = c/s
 
          fprintf(DATAFILE, "%g %g\n", mdat[i][1], mdat[i][2])
          local plot_data[]
          plot_data["i"]=python_repr(i)
          plot_data["x"]=python_repr(mdat[i][1])
          plot_data[MONOSCAN["cnt"]]=python_repr(mdat[i][2])
          _SC_NEWPLOTDATA=python_repr(plot_data)
	}
      }
    }
    monoscan__debug "loop finished"
    stat = musstmonoscan_done()
    monoscan__debug "musstmonoscan_done"
    if (stat == 0) {
      sleep(0.5)
    } else {
      pts_acq = musstmonoscan_progress()
      printf ("NB of points after IDLE %d %d\n", stat,pts_acq)
      n = musst_getdata(MUSST_AUX["default"], pts_acq, \
		MONOSCAN["nb_val"], mdat_temp)
      if (n !=  pts_acq) {
        eprintf("   ERROR: could not retrieve scan data from MUSST\n")
      } else {
        monoscan__debug "start calculation"
        #0=time, 1=position; 2=detector(i0); 3=i1
        if (pts_acq > nb_pts)
          pts_acq = nb_pts
        for (i=old_pts_acq; i<pts_acq; i++) {
           for (j=0; j<MONOSCAN["nb_val"]; j++)
             mdat[i][j]=mdat_temp[i][j]

          #position in degrees
          mdat[i][1] /= MONOSCAN["mono_step"]
          #position in energy
          s = sin(rad((mdat[i][1] * sign) + offset + MONOSCAN["offset"]))
          mdat[i][1] = c/s
 
          fprintf(DATAFILE, "%g %g\n", mdat[i][1], mdat[i][2])
          local plot_data[]
          plot_data["i"]=python_repr(i)
          plot_data["x"]=python_repr(mdat[i][1])
          plot_data[MONOSCAN["cnt"]]=python_repr(mdat[i][2])
          _SC_NEWPLOTDATA=python_repr(plot_data)
	}
      }

      break
    }
  }
 
  close(DATAFILE)
  monoscan__debug "close(DATAFILE)"
  _SC_NEWSCAN=0

  # just in case...
  waitmove
  monoscan_setvelocity MONOSCAN["mono_vel"]
  #stop MCA if needed
  if (MONOSCAN["mca_ds"]) {
    printf("\n  - Stoping Fluorescence detector\n")
    esrf_io(MONOSCAN["mca_ds"], "DevMcaStopAcq")
  }
  monoscan__debug "end"
  return(musstmonoscan_done())
}'


#%UU% startE endE nb_pts
#%MDESC% Do the monoscan form energy %B%startE%B% to energy %B%endE%B%, for
#%B%nb_pts%B% points.
def monoscan '{
local startE endE stepE nb_pts

  if ($# > 0) {
    startE = $1
    endE = $2
    nb_pts = $3
    stepE = fabs(endE - startE)/nb_pts
  } else {
    printf("Usage: %s <start_energy> <end_energy> <nb_points>\n", "$0")
    exit
  }

  # saving original velocity
  monoscan_getvelocity()

  printf("Doing scan of %d points from %f keV to %f keV with step %f eV\n", \
	nb_pts, startE, endE, stepE)

  NPTS = _monoscan(startE, endE, nb_pts)
  if (NPTS > 0) {
    printf ("  - Mono scan done.")
    printf(" %s is at %f (dial units, value form MUSST)\n", \
	  MONOSCAN["mono_motmne"], musstmonoscan_getmono())
    printf("  - total number of points in the scan : %s\n", NPTS) 
  } else {
    eprintf("Mono scan ended with error.")
    eprintf("Total number of points is %d\n", NPTS)
  }
  monoscan_cleanup
}'

#%IU% (mono_angle)
#%MDESC% Initialise the musst program and parameters for %B%mono_angle%B%.
def musstmonoscan_init(mono_angle) '{
local musstprg isgname clear

  musstprg = "~blissadm/local/isg/musst/monoscan.mprg"

  clear = 1
  isgname = MUSST_AUX["default"]
  musst_comm("ABORT")
  musst_upload_program(isgname, musstprg, clear)
  if (MONOSCAN["mca_ds"] == "") {
    musst_comm("CH CH1 RUN")
    musst_comm(sprintf("CH CH1 %d", mono_angle * MONOSCAN["mono_step"]))
  } else
    musst_comm(sprintf("CH MONOANGLE %d", mono_angle * MONOSCAN["mono_step"]))
  local_musstmonoscan_init()
}'

#%IU% (e1, e2, delta)
#%MDESC% Start the scan from %B%e1%B% to %B%e2%B%, with %B%delta%B% interval
#between the points  - MUSST commands.
def musstmonoscan(e1, e2, delta) '{
local aux

  if (e1 > e2) {
    aux = e1
    e1 = e2
    e2 = aux
  }

  musst_comm(sprintf("VAR E1 %d", e1 * MONOSCAN["mono_step"]))
  musst_comm(sprintf("VAR E2 %d", e2 * MONOSCAN["mono_step"]))
  musst_comm(sprintf("VAR DE %d", delta * MONOSCAN["mono_step"]))
  if (MONOSCAN["debug"]) {
    printf ("Musst E1 %d E2 %d DE %d enc %d\n", \
	musst_comm("?VAR E1"), musst_comm("?VAR E2"), musst_comm("?VAR DE"), \
	musst_comm("?VAL CH1"))
  }
  musst_comm("RUN MONOSCAN")
}'

#%IU% (mdat_tmp)
#%MDESC% Get the MUSST data in the %B%mdat_tmp%B% array. Return 0 if the MUSST
#has not finished the program, nb of points if finished.
def musstmonoscan_getdata(mdat_tmp) '{
local npoints nval isgname

  npoints = musstmonoscan_done()
  nval = MONOSCAN["nb_val"]
  isgname = MUSST_AUX["default"]
  n = musst_getdata(isgname, npoints, nval, mdat_tmp)
  if (n != npoints) {
    print "WHAT?? (MUSST speaking)" 
    return(0)
  } else {
    return(n)
  }
}'

#%IU% ()
#%MDESC% Return the number of points red while program in executuion.
def musstmonoscan_progress() '{
local npts
local tmp[]

  # ?EPTR returns the position of stored data pointer and the buffer number
  npts = musst_comm("?EPTR")
  split(npts, tmp)

  #get the position of the pointer
  npts = tmp[0]

  #get the number of stored points (MONOSCAN["nb_val"] data for each point)
  npts /= MONOSCAN["nb_val"]

  return(npts)
}'

#%IU% ()
#%MDESC% return 0 if scan in progress, total nb of points if done.
def musstmonoscan_done() '{
local stat

  stat = musst_comm("?STATE")
  if (stat == "IDLE") {
    local bla
    bla = musst_comm("?VAR NPOINTS")
    printf ("End enc position %d\n", musst_comm("?VAL ch1"))
    return(bla)
  }
  return(0)  
}'

#%IU% ()
#%MDESC% Return the mono angle (dial units) as read from MUSST.
def musstmonoscan_getmono() '{
local mono_steps

  if (MONOSCAN["mca_ds"] == "")
    sscanf(musst_comm("?VAL CH1"), "%li", mono_steps)
  else
    sscanf(musst_comm("?VAL MONOANGLE"), "%f", mono_steps)
  return(mono_steps / MONOSCAN["mono_step"])
}'

#%IU% 
#%MDESC%
def monoscan_debug '{
   if (MONOSCAN["debug"]) {
      MONOSCAN["debug"] = 0
      unglobal MONOSCANDEBUGT
      rdef monoscan__debug_start ""
      rdef monoscan__debug "0==\$6"
      print "MONOSCAN debug mode is OFF"
   } else {
      MONOSCAN["debug"] = 1
      global MONOSCANDEBUGT
      rdef monoscan__debug_start \'MONOSCANDEBUGT = time()\'
      rdef monoscan__debug \'print printf("%7.2f", 1000*(time() - MONOSCANDEBUGT)), "$*" \'
      print "MONOSCAN debug mode is ON"
   }
}'


def musst_getdata(isgname, nlines, npts, lmdat) '{
   local maxnl

   maxnl = 1024 #int(((0x10000 / MONOSCAN["nb_val"]) - 1) / npts)
   long array ldat[maxnl][MONOSCAN["nb_val"]]

   for (nl = 0; nl < nlines; nl += maxnl) {
      nn = nlines - nl
      if (nn > maxnl)
         nn = maxnl
      comm = sprintf("?*EDAT %d 0 %d", nn * npts, nl * npts)

      ndat = isgdevice_getdata(isgname, comm, ldat)
      if (ndat != nn * npts) 
         return(0)
      lmdat[nl:nl+nn-1][] = ldat
   }
   return(nlines)
}'

if (!(whatis("monoscan__debug_start")&2)) rdef monoscan__debug_start ''

if (!(whatis("monoscan__debug")&2)) rdef monoscan__debug '0==$6'

if (whatis("local_monoscan_getstep") == 0)
    eval("def local_monoscan_getstep()\'{ }\'")

if (whatis("local_musstmonoscan_init") == 0)
    eval("def local_musstmonoscan_init()\'{ }\'")

#%MACROS%
#%IMACROS%
#%TOC%
#%AUTHOR% M.Guijarro/A.Beteva
#%DEPENDENCIES% musst.mac
#$Revision: 1.15 $
#%END%
#%HISTORY%
#$Log: monoscan.mac,v $
#Revision 1.15  2011/07/25 11:34:16  beteva
#Added reading after MUSST has stopped. Some more debug prints. Added local_monoscan_getstep and local_musstmonoscan_init.
#