- pshell import: fix units and data scaling. - pshell import: support new multi-region scans. - angle scans: add trim function. - angle scans: update import_tpi_scan function. - angle scans: fix scales of check waves in normalization. - area display: new cursor mode for background selection. - elog: bugfixes (attachment list, check existing logbook).
1906 lines
55 KiB
Igor
1906 lines
55 KiB
Igor
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
|
#pragma version = 1.40
|
|
#pragma IgorVersion = 6.2
|
|
#pragma ModuleName = PearlElog
|
|
|
|
// author: matthias.muntwiler@psi.ch
|
|
// Copyright (c) 2013-16 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 interface for writing ELOG entries with Igor graphs as attachment.
|
|
/// @ingroup ArpesPackage
|
|
///
|
|
///
|
|
/// the functions in this module support the following ELOG features:
|
|
/// - submit new entries and replies to existing entries.
|
|
/// - text field, list box, and check box attributes.
|
|
/// - attach any Igor graph to ELOG.
|
|
/// - configurable logbook templates for logbooks that share the same configuration.
|
|
/// - common server configurations available on the ELOG command line
|
|
/// (hostname, port, SSL, username, password, sub-directory).
|
|
/// - not specific to the configuration at PEARL.
|
|
/// PEARL code is concentrated in the elog_init_pearl_templates() function.
|
|
/// - the configuration of the ELOG server and logbooks
|
|
/// as well as the most recently used attributes are persisted in the preference file.
|
|
///
|
|
/// usage:
|
|
/// 1. the administrator of the ELOG server creates logbook templates
|
|
/// according to the configuration of the logbooks.
|
|
/// the templates are written in Igor code.
|
|
/// 2. the user opens logbooks via the _Open ELOG panel_ menu item.
|
|
/// before first use, select a template and enter a name for the logbook.
|
|
/// the new logbook is written to the preference file,
|
|
/// and can afterwards be opened directly.
|
|
/// 3. if the server requires a user name and password,
|
|
/// click the login button.
|
|
/// 4. edit the message, attributes and attachments as necessary, and submit to ELOG.
|
|
/// 5. log out before saving the experiment to clear the password.
|
|
///
|
|
/// @attention the user name and password are stored in the global data tree of an experiment.
|
|
/// it is not possible to handle passwords safely in Igor.
|
|
/// they can be read by anyone having access to an open Igor experiment or a saved experiment file
|
|
/// (unless the password is reset before saving).
|
|
/// therefore:
|
|
/// - use a password for the ELOG server which is different from your other passwords.
|
|
/// - clear the password (logout button in the panel) before saving an experiment.
|
|
///
|
|
/// elog command line
|
|
///@verbatim
|
|
/// elog -h <hostname> [-p port] [-d subdir]
|
|
/// Location where elogd is running
|
|
/// -l logbook Name of logbook
|
|
/// -s Use SSL for communication
|
|
/// [-v] For verbose output
|
|
/// [-w password] Write password defined on server
|
|
/// [-u username password] User name and password
|
|
/// [-f <attachment>] Up to 50 attachments
|
|
/// -a <attribute>=<value> Up to 50 attributes
|
|
/// [-r <id>] Reply to existing message
|
|
/// [-q] Quote original text on reply
|
|
/// [-e <id>] Edit existing message
|
|
/// [-x] Suppress email notification
|
|
/// [-n 0|1|2] Encoding: 0:ELcode,1:plain,2:HTML
|
|
/// -m <textfile>] | <text>
|
|
///@endverbatim
|
|
///
|
|
///
|
|
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
|
|
///
|
|
/// @copyright 2013-16 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 PearlElog
|
|
/// @brief interface for writing ELOG entries with Igor graphs as attachment.
|
|
///
|
|
/// PearlElog is declared in @ref pearl-elog.ipf.
|
|
|
|
static strconstant package_name = "pearl_elog"
|
|
static strconstant package_path = "root:packages:pearl_elog:"
|
|
|
|
/// main function to initialize ELOG and to open an ELOG panel.
|
|
///
|
|
/// this function takes care of all necessary initialization, configuration, and preferences.
|
|
/// if a panel exists, it will be moved to the front.
|
|
///
|
|
/// @param logbook name of the logbook
|
|
/// if empty, the user is prompted to select or create a logbook by elog_prompt_logbook().
|
|
///
|
|
///
|
|
function pearl_elog(logbook)
|
|
string logbook
|
|
|
|
if (init_package() == 0)
|
|
load_prefs()
|
|
string templates = list_logbooks(templates=1)
|
|
if (ItemsInList(templates) < 1)
|
|
elog_init_pearl_templates()
|
|
endif
|
|
endif
|
|
|
|
if (strlen(logbook) == 0)
|
|
logbook = elog_prompt_logbook()
|
|
endif
|
|
|
|
string win_name = logbook + "ElogPanel"
|
|
if (strlen(logbook) > 0)
|
|
if (strlen(WinList(win_name, ";", "")) > 0)
|
|
DoWindow /F $win_name
|
|
else
|
|
win_name = PearlElogPanel(logbook)
|
|
STRUCT WMWinHookStruct s
|
|
s.eventCode = 0
|
|
s.winName = win_name
|
|
elog_panel_hook(s)
|
|
endif
|
|
endif
|
|
end
|
|
|
|
/// save preferences and recent values before Igor opens a new experiment.
|
|
static function IgorBeforeNewHook(igorApplicationNameStr)
|
|
string igorApplicationNameStr
|
|
save_prefs()
|
|
cleanup_temp_files()
|
|
return 0
|
|
end
|
|
|
|
/// save preferences and recent values before Igor quits.
|
|
static function IgorQuitHook(igorApplicationNameStr)
|
|
string igorApplicationNameStr
|
|
save_prefs()
|
|
cleanup_temp_files()
|
|
return 0
|
|
end
|
|
|
|
/// initialize the package and reload preferences after an experiment is loaded.
|
|
static function AfterFileOpenHook(refNum,file,pathName,type,creator,kind)
|
|
Variable refNum,kind
|
|
String file,pathName,type,creator
|
|
if( (kind >= 1) && (kind <= 2))
|
|
init_package(clean=1)
|
|
load_prefs()
|
|
endif
|
|
return 0
|
|
end
|
|
|
|
static constant kdfRoot = 0
|
|
static constant kdfVolatile = 1
|
|
static constant kdfPersistent = 2
|
|
static constant kdfTemplates = 3
|
|
|
|
/// get the package, logbook, or template datafolder.
|
|
///
|
|
/// @param name name of logbook or template, or empty string for respective parent folder.
|
|
///
|
|
/// @param category parameter category:
|
|
/// @arg kdfRoot package root
|
|
/// @arg kdfVolatile volatile
|
|
/// @arg kdfPersistent persistent
|
|
/// @arg kdfTemplates template
|
|
///
|
|
/// @returns data folder reference
|
|
///
|
|
static function /df get_elog_df(name, category)
|
|
string name
|
|
variable category
|
|
|
|
dfref df_package = $package_path
|
|
dfref df_persistent = df_package:persistent
|
|
dfref df_volatile = df_package:volatile
|
|
|
|
switch(category)
|
|
case kdfRoot:
|
|
dfref df_parent = df_package
|
|
break
|
|
case kdfPersistent:
|
|
dfref df_parent = df_persistent
|
|
break
|
|
case kdfTemplates:
|
|
dfref df_parent = df_persistent:templates
|
|
break
|
|
case kdfVolatile:
|
|
dfref df_parent = df_volatile
|
|
break
|
|
default:
|
|
Abort "get_elog_df: undefined data folder category."
|
|
endswitch
|
|
|
|
if ((strlen(name) > 0) && (category >= 1))
|
|
if (category == kdfTemplates)
|
|
dfref df_logbooks = df_parent
|
|
else
|
|
dfref df_logbooks = df_parent:logbooks
|
|
endif
|
|
dfref df_logbook = df_logbooks:$name
|
|
return df_logbook
|
|
else
|
|
return df_parent
|
|
endif
|
|
end
|
|
|
|
/// initialize the package data folder.
|
|
///
|
|
/// the data folder is initialized with a default, local configuration without any logbooks.
|
|
/// the server configuration should be set in the preferences.
|
|
///
|
|
/// @param clean decides what to do if the package configuration exists.
|
|
/// @arg 0 (default) keep existing configuration.
|
|
/// @arg 1 overwrite existing configuration.
|
|
///
|
|
static function init_package([clean])
|
|
variable clean
|
|
|
|
if (ParamIsDefault(clean))
|
|
clean = 0
|
|
endif
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
dfref df_root = get_elog_df("", kdfRoot)
|
|
if ((clean == 0) && (DataFolderRefStatus(df_root) == 1))
|
|
return 1
|
|
endif
|
|
|
|
setdatafolder root:
|
|
newdatafolder /o/s packages
|
|
newdatafolder /o/s $package_name
|
|
dfref df_package_root = getdatafolderdfr()
|
|
newdatafolder /o/s volatile
|
|
dfref df_volatile = getdatafolderdfr()
|
|
newdatafolder /o logbooks
|
|
setdatafolder df_package_root
|
|
newdatafolder /o/s persistent
|
|
dfref df_persistent = getdatafolderdfr()
|
|
newdatafolder /o logbooks
|
|
newdatafolder /o templates
|
|
|
|
// common configuration
|
|
setdatafolder df_persistent
|
|
string /g elog_path = "c:\\program files (x86)\\ELOG\\elog.exe"
|
|
string /g hostname = "localhost"
|
|
variable /g port = 0 // 0 = unspecified (default)
|
|
variable /g ssl = 0 // 0 = plain text (incl. passwords), 1 = secure connection
|
|
string /g subdir = ""
|
|
variable /g loglevel = 3
|
|
|
|
setdatafolder savedf
|
|
return 0
|
|
end
|
|
|
|
/// setup PEARL template logbooks.
|
|
///
|
|
/// template logbooks for PEARL.
|
|
///
|
|
/// @remark this function is specific to the setup at PEARL.
|
|
///
|
|
function elog_init_pearl_templates()
|
|
dfref savedf = getdatafolderdfr()
|
|
|
|
dfref df_root = get_elog_df("", kdfRoot)
|
|
dfref df_persistent = get_elog_df("", kdfPersistent)
|
|
dfref df_templates = get_elog_df("", kdfTemplates)
|
|
|
|
// Experiments template
|
|
setdatafolder df_templates
|
|
newdatafolder /o/s Experiments
|
|
|
|
// attributes (persistent)
|
|
// available attributes
|
|
string /g attributes = "author;project;sample;source;task;technique;file;valid;"
|
|
// controls corresponding to attributes
|
|
// prefix determines the control type: sv_ = setvariable (string), pm_ = popup menu, cb = check box
|
|
string /g controls = "sv_author;sv_project;sv_sample;pm_source;pm_task;pm_technique;sv_file;cb_valid;"
|
|
// attributes with fixed options, value item declares the options string
|
|
string /g options = "source=sources;task=tasks;technique=techniques"
|
|
// attributes which must be defined
|
|
string /g required_attributes = "author;project;sample;source;task;technique;valid"
|
|
|
|
// option lists
|
|
string /g sources = "Manual Entry;PShell;Scienta Data;SScan Data;Prosilica Data;OTF Data;Beamline Status;LEED Data;QMS Data;Matrix Data;Igor Pro;Other"
|
|
string /g tasks = "Measurement;Optimization;Analysis;Sample Preparation;Sample Storage;Comment;Development;Maintenance;Test;Other"
|
|
string /g techniques = "XPS;UPS;XPD;XAS;XMCD;PhD;ARUPS;STM;STS;LEED;AES;QMS;MBE;Sputter/Anneal;Test;Other"
|
|
|
|
// Calculations template
|
|
setdatafolder df_templates
|
|
newdatafolder /o/s Calculations
|
|
|
|
// attributes (persistent)
|
|
// available attributes
|
|
string /g attributes = "author;project;sample;program;revision;machine;job;experiment;source path;result path;valid"
|
|
// controls corresponding to attributes
|
|
// prefix determines the control type: sv_ = setvariable (string), pm_ = popup menu, cb = check box
|
|
string /g controls = "sv_author;sv_project;sv_sample;pm_program;sv_revision;pm_machine;sv_job;sv_experiment;sv_sourcepath;sv_resultpath;cb_valid"
|
|
// attributes with fixed options, value item declares the options string
|
|
string /g options = "program=programs;machine=machines"
|
|
// attributes which must be defined
|
|
string /g required_attributes = "author;project;sample"
|
|
|
|
// option lists
|
|
string /g programs = "PMSCO;EDAC;MSC;SSC;MUFPOT;DMSUP;Other"
|
|
string /g machines = "PC;VM;Ra;Merlin;llcx;Other"
|
|
|
|
// System template
|
|
setdatafolder df_templates
|
|
newdatafolder /o/s System
|
|
|
|
// attributes (persistent)
|
|
// available attributes
|
|
string /g attributes = "author;type;system;source;file"
|
|
// controls corresponding to attributes
|
|
// prefix determines the control type: sv_ = setvariable (string), pm_ = popup menu, cb = check box
|
|
string /g controls = "sv_author;pm_type;pm_system;pm_source;sv_file"
|
|
// attributes with fixed options, value item declares the options string
|
|
string /g options = "type=types;system=systems;source=sources"
|
|
// attributes which must be defined
|
|
string /g required_attributes = "author;type;system"
|
|
|
|
// option lists
|
|
string /g types = "Installation;Repair;Maintenance;Test;Commissioning;Bakeout;Incident;Cool-down;Warm-up;Storage;Other"
|
|
string /g systems = "Vacuum;Control System;BL;XA;XP;SA;SP;T;LL;Monochromator;Carving;Scienta;STM;PC-Scienta;PC-Matrix;PC-Console;PC-Console-Win;PC-XP;EPS;LAC;Desiccator"
|
|
string /g sources = "Manual Entry;PShell;Scienta Data;SScan Data;Prosilica Data;OTF Data;Beamline Status;LEED Data;QMS Data;Matrix Data;Igor Pro;Other"
|
|
|
|
setdatafolder savedf
|
|
return 0
|
|
end
|
|
|
|
/// initialize volatile variables.
|
|
///
|
|
/// create and initialize all volatile variables for the configured notebooks.
|
|
/// values of existing variables are not changed.
|
|
///
|
|
/// this function must be called after new logbooks have been configured,
|
|
/// specifically by elog_create_logbook() and load_prefs().
|
|
///
|
|
static function init_volatile_vars()
|
|
dfref savedf = GetDataFolderDFR()
|
|
|
|
dfref df_volatile_root = get_elog_df("", kdfVolatile)
|
|
dfref df_volatile_parent = df_volatile_root:logbooks
|
|
|
|
string logbooks = list_logbooks()
|
|
string logbook
|
|
variable nlb = ItemsInList(logbooks)
|
|
variable ilb
|
|
|
|
SetDataFolder df_volatile_root
|
|
if (exists("temp_graph_files") != 2)
|
|
string /g temp_graph_files = ""
|
|
endif
|
|
|
|
for (ilb = 0; ilb < nlb; ilb += 1)
|
|
logbook = StringFromList(ilb, logbooks)
|
|
|
|
SetDataFolder df_volatile_parent
|
|
if (DataFolderExists(logbook))
|
|
SetDataFolder $logbook
|
|
else
|
|
NewDataFolder /o/s $logbook
|
|
endif
|
|
|
|
if (exists("username") != 2)
|
|
string /g username = ""
|
|
endif
|
|
if (exists("password") != 2)
|
|
string /g password = ""
|
|
endif
|
|
if (exists("msg_id") != 2)
|
|
variable /g msg_id = 0
|
|
endif
|
|
if (exists("att_list") != 1)
|
|
make /n=(0,3) /t /o attach_list
|
|
make /n=(0,3) /i /o attach_sel
|
|
endif
|
|
if (exists("url") != 2)
|
|
string /g url = ""
|
|
endif
|
|
endfor
|
|
|
|
SetDataFolder savedf
|
|
return 0
|
|
end
|
|
|
|
/// @var persistent:loglevel
|
|
/// @brief filter history messages by log level.
|
|
///
|
|
/// messages are printed to the history only if their level exceeds this setting.
|
|
/// this is a global variable in the "persistent" folder of the package configuration.
|
|
///
|
|
/// @arg 0 none. do not print any messages. no messages have this level.
|
|
/// @arg 1 critical. severe error with possible data corruption.
|
|
/// @arg 2 error. a function did not complete successfully.
|
|
/// @arg 3 warning. everything worked fine, but some attention of the user is required.
|
|
/// @arg 4 info. status message which may be useful to the normal user.
|
|
/// @arg 5 debug. status message which may be useful to the developer.
|
|
///
|
|
|
|
/// create a new logbook.
|
|
///
|
|
/// create a new empty logbook or duplicate from a template.
|
|
///
|
|
/// @param name name of the new logbook.
|
|
/// if the logbook exists, the existing logbook folder is killed
|
|
/// and replaced by a new one.
|
|
/// this may fail if a window is still open.
|
|
///
|
|
/// @param template name of the template.
|
|
/// if empty string, a new empty logbook is created.
|
|
///
|
|
function elog_create_logbook(name, [template])
|
|
string name
|
|
string template
|
|
|
|
if (ParamIsDefault(template))
|
|
template = ""
|
|
endif
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
dfref df_root = get_elog_df("", kdfRoot)
|
|
dfref df_persistent_root = get_elog_df("", kdfPersistent)
|
|
dfref df_persistent_parent = df_persistent_root:logbooks
|
|
dfref df_volatile_root = get_elog_df("", kdfVolatile)
|
|
dfref df_volatile_parent = df_volatile_root:logbooks
|
|
|
|
setdatafolder df_persistent_parent
|
|
if (CheckName(name, 11) != 0)
|
|
setdatafolder savedf
|
|
Abort "invalid logbook name"
|
|
return -1
|
|
endif
|
|
|
|
if (strlen(template) > 0)
|
|
dfref df_template = get_elog_df(template, kdfTemplates)
|
|
dfref df_existing = get_elog_df(name, kdfPersistent)
|
|
if (DataFolderRefStatus(df_existing))
|
|
KillDataFolder /Z df_existing
|
|
endif
|
|
DuplicateDataFolder df_template, df_persistent_parent:$name
|
|
else
|
|
NewDataFolder /o/s df_persistent_parent:$name
|
|
|
|
// ELOG logbook name
|
|
string /g logbook = name
|
|
// attributes (persistent)
|
|
// available attributes
|
|
string /g attributes = ""
|
|
// controls corresponding to attributes
|
|
// prefix determines the control type: sv_ = setvariable (string), pm_ = popup menu, cb = check box
|
|
string /g controls = ""
|
|
// attributes with fixed options, value item declares the options string
|
|
string /g options = ""
|
|
// attributes which must be defined
|
|
string /g required_attributes = ""
|
|
endif
|
|
|
|
// usage data (persistent)
|
|
setdatafolder get_elog_df(name, kdfPersistent)
|
|
string /g recent = ""
|
|
string /g recent_message = ""
|
|
|
|
init_volatile_vars()
|
|
|
|
setdatafolder savedf
|
|
return 0
|
|
end
|
|
|
|
/// set global module configuration parameters
|
|
///
|
|
function elog_config([elog_path, hostname, port, subdir])
|
|
string elog_path
|
|
string hostname
|
|
variable port
|
|
string subdir
|
|
|
|
dfref df = get_elog_df("", kdfPersistent)
|
|
|
|
if (!ParamIsDefault(elog_path))
|
|
svar /sdfr=df g_elog_path = elog_path
|
|
g_elog_path = elog_path
|
|
endif
|
|
if (!ParamIsDefault(hostname))
|
|
svar /sdfr=df g_hostname = hostname
|
|
g_hostname = hostname
|
|
endif
|
|
if (!ParamIsDefault(port))
|
|
nvar /sdfr=df g_port = port
|
|
g_port = port
|
|
endif
|
|
if (!ParamIsDefault(subdir))
|
|
svar /sdfr=df g_subdir = subdir
|
|
g_subdir = subdir
|
|
endif
|
|
end
|
|
|
|
/// set username and password for login to a logbook
|
|
///
|
|
/// the username and password are stored (in plain text) in global strings under the selected logbook folder.
|
|
/// this is necessary for sending data to the ELOG server.
|
|
///
|
|
/// call elog_logout() to clear the password variables and to avoid unintended use of your credentials.
|
|
///
|
|
/// @warning
|
|
/// igor does not have a built-in mechanism to protect passwords.
|
|
/// user names and passwords are stored in plain text in the data folder tree.
|
|
/// as such they are saved to experiment files and preferences.
|
|
///
|
|
/// @param logbook name of the target logbook.
|
|
///
|
|
function elog_login(logbook, username, password)
|
|
string logbook
|
|
string username
|
|
string password
|
|
|
|
dfref df = get_elog_df(logbook, kdfVolatile)
|
|
svar /sdfr=df g_username=username
|
|
svar /sdfr=df g_password=password
|
|
g_username = username
|
|
g_password = password
|
|
end
|
|
|
|
/// clear username and password of a logbook or all logbooks.
|
|
///
|
|
/// the username and password are stored (in plain text) in global strings under the selected logbook folder.
|
|
/// this function resets the username and password strings.
|
|
///
|
|
/// @param logbook name of the target logbook.
|
|
/// if empty, the passwords of all logbooks are cleared.
|
|
///
|
|
function elog_logout(logbook)
|
|
string logbook
|
|
|
|
dfref df = get_elog_df(logbook, kdfVolatile)
|
|
if (strlen(logbook) > 0)
|
|
svar /z /sdfr=df g_username=username
|
|
svar /z /sdfr=df g_password=password
|
|
if (svar_exists(g_username))
|
|
g_username = ""
|
|
endif
|
|
if (svar_exists(g_password))
|
|
g_password = ""
|
|
endif
|
|
else
|
|
dfref df2 = df:logbooks
|
|
variable nlb = CountObjectsDFR(df2, 4)
|
|
variable ilb
|
|
string slb
|
|
for (ilb = 0; ilb < nlb; ilb += 1)
|
|
slb = GetIndexedObjNameDFR(df2, 4, ilb)
|
|
if (strlen(slb) > 0)
|
|
elog_logout(slb)
|
|
endif
|
|
endfor
|
|
endif
|
|
end
|
|
|
|
/// save persistent package data to the preferences file.
|
|
///
|
|
/// saves everything under the persistent folder of the package.
|
|
///
|
|
static function save_prefs()
|
|
dfref saveDF = GetDataFolderDFR()
|
|
|
|
dfref df = get_elog_df("", kdfPersistent)
|
|
if (DataFolderRefStatus(df) == 1)
|
|
string fullPath = SpecialDirPath("Packages", 0, 0, 0)
|
|
fullPath += package_name
|
|
NewPath/O/C/Q tempPackagePrefsPath, fullPath
|
|
fullPath += ":preferences.pxp"
|
|
SetDataFolder df
|
|
SaveData /O /Q /R fullPath
|
|
KillPath/Z tempPackagePrefsPath
|
|
endif
|
|
|
|
SetDataFolder saveDF
|
|
end
|
|
|
|
/// load persistent package data from the preferences file.
|
|
///
|
|
/// the preferences file is an Igor packed experiment file in a special preferences folder
|
|
static function load_prefs()
|
|
dfref saveDF = GetDataFolderDFR()
|
|
|
|
variable result = -1
|
|
init_package()
|
|
setdatafolder get_elog_df("", kdfPersistent)
|
|
|
|
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
|
|
init_volatile_vars()
|
|
result = 0
|
|
endif
|
|
endif
|
|
|
|
SetDataFolder saveDF
|
|
return result
|
|
end
|
|
|
|
/// get a list of configured logbooks or templates.
|
|
///
|
|
/// this is list of data folder names under persistent:logbooks (or persistent:templates).
|
|
/// the function does not check whether the folders contain valid data.
|
|
///
|
|
/// @param templates select whether logbooks (0, default) or templates (1) are returned.
|
|
///
|
|
/// @return semicolon-separated list of logbooks
|
|
///
|
|
static function /s list_logbooks([templates])
|
|
variable templates
|
|
|
|
if (ParamIsDefault(templates))
|
|
templates = 0
|
|
endif
|
|
|
|
dfref df_persistent = get_elog_df("", kdfPersistent)
|
|
if (templates)
|
|
dfref df_logbooks = df_persistent:templates
|
|
else
|
|
dfref df_logbooks = df_persistent:logbooks
|
|
endif
|
|
string logbooks = ""
|
|
|
|
variable nlb = CountObjectsDFR(df_logbooks, 4)
|
|
variable ilb
|
|
string slb
|
|
for (ilb = 0; ilb < nlb; ilb += 1)
|
|
slb = GetIndexedObjNameDFR(df_logbooks, 4, ilb)
|
|
if (strlen(slb) > 0)
|
|
logbooks = AddListItem(slb, logbooks)
|
|
endif
|
|
endfor
|
|
|
|
return SortList(logbooks, ";", 16)
|
|
end
|
|
|
|
/// validate attributes
|
|
///
|
|
/// @returns 0 if all required attributes are present and enumerated items are correct.
|
|
/// non-zero if a violation is detected.
|
|
///
|
|
/// @todo
|
|
/// function currently not implemented, always returns 0
|
|
function elog_validate_attributes(logbook, attributes)
|
|
|
|
string logbook // name of the logbook (as in igor folder name)
|
|
string attributes // key=value list of attributes, semicolon separated
|
|
|
|
variable result = 0
|
|
return result
|
|
end
|
|
|
|
/// create a new entry in ELOG
|
|
///
|
|
/// this is the main function to create a new entry in a logbook.
|
|
///
|
|
/// @param logbook name of the target logbook.
|
|
///
|
|
/// @param attributes key=value list of attributes, semicolon separated.
|
|
///
|
|
/// @param message free text part of the entry.
|
|
///
|
|
/// @param encoding encoding of message, 0:ELcode, 1:plain (default), 2:HTML.
|
|
///
|
|
/// @param graphs names of graph windows to be added as attachments, semicolon separated.
|
|
///
|
|
/// @param replyto existing message ID (> 1) to follow up on.
|
|
/// 0 or default: start new thread.
|
|
///
|
|
/// @return ID number of the new entry (> 0), or error code (< 0).
|
|
/// @arg -1: failed to save temporary message file.
|
|
/// @arg -2: invalid/missing command line.
|
|
/// @arg -3: invalid/missing attributes.
|
|
/// @arg -4: elog returned error
|
|
///
|
|
function elog_create_entry(logbook, attributes, message, [encoding, graphs, replyto])
|
|
string logbook
|
|
string attributes
|
|
string message
|
|
variable encoding
|
|
string graphs
|
|
variable replyto
|
|
|
|
if (ParamIsDefault(encoding))
|
|
encoding = 1
|
|
endif
|
|
if (ParamIsDefault(graphs))
|
|
graphs = ""
|
|
endif
|
|
if (ParamIsDefault(replyto))
|
|
replyto = 0
|
|
endif
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
dfref df_general = get_elog_df("", kdfPersistent)
|
|
dfref df_volatile = get_elog_df(logbook, kdfVolatile)
|
|
|
|
variable result = 0
|
|
nvar /sdfr=df_volatile msg_id
|
|
nvar /sdfr=df_general loglevel
|
|
|
|
if (elog_validate_attributes(logbook,attributes) != 0)
|
|
if (loglevel >= 2)
|
|
print "ELOG: failed to validate attributes."
|
|
endif
|
|
result = -3
|
|
endif
|
|
|
|
string cmd = prepare_command_line(logbook)
|
|
if (strlen(cmd) == 0)
|
|
if (loglevel >= 2)
|
|
print "ELOG: failed to prepare command line."
|
|
endif
|
|
result = -2
|
|
endif
|
|
|
|
if (replyto >= 1)
|
|
cmd += " -r " + num2str(replyto)
|
|
endif
|
|
cmd += " -n " + num2str(encoding)
|
|
|
|
variable nattr = ItemsInList(attributes, ";")
|
|
variable iattr
|
|
string sattr
|
|
for (iattr = 0; (iattr < nattr) && (result == 0); iattr += 1)
|
|
sattr = StringFromList(iattr, attributes, ";")
|
|
if (strlen(StringFromList(1, sattr, "=")) > 0)
|
|
sattr = ReplaceString("%", sattr, "")
|
|
cmd += " -a \"" + sattr + "\""
|
|
endif
|
|
endfor
|
|
|
|
if (result == 0)
|
|
string cmd_graphs = prepare_graph_attachments(graphs)
|
|
cmd += " " + cmd_graphs
|
|
endif
|
|
|
|
if ((result == 0) && (strlen(message) > 0))
|
|
string messagefile = create_message_file(message)
|
|
if (strlen(messagefile) > 0)
|
|
cmd += " -m \"" + messagefile + "\""
|
|
cmd += " > \"" + get_log_path() + "\""
|
|
if (loglevel >= 5)
|
|
print cmd
|
|
endif
|
|
string cmd_file_path = create_cmd_file(cmd)
|
|
ExecuteScriptText cmd_file_path
|
|
variable id = parse_result()
|
|
if (id > 0)
|
|
msg_id = id
|
|
if (loglevel >= 4)
|
|
print "ELOG: sent message " + num2str(id)
|
|
endif
|
|
else
|
|
if (loglevel >= 2)
|
|
print "ELOG: sending message failed."
|
|
endif
|
|
result = -4
|
|
endif
|
|
else
|
|
if (loglevel >= 2)
|
|
print "ELOG: failed to create temporary message file."
|
|
endif
|
|
result = -1
|
|
endif
|
|
endif
|
|
|
|
setdatafolder savedf
|
|
return result
|
|
end
|
|
|
|
/// add one or more graphs to an existing ELOG entry
|
|
///
|
|
/// @param logbook name of the target logbook
|
|
/// @param id identification number of the existing entry
|
|
/// @param graphs names of graph windows to be added as attachments, semicolon separated
|
|
///
|
|
/// @warning this will delete all existing attachments of the entry!
|
|
function elog_add_attachment(logbook, id, graphs)
|
|
string logbook
|
|
variable id // existing entry ID
|
|
string graphs // names of graph windows to be added as attachments, semicolon separated
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
dfref df_general = get_elog_df("", kdfPersistent)
|
|
dfref df_volatile = get_elog_df(logbook, kdfVolatile)
|
|
|
|
variable result = 0
|
|
nvar /sdfr=df_volatile msg_id
|
|
nvar /sdfr=df_general loglevel
|
|
|
|
string cmd = prepare_command_line(logbook)
|
|
if (strlen(cmd) == 0)
|
|
result = -2 // error: invalid/missing command line
|
|
endif
|
|
|
|
cmd += " -e " + num2str(id)
|
|
|
|
if (result == 0)
|
|
string cmd_graphs = prepare_graph_attachments(graphs)
|
|
if (strlen(cmd_graphs) == 0)
|
|
result = -3 // error: invalid/missing graphs
|
|
endif
|
|
endif
|
|
|
|
if (result == 0)
|
|
cmd += " " + cmd_graphs
|
|
cmd += " > \"" + get_log_path() + "\""
|
|
string cmd_file_path = create_cmd_file(cmd)
|
|
ExecuteScriptText cmd_file_path
|
|
id = parse_result()
|
|
if (id > 0)
|
|
msg_id = id
|
|
if (loglevel >= 4)
|
|
print "ELOG: attached graphs to message " + num2str(id)
|
|
endif
|
|
else
|
|
if (loglevel >= 2)
|
|
print "ELOG: failed to attach graphs."
|
|
endif
|
|
result = -4 // error: elog returned error
|
|
endif
|
|
endif
|
|
|
|
setdatafolder savedf
|
|
return result
|
|
end
|
|
|
|
/// format the ELOG command and essential address arguments.
|
|
///
|
|
/// the following arguments are included (from global variables) if applicable:
|
|
/// host name, port, SSL, sub-dir, username, password
|
|
/// the result string does not include leading or trailing space
|
|
///
|
|
/// @param logbook name of the target logbook
|
|
static function /s prepare_command_line(logbook)
|
|
string logbook
|
|
|
|
dfref df_general = get_elog_df("", kdfPersistent)
|
|
dfref df_persistent = get_elog_df(logbook, kdfPersistent)
|
|
dfref df_volatile = get_elog_df(logbook, kdfVolatile)
|
|
|
|
svar /sdfr=df_general elog_path
|
|
svar /sdfr=df_general hostname
|
|
nvar /sdfr=df_general port
|
|
nvar /sdfr=df_general ssl
|
|
svar /sdfr=df_general subdir
|
|
nvar /sdfr=df_general loglevel
|
|
svar /sdfr=df_volatile username
|
|
svar /sdfr=df_volatile password
|
|
|
|
string cmd
|
|
cmd = "\"" + elog_path + "\""
|
|
if (loglevel >= 5)
|
|
cmd += " -v"
|
|
endif
|
|
cmd += " -h " + hostname
|
|
if ((nvar_exists(port)) && (port > 0))
|
|
cmd += " -p " + num2str(port)
|
|
endif
|
|
if ((svar_exists(subdir)) && (strlen(subdir) > 0))
|
|
cmd += " -d " + subdir
|
|
endif
|
|
cmd += " -l \"" + logbook + "\""
|
|
if ((nvar_exists(ssl)) && (ssl != 0))
|
|
cmd += " -s"
|
|
endif
|
|
//cmd += " -w " + password
|
|
if (svar_exists(username) && svar_exists(password) && (strlen(username) > 0) && (strlen(password) > 0))
|
|
cmd += " -u " + username + " " + password
|
|
endif
|
|
|
|
if (loglevel >= 5)
|
|
print cmd
|
|
endif
|
|
|
|
return cmd
|
|
end
|
|
|
|
/// format the URL for display to the user
|
|
///
|
|
///
|
|
/// @param logbook name of the target logbook
|
|
///
|
|
static function /s format_url(logbook)
|
|
string logbook
|
|
|
|
dfref df_general = get_elog_df("", kdfPersistent)
|
|
|
|
svar /sdfr=df_general hostname
|
|
nvar /sdfr=df_general port
|
|
nvar /sdfr=df_general ssl
|
|
svar /sdfr=df_general subdir
|
|
|
|
string cmd = ""
|
|
if ((nvar_exists(ssl)) && (ssl != 0))
|
|
cmd += "https://"
|
|
else
|
|
cmd += "http://"
|
|
endif
|
|
cmd += hostname
|
|
if ((nvar_exists(port)) && (port > 0))
|
|
cmd += ":" + num2str(port)
|
|
endif
|
|
if ((svar_exists(subdir)) && (strlen(subdir) > 0))
|
|
cmd += "/" + subdir
|
|
endif
|
|
cmd += "/" + logbook
|
|
|
|
return cmd
|
|
end
|
|
|
|
/// prepare screenshots of graph windows for attachments
|
|
///
|
|
/// prepares the attachment files from Igor graph windows
|
|
/// and returns the arguments to the elog command to attach the files.
|
|
/// the result string does not include leading or trailing space
|
|
///
|
|
/// @param graphs names of graph windows to be added as attachments, semicolon separated
|
|
///
|
|
static function /s prepare_graph_attachments(graphs)
|
|
string graphs // names of graph windows to be added as attachments, semicolon separated
|
|
|
|
string cmd = ""
|
|
variable ngraphs = ItemsInList(graphs, ";")
|
|
variable igraph
|
|
string sgraph
|
|
string graph_path
|
|
for (igraph = 0; igraph < ngraphs; igraph += 1)
|
|
sgraph = StringFromList(igraph, graphs, ";")
|
|
graph_path = create_graph_file(sgraph, igraph)
|
|
if (strlen(graph_path) > 0)
|
|
cmd += " -f \"" + graph_path + "\""
|
|
endif
|
|
endfor
|
|
|
|
return cmd
|
|
end
|
|
|
|
static function /s get_timestamp(sep)
|
|
string sep
|
|
Variable now = DateTime
|
|
string dat = ReplaceString("-", Secs2Date(DateTime, -2), "")
|
|
string tim = ReplaceString(":", Secs2Time(DateTime, 3), "")
|
|
return dat + sep + tim
|
|
end
|
|
|
|
static function /s create_message_file(message)
|
|
string message
|
|
|
|
message = ReplaceString("%", message, "")
|
|
string path = SpecialDirPath("Temporary", 0, 1, 0)
|
|
variable len = strlen(path)
|
|
if (numtype(len) == 0)
|
|
path += "elog_temp_message.txt"
|
|
variable f1
|
|
Open f1 as path
|
|
fprintf f1, message
|
|
Close f1
|
|
else
|
|
path = ""
|
|
endif
|
|
|
|
return path
|
|
end
|
|
|
|
static function /s create_graph_file(graphname, fileindex)
|
|
string graphname
|
|
variable fileindex
|
|
|
|
dfref df_volatile_root = get_elog_df("", kdfVolatile)
|
|
svar /sdfr=df_volatile_root temp_graph_files
|
|
|
|
string path = SpecialDirPath("Temporary", 0, 1, 0)
|
|
string ts = get_timestamp("_")
|
|
variable len = strlen(path)
|
|
if (numtype(len) == 0)
|
|
path += "elog_" + ts + "_" + num2str(fileindex) + ".png"
|
|
SavePICT /B=72 /E=-5 /M /O /W=(0,0,8,6) /WIN=$graphname /Z as path
|
|
if (v_flag == 0)
|
|
temp_graph_files = AddListItem(path, temp_graph_files, ";", inf)
|
|
else
|
|
path = ""
|
|
endif
|
|
else
|
|
path = ""
|
|
endif
|
|
|
|
return path
|
|
end
|
|
|
|
static function /s create_cmd_file(cmd)
|
|
string cmd
|
|
|
|
string path = SpecialDirPath("Temporary", 0, 1, 0)
|
|
variable len = strlen(path)
|
|
if (numtype(len) == 0)
|
|
path += "elog_temp_cmd.bat"
|
|
variable f1
|
|
Open f1 as path
|
|
fprintf f1, cmd
|
|
Close f1
|
|
else
|
|
path = ""
|
|
endif
|
|
|
|
return path
|
|
end
|
|
|
|
static function /s get_log_path()
|
|
string path = SpecialDirPath("Temporary", 0, 1, 0)
|
|
variable len = strlen(path)
|
|
if (numtype(len) == 0)
|
|
path += "elog.log"
|
|
else
|
|
path = ""
|
|
endif
|
|
|
|
return path
|
|
end
|
|
|
|
/// delete temporary files created by the ELOG module.
|
|
///
|
|
/// this deletes all temporary graph files that are referenced by the volatile temp_graph_files list.
|
|
/// temp_graph_files is a semicolon-delimited string.
|
|
/// items are added by create_graph_file().
|
|
///
|
|
/// this function should be called before a new experiment is loaded or igor quits.
|
|
///
|
|
static function cleanup_temp_files()
|
|
dfref df_volatile_root = get_elog_df("", kdfVolatile)
|
|
if (DataFolderRefStatus(df_volatile_root))
|
|
svar /sdfr=df_volatile_root /z temp_graph_files
|
|
if (SVAR_Exists(temp_graph_files))
|
|
variable nfi = ItemsInList(temp_graph_files)
|
|
variable ifi
|
|
string sfi
|
|
for (ifi = 0; ifi < nfi; ifi += 1)
|
|
sfi = StringFromList(ifi, temp_graph_files)
|
|
DeleteFile /Z sfi
|
|
endfor
|
|
temp_graph_files = ""
|
|
endif
|
|
endif
|
|
return 0
|
|
end
|
|
|
|
static strconstant elog_success_msg = "Message successfully transmitted"
|
|
static strconstant elog_parse_id = "ID=%u"
|
|
|
|
/// parse the result file from an elog invokation.
|
|
///
|
|
/// @returns the ID of the generated message,
|
|
/// or a value <= 0 if an error occurred.
|
|
///
|
|
static function parse_result()
|
|
dfref df_general = get_elog_df("", kdfPersistent)
|
|
nvar /sdfr=df_general loglevel
|
|
|
|
string path = get_log_path()
|
|
string line = ""
|
|
string output = ""
|
|
variable success = 0
|
|
variable id = -1
|
|
string part1 = ""
|
|
string part2 = ""
|
|
|
|
variable len = strlen(path)
|
|
if (numtype(len) == 0)
|
|
variable f1
|
|
Open /R/Z f1 as path
|
|
if (v_flag == 0)
|
|
do
|
|
FReadLine f1, line
|
|
if (strlen(line) > 0)
|
|
part1 = StringFromList(0, line, ",")
|
|
part2 = ReplaceString(" ", StringFromList(1, line, ","), "")
|
|
success = cmpstr(part1, elog_success_msg) == 0
|
|
if (success)
|
|
sscanf part2, elog_parse_id, id
|
|
endif
|
|
else
|
|
break
|
|
endif
|
|
output += line
|
|
while(!success)
|
|
Close f1
|
|
endif
|
|
endif
|
|
if (loglevel >= 5)
|
|
print output
|
|
endif
|
|
|
|
return id
|
|
end
|
|
|
|
/// prompt to open or create a logbook
|
|
///
|
|
function /s elog_prompt_logbook()
|
|
string logbooks = list_logbooks(templates=0)
|
|
logbooks = AddListItem("(new)", logbooks)
|
|
string templates = list_logbooks(templates=1)
|
|
templates = AddListItem("(none)", templates)
|
|
|
|
string logbook = StringFromList(0, logbooks)
|
|
string template = StringFromList(0, logbooks)
|
|
string name = ""
|
|
string username = ""
|
|
string password = ""
|
|
|
|
prompt logbook, "logbook", popup logbooks
|
|
prompt template, "template", popup templates
|
|
prompt name, "new logbook name"
|
|
|
|
doprompt "select logbook", logbook, template, name
|
|
if (!v_flag)
|
|
if (cmpstr(logbook, "(new)") == 0)
|
|
elog_create_logbook(name, template=template)
|
|
logbook = name
|
|
endif
|
|
else
|
|
logbook = ""
|
|
endif
|
|
return logbook
|
|
end
|
|
|
|
/// prompt the user for login to a logbook
|
|
///
|
|
function elog_prompt_login(logbook)
|
|
string logbook
|
|
|
|
string logbooks = list_logbooks(templates=0)
|
|
|
|
string username = ""
|
|
string password = ""
|
|
|
|
prompt logbook, "logbook", popup logbooks
|
|
prompt username, "user name"
|
|
prompt password, "password (blank to log out)"
|
|
|
|
doprompt "log in to logbook", logbook, username, password
|
|
if (!v_flag)
|
|
elog_login(logbook, username, password)
|
|
endif
|
|
|
|
return v_flag
|
|
end
|
|
|
|
/// open a new panel for submitting data to ELOG.
|
|
///
|
|
/// this function creates only the panel but not the necessary data folders.
|
|
/// call init_package() and load_prefs() once before creating panels.
|
|
///
|
|
/// @param logbook name of the target logbook
|
|
///
|
|
function /s PearlElogPanel(logbook)
|
|
string logbook
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
dfref df_general = get_elog_df("", kdfPersistent)
|
|
dfref df_persistent = get_elog_df(logbook, kdfPersistent)
|
|
dfref df_volatile = get_elog_df(logbook, kdfVolatile)
|
|
|
|
string win_name = logbook + "ElogPanel"
|
|
string win_title = "ELOG " + logbook
|
|
|
|
NewPanel /K=1 /N=$win_name /W=(600,200,1200,700) as win_title
|
|
win_name = s_name
|
|
ModifyPanel /w=$win_name cbRGB=(52224,52224,65280)
|
|
|
|
svar /sdfr=df_persistent attributes
|
|
svar /sdfr=df_persistent controls
|
|
svar /sdfr=df_persistent options
|
|
wave /t /sdfr=df_volatile attach_list
|
|
wave /sdfr=df_volatile attach_sel
|
|
svar /sdfr=df_volatile url
|
|
|
|
variable iattr
|
|
variable nattr = ItemsInList(attributes, ";")
|
|
string s_attr
|
|
string s_control
|
|
string s_option
|
|
string persistent_path = GetDataFolder(1, df_persistent)
|
|
string volatile_path = GetDataFolder(1, df_volatile)
|
|
string options_path
|
|
string variable_path
|
|
variable ypos = 2
|
|
variable height = 0
|
|
|
|
for (iattr = 0; iattr < nattr; iattr += 1)
|
|
s_attr = StringFromList(iattr, attributes, ";")
|
|
s_control = StringFromList(iattr, controls, ";")
|
|
strswitch(s_control[0,1])
|
|
case "sv":
|
|
SetVariable $s_control, win=$win_name, pos={0,ypos}, size={300,16}, bodyWidth=230
|
|
SetVariable $s_control, win=$win_name, title=s_attr, value= _STR:""
|
|
SetVariable $s_control, win=$win_name, userdata(attribute)=s_attr
|
|
ypos += 18
|
|
break
|
|
case "pm":
|
|
options_path = persistent_path + StringByKey(s_attr, options, "=", ";")
|
|
PopupMenu $s_control, win=$win_name, pos={0,ypos}, size={300,21}, bodyWidth=230
|
|
PopupMenu $s_control, win=$win_name, title=s_attr
|
|
PopupMenu $s_control, win=$win_name, mode=1, popvalue="Test", value= #options_path
|
|
PopupMenu $s_control, win=$win_name, userdata(attribute)=s_attr
|
|
ypos += 23
|
|
break
|
|
case "cb":
|
|
CheckBox $s_control, win=$win_name, pos={70,ypos}, size={300,14}
|
|
CheckBox $s_control, win=$win_name, title=s_attr, value= 1
|
|
CheckBox $s_control, win=$win_name, userdata(attribute)=s_attr
|
|
ypos += 17
|
|
break
|
|
endswitch
|
|
endfor
|
|
|
|
TitleBox t_attach, win=$win_name, pos={308,5}, size={70,14}, title="Attachments", frame=0
|
|
height = ypos - 21 - 4
|
|
ListBox lb_attach, win=$win_name, pos={308,21}, size={264,height}
|
|
ListBox lb_attach, win=$win_name, listWave=attach_list
|
|
ListBox lb_attach, win=$win_name, mode=1, selWave=attach_sel, selRow=-1
|
|
ListBox lb_attach, win=$win_name, widths={20,160,80}
|
|
ListBox lb_attach, win=$win_name, help={"Choose graphs to attach to the message."}
|
|
|
|
Button b_attach_top, win=$win_name, pos={420,2}, size={40,18}, title="top"
|
|
Button b_attach_top, win=$win_name, fcolor=(56576,60928,47872)
|
|
Button b_attach_top, win=$win_name, proc=PearlElog#bp_attach_top
|
|
Button b_attach_top, win=$win_name, help={"Select top graph for attachment."}
|
|
Button b_attach_all, win=$win_name, pos={460,2}, size={40,18}, title="all"
|
|
Button b_attach_all, win=$win_name, fcolor=(56576,60928,47872)
|
|
Button b_attach_all, win=$win_name, proc=PearlElog#bp_attach_allnone
|
|
Button b_attach_all, win=$win_name, help={"Select all graphs for attachment."}
|
|
Button b_attach_none, win=$win_name, pos={500,2}, size={40,18}, title="none"
|
|
Button b_attach_none, win=$win_name, fcolor=(56576,60928,47872)
|
|
Button b_attach_none, win=$win_name, proc=PearlElog#bp_attach_allnone
|
|
Button b_attach_none, win=$win_name, help={"Deselect all attachments."}
|
|
Button b_save_graphs, win=$win_name, pos={540,2}, size={40,18}, title="save"
|
|
Button b_save_graphs, win=$win_name, fcolor=(56576,60928,47872)
|
|
Button b_save_graphs, win=$win_name, proc=PearlElog#bp_save_graphs
|
|
Button b_save_graphs, win=$win_name, help={"Save selected graphs as PNG bitmap files."}
|
|
Button b_attach_up, win=$win_name, pos={576,20}, size={20,20}, title="\\W517"
|
|
Button b_attach_up, win=$win_name, fcolor=(56576,60928,47872)
|
|
Button b_attach_up, win=$win_name, proc=PearlElog#bp_attach_updown
|
|
Button b_attach_up, win=$win_name, help={"Move selected graph up."}
|
|
Button b_attach_dw, win=$win_name, pos={576,40}, size={20,20}, title="\\W523"
|
|
Button b_attach_dw, win=$win_name, fcolor=(56576,60928,47872)
|
|
Button b_attach_dw, win=$win_name, proc=PearlElog#bp_attach_updown
|
|
Button b_attach_dw, win=$win_name, help={"Move selected graph down."}
|
|
|
|
ypos += 246-160
|
|
Button b_submit,win=$win_name, pos={70,ypos},size={46,20},proc=PearlElog#bp_submit,title="Submit"
|
|
Button b_submit,win=$win_name, help={"Submit form data to ELOG (new entry)."}
|
|
Button b_submit,win=$win_name, fcolor=(56576,60928,47872)
|
|
Button b_clear,win=$win_name, pos={120,ypos},size={46,20},proc=PearlElog#bp_clear,title="Clear"
|
|
Button b_clear,win=$win_name, help={"Clear the form fields"}
|
|
Button b_clear,win=$win_name, fcolor=(56576,60928,47872)
|
|
|
|
ypos += 272-246
|
|
variable_path = volatile_path + "msg_id"
|
|
SetVariable sv_id,win=$win_name, pos={51,ypos},size={119,16},bodyWidth=77
|
|
SetVariable sv_id,win=$win_name, title="ID",value=$variable_path
|
|
SetVariable sv_id,win=$win_name, help={"ID of last submitted message, or message to attach or reply to."}
|
|
|
|
TitleBox t_host, win=$win_name, pos={170,ypos+4}, size={112.00,14.00}, frame=0
|
|
TitleBox t_host, win=$win_name, variable=url
|
|
|
|
ypos += 270-272
|
|
Button b_attach,win=$win_name, pos={170,ypos},size={48,20},proc=PearlElog#bp_attach,title="Attach"
|
|
Button b_attach,win=$win_name, help={"Attach the selected graph to an existing ELOG entry (correct ID required)."}
|
|
Button b_attach,win=$win_name, fcolor=(56576,60928,47872)
|
|
Button b_reply,win=$win_name, pos={220,ypos},size={48,20},proc=PearlElog#bp_submit,title="Reply"
|
|
Button b_reply,win=$win_name, help={"Submit form data to ELOG as a reply to an existing message (correct ID required)."}
|
|
Button b_reply,win=$win_name, fcolor=(56576,60928,47872)
|
|
Button b_login,win=$win_name, pos={550,ypos},size={46,20},proc=PearlElog#bp_login,title="Login"
|
|
Button b_login,win=$win_name, help={"Enter user name and password."}
|
|
Button b_login,win=$win_name, fcolor=(56576,60928,47872)
|
|
Button b_logout,win=$win_name, pos={550,ypos},size={46,20},proc=PearlElog#bp_logout,title="Logout"
|
|
Button b_logout,win=$win_name, help={"Clear user name and password."}
|
|
Button b_logout,win=$win_name, fcolor=(56576,60928,47872), disable=3
|
|
|
|
SetWindow $win_name, hook(elogPanelHook)=PearlElog#elog_panel_hook
|
|
SetWindow $win_name, userdata(logbook)=logbook
|
|
|
|
ypos += 160-270
|
|
TitleBox t_message,win=$win_name, pos={10,ypos},size={58,16},fixedSize=1,frame=0,anchor=RT,title="Message"
|
|
DefineGuide UGH0={FT,ypos},UGV0={FL,70},UGH1={FB,-52},UGV1={FR,-2}
|
|
NewNotebook /F=0 /N=Message /OPTS=3 /W=(115,404,345,341)/FG=(UGV0,UGH0,UGV1,UGH1) /HOST=#
|
|
Notebook kwTopWin, defaultTab=20, statusWidth=0, autoSave=0
|
|
Notebook kwTopWin fSize=10, fStyle=0, textRGB=(0,0,0)
|
|
RenameWindow #,Message
|
|
string nb_name = win_name + "#Message"
|
|
SetActiveSubwindow ##
|
|
|
|
// restore recently used attributes and message
|
|
svar /z /sdfr=df_persistent recent
|
|
if (svar_exists(recent) && (strlen(recent) > 0))
|
|
set_panel_attributes(win_name, recent)
|
|
endif
|
|
svar /z /sdfr=df_persistent recent_message
|
|
if (svar_exists(recent_message) && (strlen(recent_message) > 0))
|
|
set_panel_message(win_name, recent_message)
|
|
endif
|
|
Notebook $nb_name selection={startOfFile,startOfFile}, findText={"",1}
|
|
|
|
setdatafolder savedf
|
|
return win_name
|
|
end
|
|
|
|
static function elog_panel_hook(s)
|
|
STRUCT WMWinHookStruct &s
|
|
|
|
Variable hookResult = 0
|
|
|
|
switch(s.eventCode)
|
|
case 0: // activate
|
|
string logbook = GetUserData(s.winName, "", "logbook")
|
|
if (strlen(logbook) > 0)
|
|
dfref df_volatile = get_elog_df(logbook, kdfVolatile)
|
|
svar /sdfr=df_volatile url
|
|
url = format_url(logbook)
|
|
update_attach_items(logbook)
|
|
endif
|
|
break
|
|
case 6: // resize
|
|
// move bottom-aligned controls when the window is resized
|
|
variable b_top = s.winRect.bottom + 4
|
|
Button b_submit,pos={70,b_top}
|
|
Button b_clear,pos={120,b_top}
|
|
TitleBox t_host, pos={170,b_top+4}
|
|
b_top += 24
|
|
Button b_attach,pos={170,b_top}
|
|
Button b_reply,pos={220,b_top}
|
|
Button b_login, pos={550,b_top}
|
|
Button b_logout, pos={550,b_top}
|
|
b_top += 2
|
|
SetVariable sv_id,pos={51,b_top}
|
|
break
|
|
endswitch
|
|
|
|
return hookResult // 0 if nothing done, else 1
|
|
end
|
|
|
|
static constant kAttachColSel = 0
|
|
static constant kAttachColTitle = 1
|
|
static constant kAttachColName = 2
|
|
|
|
/// update the list of attachments
|
|
static function update_attach_items(logbook)
|
|
string logbook
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
dfref df_volatile = get_elog_df(logbook, kdfVolatile)
|
|
wave /t /sdfr=df_volatile attach_list
|
|
wave /sdfr=df_volatile attach_sel
|
|
|
|
if (!waveexists(attach_list))
|
|
return -1
|
|
endif
|
|
string names = WinList("*", ";", "WIN:1;VISIBLE:1")
|
|
names = SortList(names, ";", 16)
|
|
|
|
// remove closed graphs
|
|
variable i
|
|
variable k
|
|
variable n = DimSize(attach_list, 0)
|
|
string s
|
|
for (i = n-1; i >= 0; i -= 1)
|
|
s = attach_list[i][kAttachColName]
|
|
if (WhichListItem(s, names) < 0)
|
|
DeletePoints /M=0 i, 1, attach_list, attach_sel
|
|
endif
|
|
endfor
|
|
|
|
// add new graphs
|
|
n = ItemsInList(names)
|
|
for (i = 0; i < n; i += 1)
|
|
s = StringFromList(i, names)
|
|
FindValue /text=s /txop=4 /z attach_list
|
|
if (v_value < 0)
|
|
k = DimSize(attach_list, 0)
|
|
Redimension /n=(k+1,3) attach_list, attach_sel
|
|
//InsertPoints /M=0 k, 1, attach_list, attach_sel
|
|
attach_list[k][kAttachColSel] = ""
|
|
attach_list[k][kAttachColTitle] = ""
|
|
attach_list[k][kAttachColName] = s
|
|
attach_sel[k][kAttachColSel] = 32
|
|
attach_sel[k][kAttachColTitle] = 0
|
|
attach_sel[k][kAttachColName] = 0
|
|
endif
|
|
endfor
|
|
|
|
// update titles
|
|
n = DimSize(attach_list, 0)
|
|
for (i = n-1; i >= 0; i -= 1)
|
|
s = attach_list[i][kAttachColName]
|
|
getwindow /z $s, wtitle
|
|
if (v_flag == 0)
|
|
attach_list[i][kAttachColTitle] = s_value
|
|
else
|
|
attach_list[i][kAttachColTitle] = s
|
|
endif
|
|
endfor
|
|
|
|
setdatafolder savedf
|
|
return 0
|
|
end
|
|
|
|
/// move an attachment item in the list of attachments
|
|
static function move_attach_item(logbook, item, distance)
|
|
string logbook
|
|
variable item
|
|
variable distance
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
dfref df_volatile = get_elog_df(logbook, kdfVolatile)
|
|
wave /t /sdfr=df_volatile attach_list
|
|
wave /sdfr=df_volatile attach_sel
|
|
variable n = DimSize(attach_list, 0)
|
|
variable dest = item + distance
|
|
|
|
if ((item >= 0) && (item < n) && (dest >= 0) && (dest < n))
|
|
string name = attach_list[item][kAttachColName]
|
|
variable sel = attach_sel[item][kAttachColSel]
|
|
DeletePoints /M=0 item, 1, attach_list, attach_sel
|
|
InsertPoints /M=0 dest, 1, attach_list, attach_sel
|
|
attach_list[dest][kAttachColName] = name
|
|
update_attach_items(logbook)
|
|
attach_sel[dest][kAttachColSel] = sel
|
|
endif
|
|
end
|
|
|
|
/// button procedure for the attachment up and down buttons
|
|
static function bp_attach_updown(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string logbook = GetUserData(ba.win, "", "logbook")
|
|
ControlInfo /w=$ba.win lb_attach
|
|
variable row = v_value
|
|
dfref df = $s_datafolder
|
|
wave /t /sdfr=df attach_list = $s_value
|
|
if (cmpstr(ba.ctrlName, "b_attach_up") == 0)
|
|
// up button
|
|
if (row >= 1)
|
|
move_attach_item(logbook, row, -1)
|
|
ListBox lb_attach, win=$ba.win, selRow=(row-1)
|
|
endif
|
|
else
|
|
// down button
|
|
if (row < DimSize(attach_list, 0) - 1)
|
|
move_attach_item(logbook, row, +1)
|
|
ListBox lb_attach, win=$ba.win, selRow=(row+1)
|
|
endif
|
|
endif
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
/// button procedure for the Submit and Reply buttons
|
|
static function bp_submit(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string logbook = GetUserData(ba.win, "", "logbook")
|
|
string attributes
|
|
string message
|
|
string graphs
|
|
attributes = get_panel_attributes(ba.win)
|
|
message = get_panel_message(ba.win)
|
|
graphs = get_panel_graphs(ba.win)
|
|
|
|
variable id
|
|
if (cmpstr(ba.ctrlName, "b_reply") == 0)
|
|
// Reply button
|
|
ControlInfo /w=$ba.win sv_id
|
|
id = v_value
|
|
else
|
|
// Submit button
|
|
id = 0
|
|
endif
|
|
|
|
if ((elog_validate_attributes(logbook, attributes) == 0) && (strlen(message) > 0))
|
|
variable result
|
|
result = elog_create_entry(logbook, attributes, message, graphs=graphs, replyto=id)
|
|
if (result == 0)
|
|
dfref df = get_elog_df(logbook, kdfPersistent)
|
|
svar /sdfr=df recent
|
|
recent = attributes
|
|
svar /sdfr=df recent_message
|
|
recent_message = message
|
|
else
|
|
abort "Submission failed. Error code " + num2str(result) + "."
|
|
endif
|
|
else
|
|
abort "Submission failed due to missing/invalid attribute."
|
|
endif
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
/// select top graph window for attachment
|
|
static function bp_attach_top(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string graphs = WinName(0, 1, 1)
|
|
set_panel_graphs(ba.win, graphs)
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
/// select/deselect all graph windows for attachment
|
|
static function bp_attach_allnone(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string logbook = GetUserData(ba.win, "", "logbook")
|
|
dfref df_volatile = get_elog_df(logbook, kdfVolatile)
|
|
wave /sdfr=df_volatile attach_sel
|
|
if (cmpstr(ba.ctrlName, "b_attach_all") == 0)
|
|
attach_sel[][kAttachColSel] = attach_sel[p][kAttachColSel] | 16
|
|
else
|
|
attach_sel[][kAttachColSel] = attach_sel[p][kAttachColSel] & ~16
|
|
endif
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
static function bp_attach(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string logbook = GetUserData(ba.win, "", "logbook")
|
|
string graphs
|
|
graphs = get_panel_graphs(ba.win)
|
|
|
|
variable id
|
|
ControlInfo /w=$ba.win sv_id
|
|
id = v_value
|
|
|
|
// TODO : is there a way around this restriction?
|
|
DoAlert /T="ELOG" 1, "This operation will replace all existing attachments. Do you want to continue?"
|
|
|
|
if ((id > 0) && (v_flag == 1))
|
|
variable result
|
|
result = elog_add_attachment(logbook, id, graphs)
|
|
if (result != 0)
|
|
abort "Submission failed. Error code " + num2str(result) + "."
|
|
endif
|
|
else
|
|
abort "Submission failed due to missing/invalid attribute."
|
|
endif
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
static function bp_save_graphs(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string logbook = GetUserData(ba.win, "", "logbook")
|
|
string graphs = get_panel_graphs(ba.win)
|
|
variable ngraphs = ItemsInList(graphs, ";")
|
|
|
|
variable igraph
|
|
string sgraph
|
|
string graph_path
|
|
for (igraph = 0; igraph < ngraphs; igraph += 1)
|
|
sgraph = StringFromList(igraph, graphs, ";")
|
|
graph_path = create_graph_file(sgraph, igraph)
|
|
if (strlen(graph_path) > 0)
|
|
print graph_path
|
|
endif
|
|
endfor
|
|
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
static function bp_clear(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
set_panel_attributes(ba.win, "", clear=1)
|
|
set_panel_message(ba.win, "")
|
|
set_panel_graphs(ba.win, "")
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
static function bp_login(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string logbook = GetUserData(ba.win, "", "logbook")
|
|
if (elog_prompt_login(logbook) == 0)
|
|
Button b_login, win=$ba.win, disable=3
|
|
Button b_logout, win=$ba.win, disable=0
|
|
endif
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
static function bp_logout(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string logbook = GetUserData(ba.win, "", "logbook")
|
|
elog_logout(logbook)
|
|
Button b_login, win=$ba.win, disable=0
|
|
Button b_logout, win=$ba.win, disable=3
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
static function /s get_default_panel_name()
|
|
string windowname
|
|
windowname = StringFromList(0, WinList("*ElogPanel*", ";", "WIN:64"), ";")
|
|
return windowname
|
|
end
|
|
|
|
/// get a list of attributes from the fields of the ELOG panel.
|
|
///
|
|
/// @param windowname window name of the ELOG panel
|
|
/// if empty, use default name "PearlElogPanel"
|
|
///
|
|
/// @return list of attributes to in the format <code>"key1=value1;key2=value2"</code>.
|
|
///
|
|
static function /s get_panel_attributes(windowname)
|
|
string windowname
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
if (strlen(windowname) == 0)
|
|
return ""
|
|
endif
|
|
|
|
string controls = ControlNameList(windowname, ";")
|
|
string attributes = ""
|
|
string control
|
|
string attribute
|
|
variable ico
|
|
variable nco = ItemsInList(controls, ";")
|
|
for (ico = 0; ico < nco; ico += 1)
|
|
control = StringFromList(ico, controls, ";")
|
|
attribute = GetUserData(windowname, control, "attribute")
|
|
if (strlen(attribute) > 0)
|
|
ControlInfo /w=$windowname $control
|
|
switch(v_flag)
|
|
case 2: // checkbox
|
|
attributes = ReplaceNumberByKey(attribute, attributes, v_value, "=", ";")
|
|
break
|
|
case 3: // popupmenu
|
|
case 5: // setvariable
|
|
attributes = ReplaceStringByKey(attribute, attributes, s_value, "=", ";")
|
|
break
|
|
endswitch
|
|
endif
|
|
endfor
|
|
|
|
return attributes
|
|
end
|
|
|
|
/// set the fields of the ELOG panel
|
|
///
|
|
/// @param windowname window name of the ELOG panel
|
|
/// if empty, use default name "PearlElogPanel"
|
|
///
|
|
/// @param attributes list of attributes to set (format "key1=value1;key2=value2")
|
|
///
|
|
/// @param clear what to do if a key is missing in attributes?
|
|
/// @arg 0 (default) leave the field unchanged
|
|
/// @arg 1 clear the field
|
|
///
|
|
static function /s set_panel_attributes(windowname, attributes, [clear])
|
|
string windowname
|
|
string attributes
|
|
variable clear
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
if (strlen(windowname) == 0)
|
|
return ""
|
|
endif
|
|
if (ParamIsDefault(clear))
|
|
clear = 0
|
|
endif
|
|
|
|
string path
|
|
|
|
string controls = ControlNameList(windowname, ";")
|
|
string control
|
|
string attribute
|
|
string value
|
|
variable numval
|
|
variable ico
|
|
variable nco = ItemsInList(controls, ";")
|
|
for (ico = 0; ico < nco; ico += 1)
|
|
control = StringFromList(ico, controls, ";")
|
|
attribute = GetUserData(windowname, control, "attribute")
|
|
if (strlen(attribute))
|
|
value = StringByKey(attribute, attributes, "=", ";")
|
|
if (strlen(value) || clear)
|
|
ControlInfo /w=$windowname $control
|
|
switch(v_flag)
|
|
case 2: // checkbox
|
|
numval = NumberByKey(attribute, attributes, "=", ";")
|
|
if ((numtype(numval) != 0) && clear)
|
|
numval = 0
|
|
endif
|
|
if (numtype(numval) == 0)
|
|
CheckBox $control, value=numval, win=$windowname
|
|
endif
|
|
break
|
|
case 3: // popupmenu
|
|
PopupMenu $control, popvalue=value, win=$windowname
|
|
break
|
|
case 5: // setvariable
|
|
SetVariable /z $control, value= _STR:value, win=$windowname
|
|
break
|
|
endswitch
|
|
endif
|
|
endif
|
|
endfor
|
|
|
|
return attributes
|
|
end
|
|
|
|
/// get the message field of the ELOG panel
|
|
///
|
|
/// @param windowname window name of the ELOG panel
|
|
/// if empty, use default name "PearlElogPanel"
|
|
///
|
|
/// @return message text
|
|
///
|
|
static function /s get_panel_message(windowname)
|
|
string windowname
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
if (strlen(windowname) == 0)
|
|
return ""
|
|
endif
|
|
|
|
string nb = windowname + "#Message"
|
|
notebook $nb selection={startOfFile, endOfFile}
|
|
getselection notebook, $nb, 2
|
|
|
|
return s_selection
|
|
end
|
|
|
|
/// set the message field of the ELOG panel
|
|
///
|
|
/// @param windowname window name of the ELOG panel
|
|
/// if empty, use default name "PearlElogPanel"
|
|
///
|
|
/// @param message message text that can be passed to the @c Notebook operation.
|
|
///
|
|
/// @return original message (unchanged)
|
|
///
|
|
static function /s set_panel_message(windowname, message)
|
|
string windowname
|
|
string message
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
|
|
string nb = windowname + "#Message"
|
|
notebook $nb selection={startOfFile, endOfFile},text=message
|
|
|
|
return message
|
|
end
|
|
|
|
/// get the names of the graphs selected for attachment
|
|
///
|
|
/// @param windowname panel window name
|
|
/// @returns a semicolon-separated list,
|
|
/// or the empty string if the selection is not valid.
|
|
///
|
|
static function /s get_panel_graphs(windowname)
|
|
string windowname // panel window name
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
if (strlen(windowname) == 0)
|
|
return ""
|
|
endif
|
|
|
|
string logbook = GetUserData(windowname, "", "logbook")
|
|
dfref df_volatile = get_elog_df(logbook, kdfVolatile)
|
|
wave /t /sdfr=df_volatile attach_list
|
|
wave /sdfr=df_volatile attach_sel
|
|
string graphs = ""
|
|
string windows = ""
|
|
string graphname
|
|
|
|
variable n = DimSize(attach_sel, 0)
|
|
variable i
|
|
for (i = 0; i < n; i += 1)
|
|
if (attach_sel[i][kAttachColSel] & 16)
|
|
graphname = attach_list[i][kAttachColName]
|
|
windows = WinList(graphname, ";", "WIN:1")
|
|
if (ItemsInList(windows) == 1)
|
|
graphs = AddListItem(graphname, graphs, ";", inf)
|
|
endif
|
|
endif
|
|
endfor
|
|
|
|
return graphs
|
|
end
|
|
|
|
/// update selection of graphs for attachment
|
|
///
|
|
/// @param windowname panel window name. looks for default panel if empty.
|
|
///
|
|
/// @param graphs semicolon-separated list of names of graph windows to select for attachment.
|
|
///
|
|
static function /s set_panel_graphs(windowname, graphs)
|
|
string windowname
|
|
string graphs
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
if (strlen(windowname) == 0)
|
|
return ""
|
|
endif
|
|
|
|
string logbook = GetUserData(windowname, "", "logbook")
|
|
update_attach_items(logbook)
|
|
dfref df_volatile = get_elog_df(logbook, kdfVolatile)
|
|
wave /t /sdfr=df_volatile attach_list
|
|
wave /sdfr=df_volatile attach_sel
|
|
|
|
variable n = DimSize(attach_sel, 0)
|
|
variable i
|
|
string graphname
|
|
for (i = 0; i < n; i += 1)
|
|
graphname = attach_list[i][kAttachColName]
|
|
if (WhichListItem(graphname, graphs)>= 0)
|
|
attach_sel[i][kAttachColSel] = 48
|
|
else
|
|
attach_sel[i][kAttachColSel] = 32
|
|
endif
|
|
endfor
|
|
end |