# $Revision: 1.2 $ # $Date: 2007-02-20 05:01:44 $ # Author: Mark Lesha (mle@ansto.gov.au) # Last revision by: $Author: ffr $ #------------------------------------------------------------------------- # System: Histogram Server (sample) #------------------------------------------------------------------------ ############################################## # Creating the histogram memories in SICS ############################################## # Make a histogram memory object hmm, allows control of the # remote histogram server via http, and acquisition # of histogram period data. MakeHM hmm anstohttp hmm configure hmaddress http://das1-echidna:8080 hmm configure username spy hmm configure password 007 hmm configure hmDataPath ../HMData ############################################## # Configuring the histogram server ############################################## # Procedure to read a single config (or any) file, return content as a string. proc returnconfigfile {filename} { set fh [open $filename] set xml [read $fh] #set xml [list [read $fh]] clientput $xml value close $fh return $xml } Publish returnconfigfile User # Configure to upload a complete configuration to the histogram server. # In this case it's the main config file plus the FAT, BAT and OAT files # in the same direcory as the SICS executable (for this example). # Alternatives: # - A partial config could be uploaded instead - e.g. just the main config file, # in that case the main config file points to a set of FAT, BAT OAT files # located on the server. # - The histogram server could configure itself from a config file set # kept on the local file system (not automated presently, manual control only) # - Or, no configuration at all could be uploaded, the # histogram server can configure itself using its default config files. hmm configure hmconfigscript "returnconfigfile $cfPath(hmm)/anstohm_full.xml" # Initialize the histogram server. # This call to hmm init (with init 1 configured) causes the histogram server # to be loaded with the specified configuration files. Subsequent inits (with init 0 configured) # only cause specific histogram server FAT settings to be updated. # If the histogram server's default configfiles are adequate, the init 1 stage can be skipped. # Before configuring, make sure the server is stopped, since configuration # during DAQ is not allowed. This requires init of the hmm object to level 0. # # Making sure the histogram server is stopped, so we can load configuration. hmm configure init 0 hmm init hmm stop # Load the configuration to the histogram server. hmm configure init 1 hmm init # Restore the init level to 0, subesquent inits will only upload specified FAT settings to histogram server. hmm configure init 0 ############################################## # Configuring the histogram memories in SICS ############################################## # Now issue stop to the server. # This not only makes sure it's stopped, but lets us see certain configuration variables # which get placed in the dictionary as part of the status checking done during the stop. hmm stop # Here, define a function to let us read back the value of dictionary items from the hmm # such as OAT dimensions. proc hmmdictitemval {histomem dictitem} { set resp [$histomem configure $dictitem] set retn [lindex [split $resp " "] 2] return $retn } # Configure histogram dimensions, mode, etc. using the dictionary variables. # For the dimensions, set the 'effective' OAT dimensions which are the # histogram period dimensions. Do an init after to cause memory to be allocated. hmm configure histmode transparent hmm configure bank 0 hmm configure rank 3 hmm configure dim0 [hmmdictitemval hmm oat_nyc_eff] hmm configure dim1 [hmmdictitemval hmm oat_nxc_eff] hmm configure dim2 [hmmdictitemval hmm oat_ntc_eff] hmm init ############################################## # Create beam monitor counter # and histogram memory control object # (ANSTO customized versions) ############################################## # Make and configure an ANSTO beam monitor counter. MakeCounter bm anstomonitor [ params host "das1-echidna" port "30000" ] bm SetExponent 0 # Make our special HMControl_ANSTO object with the bm controlling the hmm. # This version can pause the histogram server after the count expires # instead of just stopping it, so we can generate multiple datasets # during a scan, or overlap data acquired at different scan stations. # It can also terminate either on the counter or any of the histogram objects. MakeHMControl_ANSTO hmc bm hmm ############################################## # Creating scans and creating/attaching # associated objects such as motors to drive, # extra counters etc. ############################################## # # Define two scan objects which use the beam monitor counter. # # For hmscan, the hmc object uses the bm counter to control # acquisition duration. In other words, the acquisition duration # is controlled via SICS. This is fine if the duration doesn't # need to be controlled to an accuracy of less than one second. # The bm only allows control of acquisition duration based on # elapsed time or number of monitor counts. # # For scan2, the histogram server controls acquisition duration. # In addition to time or monitor count based termination conditions, # the histogram server can be configured to terminate after a # specific number of frames or periods have elapsed, or can be # terminated in response to an external dataset signal. # The accuracy of control of the acquisition duration is much higher # (milliseconds versus hundreds of milliseconds). # Also, the histogram server can be configured to extend acquisition # so that only whole frames or periods are acquired. # Termination condition is normally already configured via # the histogram server's configuration files. # If a static termination condition is already configured, # scan2_runa can be called, with no termination condition required. # But if the SICS user wants to dynamically commit the termination # condition configuration to the histogram server, # a wrapper function scan2_runb should be called instead. # This allows the termination condition configuration to be written to # the histogram server dynamically, under the control of SICS. # The histogram server has a wider range of options for # termination condition, and there are three termination condition # arguments instead of the usual two for SICS counter objects. # # In both cases, we make the bm the master counter for the scan, # so that bm statistics are acquired during the scan. # # 17/11/06 NOTE: The Beam Monitor is not yet interfaced directly to the # Histogram Server. This means that for BM-controlled acquisitions, # SICS needs to use the BM counter (i.e. use hmscan not scan2). # # EXAMPLES: For scan running over 5 stops and acquisition of 1 sec at each stop: # hmscan run 5 timer 1 (termination controlled by the beam monitor) # scan2_runb 5 TIME 100 IMMEDIATE (termination controlled by the histogram server) # MakeScanCommand hmscan bm $cfPath(scan)/scan.hdd recover.bin MakeScanCommand scan2 bm $cfPath(scan)/scan.hdd recover.bin # # Call is: scan2_runa proc scan2_runa {n} { # The termination condition is ignored, because the # histogram server controls the acquisition duration # directly in this case. scan2 run $n timer 0 } Publish scan2_runa User # # Call is: scan2_runb proc scan2_runb {n count_method count_size count_stop} { # Commit the termination conditions to the histogram server. # hmm configure stores the values in the dictionary, # then hmm init causes them to be sent to the histogram server. # We just 'assume' they are successfully written. hmm configure FAT_COUNT_METHOD $count_method hmm configure FAT_COUNT_SIZE $count_size hmm configure FAT_COUNT_STOP $count_stop hmm init # The termination condition is ignored, because the # histogram server controls the acquisition duration # directly in this case. So, use 'timer 0' here. scan2 run $n timer 0 } Publish scan2_runb User # Simulated counter. No error rate. Required for technical reasons... # This counter is used only to block execution till the bm count is actually reached, # for the scan example using hmc and bm objects to control the acquisition duration from SICS. MakeCounter blockctr SIM -1.0 blockctr SetExponent 0 blockctr SetMode timer blockctr SetPreset 0 # Later on we can add some motors to drive... #Motor som2 ASIM 0 100 -1.0 0.01 #hmscan add som2 0 1 ############################################## # Support for using expanded histogram period # to create interlaced/overlapped histograms ############################################## # Define an OAT offset variable to use with both scans: # It is possible to effectively offset the histogram filler's # OAT table by an arbitrary amount. For overlapped data acquisitions, we can # configure an oversized histogram period using the EXPAND_OAT parameters # in the FAT. Then at each scan stop, before acqisition commences the offset # can be adjusted using the OFFSET_OAT paramters of the FAT. By progressively # stepping the OFFSET_OAT, an overlapped image can be built up. # The global variable oatoffset is defined for this purpose. # During the scan, this variable is incremented and can be passed # in to an argument of set_oat_offset to provide progressively # increasing offset, producing an overlapped histogram. # global oatoffset # #Function to apply OAT offsets to the histogram server. proc set_oat_offset {oatoff_x oatoff_y oatoff_t} { hmm configure FAT_OFFSET_OAT_X $oatoff_x hmm configure FAT_OFFSET_OAT_Y $oatoff_y hmm configure FAT_OFFSET_OAT_T $oatoff_t hmm init return } Publish set_oat_offset User ############################################## # Support for data acquisition ############################################## # A simple procedure to read the histogram data through SICS # and dump the data to a numbered file. proc savehistodata {histomem filename} { set fh [open $filename "w"] # To get the whole memory, we don't need to specify the start or end arguments. # But we need to specify the bank number, this sets the type of data to be read. # set histodata [$histomem get [hmmdictitemval $histomem bank]] # clientput $histodata value puts -nonewline $fh $histodata close $fh return } ############################################## ############################################## ## Scan Callback Procedures ## ############################################## ############################################## # The prepare callback gets called at the start of the scan. # We use it to pause the histogram server, in order to commence the DAQ. # This 'primes' the DAE also (i.e. device drivers reboot the hardware, # buffering processes are started, etc.) proc hs_prepare {scanobjectname userobjectname} { #clientput "Enter prepare" value # # Before configuring the bm, do a short count. # This will cause the counter to reconnect if it needs to... bm count 0 timer # Now configure the beam monitor counter for better performance. # (Set a high counter sample rate to get better accuracy). bm send set scan=1 bm send set sample=1000 # Make sure the histogram server is stopped, this guarantees DAQ not in progress already. hmm stop # Zero the OAT offsets (whether used or not). global oatoffset set oatoffset 0 set_oat_offset 0 0 0 # stdscan prepare $scanobjectname $userobjectname #clientput "hmm pause being done..." value # Pause the histogram server, this primes the DAE for acqisition. hmm pause #clientput "Exit prepare" value return } Publish hs_prepare User # The count_bm_controlled callback gets called at the start of dataset acquisition. # We use it to perform the dataset acquisition, via the hmc object. # Note we do NOT call stdscan count, since we don't need to run the bm counter twice. proc hs_count_bm_controlled {scanobjectname userobjectname point mode preset} { #clientput "Enter count" value #stdscan count $scanobjectname $userobjectname $point $mode $preset # Start the acquisition, runs till the beam monitor terminates # and then enter paused mode (we have added fifth argument to allow this). # In fact, execution proceeds immediately (the hmc call doesn't block). hmc start $preset $mode pause # Now call the simulated counter. This will cause execution to block # till the hmc acquisition actually finishes. Otherwise, execution will # charge on regardless and the finish callback function gets called # before the last dataset acquisition has finished! blockctr count 0 #clientput "Exit count" value return } Publish hs_count_bm_controlled User # The count_hs_controlled callback gets called at the start of dataset acquisition. # We use it to perform the dataset acquisition, controlled by the histogram server. # Note we do NOT call stdscan count, since we don't need to run the bm counter twice. proc hs_count_hs_controlled {scanobjectname userobjectname point mode preset} { #clientput "Enter count" value #stdscan count $scanobjectname $userobjectname $point $mode $preset # Start the acquisition, runs till the histogram server auto-terminates. # This is done by specifying the termination object to be the histogram server, # not the counter object (place a 1 in 6th argument to hmc object). # The termination condition for the bm counter is just set to a large time period. # After the acquisition terminates, the beam monitor therefore has the correct # status reading and the 'Monitor' entry in the scan data table will be correct. hmc start 1000000000 timer pause 1 # Now call the simulated counter. This will cause execution to block # till the hmc acquisition actually finishes. Otherwise, execution will # charge on regardless and the finish callback function gets called # before the last dataset acquisition has finished! blockctr count 0 #clientput "Exit count" value return } Publish hs_count_hs_controlled User # The collect callback gets called at the end of the dataset acquisition. # We can put stuff here to retrieve data collected at each scan point, # and set up OAT offsets or other parameters that might need to be varied # from point to point at the histogram server, ready for the next scan point. # In this example, an increasing oatoffset variable is used to configure # the histogram server's OAT offset in the x direction, to produce # an overlapped histogram period acquisition. # Other things might be done here including adjustment of termination # condition based on beam monitor count. # Code for adjusting ancillaries, moving secondary motion stages etc. etc. # from point to point should probably be put into a drive callback function # (but not in this example script). proc hs_collect {scanobjectname userobjectname point} { #clientput "Enter collect" value set rslt [stdscan collect $scanobjectname $userobjectname $point] # Apply an OAT offset in the x direction (e.g. along tube number axis). global oatoffset incr oatoffset set_oat_offset $oatoffset 0 0 # Checking the beam monitor #clientput [bm send read] value # At each scan point, read the total x-y histogram # ans save it. This gets cleared at the start of # each dataset (when restarting from paused state), # so it represents the hstogram acquired per scan point. #clientput "Exit collect" value return } Publish hs_collect User # The finish callback gets called at the end of the scan. # We use it to stop the histogram server, terminating the dataset. proc hs_finish {scanobjectname userobjectname} { #clientput "Enter finish" value stdscan finish $scanobjectname $userobjectname #clientput "hmm stop being done..." value hmm stop # Just in case someone expects zero OAT offsets later on ;) set_oat_offset 0 0 0 # Get and write the data from the main histogram to disk (filename "HistoData"). # Sicne this is the first (and only) access to hmm data, it is retrieved from # the server and we don't need to do hmm init first to force update hmm memory. # hmm init savehistodata hmm "../data/HistoData" # #clientput "Exit finish" value return } Publish hs_finish User # Configure script mode, then we can configure all the scan callbacks. # The scan list command can be used to check that the callbacks # are properly defined. # A different count callback is defined in the two cases. # hmscan configure script #hmscan function prepare hs_prepare hmscan function count hs_count_bm_controlled hmscan function collect hs_collect hmscan function finish hs_finish # scan2 configure script #scan2 function prepare hs_prepare scan2 function count hs_count_hs_controlled scan2 function collect hs_collect scan2 function finish hs_finish # # That's all, folks...