#pragma TextEncoding = "UTF-8" #pragma rtGlobals=3 // Use modern global access method and strict wave access. #pragma IgorVersion = 6.35 #pragma ModuleName = PearlScientaLive #include "pearl-area-display" // Copyright (c) 2019 Paul Scherrer Institut // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 /// @file /// @brief utility functions for operating the Scienta analyser. /// @ingroup ArpesPackage /// /// this procedure contains various utility functions for working with the Scienta analyser, e.g. /// /// - statistical analysis of true count rates /// - estimate energy and angle resolution /// /// @author matthias muntwiler, matthias.muntwiler@psi.ch /// /// @copyright 2019 Paul Scherrer Institut @n /// Licensed under the Apache License, Version 2.0 (the "License"); @n /// you may not use this file except in compliance with the License. @n /// You may obtain a copy of the License at /// http://www.apache.org/licenses/LICENSE-2.0 /// @namespace PearlScientaLive /// @brief utility functions for operating the Scienta analyser. /// /// PearlScientaLive is declared in @ref pearl-scienta-live.ipf. /// open live display of most recent scienta measurement /// /// /// @param epicsname base name of the detector, e.g. X03DA-SCIENTA: /// image1: and cam1: are appended by the function. /// see @ref ad_connect. /// @param nickname nick name under which this detector is referred to in Igor. /// must be a valid data folder name. /// see @ref ad_connect. /// @param wbRGB window background color, e.g. "32768,49152,55296" /// function ScientaLiveDisplay(epicsname, nickname, wbRGB) string epicsname string nickname string wbRGB ad_connect(epicsname, nickname) string df_name sprintf df_name, "ad_display_profiles(root:pearl_epics:%s)", nickname dfref df = $df_name wave /sdfr=df img = image string graphname = ad_display(img) wbRGB = replacestring("(", wbRGB, "") wbRGB = replacestring(")", wbRGB, "") variable rr = str2num(StringFromList(0, wbRGB, ",")) variable gg = str2num(StringFromList(1, wbRGB, ",")) variable bb = str2num(StringFromList(2, wbRGB, ",")) ModifyGraph /w=$graphname wbRGB=(rr,gg,bb) add_roi_controls() ad_add_overlay(img) end #if igorVersion() >= 8 /// check exposure and calculate overexposure indicator mask /// /// calculate the local count rate density and return a mask /// to indicate where the maximum count rate is exceeded. /// the raw image is filtered by FFT with a gaussian kernel. /// /// the raw image must have been acquired in fixed mode. /// slicing and dwell time are accounted for. /// /// all intermediate waves are created ad-hoc as free waves. /// this function requires igor 8. /// /// @param[i] image raw image from scienta in fixed mode. /// /// @param[o] outmask mask wave. /// must have same dimensions as image. /// suggested data type /b/u. /// the mask value in overexposed regions is 0, /// in regular regions 64. /// /// @param[i] dwelltime in seconds. /// function check_exposure(image, outmask, dwelltime) wave image wave outmask variable dwelltime variable xbin = 1 variable ybin = 902 / dimsize(image, 1) variable thresh = 1e5 / 900 / 900 duplicate /free image, filt setscale /p x -dimsize(image, 0)/2, 1, "", filt // energy setscale /p y -dimsize(image, 1)/2, 1, "", filt // angle variable wx = sqrt(500) / xbin variable wy = sqrt(500) / ybin filt = exp(-((x/wx)^2 + (y/wy)^2)) variable nfilt = sum(filt) filt /= nfilt fft /free /dest=filt_fft filt duplicate /free image, img img /= dwelltime setscale /p x -dimsize(image, 0)/2, 1, "", img setscale /p y -dimsize(image, 1)/2, 1, "", img fft /free /dest=img_fft img img_fft *= filt_fft ifft /free /dest=img_ifft img_fft imagetransform swap img_ifft outmask = (img_ifft < thresh) * 64 end #endif /// optimized check exposure and calculate overexposure indicator mask /// /// calculate the local count rate density and return a mask /// to indicate where the maximum count rate is exceeded. /// the raw image is filtered by FFT with a gaussian kernel. /// /// the raw image must have been acquired in fixed mode. /// slicing and dwell time are accounted for. /// /// this function does the same as check_exposure() /// but keeps intermediate waves for time-optimized processing. /// moreover it is compatible with igor 6. /// /// @param[i] image raw image from scienta in fixed mode. /// /// @param[o] outmask mask wave. /// must have same dimensions as image. /// suggested data type /b/u. /// the mask value in overexposed regions is 0, in regular regions 64. /// /// @param[i] dwelltime in seconds. /// /// @param[i] calc_df (optional) data folder reference where intermediate and cached waves should be stored. /// by default, the data folder is named "psc_" plus the name of the image wave /// and inserted in the folder where the image wave is stored. /// /// the possible gain can be estimated from the following test data: /// - total execution time 510 ms /// - gain from re-using (but recalculating) waves: 20 ms /// - gain from re-using co_filt_fft: 220 ms /// function check_exposure_opt(image, outmask, dwelltime, [calc_df]) wave image wave outmask variable dwelltime dfref calc_df variable xbin = 1 variable ybin = 902 / dimsize(image, 1) variable thresh = 1e5 / 900 / 900 dfref save_df = GetDataFolderDFR() if (ParamIsDefault(calc_df)) dfref source_df = GetWavesDataFolderDFR(image) string calc_df_name = PearlCleanupName("psc_" + NameOfWave(image)) dfref calc_df = source_df:$calc_df_name endif NewDataFolder /o /s calc_df wave /z co_filt wave /z /c co_filt_fft wave /z co_img wave /z /c co_img_fft wave /z co_img_ifft nvar /z co_img_size_x nvar /z co_img_size_y variable cache = 0 if (waveexists(co_filt)) cache = (dimsize(image, 0) == co_img_size_x) && (dimsize(image, 1) == co_img_size_y) if (!cache) redimension /n=(dimsize(image, 0), dimsize(image, 1)) co_filt, co_filt_fft, co_img, co_img_fft, co_img_ifft endif else duplicate /o image, co_filt, co_img, co_img_ifft make /n=(dimsize(image, 0), dimsize(image, 1)) /c co_filt_fft, co_img_fft variable /g co_img_size_x variable /g co_img_size_y endif co_img_size_x = dimsize(image, 0) co_img_size_y = dimsize(image, 1) setscale /p x -co_img_size_x/2, 1, "", co_filt, co_filt_fft, co_img, co_img_fft, co_img_ifft setscale /p y -co_img_size_y/2, 1, "", co_filt, co_filt_fft, co_img, co_img_fft, co_img_ifft if (!cache) variable wx = sqrt(500) / xbin variable wy = sqrt(500) / ybin co_filt = exp(-((x/wx)^2 + (y/wy)^2)) variable nfilt = sum(co_filt) co_filt /= nfilt fft /dest=co_filt_fft co_filt endif co_img /= dwelltime fft /dest=co_img_fft co_img co_img_fft *= co_filt_fft ifft /dest=co_img_ifft co_img_fft imagetransform swap co_img_ifft redimension /n=(dimsize(co_img_ifft, 0), dimsize(co_img_ifft, 1)) outmask outmask = (co_img_ifft < thresh) * 64 SetDataFolder save_df end /// calculate the energy resolution of the analyser /// /// @param epass pass energy in eV /// @param slit analyser entrance slit in mm /// /// @return energy resolution (FWHM) function analyser_energy_resolution(epass, slit) variable epass variable slit variable respow if (epass < 4) respow = 1110 elseif (epass < 8) respow = 1400 else respow = 1750 endif return epass * max(0.2, slit) / 0.2 / respow end