#pragma rtGlobals=3 #pragma version = 1.00 #pragma IgorVersion = 6.36 #pragma ModuleName = PearlMatrixImport // author: matthias.muntwiler@psi.ch // Copyright (c) 2016 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 data file import for omicron matrix (STM) files /// /// the matrix file import requires the matrix file reader XOP by thomas braun /// (http://www.igorexchange.com/project/matrixFileReader) /// which in turn requires an installation of vernissage by omicron nanotechnology. /// /// @warning EXPERIMENTAL /// the matrix import module and its interface may change radically in future revisions! /// /// @author matthias muntwiler, matthias.muntwiler@psi.ch /// /// @copyright 2016 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 PearlMatrixImport /// @brief data file import for omicron matrix (STM) files /// /// PearlMatrixImport is declared in @ref pearl-matrix-import.ipf. static strconstant package_name = "pearl_matrix_import" static strconstant package_path = "root:packages:pearl_matrix_import:" static strconstant ks_filematch_mtrx = "*_mtrx" /// initialize the package data folder. /// /// static function init_package() dfref savedf = getdatafolderdfr() setdatafolder root: newdatafolder /o/s packages newdatafolder /o/s $package_name variable /g loglevel = 3 string /g dataFilePath = "" string /g resultFilePath = "" variable /g runCycle = 0 variable /g scanCycle = 0 string /g channelName = "" variable /g brickletID = 0 variable /g V_MatrixFileReaderOverwrite = 1 variable /g V_MatrixFileReaderFolder = 0 variable /g V_MatrixFileReaderDouble = 0 setdatafolder savedf return 0 end /// check that the package data folder exists /// /// initialize the package if the folder does not exist. /// static function check_package_folder() dfref df_pack = $(package_path) if (DataFolderRefStatus(df_pack)) svar /sdfr=df_pack /z resultFilePath if (!svar_exists(resultFilePath)) init_package() endif else init_package() endif 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() //load_prefs() endif return 0 end /// open a matrix file that was dropped into Igor. /// /// preliminary implementation. /// this should rather load the entire file and display a preview. /// graph windows should be reused by subsequent loads. /// also decide on a data saving location. /// static function BeforeFileOpenHook(refNum,fileName,path,type,creator,kind) Variable refNum,kind String fileName,path,type,creator Variable handledOpen = 0 if (StringMatch(fileName, ks_filematch_mtrx)) setdatafolder root: newdatafolder /o /s matrix mtrx_load_preview("matrix", path, fileName) handledOpen = 1 endif return handledOpen End /// generate elog message from bricklet metadata /// /// @param metadata two-column text wave /// function /s matrix_format_elog_message(metadata) wave /t metadata string key string value variable nkeys = dimsize(metadata, 0) variable ikey string message_keys message_keys = "resultFileName;sampleName;channelName;" message_keys += "XYScanner.Points.value;XYScanner.Raster_Time.value;XYScanner.Raster_Time.unit;XYScanner.Width.value;XYScanner.Width.unit;XYScanner.Height.value;XYScanner.Height.unit;" message_keys += "GapVoltageControl.Voltage.value;GapVoltageControl.Voltage.unit;" message_keys += "Regulator.Loop_Gain_1_I.value;Regulator.Loop_Gain_1_I.unit;Regulator.Setpoint_1.value;Regulator.Setpoint_1.unit;" message_keys += "Spectroscopy.Device_1_Start.value;Spectroscopy.Device_1_Start.unit;Spectroscopy.Spectroscopy_Mode.value;" string message message_keys = "" for (ikey = 0; ikey < nkeys; ikey += 1) key = metadata[ikey][0] value = metadata[ikey][1] if (WhichListItem(key, message_keys) >= 0) message += key + " = " + value + "\r" endif endfor end function matrix_preview_2d(data, metadata) wave data wave /t metadata Display AppendImage data ModifyImage data ctab= {*,*,Mud,0} ModifyGraph margin(left)=30,margin(bottom)=30,margin(top)=5,margin(right)=5,height={Plan,1,left,bottom} ModifyGraph mirror=2 ModifyGraph nticks=3 ModifyGraph axThick=0.5 ModifyGraph btLen=4 end /// load the preview of a Matrix data file /// /// the preview is loaded to the preview_image wave in the pearl_explorer data folder. /// /// the s_file_info string is updated with information about the scan dimensions. /// /// @param filename name of a file in the directory specified by the pearl_explorer_filepath path object. /// /// @return wave reference of the preview image /// static function /wave preview_matrix_file(filename) string filename dfref saveDF = GetDataFolderDFR() setdatafolder $package_path svar s_preview_file svar s_preview_source mtrx_load_preview("preview_image", "pearl_explorer_filepath", filename) s_preview_file = filename s_preview_source = "" wave /z preview_image svar /z s_file_info if (! svar_exists(s_file_info)) string /g s_file_info endif if (strlen(s_preview_file) > 0) s_file_info = mtrx_load_info("pearl_explorer_filepath", filename) else s_file_info = "" endif setdatafolder saveDF return preview_image end /// from matrixfilereader help Structure errorCode int32 SUCCESS int32 UNKNOWN_ERROR int32 ALREADY_FILE_OPEN int32 EMPTY_RESULTFILE int32 FILE_NOT_READABLE int32 NO_NEW_BRICKLETS int32 WRONG_PARAMETER int32 INTERNAL_ERROR_CONVERTING_DATA int32 NO_FILE_OPEN int32 INVALID_RANGE int32 WAVE_EXIST EndStructure /// from matrixfilereader help static Function initStruct(errorCode) Struct errorCode &errorCode errorCode.SUCCESS =0 errorCode.UNKNOWN_ERROR=10001 errorCode.ALREADY_FILE_OPEN=10002 errorCode.EMPTY_RESULTFILE=10004 errorCode.FILE_NOT_READABLE=10008 errorCode.NO_NEW_BRICKLETS=10016 errorCode.WRONG_PARAMETER=10032 errorCode.INTERNAL_ERROR_CONVERTING_DATA=10064 errorCode.NO_FILE_OPEN=10128 errorCode.INVALID_RANGE=10256 errorCode.WAVE_EXIST=10512 end /// load all data from a Matrix data file. /// function mtrx_load_all() struct errorCode errorCode initStruct(errorCode) #if exists("MFR_OpenResultFile") MFR_OpenResultFile if(V_flag != errorCode.SUCCESS) MFR_GetXOPErrorMessage return -1 endif MFR_GetBrickletData if(V_flag != errorCode.SUCCESS) MFR_GetXOPErrorMessage return -1 endif MFR_GetBrickletMetaData if(V_flag != errorCode.SUCCESS) MFR_GetXOPErrorMessage return -1 endif return 0 #else return -1 #endif end /// parse matrix file names /// /// parse matrix file names for result name, run cycle, scan cycle, and channel. /// /// @param fileName matrix result or data file name (without path). /// /// @param resultFile (out) base name of the result file. /// append "_%04u.mtrx" to get the actual result file. /// we do not know the chain link number at this stage. /// /// @param runCycle (out) run cycle number. necessary to look up the bricklet ID. /// /// @param scanCycle (out) scan cycle number. necessary to look up the bricklet ID. /// /// @param channel (out) channel name. /// /// @return file type /// @arg 0 result file (logbook) /// @arg 1 result data file (bricklet) /// /// result file names look like: /// default_2015Apr20-124353_STM-STM_AtomManipulation_0001.mtrx, /// default_2015Apr20-124353_STM-STM_AtomManipulation_0002.mtrx, etc. /// the function returns the first part up to the experiment name ("AtomManipulation" in the examples). /// all other return values set to defaults and must not be regarded. /// /// result data files look like: /// default_2015Apr20-124353_STM-STM_AtomManipulation--136_1.Aux1(V)_mtrx, /// default_2015Apr20-124353_STM-STM_AtomManipulation--136_1.I(V)_mtrx, /// default_2015Apr20-124353_STM-STM_AtomManipulation--14_1.I_mtrx, /// default_2015Apr20-124353_STM-STM_AtomManipulation--14_1.Z_mtrx, etc. /// the function returns all results as described in the parameter list. /// function mtrx_parse_filename(fileName, resultFile, runCycle, scanCycle, channel) string fileName string &resultFile variable &runCycle variable &scanCycle string &channel variable fileType = 0 resultFile = "" channel = "" runCycle = 0 scanCycle = 0 string regexp = "" string index1 = "" string index2 = "" string extension = "" if (StringMatch(fileName, "*.mtrx")) regexp = "(.+)_([[:digit:]]+)\.(.+)" SplitString /E=regexp fileName, resultFile, index1, extension fileType = 0 else regexp = "(.+)--([[:digit:]]+)_([[:digit:]]+)\.((.+)_mtrx)" SplitString /E=regexp fileName, resultFile, index1, index2, extension, channel fileType = 1 runCycle = str2num(index1) scanCycle = str2num(index2) endif return fileType end /// split a matrix filename and return the first three parts /// /// we assume that the second (third) part contains the date (time). /// the parts are separated by dash or underscore. /// function /s mtrx_split_filename(fileName, prefix, datepart, timepart) string fileName string &prefix string &datepart string &timepart string regexp regexp = "([[:alpha:][:digit:]]+)[-_]([[:alpha:][:digit:]]+)[-_]([[:alpha:][:digit:]]+)[-_].+" SplitString /E=regexp fileName, prefix, datepart, timepart return datepart end /// create or look up a data folder based on a matrix file name. /// /// the name of the folder is mtrx_date_time, where date and time are parsed from the file name. /// for this to work, the file name must consist of at least three parts that are separated by dash or underscore. /// the second (third) part contains the date (time). /// date and time are copied as strings. /// /// if the data folder exists, a reference to the existing folder is returned. /// /// @param fileName name of the result or data file. /// /// @param df_base (optional) base data folder. /// default: current folder. /// /// @return reference of the newly created or existing data folder. /// function /df mtrx_create_folder(fileName, [df_base]) string fileName dfref df_base if (ParamIsDefault(df_base)) df_base = GetDataFolderDFR() endif string prefix string datepart string timepart string folderName mtrx_split_filename(fileName, prefix, datepart, timepart) folderName = "mtrx_" + datepart + "_" + timepart folderName = CleanupName(folderName, 0) dfref df_save = GetDataFolderDFR() setdatafolder root: newdatafolder /o /s $foldername dfref df = GetDataFolderDFR() setdatafolder df_save return df end /// create a data folder for bricklet data. /// /// the name of the folder is, for example "r23s2" where the first (second) number is the run (scan) cycle. /// run cycle and scan cycle numbers are taken from the open matrix file unless overridden by optional arguments. /// /// if the data folder exists, a reference to the existing folder is returned. /// if one of the run or scan cycle numbers is lower than 1, the base folder is returned. /// /// @param df_base (optional) base data folder. /// default: current folder. /// /// @param runCycle (optional) run cycle number. must be >= 1. /// default: from last mtrx_open_file call. /// /// @param scanCycle (optional) scan cycle number. must be >= 1. /// default: from last mtrx_open_file call. /// /// @return reference of the newly created or existing data folder. /// function /df mtrx_get_cycle_folder([df_base, runCycle, scanCycle]) dfref df_base variable runCycle variable scanCycle dfref df_save = GetDataFolderDFR() dfref df_pack = $(package_path) if (ParamIsDefault(df_base)) df_base = GetDataFolderDFR() endif if (ParamIsDefault(runCycle)) nvar /sdfr=df_pack defRunCycle = runCycle runCycle = defRunCycle endif if (ParamIsDefault(scanCycle)) nvar /sdfr=df_pack defScanCycle = scanCycle scanCycle = defScanCycle endif string dfname if ((runCycle >= 1) && (scanCycle >= 1)) sprintf dfname, "r%us%u", runCycle, scanCycle setdatafolder df_base dfref df = $dfname if (DataFolderRefStatus(df) == 0) newdatafolder $dfname dfref df = $dfname endif else dfref df = df_base endif setdatafolder df_save return df end /// find out bricklet ID of a file /// /// @warning EXPERIMENTAL /// the code of this function is inefficient. /// the function may be removed in a later version. /// /// @param resultFile base name of result file without chain link number and extension. /// as returned by mtrx_parse_filename. /// /// @param runCycle requested run cycle. /// 0 = first available. /// /// @param scanCycle requested scan cycle. /// 0 = first available. /// /// @param channel channel name. for example: "I", "Z", "Aux(V)", etc. /// empty string: first available. /// /// @return bricklet ID, or -1 if an error occurred. /// function mtrx_file_brickletID(resultFile, runCycle, scanCycle, channel) string resultFile variable runCycle variable scanCycle string channel dfref df_overview = NewFreeDataFolder() variable link = 1 variable id = -1 variable idx = 0 string resultFileName #if exists("MFR_OpenResultFile") struct errorCode errorCode initStruct(errorCode) do sprintf resultFileName, "%s_%04u.mtrx", resultFile, link MFR_OpenResultFile /K resultFileName if(V_flag != errorCode.SUCCESS) return -1 endif MFR_CreateOverviewTable /DEST=df_overview // dimension labels are: brickletID, scanCycleCount, runCycleCount, sequenceID, dimension, channelName wave /t /sdfr=df_overview overviewTable make /n=(dimsize(overviewTable, 0)) /i /u /free runcycles, scancycles, ids, match make /n=(dimsize(overviewTable, 0)) /t /free channels ids = str2num(overviewtable[p][%brickletID]) if (runcycle > 0) runcycles = str2num(overviewtable[p][%runCycleCount]) else runcycles = runcycle endif if (scancycle > 0) scancycles = str2num(overviewtable[p][%scanCycleCount]) else scancycles = scancycle endif if (strlen(channel) > 0) channels = overviewTable[p][%channelName] else channels = channel endif Extract /FREE ids, match_ids, (scancycles == scanCycle) && (runcycles == runCycle) && (cmpstr(channels, channel) == 0) if (numpnts(match_ids) > 0) id = match_ids[0] else link += 1 endif while (id < 0) #endif return id end /// open a matrix result or data file /// /// this function opens a matrix result file (.mtrx) or data file (.*_mtrx). /// /// if a data file is selected, the function locates the corresponding result file, opens it, /// and looks up the bricklet ID of the data file. /// if a result file is selected, the function opens it but does not look up bricklet IDs. /// /// the result file remains open and can be accessed using the mtrx_ functions or MFR_ operations. /// once a result file is open, you can easily access any bricklets linked to it, /// i.e., any run cycle, scan cycle, and channel. /// /// the function stores information about the opened file in a global package data folder. /// if the same result file is opened again later, the information is reused and the file not read again. /// this may cause problems if the file has been modified in the meantime, /// or if the cached data become corrupt for some reason. /// the function detects if a data file is not linked in the open result file, and updates the cache. /// in other situations it may be necessary to force a reload. /// /// @todo fix possible cache issues, add an option to override the cache. /// /// @param pathName igor path name or empty string. /// /// @param fileName file name, with or without path, or empty string. /// /// @return file type /// @arg 0 result file (logbook) /// @arg 1 result data file (bricklet) /// @arg -1 error, no data loaded /// @arg -2 matrixfilereader.xop not installed /// function mtrx_open_file(pathName, fileNameOrPath) string pathName string fileNameOrPath check_package_folder() dfref df_save = GetDataFolderDFR() dfref df_pack = $(package_path) svar /sdfr=df_pack dataFilePath svar /sdfr=df_pack resultFilePath nvar /sdfr=df_pack runCycle nvar /sdfr=df_pack scanCycle svar /sdfr=df_pack channelName nvar /sdfr=df_pack brickletID string loc_resultFileName string loc_resultFilePath variable loc_runCycle variable loc_scanCycle string loc_channelName // make sure we have a valid and complete file path GetFileFolderInfo /P=$pathName /Q /Z=2 fileNameOrPath string filePath if ((v_flag == 0) && (v_isFile)) filePath = s_path else return -1 endif // get base file name string fileName string fileDir string baseFileName variable fileType fileName = ParseFilePath(0, filePath, ":", 1, 0) fileDir = ParseFilePath(1, filePath, ":", 1, 0) fileType = mtrx_parse_filename(fileName, baseFileName, loc_runCycle, loc_scanCycle, loc_channelName) variable link = 1 variable id = -1 variable result = -1 variable using_cache = 0 struct errorCode errorCode initStruct(errorCode) do sprintf loc_resultFileName, "%s_%04u.mtrx", baseFileName, link loc_resultFilePath = fileDir + loc_resultFileName #if exists("MFR_OpenResultFile") if ((strlen(resultFilePath) == 0) || (cmpstr(loc_resultFilePath, resultFilePath) != 0)) MFR_OpenResultFile /K loc_resultFilePath if(V_flag != errorCode.SUCCESS) MFR_GetXOPErrorMessage result = -1 break endif resultFilePath = loc_resultFilePath if (fileType == 1) dataFilePath = filePath else dataFilePath = "" endif runCycle = 0 scanCycle = 0 channelName = "" brickletID = 0 MFR_CreateOverviewTable /DEST=df_pack if(V_flag != errorCode.SUCCESS) MFR_GetXOPErrorMessage result = -1 break endif using_cache = 0 else using_cache = 1 endif #else print "matrixfilereader.xop not installed" result = -2 break #endif // dimension labels are: brickletID, scanCycleCount, runCycleCount, sequenceID, dimension, channelName wave /t /sdfr=df_pack overviewTable make /n=(dimsize(overviewTable, 0)) /i /u /o df_pack:runCycles, df_pack:scanCycles, df_pack:ids make /n=(dimsize(overviewTable, 0)) /t /o df_pack:channels wave /sdfr=df_pack ids, runCycles, scanCycles wave /t /sdfr=df_pack channels ids = str2num(overviewtable[p][%brickletID]) runCycles = str2num(overviewtable[p][%runCycleCount]) scanCycles = str2num(overviewtable[p][%scanCycleCount]) channels = overviewTable[p][%channelName] result = fileType // if a data file is opened, make sure we found the right result file if ((loc_runCycle > 0) && (loc_scanCycle > 0)) Extract /FREE ids, match_ids, (runCycles == loc_runCycle) && (scanCycles == loc_scanCycle) && (cmpstr(channels, loc_channelName) == 0) if (numpnts(match_ids) > 0) id = match_ids[0] runCycle = loc_runCycle scanCycle = loc_scanCycle channelName = loc_channelName brickletID = id break elseif (using_cache) resultFilePath = "" else link += 1 endif else break endif while (id < 0) return result end /// load a preview image from a Matrix data file. /// /// the data wave is loaded into the current data folder. /// /// @param destName destination wave name. the wave is created in the current data folder. /// /// @param pathName igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed /// /// @param fileName if empty a dialog box shows up /// the file name must adhere to the format /// "{prefix}-{date}-{time}-{anything}--{run_cycle}_{scan_cycle}.{extension}". /// the first three seperators can alternatively be underscores. /// it may be necessary to change the configuration of the Matrix application. /// /// @param traces (currently not used) semicolon-separated list of preferred traces. /// the items of the list are match strings for the Igor StringMatch function. /// only the first matching trace is loaded from the file. /// default: "*Up;*Down;*ReUp;*ReDown;" /// /// @return semicolon-separated list of loaded waves including partial path from current data folder. /// function /s mtrx_load_preview(destName, pathName, fileName, [traces]) string destName string pathName string fileName string traces if (ParamIsDefault(traces)) traces = "*Up;*Down;*ReUp;*ReDown;" endif dfref df_save = GetDataFolderDFR() string datanames = "" string datapaths = "" variable filestatus = mtrx_open_file(pathName, fileName) if (filestatus != 1) return "" endif dfref df_pack = $(package_path) svar /sdfr=df_pack dataFilePath svar /sdfr=df_pack resultFilePath nvar /sdfr=df_pack runCycle nvar /sdfr=df_pack scanCycle svar /sdfr=df_pack channelName nvar /sdfr=df_pack brickletID #if exists("MFR_OpenResultFile") dfref df_data = df_save variable /g df_data:V_MatrixFileReaderOverwrite = 1 variable /g df_data:V_MatrixFileReaderFolder = 0 variable /g df_data:V_MatrixFileReaderDouble = 0 struct errorCode errorCode initStruct(errorCode) MFR_GetBrickletData /N=destName /R=(brickletID) /S=2 /DEST=df_data if(V_flag == errorCode.SUCCESS) datanames = S_waveNames variable i variable n = ItemsInList(datanames) string s s = StringFromList(0, datanames) wave data = $s mtrx_scale_dataset(data) if (WaveDims(data) == 2) subtract_line_bg(data) endif datapaths = AddListItem(GetWavesDataFolder(data, 4), datapaths, ";", inf) for (i = 1; i < n; i += 1) s = StringFromList(i, datanames) killwaves /z $s endfor else MFR_GetXOPErrorMessage endif //MFR_GetBrickletMetaData /N=ANickName /R=(brickletID) // /DEST=dfref #else print "matrixfilereader.xop not installed" #endif setdatafolder df_save return datapaths end /// load all data from a Matrix data file. /// /// the data wave is loaded into a sub-subfolder the current data folder. /// the relative path has the format ":mtrx_{date}_{time}:r{run_cycle}s{scan_cycle}", /// where the parameters {date}, {time}, {run_cycle} and {scan_cycle} are copied from the file name. /// the file name must be formatted according to the specifications set out below. /// /// @param pathName igor symbolic path name. can be empty if the path is specified in FileName or a dialog box should be displayed /// /// @param fileName if empty a dialog box shows up /// the file name must adhere to the format /// "{prefix}-{date}-{time}-{anything}--{run_cycle}_{scan_cycle}.{extension}". /// the first three seperators can alternatively be underscores. /// it may be necessary to change the configuration of the Matrix application. /// /// @param traces (currently not used) semicolon-separated list of preferred traces. /// the items of the list are match strings for the Igor StringMatch function. /// only matching traces are loaded from the file. /// default: "*Up;*Down;*ReUp;*ReDown;" /// /// @return semicolon-separated list of loaded waves including partial path from current data folder. /// function /s mtrx_load_file(pathName, fileName, [traces]) string pathName string fileName string traces if (ParamIsDefault(traces)) traces = "*Up;*Down;*ReUp;*ReDown;" endif dfref df_save = GetDataFolderDFR() string datanames = "" string datapaths = "" variable filestatus = mtrx_open_file(pathName, fileName) if (filestatus != 1) return "" endif dfref df_pack = $(package_path) svar /sdfr=df_pack dataFilePath svar /sdfr=df_pack resultFilePath nvar /sdfr=df_pack runCycle nvar /sdfr=df_pack scanCycle svar /sdfr=df_pack channelName nvar /sdfr=df_pack brickletID #if exists("MFR_OpenResultFile") string resultFileName = ParseFilePath(0, resultFilePath, ":", 1, 0) dfref df_result = mtrx_create_folder(resultFileName, df_base=df_save) dfref df_data = mtrx_get_cycle_folder(df_base = df_result) variable /g df_data:V_MatrixFileReaderOverwrite = 1 variable /g df_data:V_MatrixFileReaderFolder = 0 variable /g df_data:V_MatrixFileReaderDouble = 0 struct errorCode errorCode initStruct(errorCode) string name name = CleanupName(channelName, 0) MFR_GetBrickletData /N=name /R=(brickletID) /DEST=df_data if(V_flag == errorCode.SUCCESS) datanames = S_waveNames variable i variable n = ItemsInList(datanames) string s for (i = 0; i < n; i += 1) s = StringFromList(i, datanames) wave /sdfr=df_data data = $s mtrx_scale_dataset(data) datapaths = AddListItem(GetWavesDataFolder(data, 4), datapaths, ";", inf) endfor else MFR_GetXOPErrorMessage endif //MFR_GetBrickletMetaData /N=ANickName /R=(brickletID) // /DEST=dfref #else print "matrixfilereader.xop not installed" #endif setdatafolder df_save return datapaths end function mtrx_scale_dataset(data) wave data dfref df_pack = $(package_path) nvar /sdfr=df_pack runCycle nvar /sdfr=df_pack scanCycle svar /sdfr=df_pack channelName nvar /sdfr=df_pack brickletID string scanDir = StringFromList(2, NameOfWave(data), "_") if (WaveDims(data) == 2) Note data, "AxisLabelX=X" Note data, "AxisLabelY=Y" endif Note data, "AxisLabelD=" + channelName string title sprintf title, "%u-%u %s %s", runCycle, scanCycle, channelName, scanDir Note data, "Dataset=" + title end /// load descriptive info from a Matrix data file. /// /// the info string lists the following information for each scan contained in the file: /// - path of the scan group inside the file. /// - number of scan positions. /// - dataset names of scan positioners. /// - dataset names of detectors. /// /// @param APathName igor symbolic path name. can be empty if the path is specified in AFileName or a dialog box should be displayed /// /// @param AFileName if empty a dialog box shows up /// /// @return newline terminated string. /// function /s mtrx_load_info(APathName, AFileName) string APathName string AFileName dfref saveDF = GetDataFolderDFR() dfref fileDF = NewFreeDataFolder() setdatafolder fileDF variable fileID string filepath string scanpaths variable nscans variable iscan string scanpath string info = "" setdatafolder saveDF return info end /// remove linear background line-by-line /// function subtract_line_bg(img) wave img variable nx = dimsize(img, 0) variable ny = dimsize(img, 1) variable iy make /n=(nx) /free line, fit for (iy = 0; iy < ny; iy += 1) line = img[p][iy] if (numtype(sum(line)) == 0) CurveFit /N /Q /NTHR=0 line line /D=fit img[][iy] = line[p] - fit[p] endif endfor end