diff --git a/pearl/pearl-anglescan-process-test.ipf b/pearl/pearl-anglescan-process-test.ipf deleted file mode 100644 index e7d0a14..0000000 --- a/pearl/pearl-anglescan-process-test.ipf +++ /dev/null @@ -1,80 +0,0 @@ -#pragma rtGlobals=3 // Use modern global access method and strict wave access. -#pragma IgorVersion = 6.1 -#pragma ModuleName = PearlAnglescanProcessTest -#pragma version = 1.0 - -#include "pearl-anglescan-process" -#include "unit-testing" - -// test suite for pearl-anglescan-process.ipf - -// unit testing framework: http://www.igorexchange.com/project/unitTesting -// run all test cases with RunTest("pearl-anglescan-process.ipf") -// if wave equalities fail, EnableDebugOutput() and read Igor help on equalWaves(). - -// created: matthias.muntwiler@psi.ch, 2013-11-18 -// Copyright (c) 2013 Paul Scherrer Institut -// $Id$ - -static function test_convert_angles_ttpa() - // function parameters - variable ntests = 3 - make /n=(ntests)/d/free i_theta, i_tilt, i_phi - make /n=3/d/free i_ana - make /n=1/d/free o_polar, o_azi - i_theta = {0, 90, 90} - i_tilt = {0, 0, 0} - i_phi = {0, 0, 10} - i_ana = {-30, 0, +30} - - make /n=(3,ntests)/d/free e_polar, e_azi - e_polar[][0] = {30, 0, 30} - e_azi[][0] = {-90, 0, 90} // 180, 90, 0 - - e_polar[][1] = {90, 90, 90} - e_azi[][1] = {-30, 0, +30} - - e_polar[][2] = {90, 90, 90} - e_azi[][2] = {-20, 10, +40} - - variable phi0 = 0 - e_azi += phi0 - - convert_angles_ttpa2polar(i_theta, i_tilt, i_phi, i_ana, o_polar, o_azi) - - - CHECK_EQUAL_WAVES(o_polar, e_polar, tol=0.001) - CHECK_EQUAL_WAVES(o_azi, e_azi, tol=0.001) - - nvar /z errors = root:packages:unittesting:error_count - if ((nvar_exists(errors)) && (errors > 0)) - print o_azi - print e_azi - endif -end - -static function test_hist_hemi_aziscan() - CHECK_EMPTY_FOLDER() - - make /n=360/d/free value, azi - azi = p - value = 1 - variable polar = 45 // dphi = 2 - - make_hemi_grid(91, "") - wave w_index = index - wave w_nphis = nphis - wave w_dphi = dphi - wave w_values = values - wave w_azim = azim - wave w_polar = polar - - duplicate /free w_values, e_values - variable p1 = w_index[44] - variable p2 = w_index[45] - e_values = (p >= p1) && (p < p2) ? 1 : 0 - - hemi_add_aziscan("", value, polar, azi) - - CHECK_EQUAL_WAVES(w_values, e_values, tol=0.001) -end \ No newline at end of file diff --git a/pearl/pearl-anneal.ipf b/pearl/pearl-anneal.ipf deleted file mode 100644 index 717c57e..0000000 --- a/pearl/pearl-anneal.ipf +++ /dev/null @@ -1,1508 +0,0 @@ -#pragma rtGlobals=3 // Use modern global access method and strict wave access. -#pragma version = 0.1 -#pragma IgorVersion = 6.2 -#pragma ModuleName = PearlAnneal -#include "pearl-epics" - -/// @file -/// @brief ramp generator for sample annealing -/// -/// the ramp generator increases/decreases the heating power -/// according to piecewise target function defined by the user in a set of waves. -/// each row of these waves describes one ramp phase. -/// the rows are processed sequentially. -/// -/// target waves define when a ramp phase ends. -/// when a target is reached, the generator starts to process the next one. -/// the end point of the current phase will become the start point of the next phase. -/// -/// the power target is interpolated linearly between the start and end points of a phase. -/// the ramp speed is given by the difference of the target values of the previous and current phases, -/// and the duration of the phase. -/// the power target values must be filled and be greater or equal to zero. -/// -/// the temperature targets are kept constant. -/// once a temperature target has been reached, the phase ends. -/// temperature targets are not enforced. -/// the phase will end unconditionally when the power target is reached. -/// if you need to reach a temperature target, -/// make sure that the power target is high enough, and that the ramp is slow enough -/// so that the temperature is reached before the phase ends. -/// temperature targets can be disabled by entering NaN. -/// -/// limits are not enforced. -/// if a limit is exceeded, the ramp will pause (while the power remains at its last setting). -/// the ramp resumes when the value falls below the limit. -/// limit checking can be disabled by entering NaN. -/// limits remain constant during the phase. -/// -/// trips cause the ramp to stop, and the power to be turned off. -/// trip checking can be disabled by entering NaN. -/// trip values remain constant during the phase. -/// caution: do not rely on these trips for protection of equipment or the sample! -/// there may be a considerable lag between the occurrence of a trip condition -/// and the execution of a power reset! -/// either use a suitable hardware trip mechanism, or include an appropriate safety margin. -/// -/// @arg minutes: minimum duration of the ramp phase in minutes. -/// determines the ramping speed. -/// the phase may take longer if pressure or temperature limits are reached. -/// required, must be greater than zero except for the first phase. -/// @arg target_watts: power setpoint at the end of the phase. -/// required, must be greater or equal to zero. -/// @arg target_tempA: temperature target of Lakeshore channel A in Kelvin. -/// optional, specify NaN to disable. -/// @arg target_tempB: temperature target of Lakeshore channel B in Kelvin. -/// optional, specify NaN to disable. -/// @arg target_tempPy: temperature target of the pyrometer in Kelvin. -/// optional, specify NaN to disable. -/// @arg limit_pressure: vacuum pressure limit in mbar. -/// optional, specify NaN to disable. -/// @arg trip_tempA: trip temperature of sensor A in Kelvin. -/// optional, specify NaN to disable. -/// @arg trip_tempB: trip temperature of sensor B in Kelvin. -/// optional, specify NaN to disable. -/// @arg trip_tempPy: trip temperature of pyrometer in Kelvin. -/// optional, specify NaN to disable. -/// @arg trip_pressure: trip pressure in mbar. -/// optional, specify NaN to disable. -/// -/// at the beginning of the table, a row with the current setpoints (normally zero at the beginning of a ramp) and zero duration must be included. -/// note that the power supply will remain at its last setpoint after the ramp. -/// thus, the last row should bring the power supply to a safe end value, e.g. zero. -/// -/// @pre -/// run-time requirements for online mode at the beamline -/// * EPICS.XOP of Paul Scherrer Institut, version 0.3.0 (March 2015) or later, must be loaded. -/// * caRepeater.exe program (from EPICS distribution) must be running. -/// -/// @author matthias muntwiler, matthias.muntwiler@psi.ch -/// -/// @copyright 2015 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 PearlAnneal -/// @brief ramp generator for sample annealing -/// -/// PearlAnneal is declared in @ref pearl-anneal.ipf. -/// - -static strconstant package_name = "pearl_anneal" -static strconstant package_path = "root:packages:pearl_anneal:" -// semicolon-separated list of persistent variable, string, and wave names -static strconstant prefs_objects = "" - -static function AfterCompiledHook() - // initializes package data once when the procedure is first loaded - - dfref savedf = GetDataFolderDFR() - variable do_init = 1 - if (DataFolderExists(package_path)) - setdatafolder $(package_path) - nvar /z init_done - if (nvar_exists(init_done)) - if (init_done) - do_init = 0 - endif - endif - endif - - if (do_init) - init_package() - load_prefs() - setdatafolder $(package_path) - variable /g init_done = 1 - endif - - setdatafolder savedf - return 0 -end - -/// initialize the package data folder -/// -/// create the package data folder, and all necessary control and data objects. -/// reset all variables. -static function init_package() - dfref savedf = getdatafolderdfr() - setdatafolder root: - newdatafolder /o/s packages - newdatafolder /o/s $package_name - - // configuration (persistent) - string /g graphname = "graph_anneal_tracker" - string /g dataname = "anneal" - - // recently used (persistent) - - // recently used (volatile) - - // run-time variables (volatile) - string /g controls, monitors - variable /g psu_connected = 0 - variable /g ls_connected = 0 - variable /g pyro_connected = 0 - variable /g vac_connected = 0 - - // channel ID - variable /g chidSetVolts = 0 - variable /g chidGetVolts = 0 - variable /g chidSetAmps = 0 - variable /g chidGetAmps = 0 - variable /g chidGetWatts = 0 - variable /g chidSetOnOff = 0 - variable /g chidGetOnOff = 0 - variable /g chidStatCC = 0 - variable /g chidStatCV = 0 - variable /g chidGetRemote = 0 - - variable /g chidGetTempA = 0 - variable /g chidGetTempB = 0 - variable /g chidGetPyro1 = 0 - variable /g chidGetPyroQ = 0 - - variable /g chidGetPressure = 0 - - // current PV values - variable /g curGetVolts = 0 - variable /g curSetVolts = 0 - variable /g curGetAmps = 0 - variable /g curSetAmps = 0 - variable /g curGetWatts = 0 - variable /g curSetWatts = 0 - variable /g curGetOnOff = 0 - variable /g curStatCC = 0 - variable /g curStatCV = 0 - - variable /g curGetTempA = 0 - variable /g curGetTempB = 0 - variable /g curGetPyro1 = 0 - variable /g curGetPyroQ = 0 - - variable /g curGetPressure = 0 - - // current phase indicators - variable /g curTargetWatts = nan - variable /g curTargetTempA = nan - variable /g curTargetTempB = nan - variable /g curTargetTempPy = nan - variable /g curTripTempA = nan - variable /g curTripTempB = nan - variable /g curTripTempPy = nan - variable /g curLimitPressure = nan - variable /g curTripPressure = nan - variable /g curPhaseMinutes = 0 - - // chart control and data - make /n=500 /o recVolts, recAmps, recWatts, recTemp, recPressure, recMinutes - variable /g recPoint - variable /g recMinutesStart - recPoint = 0 - recMinutesStart = datetime / 60 - - // ramp status: 1 = running, 0.5 = paused, 0 = off - variable /g ramp_status - // index of the current ramp phase - variable /g ramp_phase - // ramping direction +1 = up, -1 = down - variable /g ramp_dir - // system time in minutes at the start of the current phase - variable /g minutes_start - // system time in minutes at the time of the previous step - variable /g minutes_previous - // status message for user - string /g ramp_message - - ann_new_ramp_table(edit_table=0) - - setdatafolder savedf -end - -static function save_prefs() - // saves persistent package data to the preferences file - dfref saveDF = GetDataFolderDFR() - - string fullPath = SpecialDirPath("Packages", 0, 0, 0) - fullPath += package_name - NewPath/O/C/Q tempPackagePrefsPath, fullPath - fullPath += ":preferences.pxp" - - SetDataFolder root:packages - SetDataFolder $package_name - SaveData /O /Q /J=prefs_objects fullPath - - KillPath/Z tempPackagePrefsPath - - SetDataFolder saveDF -end - -static function load_prefs() - // loads persistent package data from the preferences file - // the preferences file is an Igor packed experiment file in a special preferences folder - dfref saveDF = GetDataFolderDFR() - - variable result = -1 - setdatafolder root: - NewDataFolder /O/S packages - NewDataFolder /O/S $package_name - string fullPath = SpecialDirPath("Packages", 0, 0, 0) - fullPath += package_name - - GetFileFolderInfo /Q /Z fullPath - if (V_Flag == 0) // Disk directory exists? - fullPath += ":preferences.pxp" - GetFileFolderInfo /Q /Z fullPath - if (V_Flag == 0) // Preference file exist? - LoadData /O /R /Q fullPath - result = 0 - endif - endif - - SetDataFolder saveDF - return result -end - -/// save current ramp table -/// -/// WORK IN PROGRESS -static function save_ramp() - dfref saveDF = GetDataFolderDFR() - - SetDataFolder root:packages - SetDataFolder $package_name - - wave minutes - wave target_watts - wave target_tempA - wave target_tempB - wave target_tempPy - wave trip_tempA - wave trip_tempB - wave trip_tempPy - wave limit_pressure - wave trip_pressure - - Save /T /M="\r\n" /I minutes,target_watts,target_tempPy,target_tempB,target_tempA,limit_pressure,trip_tempPy,trip_tempB,trip_tempA,trip_pressure as "anneal-ramp.itx" - - SetDataFolder saveDF -end - -/// Igor sometimes crashes if the PVs are not disconnected when it quits -static function IgorQuitHook(app) - string app - epics_disconnect() -end - -/// connect to all required EPICS devices. -/// -/// can be called repeatedly. the function exits gracefully if connections are existing. -/// -/// @return zero if successful, non-zero if an error occurred -static function epics_connect() - dfref savedf = getdatafolderdfr() - setdatafolder $(package_path) - - nvar psu_connected - nvar ls_connected - nvar vac_connected - nvar pyro_connected - - if (!psu_connected) - epics_connect_psu() - endif - if (!ls_connected) - epics_connect_ls() - endif - if (!vac_connected) - epics_connect_vac() - endif - if (!pyro_connected) - epics_connect_pyro() - endif - - setdatafolder saveDF - return !(psu_connected && ls_connected && vac_connected && pyro_connected) -end - -/// connect to the power supply unit -/// -/// if the EPICS XOP is not loaded, the function does nothing. -/// if channels are not available, the function exits with an error code. -/// the run-time error status is reset. -/// -/// @return zero if successful, non-zero if an error occurred -/// -/// @todo the X03DA channel names are hard-coded. -static function epics_connect_psu() - dfref savedf = getdatafolderdfr() - setdatafolder $(package_path) - - // create variables and waves - nvar connected = psu_connected - svar ramp_message - - // channel ID variables - nvar chidSetVolts - nvar chidGetVolts - nvar chidSetAmps - nvar chidGetAmps - nvar chidGetWatts - nvar chidSetOnOff - nvar chidGetOnOff - nvar chidStatCC - nvar chidStatCV - nvar chidGetRemote - - nvar curGetVolts - nvar curGetAmps - nvar curGetWatts - nvar curGetOnOff - nvar curStatCC - nvar curStatCV - - string psu_name = "X03DA-PSU-XP:" - variable timeout = 5 // seconds - - #if exists("pvWait") - // EPICS.XOP version 0.3.0 or later - pvOpen /Q chidSetVolts, psu_name + "SETVOLTS" - pvOpen /Q chidGetVolts, psu_name + "GETVOLTS" - pvOpen /Q chidSetAmps, psu_name + "SETCUR" - pvOpen /Q chidGetAmps, psu_name + "GETCUR" - pvOpen /Q chidGetWatts, psu_name + "CALCPWR" - pvOpen /Q chidSetOnOff, psu_name + "SETONOFF" - pvOpen /Q chidGetOnOff, psu_name + "GETONOFF" - pvOpen /Q chidGetRemote, psu_name + "COMGETRMT" // string - pvOpen /Q chidStatCC, psu_name + "STAT-CC" - pvOpen /Q chidStatCV, psu_name + "STAT-CV" - - pvWait timeout - #endif - - if (GetRTError(1)) - connected = 0 - ramp_message = "PSU: no connection" - else - connected = 1 - endif - - #if exists("pvMonitor") - if (connected) - pvMonitor chidGetVolts, curGetVolts - pvMonitor chidSetVolts, curSetVolts - pvMonitor chidGetAmps, curGetAmps - pvMonitor chidSetAmps, curSetAmps - pvMonitor chidGetWatts, curGetWatts - pvMonitor chidGetOnOff, curGetOnOff - pvMonitor chidStatCC, curStatCC - pvMonitor chidStatCV, curStatCV - endif - #endif - - setdatafolder saveDF - return !connected -end - -/// connect to the lakeshore temperature controller -/// -/// if the EPICS XOP is not loaded, the function does nothing. -/// if channels are not available, the function exits with an error code. -/// the run-time error status is reset. -/// -/// @return zero if successful, non-zero if an error occurred -/// -/// @todo the X03DA channel names are hard-coded. -static function epics_connect_ls() - dfref savedf = getdatafolderdfr() - setdatafolder $(package_path) - - nvar connected = ls_connected - svar ramp_message - - nvar chidGetTempA - nvar chidGetTempB - - nvar curGetTempA - nvar curGetTempB - - string base_name = "X03DA-PC-LAKESHOREXP:" - variable timeout = 5 // seconds - - #if exists("pvWait") - // EPICS.XOP version 0.3.0 or later - pvOpen /Q chidGetTempA, base_name + "A-TEMP_RBV" - pvOpen /Q chidGetTempB, base_name + "B-TEMP_RBV" - - pvWait timeout - #endif - - if (GetRTError(1)) - connected = 0 - ramp_message = "Lakeshore: no connection" - else - connected = 1 - endif - - #if exists("pvMonitor") - if (connected) - pvMonitor /F=ann_callback_ls chidGetTempA, curGetTempA - pvMonitor /F=ann_callback_ls chidGetTempB, curGetTempB - endif - #endif - - setdatafolder saveDF - return !connected -end - -/// connect to the vacuum gauge -/// -/// if the EPICS XOP is not loaded, the function does nothing. -/// if channels are not available, the function exits with an error code. -/// the run-time error status is reset. -/// -/// @return zero if successful, non-zero if an error occurred -/// -/// @todo the X03DA channel names are hard-coded. -static function epics_connect_vac() - dfref savedf = getdatafolderdfr() - setdatafolder $(package_path) - - nvar connected = vac_connected - svar ramp_message - - nvar chidGetPressure - - nvar curGetPressure - - string base_name = "X03DA-PVC-XP:" - variable timeout = 5 // seconds - - #if exists("pvWait") - // EPICS.XOP version 0.3.0 or later - pvOpen /Q chidGetPressure, base_name + "IG-PRESSURE" - - pvWait timeout - #endif - - if (GetRTError(1)) - connected = 0 - ramp_message = "vacuum gauge: no connection" - else - connected = 1 - endif - - #if exists("pvMonitor") - if (connected) - pvMonitor /F=ann_callback_pvc chidGetPressure, curGetPressure - endif - #endif - - setdatafolder saveDF - return !connected -end - -/// connect to the pyrometer -/// -/// if the EPICS XOP is not loaded, the function does nothing. -/// if channels are not available, the function exits with an error code. -/// the run-time error status is reset. -/// -/// @return zero if successful, non-zero if an error occurred -/// -/// @todo the X03DA channel names are hard-coded. -/// -/// IOC implemented in LabView -/// X03DA-LV-MAURER:TEMP-1 -/// X03DA-LV-MAURER:TEMP-Q -static function epics_connect_pyro() - dfref savedf = getdatafolderdfr() - setdatafolder $(package_path) - - nvar connected = pyro_connected - svar ramp_message - - nvar chidGetPyro1 - nvar chidGetPyroQ - - nvar curGetPyro1 - nvar curGetPyroQ - - string base_name = "X03DA-LV-MAURER:" - variable timeout = 5 // seconds - - #if exists("pvWait") - // EPICS.XOP version 0.3.0 or later - pvOpen /Q chidGetPyro1, base_name + "TEMP-1" - pvOpen /Q chidGetPyroQ, base_name + "TEMP-Q" - - pvWait timeout - #endif - - if (GetRTError(1)) - connected = 0 - ramp_message = "pyrometer: no connection" - else - connected = 1 - endif - - #if exists("pvMonitor") - if (connected) - pvMonitor /F=ann_callback_ls chidGetPyro1, curGetPyro1 - pvMonitor /F=ann_callback_ls chidGetPyroQ, curGetPyroQ - endif - #endif - - setdatafolder saveDF - return !connected -end - -static function epics_disconnect_chid(chid_var_name) - string chid_var_name - - #if exists("pvClose") - nvar /z chid = $chid_var_name - if (nvar_exists(chid)) - if (chid != 0) - pvClose chid - endif - chid = 0 - endif - #endif -end - -/// disconnect from all EPICS devices. -/// -static function epics_disconnect() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - epics_disconnect_psu() - epics_disconnect_ls() - epics_disconnect_vac() - epics_disconnect_pyro() - - setdatafolder savedf -end - -/// disconnect from the power supply unit -/// -static function epics_disconnect_psu() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - nvar connected = psu_connected - if (connected) - connected = 0 - epics_disconnect_chid("chidSetVolts") - epics_disconnect_chid("chidGetVolts") - epics_disconnect_chid("chidSetAmps") - epics_disconnect_chid("chidGetAmps") - epics_disconnect_chid("chidGetWatts") - epics_disconnect_chid("chidSetOnOff") - epics_disconnect_chid("chidGetOnOff") - epics_disconnect_chid("chidGetRemote") - epics_disconnect_chid("chidStatCC") - epics_disconnect_chid("chidStatCV") - endif - - setdatafolder savedf -end - -/// disconnect from the lakeshore controller -/// -static function epics_disconnect_ls() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - nvar connected = ls_connected - if (connected) - connected = 0 - - epics_disconnect_chid("chidGetTempA") - epics_disconnect_chid("chidGetTempB") - endif - - setdatafolder savedf -end - -/// disconnect from the vacuum gauge -/// -static function epics_disconnect_vac() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - nvar connected = vac_connected - if (connected) - connected = 0 - - epics_disconnect_chid("chidGetPressure") - endif - - setdatafolder savedf -end - -/// disconnect from the pyrometer -/// -static function epics_disconnect_pyro() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - nvar connected = pyro_connected - if (connected) - connected = 0 - - epics_disconnect_chid("chidGetPyro1") - epics_disconnect_chid("chidGetPyroQ") - endif - - setdatafolder savedf -end - -/// create a new ramp table and open it in a table window. -/// -/// the waves are created in the current data folder. -/// to be executed, they must be copied into the package folder. -/// -function ann_new_ramp_table([edit_table]) - variable edit_table - - if (ParamIsDefault(edit_table)) - edit_table = 1 - endif - - dfref savedf = GetDataFolderDFR() - - make /n=3 /o minutes,cum_minutes,target_watts - make /n=3 /o target_tempA, target_tempB, target_tempPy - make /n=3 /o limit_pressure - make /n=3 /o trip_tempA, trip_tempB, trip_tempPy - make /n=3 /o trip_pressure - make /n=3 /o est_temp - - minutes = 1 - cum_minutes = nan - target_watts[0] = {0, 5, 0} - target_tempA = nan - target_tempB = nan - target_tempPy = nan - limit_pressure = 1e-8 - trip_tempA = nan - trip_tempB = 450 - trip_tempPy = nan - trip_pressure = 5e-8 - est_temp = nan - - if (edit_table) - edit /k=1 minutes, target_watts - appendtotable target_tempA, trip_tempA - appendtotable target_tempB, trip_tempB - appendtotable target_tempPy, trip_tempPy - appendtotable limit_pressure,trip_pressure - endif - - setdatafolder savedf -end - -/// initialize the background tasks -/// -/// can be called repeatedly. the function exits gracefully if tasks are running. -/// -function ann_init_bg() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - CtrlNamedBackground ann_ramp, period = 60, proc = PearlAnneal#ann_ramp_bg - CtrlNamedBackground ann_record, period = 600, proc = PearlAnneal#ann_record_bg - - setdatafolder savedf -end - -/// background task of the recorder -static function ann_record_bg(s) - STRUCT WMBackgroundStruct &s - - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - nvar curGetVolts - nvar curGetAmps - nvar curGetWatts - nvar curGetOnOff - nvar curStatCC - nvar curStatCV - - nvar curGetTempA - nvar curGetTempB - nvar curGetPyro1 - nvar curGetPyroQ - - nvar curGetPressure - - nvar recPoint - nvar recMinutesStart - - wave recMinutes - wave recVolts - wave recAmps - wave recWatts - wave recTemp - wave recPressure - - variable nshift = 12 - variable plo - variable phi - - if (recPoint >= numpnts(recWatts)) - plo = 0 - phi = numpnts(recWatts) - nshift - 1 - recMinutes[plo, phi] = recMinutes[p + nshift] - recVolts[plo, phi] = recVolts[p + nshift] - recAmps[plo, phi] = recAmps[p + nshift] - recWatts[plo, phi] = recWatts[p + nshift] - recTemp[plo, phi] = recTemp[p + nshift] - recPressure[plo, phi] = recPressure[p + nshift] - - plo = numpnts(recWatts) - nshift - phi = numpnts(recWatts) - 1 - recMinutes[plo, phi] = nan - recVolts[plo, phi] = nan - recAmps[plo, phi] = nan - recWatts[plo, phi] = nan - recTemp[plo, phi] = nan - recPressure[plo, phi] = nan - - recPoint = plo - endif - - variable temp = curGetTempA - if (curGetPyroQ >= 625) - temp = max(temp, curGetPyroQ) - elseif (curGetPyro1 >= 625) - temp = max(temp, curGetPyro1) - endif - - recMinutes[recPoint] = datetime / 60 - recMinutesStart - recVolts[recPoint] = curGetVolts - recAmps[recPoint] = curGetAmps - recWatts[recPoint] = curGetWatts - recTemp[recPoint] = temp - recPressure[recPoint] = curGetPressure - - recPoint += 1 - - setdatafolder savedf - return 0 -End - -/// background task of the ramp -static function ann_ramp_bg(s) - STRUCT WMBackgroundStruct &s - - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - ann_ramp_step() - - setdatafolder savedf - return 0 -End - -/// prepare and execute the next ramp step -/// -/// check trips and limits before calling ann_ramp_step_exec() -/// -function ann_ramp_step() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - nvar minutes_start - nvar minutes_previous - nvar ramp_phase - svar ramp_message - - wave minutes - wave target_watts - - variable minutes_now = datetime / 60 - variable minutes_phase = minutes_now - minutes_start - variable minutes_step = minutes_now - minutes_previous - - variable trip - variable hold - variable phase_complete - - ann_ramp_update(ramp_phase) - // check trip conditions - trip = ann_ramp_trip(ramp_phase) - if (!trip) - // check hold conditions - hold = ann_ramp_hold(ramp_phase) - if (!hold) - // check targets - phase_complete = ann_ramp_target(ramp_phase) - if (!phase_complete) - // execute step - phase_complete = ann_ramp_step_exec(minutes_now) - ramp_message = "" - endif - if (phase_complete) - ramp_phase += 1 - minutes_start = minutes_now - // check end of ramp - if ((ramp_phase >= numpnts(minutes)) || (ramp_phase >= numpnts(target_watts)) || numtype(minutes[ramp_phase]) || numtype(target_watts[ramp_phase])) - ann_ramp_stop(0) - endif - endif - endif - endif - - minutes_previous = minutes_now - - setdatafolder savedf - return 0 -end - -/// update control panel variables -static function ann_ramp_update(phase) - variable phase - - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - wave minutes - wave target_watts - wave target_tempA - wave target_tempB - wave target_tempPy - wave trip_tempA - wave trip_tempB - wave trip_tempPy - wave limit_pressure - wave trip_pressure - - nvar curTargetWatts - nvar curTargetTempA - nvar curTargetTempB - nvar curTargetTempPy - nvar curTripTempA - nvar curTripTempB - nvar curTripTempPy - nvar curLimitPressure - nvar curTripPressure - nvar curPhaseMinutes - - curPhaseMinutes = minutes[phase] - curTargetWatts = target_watts[phase] - curTargetTempA = target_tempA[phase] - curTargetTempB = target_tempB[phase] - curTargetTempPy = target_tempPy[phase] - curTripTempA = trip_tempA[phase] - curTripTempB = trip_tempB[phase] - curTripTempPy = trip_tempPy[phase] - curLimitPressure = limit_pressure[phase] - curTripPressure = trip_pressure[phase] - - setdatafolder savedf -end - -/// execute the next ramp step -/// -/// calculate new setpoints and update the power supply setpoints. -/// no trips and limits checked in this function. -/// -/// @return zero during ramp phase, non-zero at end of ramp phase -static function ann_ramp_step_exec(minutes_now) - variable minutes_now - - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - nvar chidSetVolts - nvar chidSetAmps - - nvar curGetVolts - nvar curGetAmps - nvar curGetWatts - nvar curSetVolts - nvar curSetAmps - nvar curSetWatts - - nvar minutes_start - nvar minutes_previous - nvar ramp_phase - nvar ramp_dir - - variable p2 = ramp_phase - variable p1 = p2 - 1 - - variable minutes_phase = minutes_now - minutes_start - variable minutes_step = minutes_now - minutes_previous - - wave minutes - wave target_watts - - variable step_watts - variable next_volts - variable next_amps - variable next_watts - variable resistance - - variable max_step_volts = 0.5 - variable max_step_amps = 0.1 - variable max_test_volts = 5.0 - variable max_test_amps = 0.5 - - variable watts_complete - - // calculate power step - step_watts = (target_watts[p2] - target_watts[p1]) / minutes[p2] * minutes_step - next_watts = curSetWatts + step_watts - - // check end of ramp phase - if (step_watts > 0.0001) - watts_complete = next_watts > target_watts[p2] - elseif (step_watts < -0.0001) - watts_complete = next_watts < target_watts[p2] - else - watts_complete = minutes_phase >= minutes[p2] - endif - - // limit power - if (watts_complete) - next_watts = curSetWatts - else - next_watts = limit(next_watts, 0, max(target_watts[p1], target_watts[p2])) - endif - - // calculate voltage and current - if (next_watts >= 0.1) - curSetWatts = next_watts - if ((curGetVolts > 0.1) && (curGetAmps > 0.1)) - resistance = curGetVolts / curGetAmps - next_volts = limit(sqrt(next_watts * resistance), 0, curGetVolts + max_step_volts) - next_amps = limit(sqrt(next_watts / resistance), 0, curGetAmps + max_step_amps) - else - // apply small voltage to measure the resistance - next_volts = min(curSetVolts + 0.5, max_test_volts) - next_amps = min(curSetAmps + 0.1, max_test_amps) - endif - else - curSetWatts = next_watts - next_volts = 0 - next_amps = 0 - endif - - // change setpoints - pvPutNumber /Q chidSetVolts, next_volts - pvPutNumber /Q chidSetAmps, next_amps - pvWait 5 - - setdatafolder savedf - return watts_complete -end - -/// check trip conditions -/// -/// turn of power and stop the ramp if any of the trip conditions is met. -/// -/// @return non-zero if a trip condition is detected, zero if everything is okay. -static function ann_ramp_trip(phase) - variable phase - - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - variable trip = 0 - - wave trip_tempA - wave trip_tempB - wave trip_tempPy - wave trip_pressure - - nvar curGetTempA - nvar curGetTempB - nvar curGetTempPyro1 - nvar curGetTempPyroQ - nvar curGetPressure - svar ramp_message - - if ((phase < numpnts(trip_tempA)) && (numtype(trip_tempA[phase]) == 0) && (curGetTempA >= trip_tempA[phase])) - ramp_message = "temperature A trip" - trip = 1 - endif - if ((phase < numpnts(trip_tempB)) && (numtype(trip_tempB[phase]) == 0) && (curGetTempB >= trip_tempB[phase])) - ramp_message = "temperature B trip" - trip = 2 - endif - if ((phase < numpnts(trip_tempPy)) && (numtype(trip_tempPy[phase]) == 0) && (curGetTempPyro1 >= trip_tempPy[phase])) - ramp_message = "pyrometer trip (1)" - trip = 3 - endif - if ((phase < numpnts(trip_tempPy)) && (numtype(trip_tempPy[phase]) == 0) && (curGetTempPyroQ >= trip_tempPy[phase])) - ramp_message = "pyrometer trip (Q)" - trip = 4 - endif - if ((phase < numpnts(trip_pressure)) && (numtype(trip_pressure[phase]) == 0) && (curGetPressure >= trip_pressure[phase])) - ramp_message = "pressure trip" - trip = 5 - endif - - if (trip) - ann_ramp_stop(1) - endif - - setdatafolder savedf - return trip -end - -/// check hold conditions -/// -/// @return non-zero if a hold condition is detected, zero if everything is okay. -/// -static function ann_ramp_hold(phase) - variable phase - - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - nvar curGetPressure - - variable hold = 0 - - wave limit_pressure - - if ((phase < numpnts(limit_pressure)) && (numtype(limit_pressure[phase]) == 0) && (curGetPressure >= limit_pressure[phase])) - hold = 5 - endif - - setdatafolder savedf - return hold -end - -/// check target conditions -/// -/// @return non-zero if a target reached, zero otherwise. -static function ann_ramp_target(phase) - variable phase - - if (phase < 1) - return 0 - endif - - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - variable target = 0 - - wave target_watts - wave target_tempA - wave target_tempB - wave target_tempPy - - variable direction_up = target_watts[phase] >= target_watts[phase - 1] - - nvar curGetTempA - nvar curGetTempB - nvar curGetTempPyro1 - nvar curGetTempPyroQ - svar ramp_message - - if ((phase < numpnts(target_tempA)) && (numtype(target_tempA[phase]) == 0)) - if (direction_up) - if (curGetTempA >= target_tempA[phase]) - target = 1 - endif - else - if (curGetTempA <= target_tempA[phase]) - target = 1 - endif - endif - endif - - if ((phase < numpnts(target_tempB)) && (numtype(target_tempB[phase]) == 0)) - if (direction_up) - if (curGetTempB >= target_tempB[phase]) - target = 2 - endif - else - if (curGetTempB <= target_tempB[phase]) - target = 2 - endif - endif - endif - - if ((phase < numpnts(target_tempPy)) && (numtype(target_tempPy[phase]) == 0)) - if (direction_up) - if (curGetTempPyro1 >= target_tempPy[phase]) - target = 3 - endif - else - if (curGetTempPyro1 <= target_tempPy[phase]) - target = 3 - endif - endif - endif - - if ((phase < numpnts(target_tempPy)) && (numtype(target_tempPy[phase]) == 0)) - if (direction_up) - if (curGetTempPyroQ >= target_tempPy[phase]) - target = 4 - endif - else - if (curGetTempPyroQ <= target_tempPy[phase]) - target = 4 - endif - endif - endif - - switch(target) - case 1: - ramp_message = "temperature A target reached" - break - case 2: - ramp_message = "temperature B target reached" - break - case 3: - ramp_message = "pyrometer 1 target reached" - break - case 4: - ramp_message = "pyrometer Q target reached" - break - endswitch - - setdatafolder savedf - return target -end - -/// start an annealing ramp -function ann_ramp_start() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - epics_connect() - - nvar recPoint - nvar recMinutesStart - recPoint = 0 - recMinutesStart = datetime / 60 - - wave recMinutes - wave recVolts - wave recAmps - wave recWatts - wave recTemp - wave recPressure - - recMinutes = nan - recVolts = nan - recAmps = nan - recWatts = nan - recTemp = nan - recPressure = nan - - nvar minutes_start - minutes_start = datetime / 60 - nvar minutes_previous - minutes_previous = minutes_start - nvar ramp_phase - ramp_phase = 1 - nvar ramp_status - ramp_status = 1 - - nvar chidSetVolts - nvar chidSetAmps - nvar chidSetOnOff - - wave target_watts - - pvPutNumber /Q chidSetVolts, 0.5 - pvPutNumber /Q chidSetAmps, 0.5 - pvPutNumber /Q chidSetOnOff, 0 - pvWait 5 - - nvar curSetWatts - curSetWatts = target_watts[0] - - ann_init_bg() - CtrlNamedBackground ann_ramp, start - CtrlNamedBackground ann_record, start - - setdatafolder savedf - return 0 -end - -function ann_ramp_pause() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - CtrlNamedBackground ann_ramp, stop - - nvar ramp_status - ramp_status = 0.5 - - setdatafolder savedf - return 0 -end - -function ann_ramp_resume() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - CtrlNamedBackground ann_ramp, start - - nvar ramp_status - ramp_status = 1 - - setdatafolder savedf - return 0 -end - -/// stop a running annealing ramp -/// -/// @param reset_psu 1 = turn off the power supply, 0 = do not change the power supply -/// the power supply is also turned off if the current target power is below 1 W. -function ann_ramp_stop(reset_psu) - variable reset_psu - - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - CtrlNamedBackground ann_ramp, stop - CtrlNamedBackground ann_record, stop - - nvar ramp_phase - ramp_phase = 0 - nvar ramp_status - ramp_status = 0 - nvar curTargetWatts - - if (reset_psu || (curTargetWatts < 1)) - nvar chidSetVolts - nvar chidSetAmps - nvar chidSetOnOff - pvPutNumber /Q chidSetVolts, 0 - pvPutNumber /Q chidSetAmps, 0 - pvPutNumber /Q chidSetOnOff, 1 - pvWait 5 - endif - - setdatafolder savedf - return 0 -end - -function ann_display_ramp() - dfref savedf = GetDataFolderDFR() - setdatafolder $(package_path) - - wave recMinutes - wave recVolts - wave recAmps - wave recWatts - wave recTemp - wave recPressure - - display recWatts vs recMinutes - appendtograph /r recVolts vs recMinutes - appendtograph /r recAmps vs recMinutes -end - -Window panel_ramp_gen() : Panel - PauseUpdate; Silent 1 // building window... - NewPanel /K=1 /W=(441,64,887,702) as "ramp generator" - ValDisplay valdisp0,pos={11,178},size={233,42},bodyWidth=200,title="pyro 1" - ValDisplay valdisp0,limits={0,1500,625},barmisc={10,50} - ValDisplay valdisp0,value= #"root:packages:pearl_anneal:curGetPyro1" - ValDisplay valdisp1,pos={11,233},size={233,42},bodyWidth=200,title="pyro q" - ValDisplay valdisp1,limits={0,1500,625},barmisc={10,50} - ValDisplay valdisp1,value= #"root:packages:pearl_anneal:curGetPyroQ" - ValDisplay valdisp2,pos={11,73},size={234,42},bodyWidth=200,title="lake A" - ValDisplay valdisp2,limits={0,1500,300},barmisc={10,50} - ValDisplay valdisp2,value= #"root:packages:pearl_anneal:curGetTempA" - ValDisplay valdisp3,pos={10,128},size={234,42},bodyWidth=200,title="lake B" - ValDisplay valdisp3,limits={0,1500,300},barmisc={10,50} - ValDisplay valdisp3,value= #"root:packages:pearl_anneal:curGetTempB" - ValDisplay valdisp4,pos={16,23},size={229,42},bodyWidth=200,title="watts" - ValDisplay valdisp4,limits={0,90,0},barmisc={10,50} - ValDisplay valdisp4,value= #"root:packages:pearl_anneal:curGetWatts" - ValDisplay valdisp5,pos={6,5},size={60,14},title="phase" - ValDisplay valdisp5,limits={0,0,0},barmisc={0,1000} - ValDisplay valdisp5,value= #"root:packages:pearl_anneal:ramp_phase" - ValDisplay valdisp6,pos={0,282},size={244,42},bodyWidth=200,title="pressure" - ValDisplay valdisp6,format="%.1e",limits={1e-09,1e-08,0},barmisc={10,80} - ValDisplay valdisp6,value= #"root:packages:pearl_anneal:curGetPressure" - ValDisplay valdisp7,pos={335,90},size={47,14},bodyWidth=14,title="power" - ValDisplay valdisp7,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (60928,60928,60928),lowColor= (0,52224,0),zeroColor= (61440,61440,61440) - ValDisplay valdisp7,value= #"root:packages:pearl_anneal:curGetOnOff" - ValDisplay valdisp16,pos={262,168},size={114,14},bodyWidth=34,title="target temp pyro" - ValDisplay valdisp16,limits={0,0,0},barmisc={0,1000},mode= 2,highColor= (60928,60928,60928),lowColor= (65280,0,0),zeroColor= (0,52224,0) - ValDisplay valdisp16,value= #"root:packages:pearl_anneal:curTargetTempPy" - ValDisplay valdisp17,pos={300,4},size={80,14},bodyWidth=14,title="power supply" - ValDisplay valdisp17,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440) - ValDisplay valdisp17,value= #"root:packages:pearl_anneal:psu_connected" - ValDisplay valdisp18,pos={317,21},size={64,14},bodyWidth=14,title="lakeshore" - ValDisplay valdisp18,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440) - ValDisplay valdisp18,value= #"root:packages:pearl_anneal:ls_connected" - ValDisplay valdisp19,pos={318,38},size={64,14},bodyWidth=14,title="pyrometer" - ValDisplay valdisp19,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440) - ValDisplay valdisp19,value= #"root:packages:pearl_anneal:pyro_connected" - ValDisplay valdisp20,pos={293,52},size={91,14},bodyWidth=14,title="vacuum system" - ValDisplay valdisp20,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440) - ValDisplay valdisp20,value= #"root:packages:pearl_anneal:vac_connected" - ValDisplay valdisp21,pos={341,76},size={41,14},bodyWidth=14,title="ramp" - ValDisplay valdisp21,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (61440,61440,61440),zeroColor= (0,34816,52224) - ValDisplay valdisp21,value= #"root:packages:pearl_anneal:ramp_status" - ValDisplay valdisp8,pos={278,120},size={100,14},title="target watts" - ValDisplay valdisp8,limits={0,0,0},barmisc={0,1000} - ValDisplay valdisp8,value= #"root:packages:pearl_anneal:curTargetWatts" - ValDisplay valdisp9,pos={278,137},size={100,14},title="target temp A" - ValDisplay valdisp9,limits={0,0,0},barmisc={0,1000} - ValDisplay valdisp9,value= #"root:packages:pearl_anneal:curTargetTempA" - ValDisplay valdisp10,pos={278,152},size={100,14},title="target temp B" - ValDisplay valdisp10,limits={0,0,0},barmisc={0,1000} - ValDisplay valdisp10,value= #"root:packages:pearl_anneal:curTargetTempB" - ValDisplay valdisp11,pos={271,266},size={100,14},title="limit pressure" - ValDisplay valdisp11,limits={0,0,0},barmisc={0,1000} - ValDisplay valdisp11,value= #"root:packages:pearl_anneal:curLimitPressure" - ValDisplay valdisp12,pos={261,205},size={100,14},title="trip temp A" - ValDisplay valdisp12,limits={0,0,0},barmisc={0,1000} - ValDisplay valdisp12,value= #"root:packages:pearl_anneal:curTripTempA" - ValDisplay valdisp13,pos={262,224},size={100,14},title="trip temp B" - ValDisplay valdisp13,limits={0,0,0},barmisc={0,1000} - ValDisplay valdisp13,value= #"root:packages:pearl_anneal:curTripTempB" - ValDisplay valdisp14,pos={276,242},size={100,14},title="trip pyro" - ValDisplay valdisp14,limits={0,0,0},barmisc={0,1000} - ValDisplay valdisp14,value= #"root:packages:pearl_anneal:curTripTempPy" - ValDisplay valdisp15,pos={273,309},size={100,14},title="ramp interval" - ValDisplay valdisp15,limits={0,0,0},barmisc={0,1000} - ValDisplay valdisp15,value= #"root:packages:pearl_anneal:curPhaseMinutes" - Button b_start,pos={15,362},size={50,20},proc=PearlAnneal#bp_ramp_start,title="start" - Button b_start,fColor=(0,52224,0) - Button b_pause,pos={75,362},size={50,20},proc=PearlAnneal#bp_ramp_pause,title="pause" - Button b_stop,pos={135,362},size={50,20},proc=PearlAnneal#bp_ramp_stop,title="stop" - Button b_stop,fColor=(52224,0,0) - Button b_edit,pos={195,362},size={50,20},proc=PearlAnneal#bp_ramp_edit,title="edit" - ValDisplay valdisp11_1,pos={274,282},size={100,14},title="trip pressure" - ValDisplay valdisp11_1,limits={0,0,0},barmisc={0,1000} - ValDisplay valdisp11_1,value= #"root:packages:pearl_anneal:curTripPressure" - TitleBox title0,pos={16,334},size={400,20} - TitleBox title0,variable= root:packages:pearl_anneal:ramp_message,fixedSize=1 - DefineGuide UGH0={FT,390} - String fldrSav0= GetDataFolder(1) - SetDataFolder root:packages:pearl_anneal: - Display/W=(82,153,246,462)/FG=(FL,UGH0,FR,FB)/HOST=# recTemp vs recMinutes - AppendToGraph/R recPressure vs recMinutes - AppendToGraph/L=power recWatts vs recMinutes - NewFreeAxis/O/L power - SetDataFolder fldrSav0 - ModifyGraph margin(left)=80 - ModifyGraph rgb(recPressure)=(0,0,65280),rgb(recWatts)=(0,39168,0) - ModifyGraph log(right)=1 - ModifyGraph mirror(bottom)=2 - ModifyGraph nticks=3 - ModifyGraph minor=1 - ModifyGraph axThick=0.5 - ModifyGraph axRGB(left)=(65280,0,0),axRGB(right)=(0,0,65280),axRGB(power)=(0,39168,0) - ModifyGraph tlblRGB(left)=(65280,0,0),tlblRGB(right)=(0,0,65280),tlblRGB(power)=(0,39168,0) - ModifyGraph alblRGB(left)=(65280,0,0),alblRGB(right)=(0,0,65280),alblRGB(power)=(0,39168,0) - ModifyGraph lblPos(left)=42,lblPos(power)=35 - ModifyGraph lblLatPos(left)=1 - ModifyGraph btLen=4 - ModifyGraph freePos(power)=48 - Label left "temperature (K)" - Label bottom "time (minutes)" - Label right "pressure (mbar)" - Label power "power (W)" - SetAxis/E=1 power 0,80 - RenameWindow #,G0 - SetActiveSubwindow ## -EndMacro - -static function bp_ramp_start(ba) : ButtonControl - struct WMButtonAction &ba - - switch( ba.eventCode ) - case 2: // mouse up - dfref ann_df = $(package_path) - nvar /sdfr=ann_df ramp_status - if (ramp_status < 0.4) - ann_ramp_start() - endif - break - case -1: // control being killed - break - endswitch - - return 0 -end - -static function bp_ramp_pause(ba) : ButtonControl - struct WMButtonAction &ba - - switch( ba.eventCode ) - case 2: // mouse up - dfref ann_df = $(package_path) - nvar /sdfr=ann_df ramp_status - if (ramp_status > 0.6) - ann_ramp_pause() - Button b_pause, win=$(ba.win), title="resume" - else - ann_ramp_resume() - Button b_pause, win=$(ba.win), title="pause" - endif - break - case -1: // control being killed - break - endswitch - - return 0 -end - -static function bp_ramp_stop(ba) : ButtonControl - struct WMButtonAction &ba - - switch( ba.eventCode ) - case 2: // mouse up - ann_ramp_stop(1) - break - case -1: // control being killed - break - endswitch - - return 0 -end - -static function bp_ramp_edit(ba) : ButtonControl - struct WMButtonAction &ba - - dfref savedf = GetDataFolderDFR() - switch( ba.eventCode ) - case 2: // mouse up - setdatafolder $(package_path) - - wave minutes - wave target_watts - wave target_tempA - wave target_tempB - wave target_tempPy - wave trip_tempA - wave trip_tempB - wave trip_tempPy - wave limit_pressure - wave trip_pressure - - edit /k=1 minutes, target_watts - appendtotable target_tempA, trip_tempA - appendtotable target_tempB, trip_tempB - appendtotable target_tempPy, trip_tempPy - appendtotable limit_pressure,trip_pressure - - break - case -1: // control being killed - break - endswitch - - setdatafolder savedf - return 0 -end diff --git a/pearl/pearl-area-live.ipf b/pearl/pearl-area-live.ipf deleted file mode 100644 index 3865f7e..0000000 --- a/pearl/pearl-area-live.ipf +++ /dev/null @@ -1,368 +0,0 @@ -#pragma rtGlobals=3 // Use modern global access method and strict wave access. -#pragma IgorVersion = 6.1 -#pragma ModuleName = PearlAreaLive -#pragma version = 1.03 -#include "pearl-epics", version >= 1.02 - -// preview panel for EPICS area detectors -// such as CCD cameras, 2D electron analysers -// the image is read from the NDPluginStdArrays plugin of the area detector -// make sure that plugin is enabled - -// created: matthias.muntwiler@psi.ch, 2013-05-29 -// $Id$ - -static strconstant package_name = "pearl_epics" -static strconstant package_path = "root:pearl_epics:" -// semicolon-separated list of persistent variable, string, and wave names -static strconstant prefs_objects = "" - -function ad_connect(epicsname, nickname) - // connects to the necessary EPICS channels of the detector - // to disconnect, call epics_disconnect() - // (caution: this will disconnect all EPICS channels of all PEARL EPICS procedures!) - string epicsname // base name of the detector, e.g. X03DA-SCIENTA: - // image1: and cam1: are appended by the function - string nickname // nick name under which this detector is referred to in Igor - // must be a valid data folder name - // the data folder is created under root:pearl_epics - - dfref savedf = GetDataFolderDFR() - setdatafolder root: - - // data folder for common EPICS metadata - newdatafolder /o/s $package_name - dfref epicsdf = GetDataFolderDFR() - string /g ad_chids - string /g ad_nicknames - - // data folder this detector - string foldername = nickname - newdatafolder /s/o $foldername - dfref detectordf = GetDataFolderDFR() - - // create variables and waves - make /n=(1)/o arraydata, xscale, yscale - make /n=(1,1)/o image - variable /g ndimensions - variable /g arraysize0, arraysize1 - variable /g datatype - variable /g colormode - string /g controls, monitors - string /g xunits, yunits - - print "connecting EPICS channels..." - - // channel lists - controls = "" - monitors = "" - string imagename = epicsname + "image1:" - string camname = epicsname + "cam1:" - - // we will set our own monitor on ArrayData, so add this to the controls list - controls = ReplaceStringByKey("ArrayData", controls, imagename + "ArrayData", "=") - // check whether it has been set already - variable chidArrayData = epics_chid(imagename + "ArrayData") - variable array_connected = chidArrayData > 0 - - monitors = ReplaceStringByKey("NDimensions", monitors, imagename + "NDimensions_RBV", "=") - monitors = ReplaceStringByKey("ArraySize0", monitors, imagename + "ArraySize0_RBV", "=") - monitors = ReplaceStringByKey("ArraySize1", monitors, imagename + "ArraySize1_RBV", "=") - monitors = ReplaceStringByKey("DataType", monitors, imagename + "DataType_RBV", "=") - monitors = ReplaceStringByKey("ColorMode", monitors, imagename + "ColorMode_RBV", "=") - monitors = ReplaceStringByKey("XScale", monitors, camname + "CHANNEL_SCALE_RBV", "=") - monitors = ReplaceStringByKey("YScale", monitors, camname + "SLICE_SCALE_RBV", "=") - - variable nroi = 4 - variable iroi - string roikey, roiname - for (iroi = 0; iroi < nroi; iroi += 1) - roikey = "ROI" + num2str(iroi + 1) - roiname = epicsname + "ROI" + num2str(iroi + 1) + ":" - - controls = ReplaceStringByKey(roikey + "Enable", controls, roiname + "EnableCallbacks", "=") - controls = ReplaceStringByKey(roikey + "EnableX", controls, roiname + "EnableX", "=") - controls = ReplaceStringByKey(roikey + "MinX", controls, roiname + "MinX", "=") - controls = ReplaceStringByKey(roikey + "SizeX", controls, roiname + "SizeX", "=") - controls = ReplaceStringByKey(roikey + "EnableY", controls, roiname + "EnableY", "=") - controls = ReplaceStringByKey(roikey + "MinY", controls, roiname + "MinY", "=") - controls = ReplaceStringByKey(roikey + "SizeY", controls, roiname + "SizeY", "=") - - monitors = ReplaceStringByKey(roikey + "Enable", monitors, roiname + "EnableCallbacks_RBV", "=") - monitors = ReplaceStringByKey(roikey + "EnableX", monitors, roiname + "EnableX_RBV", "=") - monitors = ReplaceStringByKey(roikey + "MinX", monitors, roiname + "MinX_RBV", "=") - monitors = ReplaceStringByKey(roikey + "SizeX", monitors, roiname + "SizeX_RBV", "=") - monitors = ReplaceStringByKey(roikey + "EnableY", monitors, roiname + "EnableY_RBV", "=") - monitors = ReplaceStringByKey(roikey + "MinY", monitors, roiname + "MinY_RBV", "=") - monitors = ReplaceStringByKey(roikey + "SizeY", monitors, roiname + "SizeY_RBV", "=") - endfor - - // connect EPICS channels - epics_connect(controls, monitors) - - // keep track of detector IDs - ad_nicknames = AddListItem(nickname, ad_nicknames) - variable iad = WhichListItem(nickname, ad_nicknames, ";", 0, 0) - ad_chids = AddListItem(num2istr(epics_chid(imagename + "ArrayData")), ad_chids, ";", iad) - - // set callback function - if (!array_connected) - pvMonitor /F=ad_live_callback epics_chid(imagename + "ArrayData") - endif - - print "...done" - setdatafolder savedf -end - -function ad_live_callback(chan) - variable chan - - dfref savedf = GetDataFolderDFR() - setdatafolder $package_path - - // find the data folder of the detector - svar ad_chids - svar ad_nicknames - variable iad = WhichListItem(num2istr(chan), ad_chids, ";", 0, 0) - if (iad >= 0) - string nickname = StringFromList(iad, ad_nicknames) - else - return -1 - endif - setdatafolder $nickname - - // retrieve data - svar controls - svar monitors - variable chidArrayData = epics_chid(StringByKey("ArrayData", controls, "=")) - variable chidNDimensions = epics_chid(StringByKey("NDimensions", monitors, "=")) - variable chidArraySize0 = epics_chid(StringByKey("ArraySize0", monitors, "=")) - variable chidArraySize1 = epics_chid(StringByKey("ArraySize1", monitors, "=")) - variable chidDataType = epics_chid(StringByKey("DataType", monitors, "=")) - variable chidColorMode = epics_chid(StringByKey("ColorMode", monitors, "=")) - variable chidXScale = epics_chid(StringByKey("XScale", monitors, "=")) - variable chidYScale = epics_chid(StringByKey("YScale", monitors, "=")) - - wave arraydata - wave image - nvar ndimensions - nvar arraysize0 - nvar arraysize1 - nvar datatype - nvar colormode - wave xscale - wave yscale - - pvGet chidNDimensions, ndimensions - pvGet chidArraySize0, arraysize0 - pvGet chidArraySize1, arraysize1 - pvGet chidDataType, datatype - pvGet chidColorMode, colormode - - // sanity checks - if (ndimensions != 2) - return -2 - endif - if (colormode != 0) - return -3 - endif - - redimension /n=(arraysize0 * arraysize1) arraydata - redimension /n=(arraysize0, arraysize1) image - redimension /n=(arraysize0) xscale - redimension /n=(arraysize1) yscale - - switch(datatype) - case 0: // int8 - redimension /b arraydata, image - break - case 1: // uint8 - redimension /b/u arraydata, image - break - case 2: // int16 - redimension /w arraydata, image - break - case 3: // uint16 - redimension /w/u arraydata, image - break - case 4: // int32 - redimension /i arraydata, image - break - case 5: // uint32 - redimension /i/u arraydata, image - break - case 6: // float32 - redimension /s arraydata, image - break - case 7: // float64 - redimension /d arraydata, image - break - endswitch - - pvGetWave chidArrayData, arraydata - pvGetWave chidXScale, xscale - pvGetWave chidYScale, yscale - - image = arraydata[p + q * arraysize0] - setscale /i x xscale[0], xscale[numpnts(xscale)-1], image - setscale /i y yscale[0], yscale[numpnts(yscale)-1], image - - ad_update_profiles(image) - - // update ROI rectangles - svar /z graphname = :view_image:prof_graphname - if (svar_exists(graphname)) - variable nroi = 4 - variable iroi - for (iroi = 0; iroi < nroi; iroi += 1) - ad_update_ROI(graphname, iroi) - endfor - endif - - setdatafolder savedf - return 0 -end - -static function ad_update_ROI(graphname, iroi) - string graphname - variable iroi - - string roikey - variable enable - svar monitors - - wave xscale - wave yscale - - variable enableX = 0 - variable minX = 0 - variable sizeX = numpnts(xscale) - - variable enableY = 0 - variable minY = 0 - variable sizeY = numpnts(yscale) - - roikey = "ROI" + num2str(iroi + 1) - enable = epics_get_num(StringByKey(roikey + "Enable", monitors, "=")) - if (enable) - enableX = epics_get_num(StringByKey(roikey + "EnableX", monitors, "=")) - if (enableX) - minX = epics_get_num(StringByKey(roikey + "MinX", monitors, "=")) - sizeX = epics_get_num(StringByKey(roikey + "SizeX", monitors, "=")) - endif - - enableY = epics_get_num(StringByKey(roikey + "EnableY", monitors, "=")) - if (enableY) - minY = epics_get_num(StringByKey(roikey + "MinY", monitors, "=")) - sizeY = epics_get_num(StringByKey(roikey + "SizeY", monitors, "=")) - endif - - variable x1 = xscale[minX] - variable x2 = xscale[minX + sizeX - 1] - variable y1 = yscale[minY] - variable y2 = yscale[minY + sizeY - 1] - endif - - ad_update_ROI_rect(graphname, iroi, x1, y1, x2, y2, enable) -end - -static function ad_update_ROI_rect(graphname, iroi, x1, y1, x2, y2, enable) - string graphname - variable iroi // 0...3 - variable x1,y1,x2,y2 - variable enable // enable = 1; disable = 0 - string roiname = "roi" + num2str(iroi + 1) - variable color = 65536 * (1 - iroi/8) - 1 - - if (enable) - DrawAction /w=$graphname getgroup=$roiname, delete, begininsert - SetDrawEnv /w=$graphname gstart,gname=$roiname - SetDrawEnv /w=$graphname xcoord= bottom,ycoord= left - SetDrawEnv /w=$graphname linefgc= (65535,color,color) - SetDrawEnv /w=$graphname fillpat= 0 - SetDrawEnv /w=$graphname linethick= 0.50 - DrawRect /w=$graphname x1,y1,x2,y2 - SetDrawEnv /w=$graphname gstop - DrawAction /w=$graphname endinsert - else - DrawAction /w=$graphname getgroup=$roiname, delete - endif -end - -function ad_set_ROI(nickname, iroi, p1, q1, p2, q2, enable) - // set a ROI rectangle to the given coordinates - string nickname - variable iroi // 0...3 - variable p1,q1,p2,q2 // rectangular coordinates of the new ROI (point scaling) - variable enable // enable = 1; disable = 0 - - string roiname = "roi" + num2str(iroi + 1) - string roikey - - dfref savedf = GetDataFolderDFR() - setdatafolder $package_path - setdatafolder $nickname - - svar controls - wave xscale - wave yscale - - variable minX = min(p1, p2) - variable sizeX = max(p1, p2) - min(p1, p2) + 1 - variable enableX = sizeX > 0 - variable minY = min(q1, q2) - variable sizeY = max(q1, q2) - min(q1, q2) + 1 - variable enableY = sizeY > 0 - - roikey = "ROI" + num2str(iroi + 1) - epics_set_num(StringByKey(roikey + "Enable", controls, "="), enable) - if (enable) - epics_set_num(StringByKey(roikey + "EnableX", controls, "="), enableX) - if (enableX) - epics_set_num(StringByKey(roikey + "MinX", controls, "="), minX) - epics_set_num(StringByKey(roikey + "SizeX", controls, "="), sizeX) - endif - - epics_set_num(StringByKey(roikey + "EnableY", controls, "="), enableY) - if (enableY) - epics_set_num(StringByKey(roikey + "MinY", controls, "="), minY) - epics_set_num(StringByKey(roikey + "SizeY", controls, "="), sizeY) - endif - endif - - svar graphname = :view_image:prof_graphname - ad_update_ROI(graphname, iroi) - - setdatafolder savedf -end - -function add_roi_controls() - PopupMenu pm_set_roi mode=0,value="ROI 1;ROI 2;ROI 3;ROI 4",title="Set ROI" - PopupMenu pm_set_roi pos={400,0},bodyWidth=60,proc=PearlAreaLive#pmp_set_roi - PopupMenu pm_set_roi help={"Set a detector ROI to the current cursor selection"} -end - - -static function pmp_set_roi(pa) : PopupMenuControl - STRUCT WMPopupAction &pa - - switch( pa.eventCode ) - case 2: // mouse up - variable popNum = pa.popNum - string imgname = StringFromList(0, ImageNameList(pa.win, ";")) - wave /z image = ImageNameToWaveRef(pa.win, imgname) - if (waveexists(image)) - wave /z source = PearlAreaDisplay#get_source_image(image) - if (waveexists(source)) - dfref sourcedf = GetWavesDataFolderDFR(source) - string nickname = GetDataFolder(0, sourcedf) - ad_set_ROI(nickname, popNum - 1, pcsr(A, pa.win), qcsr(A, pa.win), pcsr(B, pa.win), qcsr(B, pa.win), 1) - endif - endif - break - case -1: // control being killed - break - endswitch - - return 0 -End diff --git a/pearl/pearl-area-profiles-test.ipf b/pearl/pearl-area-profiles-test.ipf deleted file mode 100644 index c3bcf7f..0000000 --- a/pearl/pearl-area-profiles-test.ipf +++ /dev/null @@ -1,454 +0,0 @@ -#pragma rtGlobals=3 // Use modern global access method and strict wave access. -#pragma IgorVersion = 6.1 -#pragma ModuleName = PearlAreaProfilesTest -#pragma version = 1.02 - -#include "pearl-area-profiles" -#include "unit-testing" - - -/// @file -/// @brief test suite for pearl-area-profiles.ipf -/// -/// unit testing framework: http://www.igorexchange.com/project/unitTesting. -/// run all test cases with RunTest("pearl-area-profiles-test.ipf"). -/// if wave equalities fail, EnableDebugOutput() and read Igor help on equalWaves(). -/// -/// @author matthias muntwiler, matthias.muntwiler@psi.ch -/// -/// @copyright 2013-15 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 PearlAreaProfilesTest -/// @brief profile extraction for multi-dimensional datasets acquired from area detectors. -/// -/// PearlAreaProfilesTest is declared in @ref pearl-area-profiles-test.ipf. -/// - - -/// test the ad_profile_x() function -static function test_ad_profile_x_w() - make /n=(11,21) /d /free source - setscale /p x 10, 1, "X", source - setscale /p y 100, 100, "Y", source - setscale d 0, 0, "D", source - source = x + y - - make /n=11 /d /free expected - setscale /p x 10, 1, "X", expected - setscale d 0, 0, "D", expected - expected = 30 + 3 * p + 500 + 600 + 700 - - make /n=1 /d /free result1, result0 - variable p1, p2 - - p1 = 4 - p2 = 6 - ad_profile_x_w(source, p1, p2, result1, noavg=1) - CHECK_EQUAL_WAVES(result1, expected, tol=1e-6) - - expected /= 3 - ad_profile_x_w(source, p1, p2, result0, noavg=0) - CHECK_EQUAL_WAVES(result0, expected, tol=1e-6) -end - -/// test the ad_profile_y() function -static function test_ad_profile_y_w() - make /n=(11,21) /d /free source - setscale /p x 10, 1, "X", source - setscale /p y 100, 100, "Y", source - setscale d 0, 0, "D", source - source = x + y - - make /n=21 /d /free expected - setscale /p x 100, 100, "Y", expected - setscale d 0, 0, "D", expected - expected = 3 * x + 14 + 15 + 16 - - make /n=1 /d /free result1, result0 - variable p1, p2 - - p1 = 4 - p2 = 6 - ad_profile_y_w(source, p1, p2, result1, noavg=1) - CHECK_EQUAL_WAVES(result1, expected) - - expected /= 3 - ad_profile_y_w(source, p1, p2, result0, noavg=0) - CHECK_EQUAL_WAVES(result0, expected) -end - -/// test the ad_extract_slab_x() function -static function test_ad_extract_slab_x() - variable nx = 11 - variable ny = 16 - variable nz = 21 - make /n=(nx,ny,nz) /d /free source - setscale /i x -1, 1, "X", source - setscale /i y -2, 2, "Y", source - setscale /i z -3, 3, "Z", source - setscale d 0, 0, "D", source - source = x + y + z - source[4][][] = 1 - source[5][][] = 1 - - make /n=(ny,nz) /d /free expected - setscale /i x -2, 2, "Y", expected - setscale /i y -3, 3, "Z", expected - setscale d 0, 0, "D", expected - expected = 2 - - variable p1, p2 - p1 = 4 - p2 = 5 - - wave result = ad_extract_slab_x(source, p1, p2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - expected = 1 - wave result = ad_extract_slab_x(source, p1, p2, "", noavg=0) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - p1 = -inf - p2 = 5 - source = y + z - expected = (x + y) * 6 - wave result = ad_extract_slab_x(source, p1, p2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - p1 = 4 - p2 = +inf - expected = (x + y) * (nx - 4) - wave result = ad_extract_slab_x(source, p1, p2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) -end - -/// test the ad_extract_slab_y() function -static function test_ad_extract_slab_y() - variable nx = 11 - variable ny = 16 - variable nz = 21 - make /n=(nx,ny,nz) /d /free source - setscale /i x -1, 1, "X", source - setscale /i y -2, 2, "Y", source - setscale /i z -3, 3, "Z", source - setscale d 0, 0, "D", source - source = x + y + z - source[][4][] = 1 - source[][5][] = 1 - - make /n=(nx,nz) /d /free expected - setscale /i x -1, 1, "X", expected - setscale /i y -3, 3, "Z", expected - setscale d 0, 0, "D", expected - expected = 2 - - variable p1, p2 - p1 = 4 - p2 = 5 - - wave result = ad_extract_slab_y(source, p1, p2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - expected = 1 - wave result = ad_extract_slab_y(source, p1, p2, "", noavg=0) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - p1 = -inf - p2 = 5 - source = x + z - expected = (x + y) * 6 - wave result = ad_extract_slab_y(source, p1, p2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - p1 = 4 - p2 = +inf - expected = (x + y) * (ny - 4) - wave result = ad_extract_slab_y(source, p1, p2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) -end - -/// test the ad_extract_slab_z() function -static function test_ad_extract_slab_z() - variable nx = 11 - variable ny = 16 - variable nz = 21 - make /n=(nx,ny,nz) /d /free source - setscale /i x -1, 1, "X", source - setscale /i y -2, 2, "Y", source - setscale /i z -3, 3, "Z", source - setscale d 0, 0, "D", source - source = x + y + z - source[][][4] = 1 - source[][][5] = 1 - - make /n=(nx,ny) /d /free expected - setscale /i x -1, 1, "X", expected - setscale /i y -2, 2, "Y", expected - setscale d 0, 0, "D", expected - expected = 2 - - variable p1, p2 - p1 = 4 - p2 = 5 - - wave result = ad_extract_slab_z(source, p1, p2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - expected = 1 - wave result = ad_extract_slab_z(source, p1, p2, "", noavg=0) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - p1 = -inf - p2 = 5 - source = x + y - expected = (x + y) * 6 - wave result = ad_extract_slab_z(source, p1, p2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - p1 = 4 - p2 = +inf - expected = (x + y) * (nz - 4) - wave result = ad_extract_slab_z(source, p1, p2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) -end - -/// test the ad_extract_slab() function -static function test_ad_extract_slab() - variable nx = 11 - variable ny = 16 - variable nz = 21 - - make /n=(nx,ny,nz) /d /free source - setscale /i x -1, 1, "X", source - setscale /i y -2, 2, "Y", source - setscale /i z -3, 3, "Z", source - setscale d 0, 0, "D", source - source = x + y + z - - variable x1, x2 - variable y1, y2 - variable z1, z2 - - make /n=(ny,nz) /d /free expected - setscale /i x -2, 2, "Y", expected - setscale /i y -3, 3, "Z", expected - setscale d 0, 0, "D", expected - - x1 = 0 - x2 = 0 - y1 = nan - y2 = nan - z1 = nan - z2 = nan - expected = source[(nx-1)/2][p][q] - wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - x1 = -inf - x2 = inf - expected = (x + y) * nx - wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - make /n=(nx,nz) /d /free expected - setscale /i x -1, 1, "X", expected - setscale /i y -3, 3, "Z", expected - setscale d 0, 0, "D", expected - - x1 = nan - x2 = nan - y1 = 0 - y2 = 0 - z1 = nan - z2 = nan - expected = source[p][(ny-1)/2][q] - wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - y1 = -inf - y2 = +inf - expected = (x + y) * ny - wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - make /n=(nx,ny) /d /free expected - setscale /i x -1, 1, "X", expected - setscale /i y -2, 2, "Y", expected - setscale d 0, 0, "D", expected - - x1 = nan - x2 = nan - y1 = nan - y2 = nan - z1 = 0 - z2 = 0 - expected = source[p][q][(nz-1)/2] - wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - z1 = -inf - z2 = inf - expected = (x + y) * nz - wave result = ad_extract_slab(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) -end - -/// test the ad_extract_rod_x() function -static function test_ad_extract_rod_x() - variable nx = 11 - variable ny = 16 - variable nz = 21 - make /n=(nx,ny,nz) /d /free source - setscale /i x -1, 1, "X", source - setscale /i y -2, 2, "Y", source - setscale /i z -3, 3, "Z", source - setscale d 0, 0, "D", source - source = x + y + z - source[][4][4] = 1 - source[][4][5] = 1 - source[][5][4] = 1 - source[][5][5] = 1 - - make /n=(nx) /d /free expected - setscale /i x -1, 1, "X", expected - setscale d 0, 0, "D", expected - expected = 4 - - variable q1, q2 - variable r1, r2 - q1 = 4 - q2 = 5 - r1 = 4 - r2 = 5 - - wave result = ad_extract_rod_x(source, q1, q2, r1, r2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - expected = 1 - wave result = ad_extract_rod_x(source, q1, q2, r1, r2, "", noavg=0) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) -end - -/// test the ad_extract_rod() function, X coordinate -static function test_ad_extract_rod__x() - variable nx = 11 - variable ny = 16 - variable nz = 21 - - make /n=(nx,ny,nz) /d /free source - setscale /i x -1, 1, "X", source - setscale /i y -2, 2, "Y", source - setscale /i z -3, 3, "Z", source - setscale d 0, 0, "D", source - source = x + y + z - - variable x1, x2 - variable y1, y2 - variable z1, z2 - - make /n=(nx) /d /free expected - setscale /i x -1, 1, "X", expected - setscale d 0, 0, "D", expected - - x1 = nan - x2 = nan - y1 = 0 - y2 = 0 - z1 = 0 - z2 = 0 - expected = source[p][(ny-1)/2][(nz-1)/2] - wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - y1 = -inf - y2 = +inf - z1 = -inf - z2 = +inf - expected = x * ny * nz - wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) -end - -/// test the ad_extract_rod() function, Y coordinate -static function test_ad_extract_rod__y() - variable nx = 11 - variable ny = 16 - variable nz = 21 - - make /n=(nx,ny,nz) /d /free source - setscale /i x -1, 1, "X", source - setscale /i y -2, 2, "Y", source - setscale /i z -3, 3, "Z", source - setscale d 0, 0, "D", source - source = x + y + z - - variable x1, x2 - variable y1, y2 - variable z1, z2 - - make /n=(ny) /d /free expected - setscale /i x -2, 2, "Y", expected - setscale d 0, 0, "D", expected - - x1 = 0 - x2 = 0 - y1 = nan - y2 = nan - z1 = 0 - z2 = 0 - expected = source[(nx-1)/2][p][(nz-1)/2] - wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - x1 = -inf - x2 = +inf - z1 = -inf - z2 = +inf - expected = x * nx * nz - wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) -end - -/// test the ad_extract_rod() function, Z coordinate -static function test_ad_extract_rod__z() - variable nx = 11 - variable ny = 16 - variable nz = 21 - - make /n=(nx,ny,nz) /d /free source - setscale /i x -1, 1, "X", source - setscale /i y -2, 2, "Y", source - setscale /i z -3, 3, "Z", source - setscale d 0, 0, "D", source - source = x + y + z - - variable x1, x2 - variable y1, y2 - variable z1, z2 - - make /n=(nz) /d /free expected - setscale /i x -3, 3, "Z", expected - setscale d 0, 0, "D", expected - - x1 = 0 - x2 = 0 - y1 = 0 - y2 = 0 - z1 = nan - z2 = nan - expected = source[(nx-1)/2][(ny-1)/2][p] - wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) - - x1 = -inf - x2 = +inf - y1 = -inf - y2 = +inf - expected = x * nx * ny - wave result = ad_extract_rod(source, x1, x2, y1, y2, z1, z2, "", noavg=1) - CHECK_EQUAL_WAVES(result, expected, tol=0.001) -end diff --git a/pearl/pearl-arpes-scans.ipf b/pearl/pearl-arpes-scans.ipf deleted file mode 100644 index 2d6c7c6..0000000 --- a/pearl/pearl-arpes-scans.ipf +++ /dev/null @@ -1,152 +0,0 @@ -#pragma rtGlobals=3 // Use modern global access method and strict wave access. -#pragma IgorVersion = 6.1 -#pragma ModuleName = PearlArpesScans -#pragma version = 1.01 -#include "mm-physconst" -#include "pearl-optics-theory" -#include "pearl-epics", version >= 1.01 - -// EPICS scans of Scienta -// matthias muntwiler, 2013-03-15 -// $Id: pearl-optics-scans.ipf 129 2013-06-26 15:53:13Z muntwiler_m $ - -static strconstant basename = "X03DA-SCIENTA:" -static strconstant camname = "cam1:" -static strconstant hdfname = "HDF1:" -static strconstant imgname = "image1:" -static strconstant statsname = "Stats1:" - -function scienta_connect() - - dfref savedf = GetDataFolderDFR() - print "connecting EPICS channels..." - - // channel lists - string controls = "" - controls += basename + camname + "PASS_ENERGY;" - controls += basename + camname + "LOW_ENERGY;" - controls += basename + camname + "CENTRE_ENERGY;" - controls += basename + camname + "HIGH_ENERGY;" - controls += basename + camname + "LENS_MODE;" - controls += basename + camname + "ACQ_MODE;" - controls += basename + camname + "ENERGY_MODE;" - controls += basename + camname + "DETECTOR_MODE;" - controls += basename + camname + "ELEMENT_SET;" - controls += basename + camname + "STEP_SIZE;" - controls += basename + camname + "SLICES;" - controls += basename + camname + "NumExposures;" - controls += basename + camname + "FRAMES;" - controls += basename + camname + "STEP_TIME;" - - string monitors = "" - monitors += basename + camname + "PASS_ENERGY_RBV;" - monitors += basename + camname + "LOW_ENERGY_RBV;" - monitors += basename + camname + "CENTRE_ENERGY_RBV;" - monitors += basename + camname + "HIGH_ENERGY_RBV;" - monitors += basename + camname + "ENERGY_WIDTH_RBV;" - monitors += basename + camname + "LENS_MODE_RBV;" - monitors += basename + camname + "ACQ_MODE_RBV;" - monitors += basename + camname + "ENERGY_MODE_RBV;" - monitors += basename + camname + "DETECTOR_MODE_RBV;" - monitors += basename + camname + "ELEMENT_SET_RBV;" - monitors += basename + camname + "STEP_SIZE_RBV;" - monitors += basename + camname + "SLICES_RBV;" - monitors += basename + camname + "NumExposures_RBV;" - monitors += basename + camname + "CURRENT_CHANNEL_RBV;" - monitors += basename + camname + "TOTAL_POINTS_RBV;" - monitors += basename + camname + "PROGRESS_RBV;" - //monitors += basename + camname + "INT_SPECTRUM;" - monitors += basename + camname + "BinX_RBV;" - monitors += basename + camname + "BinY_RBV;" - monitors += basename + camname + "MinX_RBV;" - monitors += basename + camname + "MinY_RBV;" - monitors += basename + camname + "SizeX_RBV;" - monitors += basename + camname + "SizeY_RBV;" - monitors += basename + camname + "ReverseX_RBV;" - monitors += basename + camname + "ReverseY_RBV;" - - // variable name list corresponding to channel lists - string variables = "" - variables = AddListItem("ArrayData", variables, ";", ItemsInList(variables)) - - // connect EPICS channels - epics_connect(controls, monitors) - - - print "...done" - setdatafolder savedf - -end - -function pearl_set_attr_ch(attr_wave_name, attr_channel_name) - string attr_wave_name - string attr_channel_name - - variable result - variable chid - pvOpen chid, attr_channel_name - - switch(wavetype($attr_wave_name, 1)) - case 1: // numeric - wave w_attr = $attr_wave_name - pvPutNumber /Q chid, w_attr[0] - result = 0 - break - case 2: // text - wave /t wt_attr = $attr_wave_name - pvPutString /Q chid, wt_attr[0] - result = 0 - break - default: // error - result = -1 - endswitch - - pvClose chid - - return result -end - -function pearl_set_sscan(scan_rec_num) - variable scan_rec_num - - string chan_base = "X03DA-PC:scan" + num2str(scan_rec_num) + ":" - string wave_base = "Scan" + num2str(scan_rec_num) - - variable nfields - variable ifield - string wave_name - string chan_name - wave /z w_active = $(wave_base + "Active") - if (WaveExists(w_active)) - if (w_active[0] != 0) - nfields = 4 - for (ifield = 1; ifield <= nfields; ifield += 1) - sscanf wave_name, "%sPositioner%u", ifield - sscanf chan_name, "%sP%uPV", chan_base, ifield - pearl_set_attr_ch(wave_name, chan_name) - sscanf wave_name, "%sReadback%u", ifield - sscanf chan_name, "%sR%uPV", chan_base, ifield - pearl_set_attr_ch(wave_name, chan_name) - sscanf wave_name, "%sTrigger%u", ifield - sscanf chan_name, "%sT%uPV", chan_base, ifield - pearl_set_attr_ch(wave_name, chan_name) - endfor - nfields = 20 - for (ifield = 1; ifield <= nfields; ifield += 1) - sscanf wave_name, "%sDetector%u", ifield - sscanf chan_name, "%sD%uPV", chan_base, ifield - pearl_set_attr_ch(wave_name, chan_name) - endfor - endif - endif -end - -function pearl_repeat_scan() - // set up a scan according to the attributes of the given dataset - dfref savedf = GetDataFolderDFR() - - setdatafolder :attr - - - setdatafolder savedf -end \ No newline at end of file diff --git a/pearl/pearl-data-export.ipf b/pearl/pearl-data-export.ipf deleted file mode 100644 index a6d5148..0000000 --- a/pearl/pearl-data-export.ipf +++ /dev/null @@ -1,28 +0,0 @@ -#pragma rtGlobals=3 // Use modern global access method and strict wave access. - -function export_otf() - // export OTF folders to text files - - string objname - variable index= 0 - - setdatafolder root: - dfref parentfolder = getdatafolderdfr() - string filename - - do - objname = GetindexedObjNameDFR(parentfolder, 4, index) - if (strlen(objname) > 0) - if (cmpstr(StringFromList(0, objname, "_"), "otf") == 0) - setdatafolder parentfolder - setdatafolder $objname - wave ringcurrent,photonenergy,current_ch1,current_ch2 - filename = objname + ".txt" - Save/G/M="\r\n"/W/P=pearl_explorer_filepath photonenergy,current_ch1,current_ch2,ringcurrent as filename - endif - index += 1 - else - break - endif - while(1) -end diff --git a/pearl/pearl-preparation.ipf b/pearl/pearl-preparation.ipf deleted file mode 100644 index 97c3fc5..0000000 --- a/pearl/pearl-preparation.ipf +++ /dev/null @@ -1,73 +0,0 @@ -#pragma rtGlobals=3 // Use modern global access method and strict wave access. -#pragma IgorVersion = 6.1 -#pragma ModuleName = PearlPreparation -#pragma version = 1.04 -#include "pearl-area-display" // 2D and 3D data visualization -#include "pearl-area-profiles" // data processing for multi-dimensional datasets -#include "pearl-elog" -#if exists("pvOpen") -#include "pearl-epics" // EPICS access under Igor -#include "pearl-anneal" // automated sample annealing -#endif - -// author: matthias.muntwiler@psi.ch -// Copyright (c) 2015 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 PEARL sample preparation package -/// -/// this procedure defines the PEARL sample preparation package -/// the main purpose of this file is to load the necessary dependent procedures -/// (see the include statements at the top) -/// -/// @pre -/// * on-line process control functionality requires the EPICS XOP to be loaded -/// -/// @author matthias muntwiler, matthias.muntwiler@psi.ch -/// -/// @copyright 2015 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 PearlPreparation -/// @brief PEARL sample preparation package -/// -/// PearlPreparation is declared in @ref pearl-preparation.ipf. -/// - -/// @defgroup PreparationPackage Sample preparation package -/// @brief PEARL sample preparation package -/// -/// The purpose of a package is to load a bunch of dependent procedure files. -/// The sample preparation package loads the following files. -/// -/// * pearl-area-import.ipf -/// * pearl-area-display.ipf -/// * pearl-area-profiles.ipf -/// * pearl-elog.ipf -/// * pearl-anneal.ipf -/// -/// The following files are loaded if the EPICS.XOP is present: -/// -/// * pearl-epics.ipf -/// - -/// initializes package data once when the procedure is first loaded -static function AfterCompiledHook() - - dfref savefolder = GetDataFolderDFR() - - return 0 -end - -function UnloadPearlPreparationPackage() - execute /p/q/z "DELETEINCLUDE \"pearl-preparation\"" - execute /p/q/z "COMPILEPROCEDURES " -end \ No newline at end of file