esrf

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

#%TITLE% FLIP.MAC Flip Magnet
#%NAME%
# Flip magnet polarity during scans.
#%CATEGORY% Other hardware, Tools
#%DESCRIPTION%
# Those macros add to standard scan facility (motor scans and time scan), the possibility of flipping magnet polarity or whatever at counting. The data are plotted in additional windows and saved to standard DATAFILE in additional columns. 
#%EXAMPLE%
#%DL%
#%DT%flipsetup; flipcounterselect det; flipstyle 4; fliphdwrelay ID16/Relay/80 %DD% initialisation and setup.
#%DT%flip ascan m0 0 10 10 1 %DD% flip scan command.
#%DT%flipon; ascan m0 0 10 10 1 ; flipoff%DD% almost the same. %B%_flip_usermacro1%B% and %B%2%B% are not called, nor %B%_flip_readpol%B% macro.
#%XDL%
#%SETUP%
#%DL%There is no general setup macro but several ones. 
#%DT%flipsetup macro:
#%DD% initialisation, default and general setup: COMPULSORY. 
#%DT%flipcounterselect macro:
#%DD% counters selection for plotting. 
#%DT%flipsave macro:
#%DD% counters selection for data saving. 
#%DT%flipstyle* macros:
#%DD% way of flipping setup. basically, sets the number of countings at each scan steps. 
#%DT%fliphdw* macros:
#%DD% installation of the device that will control the flipping. You can add your own device. Check the ones that are already existing (fliphdw* macros) and see how to proceed in %B%%{%<A HREF="#INTERNALS_1">INTERNALS,chapter I</A>%}%%B%.
#%DT%flipcal*/flipcal*off macros:
#%DD% insert or remove some online calculations to/from the flip. You can add your own calculations as well. (%B%%{%<A HREF="#INTERNALS_2">INTERNALS, chapter II</A>%}%%B%).
#%XDL%
#%INTERNALS%
#%{%<A NAME="INTERNALS_1"></A>%}%
#%DL% 
#%DT% I - HARDWARE CONTROL.
#%DD%
#%PRE%
# setup macros 	: %B%fliphdw* flipresetcontrol%B%
# global related : %B%FLPOL%B%
#%PRE%
#%DL%
#%DT% %B%fliphdw*%B% macro %DD% installs the flipping hardware control into flip software by r-def-ing %B%_flip_*%B% macros listed below:
#%DL%
#%DT%_flip_flip%DD%polarity toggling		
#%DT%_flip_neg%DD%polarity - setting		
#%DT%_flip_pos%DD%polarity + setting		
#%DT%_flip_move%DD%whatever to be executed prior to motor move.	
#%DT%_flip_get%DD%whatever to be executed after angles reading. 
#%DT%_flip_readpol%DD%returns the actual polarity
#%XDL%
#%DT%flipresetcontrol%DD% un-install everything. It is safe to call it at the beginning of any fliphdw* macros.
#%DT%FLPOL%DD%internally given -1/1 values to keep track of the polarity. 
#%XDL%
#%BR%
# %B%_flip_move%B% and %B%_flip_get%B% were created to allow "flip scans" 
# of a magnet pseudo motor. This sort of scan implies the polarity 
# control is disabled from motion commands, so that the absolute intensity of 
# the field can vary along the scan, while its polarity is flipped only at 
# each scan step. 
#%BR%%BR%
#%DL% %B%ATTENTION%B%%BR%%BR%
#%DT% _flip_flip, _flip_neg and _flip_pos %DD% macros must never call each others because of the internal assignment of FLPOL. 
#%DT% FLPOL%DD% is always updated %B%at the end%B% of each %B%_flip_flip%B%, %B%_flip_neg%B%  and %B%_flip_pos%B% macros.
#%DT% _flip_readpol%DD% is just read once at the beginning of a scan, %B%%{%<a href="flip_src.html#flip">flip</a>%}%%B% command only, in order to read in the actual polarity of the hardware. It will not be called if flipon/flipoff is used rather than the prefix flip.
#%XDL%
#%BR%
#%DL% %B%EXEMPLES%B% %BR%%BR%
#%DT% %{%<a href="flip_src.html#fliphdwsim">fliphdwsim</a>%}%  %{%<a href="flip_src.html#fliphdwrelay">fliphdwrelay</a>%}%  %{%<a href="flip_src.html#fliphdwpulse">fliphdwpulse</a>%}%  %{%<a href="flip_src.html#fliphdwdacpulse">fliphdwdacpulse</a>%}%  %{%<a href="flip_src.html#fliphdwdio">fliphdwdio</a>%}%  %{%<a href="flip_src.html#fliphdwsd">fliphdwsd</a>%}%  %{%<a href="flip_src.html#fliphdwox">fliphdwoxford</a>%}%.
#%DD%
#%XDL%
#%XDL%
#%BR%%BR%
#%{%<A NAME="INTERNALS_2"></A>%}%
#%DL% 
#%DT% II - DATA STORAGE AND ONLINE CALCULATIONS.
#%DD% 
#%PRE%
# setup macros 		: %B%flipcal* flipcal*off%B%
# cdef key     		: free, one per calculation.
# global array related	: %B%FLPDAT%B%
#%PRE%
#%DL%
#%DT% flipcal* macro%DD% installs online calculations into flip software by c-def-ing %B%_flip_*%B% macros listed below with macros performing calculations. Several calculations can be installed each having a specific cdef key.
#%DL%
#%DT%_flip_calcs%DD%calculation macros	
#%DT%_flip_calcs_splot%DD%related final plotting
#%XDL%
#%DT%flipcal*off%DD%un-install the corresponding calculation.
#%DT%FLPDAT%DD%array holds the scan data. It is filled up in %B%%{%<A HREF="flip_src.html#_flip_count">_flip_count</A>%}%%B% macro, called from %B%scan_count%B%, and always before %B%_flip_calcs%B%. It is formatted the following way:
#%PRE%
#array FLPDAT [4096] [ 1 + FLPSTYLE * COUNTERS]
#
#ie: [scan step] [0] 		: motor position or whatever x.
#                [1:COUNTERS] 	: 1st counter positions set 
#				  1st positive polarity counting
#                [COUNTERS+1:2*COUNTERS]
#			 	: 2nd counter positions set 
#				  1st negative polarity counting
#                [2*COUNTERS+1:3*COUNTERS]
#			 	: 3rd counter positions set 
#				  2nd positive polarity counting
#		...
#%PRE%
#%XDL%
#%BR%%BR%
#%DL% %B%EXEMPLES%B%%BR%%BR%
#%DT% %{%<a href="flip_src.html#flipcaldelta">flipcaldelta</a>%}%   %{%<a href="flip_src.html#flipcadeltaoff">flipcadeltaoff</a>%}%
#%DD%
#%XDL%
#%XDL%
#%BR%%BR%
#%DL%
#%DT% III - SCAN 
#%DD%
#%PRE%
# macros        : %B%flip  flipon  flipoff%B%
# cdef key      : %B%flps%B%
#%PRE%
#
#The flip software is hooked to standard scan user macros from %B%flipon/flipoff%B% commands, or by having usual scan commands preceeded by the word %B%%{%<a href="flip_src.html#flip">flip</a>%}%%B%. (eg: flip ascan mot0 0 10 10 1). In the last case, all is removed at the end of the scan. The hooks are listed below: (see %{%<a href="flip_src.html#flipon">flipon</a>%}%)
#%BR%%BR%%UL%
#%LI%%B%user_cleanup2%B%_flip_cleanup
#%LI%%B%user_checkall%B%_flip_move
#%LI%%B%user_getpangles%B%_flip_get;_flip_heading
#%LI%%B%Fheader%B%_flip_Fhead
#%LI%%B%Flabel%B%_flip_Flab
#%LI%%B%Pheader%B%_flip_Phead
#%LI%%B%Plabel%B%_flip_Plab
#%LI%%B%Fout%B%_flip_Fout
#%LI%%B%Pout%B%_flip_Pout
#%LI% and rdef %B%scan_count%B%_flip_count
#%XUL%
#%XDL%
#%BR%%BR%
#%DL%
#%DT% IV - PLOT COUNTERS SELECTION
#%DD%
#%PRE%
# macros         : %B%flipcounterselect%B%
# globals 	: %B%FLP_CNO  FLP_CLST%B%
#%PRE%
# %B%%{%<a href="flip_src.html#flipcounterselect">flipcounterselect</a>%}%%B% macro selects the counters to be plotted in the flip window, as %B%setplot%B% does for standard scan window. %B%FLP_CNO%B% holds the number of selected counters, and the array %B%FLP_CLST%B% holds selected counters mnemonics.
#%XDL%
#%BR%%BR%
#%DL%
#%DT% V - SAVE COUNTERS SELECTION
#%DD%
#%PRE%
# macros         : %B%flipsave%B%
# globals 	: %B%FLP_SNO  FLP_SLST%B%
#%PRE%
# %B%%{%<a href="flip_src.html#flipsave">flipsave</a>%}%%B% macro selects the counters which value should be dumped to scan file more than once at each scan step (in fact, each time a flip counting occurs). %B%FLP_SNO%B% holds the number of selected counters, and the array %B%FLP_SLST%B% holds selected counters numbers. If %B%flipsave%B% is never called, default behavior applies, i.e. all the measurements are dumped to the file. 
#Any scan will always start with a measurement at POSITIVE polarity. Then the following measurements results are always dumped alternating - and +, even if they did not actually occured that way.
#%XDL%
#%END%

#----------------------------------------------------------------------- SETUP 

#%UU% [sleep]
#%MDESC% General initialisation and default settings. 
#%BR% One can specify here the time to wait after flipping has occured.

def flipsetup '

  global FLP_SLEEP

  flipinit

  if ($1) FLP_SLEEP = $1
  else if (!$#) FLP_SLEEP = getval ("Wait time after flip, in sec.",FLP_SLEEP)
  
  setup_tail("flip")
'

#%UU% 
#%MDESC% Initialises internal macros and set defaults.
#%BR% Called by %B%flipsetup%B%.
def flipinit '
  global FLPOL FLP_CNO FLP_CLST FLP_SNO FLP_SLST FLP_SLEEP
  global FLIP_ON

  FLP_CLST[-1]=0
  FLP_SLST[-1]=0

  if (!(whatis("_flip_calcs")&2)) rdef _flip_calcs \'\'
  if (!(whatis("_flip_calcs_splot")&2)) rdef _flip_calcs_splot \'\'
  if (!(whatis("_flip_move")&2)) rdef _flip_move \'\'
  if (!(whatis("_flip_get")&2)) rdef _flip_get \'\'
  if (!(whatis("_flip_Fhead")&2)) rdef _flip_Fhead \'\'
  if (!(whatis("_flip_Phead")&2)) rdef _flip_Phead \'\'
  if (!(whatis("_flip_usermacro1")&2)) rdef _flip_usermacro1 \'\'
  if (!(whatis("_flip_usermacro2")&2)) rdef _flip_usermacro2 \'\'
  if (!(whatis("_flip_flip")&2)) rdef _flip_flip \'\'
  if (!(whatis("_flip_pos")&2)) rdef _flip_pos \'\'
  if (!(whatis("_flip_readpol")&2)) rdef _flip_readpol \'FLPOL\'
  if (!(whatis("_flip_Flab")&2)) rdef _flip_Flab \'""\'\'
  if (!(whatis("_flip_Fout")&2)) rdef _flip_Fout \'""\'
  if (!(whatis("_flip_Plab")&2)) rdef _flip_Plab \'""\'
  if (!(whatis("_flip_Pout")&2)) rdef _flip_Pout \'""\'

  cdef ("config_mac","_flip_config;","flipscan")
  
  # default:

  if (0==FLPSTYLE) {
    flipstyle 2 
    fliphdwsim
  }
  if (0==FLP_CNO) {
    flipcounterselect ALL
  }
  if (0==FLP_SNO) {
    flipsave ALL
  }
'

#%UU%
#%MDESC% Remove flip software.
def flipunsetup '
  unglobal FLPOL FLP_CNO FLP_CLST FLPCOUNTERS FLPSTYLE FLP_LABEL FLP_OUT 
  unglobal Y_FL FLPG
  flipoff
  flipresetcontrol
  cdef ("","","flipscan","delete")
  print "FLIP deleted"
'

#%IU%
#%MDESC% Configuration macro. (%B%config_mac%B%)
def _flip_config ''

#%UU% [[number (always even)] [flag]] | | [style_string]
#%MDESC% Sets the number of countings and flippings.
#%BR% If %B%flag%B% is zero, flipping occurs between each couting; if it is 1, I dont know how to explain it, but the %B%style_string%B% way might help. 
#It is a string of %B%+%B% and %B%-%B% ordered along with the flippings. e.g. %B%+-+-%B% would mean 4 countings flipped (flipstyle 4), %B%+--+%B% is also 4 countings, but not flipped at the middle. It is flag 1. (flipstyle 4 1). 
#There must be as many negative as positive countings for it works, and it will neither allow an odd number of countings. Means that allowed entries are 1, 2, 4 0, 4 1, or +--+, or +-+-. +-+--+-+ would also work, but not +-++-+...

def flipstyle '{    

  global FLPSTYLE FLPOPTION FLP
  local i1 i2

  i1="$1"+0; i2="$2"+0

  FLPSTYLE = i1>=2?2*int(i1/2):1  
  FLPOPTION = FLPSTYLE>2?i2:0
    
  _flip_style_keep_request $*

  if (FLPSTYLE==1) {
    FLP[-1]="< -"
    FLP[1]="< +"
    rdef _flip_Plab \'""\'
    rdef _flip_Pout \'sprintf("%s ",FLP[FLPOL])\'

  } else {
    rdef _flip_Plab \'sprintf("%7.7s %7.7s ",cnt_name(DET),cnt_name(MON))\'
    rdef _flip_Pout \'sprintf("- | + %7.5g %7.5g ",                                                              FLPDAT[NPTS][DET+1+COUNTERS*(FLPSTYLE-2)],                                     FLPDAT[NPTS][MON+1+COUNTERS*(FLPSTYLE-2)])\'
  }
}
'

def _flip_style_keep_request '{
  global FLPSTYLEREQ
  local tok str1 str2
  FLPSTYLEREQ="$*"  
  if (index(FLPSTYLEREQ,"+")) {
    if ($#>1) { 
      FLPSTYLE = split (FLPSTYLEREQ,toks)
      if (FLPSTYLE>=2) FLPSTYLE = 2*int(FLPSTYLE/2)
      else FLPSTYLE = 1   
      str1 = str2 = ""
      str1 = toks[FLPSTYLE/2-1]
      str2 = toks[FLPSTYLE/2]
    } else {
      FLPSTYLE = length (FLPSTYLEREQ)
      if (FLPSTYLE>=2) FLPSTYLE = 2*int(FLPSTYLE/2)
      else FLPSTYLE = 1   
      str1 = substr(FLPSTYLEREQ,FLPSTYLE/2,1)
      str2 = substr(FLPSTYLEREQ,FLPSTYLE/2+1,1)
    }
    if (str1==str2 && FLPSTYLE>2) FLPOPTION=1
    else FLPOPTION=0
  }
}
'

#%UU% [ALL|mnemonic] [mnemonic] [mnemonic] ...
#%MDESC% Select the counters that will be plotted in flip window.

def flipcounterselect '{
  global FLPCOUNTERS FLP_CLST
  
  FLP_CLST[0]

  for (i=0;i<COUNTERS;i++) FLPCOUNTERS[i]=cnt_mne(i);

  if ($#) {
    if ("$1" == "ALL") {
      FLP_CNO=COUNTERS
      for (i=0;i<COUNTERS;i++) FLP_CLST[i]=FLPCOUNTERS[i]
    } else {
      FLP_CNO = split ("$*",FLP_CLST)
    }

  } else {
    clscreen()
    FLP_CNO = menu_2lists(FLP_CLST,FLP_CNO,FLPCOUNTERS,COUNTERS)
  }
}
'


#%UU% [ALL|mnemonic] [mnemonic] [mnemonic] [mnemonic]
#%MDESC% Select the counters that will be dumpped their content to the file for additionnal measurements produced by flip. 
def flipsave '{
global FLPCOUNTERS FLP_SLST
  
#  if ("$1"=="binned") FLP_SMOD=1
#  else FLP_SMOD=0			# raw


  FLP_SLST[0]

  for (i=0;i<COUNTERS;i++) FLPCOUNTERS[i]=i;

  if ($#) {
    if ("$1" == "ALL") {
      FLP_SNO=COUNTERS
      for (i=0;i<COUNTERS;i++) FLP_SLST[i]=FLPCOUNTERS[i]
    } else {
      FLP_SNO = split ("$*",FLP_SLST)
    }

  } else {
    clscreen()
    FLP_SNO = menu_2lists(FLP_SLST,FLP_SNO,FLPCOUNTERS,COUNTERS)
  }

  for (i=0;i<FLP_SNO;i++) FLP_SLST[i]=cnt_num(FLP_SLST[i])
}
'

#----------------------------------------------------------------------- SAVING

#%IU%
#%MDESC% %B%_cols%B% update and File output formatting. (%B%Fheader%B%).
def _flip_Fhead '{
  if (COUNTERS && FLPSTYLE) {
    array FLPDAT [4096][COUNTERS*FLPSTYLE+1]
  }
  _flip_Foutput
  rdef _flip_Fout FLP_OUT
  printf("#C flipstyle %s : %d %d\n", FLPSTYLEREQ,FLPSTYLE,FLPOPTION)
}
  _cols+=FLP_SNO?FLP_SNO*(FLPSTYLE-1):(COUNTERS-1)*(FLPSTYLE-1)
'


#%IU%
#%MDESC% Compiles the global variables %B%FLP_OUT%B% and %B%FLP_LABEL%B% out of the flip style set up. Both are used for printing out flip data to scan file. Each counter name is added a suffix like "_1", for each measurement over the regular one. 
#%PRE%
#e.g.:
# FLP_LABEL = "Counter 1  Counter 2" or "Counter 1  Counter 2  Counter 1_1 ..."
# FLP_OUT   = ",FLPDAT[NPTS][1],FLPDAT[NPTS][2]"
#%PRE%

def _flip_Foutput '{

  global FLP_LABEL FLP_OUT
  local _countings _counters cno val ii jj fmt ix

  FLP_LABEL = ""
  _countings = FLPSTYLE-1
  if (_countings<0) _countings=0
  _counters = FLP_SNO?FLP_SNO:COUNTERS-1

  for (ii=0;ii<_countings;ii++) {
    zz=dd=-1
    for (jj=0;jj<_counters;jj++) {
      cno=FLP_SNO?FLP_SLST[jj]:jj+1
      if (cno != MON && cno != DET && cnt_name(cno) != "unused") {
        FLP_LABEL = FLP_LABEL cnt_name(cno) "_" ii+1 "  "
        fmt = fmt "%g "
        ix = 1 + cno+COUNTERS*ii
        val = sprintf("%s,FLPDAT[NPTS][%d]",val,ix)
      }
      if (cno==MON) zz=MON
      if (cno==DET) dd=DET
    }
    if (zz >= 0) {
      FLP_LABEL = FLP_LABEL cnt_name(zz) "_" ii+1 "  "
      fmt = fmt "%g "
      ix = 1 + zz+COUNTERS*ii
      val = sprintf("%s,FLPDAT[NPTS][%d]",val,ix)
    } 
    if (dd >= 0) { 
      FLP_LABEL = FLP_LABEL cnt_name(DET) "_" ii+1 "  "
      fmt = fmt "%g "
      ix = 1 + DET+COUNTERS*ii
      val = sprintf("%s,FLPDAT[NPTS][%d]",val,ix)
    }
  }

  FLP_OUT = "sprintf(\"" fmt "\"" val ")"
}
'

def flip_Foutput_old '{

  global FLP_LABEL FLP_OUT
  local ctnum val fmt ix

  if (COUNTERS && FLPSTYLE) {
    array FLPDAT [4096][COUNTERS*FLPSTYLE+1]
  }

  FLP_LABEL = ""
  ctnum = FLPSTYLE-1
  if (ctnum<0) ctnum=0

  for (num=0;num<ctnum;num++) {
    for (cno=1;cno<COUNTERS;cno++) {
      zz=MON
      if (cno != zz && cno != DET && cnt_name(cno) != "unused") {
        FLP_LABEL = FLP_LABEL cnt_name(cno) "_" num+1 "  "
        fmt = fmt "%g "
        ix = 1 + cno+COUNTERS*num
        val = sprintf("%s,FLPDAT[NPTS][%d]",val,ix)
      }
    }
    if (zz >= 0) {
      FLP_LABEL = FLP_LABEL cnt_name(zz) "_" num+1 "  "
      fmt = fmt "%g "
      ix = 1 + zz+COUNTERS*num
      val = sprintf("%s,FLPDAT[NPTS][%d]",val,ix)
    } 
    FLP_LABEL = FLP_LABEL cnt_name(DET) "_" num+1 "  "
    fmt = fmt "%g "
    ix = 1 + DET+COUNTERS*num
    val = sprintf("%s,FLPDAT[NPTS][%d]",val,ix)
  }

  FLP_OUT = "sprintf(\"" fmt "\"" val ")"
}
'

#%IU%
#%MDESC% (%B%Flabel%B%)
def _flip_Flab  'sprintf(FLP_LABEL)'

#-------------------------------------------------------------------- HARDWARE
#%UU%
#%MDESC% Remove any flip controller installed.
def flipresetcontrol '
  global FLPHDW
  rdef _flip_readpol \'FLPOL\'
  rdef _flip_pos \'\'
  rdef _flip_flip \'\'
  rdef _flip_move \'\'
  rdef _flip_get \'\'
  FLPHDW = substr("$*",8)
'

#%UU% 
#%MDESC% Install a simulation of a hardware flipping. 

def fliphdwsim '

  flipresetcontrol $0 

  rdef _flip_pos \'
    printf ("\n<+>")
  \'

  rdef _flip_flip \'
    if (FLPOL>0) { 
      printf("<->")
    } else { 
      printf("<+>")
    }
  \'

  rdef _flip_move \'
    print "disable"
  \'

  rdef _flip_get \'
    print "enable"
  \'
'

#%UU% <relay_device_server_name> 
#%MDESC% needs %B%dio.mac%B% macros. %BR%Install one CS Relay device server to control the flipping. Relay opens for negative polarity and closes for positive. 

def fliphdwrelay '
if ($#) {

    flipresetcontrol $0 $*

    rdef _flip_pos \'
      dio_devclose("$1") 
   \'

    rdef _flip_flip \'
      if (FLPOL<=0) {
        dio_devclose("$1") 
      } else {
        dio_devopen("$1") 
      }
    \'
}
'

#%UU% <pulsedrelay_device_server_name> <pulse_time>
#%MDESC% needs %B%dio.mac%B% macros.%BR%Install one CS Pulsed Relay device server to control the flipping. Flipping occurs on relay pulsing. 

def fliphdwpulse '
if ($#) {

    flipresetcontrol $0 $*

    rdef _flip_flip \'
      dio_devpulse("$1",$2)
    \'

    rdef _flip_pos \'    
      if (FLPOL<=0) dio_devpulse("$1",$2)
    \'
  }
'

#%UU% <dac_device_server_name> <pulse_time> <rest_voltage> <pulse_voltage>
#%MDESC% Install one DAC (icv712) output to control the flipping. Flipping occurs when output pulses. 
def fliphdwdacpulse '

if ($#==4) {
    flipresetcontrol $0 $*

    rdef _flip_flip \'
      esrf_io("$1","DevSetValue",$4)
      sleep ($2)
      esrf_io("$1","DevSetValue",$3);
    \'

    rdef _flip_pos \'
      if (FLPOL<=0) {
        esrf_io("$1","DevSetValue",$4)
        sleep ($2)
        esrf_io("$1","DevSetValue",$3);
      }
    \'

    esrf_io("$1","DevSetValue",$3)
}
'

#%UU% <dac_device_server_name> <pulse_time> <pulse_voltage> <rest_voltage> 
#%MDESC% Install one DAC (icv712) output to control the flipping. Goes to positive polarity when pulse is positive, and to negative when pulse is negative. 
def fliphdwdacpulse1 '

if ($#==4) {
    flipresetcontrol $0 $*

    rdef _flip_flip \'
      if (FLPOL<=0) {
        esrf_io("$1","DevSetValue",$3)
        sleep ($2)
        esrf_io("$1","DevSetValue",$4);
      } else {
        esrf_io("$1","DevSetValue",-$3)
        sleep ($2)
        esrf_io("$1","DevSetValue",-$4);
      }
    \'

    rdef _flip_pos \'
      if (FLPOL<=0) {
        esrf_io("$1","DevSetValue",$3)
        sleep ($2)
        esrf_io("$1","DevSetValue",$4);
      }
    \'
}
'

#%UU% <dac_device_server_name> <positive_voltage> <negative_voltage> 
#%MDESC% Install one DAC (icv712) output to control the flipping. Goes to positive polarity when <positive_voltage> is applied, and to negative when <negative_voltage> is applied. 
def fliphdwdac '

if ($#>=2) {
    flipresetcontrol $0 $*

    rdef _flip_flip \'
      esrf_io("$1","DevSetValue",FLPOL>0?$3:$2)
    \'

    rdef _flip_pos \'
        esrf_io("$1","DevSetValue",$2)
    \'
}
'

#%UU% <dio_actuator_name>
#%MDESC% needs %B%dio.mac%B% macros and %B%diosetup%B% done.%BR%
#Install one DIO channel to control the flipping. This works only if %B%diosetup%B% has been done. Otherwise, use %B%fliphdwrelay%B% or %B%fliphdwpulse%B%.  

def fliphdwdio '{

if (DIOid["$1"]) {

  flipresetcontrol $0 $*

  rdef _flip_pos \'
    dio_close(DIOid["$1"])
  \'

   rdef _flip_flip \'
     if (FLPOL<=0) {
       dio_close(DIOid["$1"])
     } else {
       dio_open (DIOid["$1"])
     }
   \'
} 
else print "do \"diosetup\" first" 
}
'

#%UU% 
#%MDESC% needs %B%sdlin.mac%B% macros and %B%sdsetup%B%%BR%
#Install the Sodilec BOS/S Power Supply to control the flipping. 
def fliphdwsd '{

  flipresetcontrol $0 $*

  rdef _flip_readpol \'((SD_SETPOINT >0) ? 1 : -1)\'

  rdef _flip_move \'SDPOLF=0\'
  rdef _flip_get  \'SDPOLF=1\'
  rdef _flip_pos  \'
    sdset fabs(SD_SETPOINT)
  \'
  
  rdef _flip_flip \'
    if (FLPOL>0) {
      sdset -fabs(SD_SETPOINT)
    } else {
      sdset fabs(SD_SETPOINT)
    }
  \'
}
'

#%UU% <oxpssetup_device_number> 
#%MDESC% needs %B%oxPS1.mac%B% macros, and %B%oxpssetup%B%%BR% Install an Oxford PS 180 or 120 type Power Supply to control the flipping. <oxpssetup_device_number> starts from 1.

def fliphdwoxford '{

 local _oxx 
    
 if (!$#) {
   print "usage: $0 devnum"
   print "eg:    $0 1"
   exit
 } 

 flipresetcontrol $0 $*
 
 rdef _flip_move \'OXPOLF=0\'
 rdef _flip_get  \'OXPOLF=1\'

 rdef _flip_pos \'
     _oxps_checkmode $1-1
     oxps_iof($1-1,"P1")
     oxps_iof($1-1,"P1")
     _oxps_wait_mag_pol $1-1 1
     _oxps_ifpersistant $1-1
#    FLPOL=1
 \'

 rdef _flip_flip \'
   _oxps_checkmode $1-1
   ox_iof($1-1,"P4")
   _oxps_wait_mag_pol $1-1 -FLPOL
   _oxps_ifpersistant $1-1
 \'

 
}
'

#---------------------------------------------------------------- CALCULATIONS

#%UU%
#%MDESC% Install some online DELTA calculation.
def flipcaldelta '
  cdef ("_flip_calcs","_flip_delta;","flpdelta")
  cdef ("_flip_calcs_splot","_flip_splot 3 FLPDELTA 1;","flpdelta")
'
#%UU% 
#%MDESC% Un-install delta calculation.
def flipcaldeltaoff 'cdef ("","","flpdelta","delete")'

#%IU%
#%MDESC% DELTA online calculations. %BR%i.e. substracts negative countings from positive countings, stores the result in %B%FLPDELTA%B% array, and plots it out.

def _flip_delta '{
  local offs num
  
  if (0==NPTS) { array FLPDELTA [4096][1+COUNTERS] }
  FLPDELTA[NPTS][0]= _stype&1?A[_m[0]]:_time 

  for (num=0;num<FLPSTYLE;num+=2) {
    offs = COUNTERS*num
    FLPDELTA[NPTS][1:] += FLPDAT[NPTS][1+offs:COUNTERS+offs]  
    offs += COUNTERS
    FLPDELTA[NPTS][1:] -= FLPDAT[NPTS][1+offs:COUNTERS+offs]  
  }
  _flip_rplot 3 FLPDELTA FLIP_DELTA 1
}
'

#%UU%
#%MDESC% Install some online AVERAGE calculation.
def flipcalaverage '
  cdef ("_flip_calcs","_flip_average;","flpaver")
  cdef ("_flip_calcs_splot","_flip_splot 4 FLPAVER 1;","flpaver")
'

#%UU% 
#%MDESC% Un-install average calculation.
def flipcalaverageoff 'cdef ("","","flpaver","delete")'
#%IU%
#%MDESC% AVERAGE online calculations. %BR% i.e. average all countings, stores the result in %B%FLPAVER%B% array, and plots it out.

def _flip_average '{
  local offs num
  
  if (0==NPTS) { array FLPAVER [4096][1+COUNTERS] }
  FLPAVER[NPTS][0]= _stype&1?A[_m[0]]:_time

  for (num=0;num<FLPSTYLE;num+=1) {
    offs = COUNTERS*num
    FLPAVER[NPTS][1:] += FLPDAT[NPTS][1+offs:COUNTERS+offs]  
  }
  FLPAVER[NPTS][1:]/=FLPSTYLE
  _flip_rplot 4 FLPAVER FLIP_AVERAGE 1
}
'

#------------------------------------------------------------------------ FLIP 
#%UU% <standard_usual_scan_command>
#%MDESC% Does the flip scan. 
def flip '{
  flipon
  FLPOL = _flip_readpol
  _flip_usermacro1
}

$*
flipsplot 
_flip_usermacro2
flipoff
'

#%UU%
#%MDESC% Hooks the flip to standard scans.
def flipon '{
  cdef("user_cleanup2","_flip_cleanup;","flps")
  cdef("user_checkall","_flip_move;","flps",0x10)
  cdef("user_getpangles","_flip_get;_flip_heading;","flps",0x20)
  cdef("Fheader","_flip_Fhead;","flps") 
  cdef("Flabel","_flip_Flab","flps")
  cdef("Pheader","_flip_Phead;","flps")
  cdef("Plabel","_flip_Plab","flps")
  cdef("Fout","_flip_Fout","flps")
  cdef("Pout","_flip_Pout","flps")

  rdef scan_count \'_flip_count\'

  FLIP_ON = 1
}
'

#%UU%
#%MDESC% Detach the flip from standard scans.
def flipoff '{
  cdef("","","flps","delete")
  cdef("Flabel","\"\"","flps",0)
  cdef("Plabel","\"\"","flps",0)
  cdef("Fout","\"\"","flps",0)
  cdef("Pout","\"\"","flps",0)

  rdef scan_count \'_count\'

  FLIP_ON = 0
}
'

#%IU% 
#%MDESC% Scan heading string. (%B%HEADING%B%)
def _flip_heading 'HEADING = "flip " HEADING'

#%IU%
#%MDESC% (%B%scan_count%B%). Here is the flipping_counting manager.
def _flip_count '{

	local ctnum
        local cc offs

        waitmove

  	for (ctnum=0;ctnum<FLPSTYLE;ctnum++) {

    	  if ((FLPSTYLE>1 && !ctnum) || (FLPSTYLE==1 && !NPTS)) { 
            _flip_pos 
            sleep(FLP_SLEEP)
            FLPOL=1
	  } else if (FLPSTYLE==1 || !FLPOPTION || (((FLPSTYLE/2)!=ctnum))) { 
            _flip_flip
            sleep(FLP_SLEEP)
            FLPOL=-FLPOL
          }

          if ($1) for (;;) {
            count_em $1
            waitcount
            get_counts
            chk_beam
          }

          if (S[sec] && MON >= 0)
                MON_RATE=S[MON]/S[sec]
          offs = int (ctnum/2)*2
          if (FLPSTYLE>1 && FLPOL<0) offs++
          for (cc=0;cc<COUNTERS;cc++)  FLPDAT[NPTS][1+cc+COUNTERS*offs]=S[cc]
  	}


  	for (cc=0;cc<COUNTERS;cc++) {
	  S[cc] = FLPDAT[NPTS][1+cc+COUNTERS*(FLPSTYLE-1)]
        }
        FLPDAT [NPTS][0] =  _stype&1?A[_m[0]]:_time

  	_flip_calcs
  	_flip_rplot 2 FLPDAT FLIP FLPSTYLE
}
'


#%IU%
#%MDESC% Cleanup macro. (%B%user_cleanup2%B%)
def _flip_cleanup '{
  _flip_get
  flipsplot 
  _flip_usermacro2
  flipoff
}
'


#--------------------------------------------------------------------- PLOTTING

#%IU% <filter_num> <data_array_name> [window_title]
#%MDESC% Running scan plot for all flip data.
def _flip_rplot '{

  global Y_FL
  local pstr num

  plot_cntl("filter$1")

  if (PLOT_MODE&128) {
    plot_cntl(sprintf("colors=%s",rplot_col))
    plot_cntl("open")
  }

  if ((_stype&8? _g1:NPTS) == 0) {
    for (Y_FL = cnt_name(cnt_num(FLP_CLST[0])),uu=1;uu<FLP_CNO;uu++) {
      Y_FL = Y_FL" "cnt_name(cnt_num(FLP_CLST[uu]))
    }
    plot_range(_sx,_fx,YMIN,"auto")
    plot_cntl("title=$3")
    plot_cntl(PLOT_MODE&32? "ylog":"-ylog")
    plot_cntl(PLOT_MODE&256? "-dots":"dots")
    plot_cntl(PLOT_MODE&512? "-lines":"lines")
    plot_cntl(PLOT_MODE&1024? "-ebars":"ebars")
    plot_cntl("erase")
    plot_move(0,1,sprintf("Flip %s",T_L))
    plot_move(0,2,Y_FL)
    plot_move(0,-1,sprintf("%.8s", X_L))
  }

  if (_stype&16) plot_range("auto","auto",YMIN,"auto")

  num = $4?$4:FLPSTYLE
  pstr = _flip_plotwhat(num)
  array_plot($2[0:NPTS][pstr])
  plot_move(0,0)
  plot_cntl("filter1")
}
'


#%UU%
#%MDESC% Screen plot of flip data.
def flipsplot '{
 
  _flip_splot 2 FLPDAT FLPSTYLE
  _flip_calcs_splot 
}
'

#%IU% <filter_num> <data_array_name> 
#%MDESC% Final scan plot for all flip data.
def _flip_splot '{
  local pstr num

  plot_cntl("filter$1")

  if (PLOT_MODE&128) {
    plot_cntl(sprintf("colors=%s",splot_col))
    plot_cntl("open")
  }
  plot_cntl("erase")
  plot_range("auto","auto",YMIN,"auto")
  plot_move(0,1,sprintf("Flip %s",T_L))
  plot_move(0,2,Y_FL)
  plot_move(0,-1,sprintf("%.8s", X_L))

  num = $3?$3:FLPSTYLE
  pstr = _flip_plotwhat(num)
  array_plot($2[0:NPTS-1][pstr])

  plot_move(0,3)
  plot_cntl("filter1")
}
'


#%IU% (number_of_countings)
#%MDESC% Returns %B%FLPDAT%B% array index string of what to plot.
def _flip_plotwhat(loop1end) '{
  local num 

  pstr = "0"
  for (num=0;num<loop1end;num++) {
    for (cno=0;cno<FLP_CNO;cno++) {
      pstr = pstr "," cnt_num(FLP_CLST[cno])+1+COUNTERS*num
    }
  }
  return pstr
}
'

#--------------------------------------------------------------- CPLOT ACCESS

#%UU% [detector-mnemonic] [detector-mnemonic] ... 
#%MDESC% flip data printer plot, pplot like.
def flippplot 'cp_setprinter; _flip_cplot $*'

#%UU% [detector-mnemonic] [detector-mnemonic] ... 
#%MDESC% flip data cplot, cplot like.
def flipcplot 'cp_setx11;_flip_cplot $*'

#%IU%
#%MDESC% Does for cplot.
def _flip_cplot '{
  global FLPG
  local yind ylabel 

  _flip_y $*

  nn = 1+COUNTERS*FLPSTYLE
  FLPG = groupinit(FLPG, int (65536/nn), nn)

  data_read (FLPDAT[0:NPTS][yind],FLPG)

  cp_mplot FLPG 0 \'"yind"\' \'"T_L"\' \'"X_L"\' \'"ylabel"\' 
}
'


#%IU%
#%MDESC% Compiles Y index string to pass to cp_mplot.
def _flip_y '{

  local firsthit

  yind = 0
  ylabel = ""

  if (!$#) {
    yind = substr(_flip_plotwhat(FLPSTYLE),3)

  } else {

    split("$*",_p)

    for (i2=0,firsthit=1;i2<COUNTERS;i2++) {
      for (i1=0;i1<$#;i1++) {
        if (cnt_num(_p[i1]) == i2) {
          if (firsthit) {
            yind=sprintf("%d",i2+1)
            if (FLPSTYLE>=2) yind = sprintf ("%s,%d",yind,i2+1+COUNTERS)
            ylabel = sprintf("%s ",cnt_name(i2))
            firsthit = 0
          } else { 
            yind=sprintf("%s,%d",yind,i2+1)
            if (FLPSTYLE>=2) yind = sprintf ("%s,%d",yind,i2+1+COUNTERS)
            ylabel = sprintf("%s%s ",ylabel,cnt_name(i2))
          }
        }   
      }
    }
  }
}
'

#--------------------------------------------------------------- MISC

#%UU%
#%MDESC% Shows what is installed.
def flipstat '{
  printf( "\nflipstat : ")
  if (FLPSTYLE) {
    printf( "requested flipstyle %s\n-----\n", FLPSTYLEREQ)
    printf( "number of countings      (flipstyle): %d. ",FLPSTYLE,FLPOPTION)
    for (i=0;i<4;i++) {
      local ctnum flpol 
      for (ctnum=0;ctnum<FLPSTYLE;ctnum++) {
        if ((FLPSTYLE>1 && !ctnum) || (FLPSTYLE==1 && !i)) {
          flpol=1
        } else if (FLPSTYLE==1 || !FLPOPTION || (((FLPSTYLE/2)!=ctnum))) { 
          flpol=-flpol
        }
        printf("%s",flpol>0?"+":"-")    
      }
      printf (" ; ")
    }
    print 
    printf( "plotted counters (flipcounterselect): ")
    for (i=0;i<FLP_CNO;i++) printf("%s  ",FLP_CLST [i]);
    print
    printf( "saved counters            (flipsave): ")
    for (i=0;i<FLP_SNO;i++) printf("%s  ",cnt_mne(FLP_SLST [i]));
    print
    printf( "hardware installed        (fliphdw*): %s\n",FLPHDW)
    printf( "sleep after flip         (flipsetup): %g\n",FLP_SLEEP)
  } else
    print "Setup not done"
}
'

#%IU%
#%MDESC% Menu stuff.
def menu_2lists (list,sz,list0,sz0) '{

  local sel ttyx i j text
  
  for (sel="";sel!="q";sel = getval(sprintf("enter element to move or %sq%suit\n\n ---> ",MENU_ONB,MENU_OFS),"q")) { 
    ttyx[0]=ttyx[1]=length("SELECTION: ")
    tty_move(0,5,"SELECTION: ");tty_cntl("ce")
    tty_move(0,7,"    OTHER: ");tty_cntl("ce")
    for (i=0;i<sz0;i++) {
      text = sprintf("<%s%s%s>",MENU_ONB,list0[i],MENU_OFS)
      for (j=0;j<sz;j++) {
         if (list0[i]==list[j]) break
      }
      if (sel == list0[i]) {
        if (j==sz) {
          list[sz++]=sel
        } else {
          list[j]=list[--sz]
          delete list[sz]
          j=sz
        }
      }
      if (j==sz) {
        tty_move(ttyx[0],7,text) 
        ttyx[0]+=length(text)-2
      } else {
        tty_move(ttyx[1],5,text); 
        ttyx[1]+=length(text)-2
      }
    }
    tty_move(0,11);tty_cntl("ce");tty_move(0,9)
  }

return (sz)
}
'

#%IU%
#%MDESC% For use of blmenu (use blmenu.mac).
def flipbody(mode) '{

   if (mode == 1) {
      if (FLIP_ON) {
         flipoff
      }
      else {
         flipon
      }
      
   }
   return(sprintf("%s",FLIP_ON?"ON":"OFF"))
}
'


#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#The file %B%flip.mac%B% has to be read in.%BR%
#It also needs:
#%UL%
#%LI%%B%stlocal.mac%B%
#%LI%flipping device %B%specific macros%B%.(oxPS.mac, dio.mac ...)
#%XUL%
#%AUTHOR%
# FLIP.MAC - Marie-Claire LAGIER - 96/10/21

#%TOC%


## DATE Wed Mar  4 15:57:42 MET 1998 REV 2.6;